由数码管动态显示浅谈单片机程序

发布者:学海星空最新更新时间:2015-06-23 来源: 51hei关键字:数码管  动态显示  单片机程序 手机看文章 扫描二维码
随时随地手机看文章
数码管动态显示原理:动态显示的特点是将所有位数码管的段选线并联在一起,由位选线控制是哪一位数码管有效。这样一来,就没有必要每一位数码管接一组IO口,从而大大地节约了IO口。选亮数码管采用动态扫描显示。所谓动态扫描显示即轮流向各位数码管送出字形码和相应的位选,利用发光管的余辉和人眼视觉暂留作用,使人的感觉好像各位数码管同时都在显示。 即实际上,每个数码管是一个个的依次点亮。利用人眼视觉停留,快速扫描,一般每隔10ms以的下时间刷新一次数码管显示即可看到稳定的显示效果。本人亲自试验,最好刷新时间设定为5ms一下,高于5ms显示会略微有些晃眼。

传统的数码管显示程序为:

#define  DUAN        P1

#define  WEI           P0

 

void delayms(uchar x)

{

      uchar  y=120;

             while(x--)

                    while(y--);

}

 

WEI=0;         //消影   共阳,共阴为 WEI=0xff

DUAN=code[value_duan1];           //送段选数据

WEI=value_wei1;             //送位选数据,确定第几个数码管点亮

Delayms(5);        //延时5ms使其显示稳定

 

WEI=0;         //消影   共阳,共阴为 WEI=0xff

DUAN=code[value_duan2];           //送段选数据

WEI= value_wei2;            //送位选数据,确定第几个数码管点亮

Delayms(5);        //延时5ms使其显示稳定

 

 

当延时后依次再送下一个数据,再延时······

这里我想再次说一下关于延时的问题。一般教科书或者说目前绝大多数能看到的数码管处理程序资料大多都是按照上面的方式处理的。我想问一下,这里延时5ms的意义何在?可否不延时?答案是可以,但显示结果就是最后一个被点亮的数码管会比较亮,其余的都比较暗。至于原因很简单,点亮最后一个数码管后,单片机CPU还要跑其他程序,然后再次跑到数码管显示处理函数时再依次点亮第一第二个数码管。显然这样最后一个被点亮的数码管点亮的时间远远比其他的数码管时间要长,自然这一个特别亮,其余的很暗淡。然而加上5ms延时的话呢?由于单片机速度还算比较快(一般一条指令1us),5ms相当于5000条指令。5000条指令什么概念呢?怎么说呢,若程序里不用“delay”这样的空指令的话,一般一个大型项目就差不多了。一般而言,比如AD测温、电子时钟等这样小项目实际有用的指令绝对不会达到好几千的样子。所以说5ms对于单片机来说是个相当长的时间。

再回到延时5ms后显示较为稳定的问题上。因为点亮最后一个数码管延时5ms后单片机在跑其他的指令时相对要不了多久(前提是其余地方没有“delay”空指令),所以最后一个数码管比其他数码管多亮的时间就不太明显了,这样自然显示也会比较均匀一些。但是事实上,最后一个被点亮的数码管还是稍微比别的数码管亮一些。注意上面所说的是单片机跑其他指令用的时间不长的情况。如果,程序比较大,模块很多,单片机要处理的事情很多呢?比方说一个float型数据的除法(不知道读者有没有在单片机上试过)所耗费的指令数可能你都想象不到(尤其是对于内部不含硬件除法器单片机,其除法指令转换成其他的运算)。我当时做AD测电阻时用的sonix芯片(没有除法器),开始程序里面一个float型除法,整个程序当时有1.5k的样子,数码管显示,老是一个亮,其余的暗淡,而且很不稳定。后来查找原因,就是因为那条float型除法的问题,竟然占了大几ms的时间。当删除那条指令后,整个程序只有700多字节,也就是说就这么一条指令就直接让程序大小翻倍了!查看编译器翻译成的汇编指令占了相当大一部分,而且还有很多CALL指令。所以说,8位单片机 确实不适合做除法以及float运算。

扯远了,回到数码管问题。综上面所述,delayms(5)的方式是不可靠的。而且最为关键的时delay指令是毫无意义的,就是让单片机啥也不做,在那里死等。试想一下,单片机还要处理其他事情,光在这里死等岂不是太浪费了吗?就好比人一样我可以在吃饭的同时听音乐,而不是先吃饭,饭吃完了再专门听音乐。单片机也是一样,要的是效率,而不是在那里死等。

那么这种方式不好,该怎么办呢?要不要延时?延时肯定是需要的,不然显示不均匀,但不是这种方式。正确的方式是定时器定时5ms,5ms到后刷新一次数码管,这样一来单片机不会在这里死等,二来数码管显示时间绝对均匀。对于定时器,一般的单片机至少有一个,而且它作为单片机的独立模块,根本不影响cpu工作。以3个数码管为例,其程序代码如下

#define  DUAN        P1       //宏定义段选

#define  WEI           P0        //宏定义位选

 

