动态数码管显示实验
一、动态数码管显示原理
数码管的动态显示是利用减少段选线,分开位选线,利用位选线不同时选择通断,改变段选数据来实现的。 比如在第一次选中第一位数码管时,给段选数据0,下一次位选中第二位数码管时显示1。
为了在显示1的时候,0不会消失(当然实际上是消失了),必须在人肉眼观察不到的时间里再次点亮第一次点亮的0。 而这时就需要记住,人的肉眼正常情况下只能分辨变化超过24ms间隔的运动。
也就是说,在下一次点亮0这个数字的时间差不得大于24ms。 这时就会发现,数码管点亮是在向右或者向左一位一位点亮,形成了动态效果。如果把间隔时间改长就能直接展现这一现象。
二、硬件电路的分析


由动态数码管模块可以看出该数码管的段选数据是由P0来控制 ,位选数据由138译码器P22-P24来控制。如点亮数码管,则需使对应数码管有效,由图片可知,该数码管类型为共阴极数码管,所以公共端(com)需要低电平则可以点亮,即位选输出低电平。
假设使动态数码管模块LED8显示数字0,第一步需要是的位选LED8有效,又因为该数码管结构为共阴极,所以LED8低电平有效;段选部分,因为数码管结构为共阴极,所以只需P0输入0X3F。
假设使动态数码管模块LED7显示数字1,第一步需要是的位选LED7有效,又因为该数码管结构为共阴极,所以LED7低电平有效;段选部分,因为数码管结构为共阴极,所以只需P0输入0X06。又因为0和1之间的延时需要控制在肉眼不能识别的范围,大概的1ms左右。
三、软件编程
1. 头文件和宏定义: 包含 "reg52.h" 头文件,这是针对8051单片机特定的寄存器定义。
使用 typedef 对数据类型进行重定义,u16定义为 unsigned int,u8定义为unsigned char。
使用#define 定义了 SMG_A_DP_PORT 为P0,这代表数码管的数据端口连接到P0端口。

2. 数码管位选信号和段码表:使用sbit关键字定义了三个位选信号控制脚 (LSA, LSB, LSC),它们分别连接到 P2^2, P2^3, 和 P2^4。

定义了一个数组gsmg_code存储0到F(十六进制)的数码管显示编码。

3. 延时函数:delay_10us函数通过一个 while 循环实现大约10微秒的延时,参数 ten_us指定延时的倍数。
/*******************************************************************************
* 函 数 名 : delay_10us
* 函数功能 : 延时函数,ten_us=1时,大约延时10us
* 输 入 : ten_us
* 输 出 : 无
*******************************************************************************/
void delay_10us(u16 ten_us)
{
while(ten_us--);
}
4.数码管显示函数:smg_display函数负责动态驱动数码管显示。它循环遍历每一位,通过设置不同的位选信号来选择哪一位数码管被激活,并通过SMG_A_DP_PORT送出相应的段码到数码管。 在每次传送段选数据后,调用 delay_10us(100)来稳定显示,然后清除SMG_A_DP_PORT以消除鬼影。
/*******************************************************************************
* 函 数 名 : smg_display
* 函数功能 : 动态数码管显示
* 输 入 : 无
* 输 出 : 无
*******************************************************************************/
void smg_display(void)
{
u8 i=0;
for(i=0;i<8;i++)
{
switch(i)//位选
{
case 0: LSC=1;LSB=1;LSA=1;break;
case 1: LSC=1;LSB=1;LSA=0;break;
case 2: LSC=1;LSB=0;LSA=1;break;
case 3: LSC=1;LSB=0;LSA=0;break;
case 4: LSC=0;LSB=1;LSA=1;break;
case 5: LSC=0;LSB=1;LSA=0;break;
case 6: LSC=0;LSB=0;LSA=1;break;
case 7: LSC=0;LSB=0;LSA=0;break;
}
SMG_A_DP_PORT=gsmg_code[i];//传送段选数据
delay_10us(100);//延时一段时间,等待显示稳定
SMG_A_DP_PORT=0x00;//消音
}
}
/*******************************************************************************
* 函 数 名 : main
* 函数功能 : 主函数
* 输 入 : 无
* 输 出 : 无
*******************************************************************************/
void main()
{
while(1)
{
smg_display();
}
}
5. 主函数:main函数中包含了一个无限循环,不断调用smg_display函数,以维持数码管的显示。
四、运行结果

五、其他小结
unsigned char code leddata[]={0x6D};
当在声明数组时添加关键字code时,表示该数组是一个存储在ROM中的常量数组。
这样做可以节省RAM空间,因为将常量数据存储在ROM中不会占用RAM空间,而且常量数据在程序运行期间是只读的,不需要被修改。
p00 p01 p02 p03 p04 p05 p06 p07
1 1 1 1 0 0 1 0
作者:小x来啦