数码管是电子产品设计中不可或缺的显示原件,驱动简单、可靠性高、抗干扰能力强、温度适应性广、价格低廉。在实际项目中使用非常广泛。
数码管的驱动也非常简单,在所有的电子类教程中都有。我们随便可以写一个。
数码管的原理图与电路图如上所示。这是一款共阴极的数码管。共阳极数码管处理方式与共阳极非常相似。我们来写出该款数码管的编码表。参照以下电路图我们写出该数码管的驱动。
为了布线方便,并不是P2_0至P2^7依次驱动a至dp.而是根据布线方便任意连接。这个不是问题,我们依然可以写出编码表。
0 --------- 0XBE
1 --------- 0X18
2 --------- 0XAD
3 --------- 0X9D
4 --------- 0X1B
5 --------- 0X97
6 --------- 0XB7
7 --------- 0X1C
8 --------- 0XBF
9 --------- 0X9F
A ----------0X3F
B ----------0XB3
C ----------0XA6
D ----------0XB9
E ----------0XA7
F ----------0X27
在一般教程中的使用方法大概如下:
static unsigned char code LED[16] = { 0XBE, 0X18, 0XAD, 0X9D, 0X1B, 0X97, 0XB7, 0X1C,0XBF, 0X9F,0X3F,0XB3,0XA6,0XB9,0XA7,
0X27
};
因为有两位数码管所以有片选位。为了实现大的电流,我们可以采用UNL2003驱动。
我们假设Dig0由P3_1驱动,Dig1由P3_2驱动。
sbit DING_0_SEL_PIN = P3^1;
sbit DING_1_SEL_PIN = P3^2;
#define DATA_OUT_PIN P2
我们编写一个显示函数
void display( unsigned char dat )
{
static unsigned char stateM=0;
dat = dat % 100;
DING_0_SEL_PIN =0;
DING_1_SEL_PIN =0;
switch(stateM)
{
case 0:
DATA_OUT_PIN =dat /10;
DING_0_SEL_PIN =1;
DING_1_SEL_PIN =0;
stateM =1;
break;
case 1:
DATA_OUT_PIN =dat /10%10;
DING_0_SEL_PIN =0;
DING_1_SEL_PIN =1;
stateM =0;
break;
default:
stateM =0;
break;
}
}
以上代码基本上实现了数码管的驱动,但是这个驱动有一定局限性,首先,显示的字库只有0-9和A、b、C、d、E、F。并且不能显示范围是0~99.不能显示负数。
在不久前我们遇到客户这样的要求,需要显示的菜单如下:
用户参数菜单
代号
意义
设置范围
默认值
tN
排水阀关闭时间
(0~99分钟)
5分钟
tF
排水阀打开时间
(1~99秒)
3秒
管理者参数菜单
tL
压缩机防频繁启动延时
1~5分钟
1分钟
PU
温度修正
-10~+10度
0度
AJ
电流检测延时时间
0~60秒
3秒
以上菜单中"t"、“J”、“U”在原来的字库中是没有的,虽然使用数码管显示这些字符不够完美,但是勉强是可以显示的。但是原来的驱动就不能胜任了。我的一位同事重新编写驱动和编码表。
首先建立一个字库文件ZK.h
#ifndef _ZK_H_
#define _ZK_H_
typedef struct LED_ELEMENT
{
char ch_ar; //字符
unsigned char led_dis; //显示数据
}LED_ELEMENT;
#define TABLE_NUMBER_MAXsizeof(LED_TABLE)/sizeof(LED_ELEMENT)
#define NO_CHAR 0X40
static LED_ELEMENT code LED_TABLE[]={
'0', 0X7E, //---0
'1', 0X30, //---1
'2', 0X6D, //---2
'3', 0X79, //---3
'4', 0X33, //---4
'5', 0X5B, //---5
'6', 0X5F, //---6
'7', 0X70, //---7
'8', 0X7F, //---8
'9', 0X7B, //---9
'A', 0X77, //---A
'B', 0X1F, //---B
'C', 0X4E, //---C
'D', 0X3D, //---D
'E', 0X4F, //---E
'F', 0X47, //---F
'O', 0X7E, //---'O'
'P', 0X67, //--'P' 字母 P
'E', 0X4F, //---'E'字母 E
'L', 0X0E, //---'L'字母 L
'V', 0X3E, //---'V'字母 V
'T', 0X0F, //---'T'字母 T
'-', 0X01, //--'-' 负号
'J', 0X38, //---'J' 字母 J
'S', 0X4F, //---'S' 字母 S
'N', 0X76, //---'N' 字母 N
'Y', 0X27, //---'Y' 字母 Y
'@', 0X63, //---'0' 摄氏度
'U', 0X3E, //---'U' 字母 U
'*', 0x00 //---熄灭
};
#endif
#define NO_CHAR 0x00
我们编写一个显示驱动,
/*************************************
功能:字符转化位LED显示数据
参数: ch 原字符,比如-‘A’、'B'、等等
返回:ch元字符对应的字库中LED显示数据
返回NO_CHAR表示没有找到该字符
**************************************/
unsigned char chToLed(unsigned char ch )
{
unsigned char i;
for( i=0; i
{
if(ch == LED_TABLE[i].ch_ar)
return LED_TABLE[i].led_dis;
}
return NO_CHAR;
}
/*****************************
功能:驱动数码管显示
参数:str显示的字符串,len字符串长度,在本例中
有两位数码,所以固定为2
返回:
无:
******************************/
void display(const char str[],const unsigned char len)
{
unsgiend char i;
char dis[2];
static unsigned stateM =0;
if(len !=2) return ;
for( i =0; i
{
dis[ i] = chToLed(str[i]);
}
DING_0_SEL_PIN =0;
DING_1_SEL_PIN =0;
switch(stateM)
{
case 0:
DATA_OUT_PIN = dis[0];
DING_0_SEL_PIN =1;
DING_1_SEL_PIN =0;
stateM =1;
break;
case 1:
DATA_OUT_PIN =dis[1];
DING_0_SEL_PIN =0;
DING_1_SEL_PIN =1;
stateM =0;
break;
default:
stateM =0;
break;
}
}
以上代码我们实现了数码管的启动,并且有了更宽泛的 字库!