void  timer();           //定时器处理函数,用定时器定时5ms

{

      if(定时标志位置一)

      {

             定时标志清零;

             If(T_5ms)                    //若T_5ms大于0,每5ms减1

                    T_5ms--;

      }

}

if(T_5ms==2)

{

             WEI=0;          //消影  共阳,共阴为 WEI=0xff

             DUAN=code[value_duan1];

             WEI= value_wei1;

}

if(T_5ms==1)

{

             WEI=0;

             DUAN=code[value_duan1];

             WEI= value_wei2;

}

if(T_5ms==0)

{

             T_5ms=3;                   //计时寄存器重新赋值

             WEI=0;

             DUAN=code[value1];

             WEI=value2;

}

 

这样CPU不用在这里死等,每次程序跑到这里时,只需做个判断就好了,5ms到后就进去点亮数码管,否则就不进去,显示效果绝对均匀。同理,诸如键盘扫描程序,延时消抖,都可以采用这种方式,而不用delay。

也许读者可能发现了问题,对,还是有点问题。假若程序在其他地方耗费时间大于5ms的话,那么这里的定时5ms就失去了作用。确实是这样的。实际上对于好程序来说,主循环绝对控制在1ms一下(CPU跑1Mhz,即1条指令1us)。也许你会问,有些模块不可能1ms以内就完成啊。是的,有些时候某些模块确实需要很久才能完成。这就涉及到程序分时分段处理的问题。好比人做事情一样,我这件事今天做不完,但可以明天再做,而且同时今天我也要吃饭、睡觉做其他的事情,而不是说这件事没做完,别的什么也不干了。单片机也是如此。不管在大的程序,都是分时分段处理的,不然CPU会崩溃的,CPU不可能同时把所有的都一起处理了,而是这段时间处理一点,下段时间再处理一点。这样在总的时间上是一样的,CPU完成的事情却翻倍了。说道这里程序主循环控制在1ms绝对不成问题了。在试想一下,在程序里面到处delay是不是很可怕?比如按键,消抖可以delay 10ms,如果是长按键呢?难道要delay 3s或更长?所以说不管从功能上还是程序结构上,delay是绝对不可取的。对于delay,几个us(相当于几个nop指令)还是允许的。

说到这里,程序分时分段思想已经很明白了。虽然说一个大型项目,包括很多模块,比如按键、AD采样、数码管显示(或lcd显示)、PWM输出、UART、IIC通讯等等,但是并不是说每个模块都在同一时间完成。比如按键按一下大概几百毫秒的样子,长按好几秒的样子,主程序不是一直在这里等,而是一遍又一遍的循环扫描,当扫描的按键键值变化而且连续在100ms以内没有变化,那么确认此次为短按键按下。每次在扫描键盘时大概耗费几十us,然后接着以同样的方式扫描其他模块。这样主循环把所有的模块都扫一遍顶多也就几百us的样子。这样说来,一次按键按下事件,程序已经把它分成了大概几百次来完成,即为分时处理。而不是以delay的方式死等这一次事件完成。其他模块都遵循这个道理。

告别delay,主循环while(1)周期做到小于1ms,那么就告别了学校教育从而进入实际应用!为什么学校所教的不是这种思想呢?因为在学校和实践严重脱节,没有考虑过真正的项目。所学的都是一些独立子程序模块。由于子程序结构简单,程序较小,delay无所谓。而把各个模块都加在一起,可能就会出毛病。实际情况要考虑的还多的很,比如功耗、成本等等。在学校只管能搞出结果就不错了,哪管这个芯片多少钱,这个电容多少钱?对于真正的项目应用,实现功能只算很小很小的一部分。由于学校所学和实际脱节,所以这也是当今大学生难找工作的原因之一,这也是当今中国教育的缺陷!当然成为单片机高手,还有很多路要走,了解这些只是一个门槛而已。

关键字:数码管  动态显示  单片机程序 引用地址:由数码管动态显示浅谈单片机程序

上一篇:学习单片机的日记
下一篇:stc12c5a60s2单片机spwm发生程序带仿真文件

推荐阅读最新更新时间:2024-03-16 14:04

51单片机-按键&蜂鸣器&数码管
在上一讲的代码中我们可以不用写“sbit GND = P2^3;”,像宋老师那样直接在开头“P2 = 0xF7;”仅让P2.3输出0其他输出1即可,这样P2.7就有被拉低的条件了。 1.趁热打铁 沿袭上一讲的功能,我们新学的按键知识需要结合所学过的无源蜂鸣器硬件一起捣鼓玩玩。同上一讲的代码功能一样,这次用的是无源蜂鸣器,按键按下时,蜂鸣器就响,松开不按时就不响。 2.分析 我们先缕缕思路,显然无源蜂鸣器要想鸣叫,就不能像“LED2=KEY4;”这样赋值的方式。我们已经知道,在P2.3输出低电平的情况下,K4按下的时候程序中KEY4就等于0,松开不按时KEY4等于1。 这里可以在主函数中的死循环里用“if(KEY4==0
[单片机]
基于AVR单片机的mega16内部EEPROM操作C语言程序设计
#include iom16v.h #include macros.h #include math.h #define uchar unsigned char #define uint unsigned int uchar const seg_data ={0xC0,0xF9,0xA4,0xB0,0x99,0x92,0x82,0xF8,0x80,0x90,0xff}; //0~9和熄灭符的段码表 uchar const bit_tab ={0xbf,0x7f}; //第7、8只数码管位选表 uchar disp_buf ={0,0}; //定义2个显示缓冲单元 uchar val; #define beep_0 (PORTD=
[单片机]
单片机C程序main函数之前做了什么
在测试c语言单片机程序的时候,发现在main函数的执行之前,有很长的一段时间的延时,单片机在这段时间在做什么?进行了一下分析,得到结论如下: C程序 #include reg51.h sbit p1_7=P1^7; void interrupt0() interrupt 0 using 2 { p1_7=!p1_7; } void main() { EA=1; IT0=1; EX0=1; p1_7=0; do{}while(1); } 生成的机器码: :03000300020006F2   中断入口 :03000600B297327C   中断程序 :0B000900D2AFD288D2A8C29780FE229E 
[单片机]
串行接口LED数码管及键盘管理ZLG7289A的原理与应用
1 概述 ZLG7289A是广州周立功单片机发展有限公司自行设计的、具有SPI串行接口功能的、可同时驱动8位共阴式数码管(或64只独立LED)的智能显示驱动芯片。该芯片同时可连接多达64键的键盘矩阵。单块芯片即可完成LED显示以及键盘接口的全部功能。 ZLG7289A内部含有译码器,可直接接收BCD码或16进制码,并同时具有2种译码方式,此外还具有多种控制指令,如消隐、闪烁、左移、右移、段寻址等。 通过ZLG7289A自身所具有的片选信号,可以方便地实现多于8 位显示或多于64 键的键盘接口。该芯片的主要特性如下: ●带有串行接口,无需外围元件即可直接驱动LED; ●各位可独立控制译码/不译码及消隐和闪烁属
[嵌入式]
数控电源AVR单片机C程序
编译环境为CodeWizardAVR #include mega8.h #include delay.h #include stdio.h #include stdlib.h #define Voltage_UP PINB.0 #define Voltage_Down PINB.2 #define UD PORTB.3 #define CS PORTB.5 #define INC PORTB.4 #define Voltage_LED PORTB.6 #define Current_LED PORTB.7 #define Current_Detect 0 #define Out_Detect 1 #define
[单片机]
LED数码管的识别及检测方法
1. LED数码管介绍 LED数码管也称半导体数码管,它是将若干发光二极管按一定图形排列并封装在一起的最常用的数码显示器件之一。LED数码管种类很多,品种五花八门,这里仅向初学者介绍最常用的小型“8”字形LED数码管的识别与使用方法。 目前,常用的小型LED数码管多为“8”字形数码管,它内部由8个发光二极管组成,其中7个发光二极管(a~g)作为7段笔画组成“8”字结构(故也称7 段LED数码管),剩下的1个发光二极管(h或dp)组成小数点,如图1(a)所示。各发光二极管按照共阴极或共阳极的方法连接,即把所有发光二极管的负极(阴极)或正极(阳极)连接在一起,作为公共引脚;而每个发光二极管对应的正极或者负极分别作为独立引脚(称
[测试测量]
LED<font color='red'>数码管</font>的识别及检测方法
AVR单片机通过74HC595驱动数码管显示
一个很简单的avr单片机的仿真,用74hc595芯片来驱动单个数码管显示数字,下面是仿真原理图 源程序: #include iom16v.h #include macros.h void delay(int k){ int i=0,j=0; for(i=0;i k;i++){ for(j=0;j 6;j++){ ; } } } void InputData(unsigned char data){ unsigned char i; unsigned char k; for(i=0;i 8;i++){
[单片机]
AVR<font color='red'>单片机</font>通过74HC595驱动<font color='red'>数码管</font>显示
C8051FXXX单片机FLASH程序的自动升级
作者Email: wolfman6353@sina.com 引言: C8051FXXX系列高速SOC单片机是由美国Cygnal公司开发的完全集成的混合信号系统级芯片,具有与8051兼容的微处理器内核,内部集成FLASH程序存储器,具有在系统重新编程能力,以C8051F020为例,内部集成64K的FLASH程序存储器。在系统控制软件的开发调试阶段,可用集成开发环境来下载及测试系统,但当将C8051F020目标系统集成到产品后,则由于操作系统及软硬件接口不一样等等原因,不能在最终产品中用集成开发环境来下载FLASH程序,故产品到了用户处之后,如要再进行FLASH程序的更新,则必须更换相应的集成电路印刷板,造成很多麻烦及不可靠因素。
[应用]
小广播
添点儿料...
无论热点新闻、行业分析、技术干货……
设计资源 培训 开发板 精华推荐

最新单片机文章
何立民专栏 单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

换一换 更多 相关热搜器件
电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved