关于51单片机数码管消影

自学单片机学到中断部分,用数码管动态显示刷新频率高的时候会有重影,为了消除重影我查找了网上很多资料,好多错的。

看看原理图:

百度百科:74HC573 数码管———————————————————————————————————–74HC573是拥有八路输出的透明锁存器,输出为三态门,是一种高性能硅栅CMOS器件。SL74HC573跟LS/AL573的管脚一样。器件的输入是和标准CMOS输出兼容的,加上拉电阻他们能和LS/ALSTTL输出兼容。———————————————————————————————————–数码管动态显示接口是将所有数码管的8个显示笔划”a,b,c,d,e,f,g,dp”的同名端连在一起,另外为每个数码管的公共极COM增加位选通控制电路,位选通由各自独立的I/O线控制,当单片机输出字形码时,所有数码管都接收到相同的字形码,但究竟是哪个数码管会显示出字形,取决于单片机对位选通COM端电路的控制,所以我们只要将需要显示的数码管的选通控制打开,该位就显示出字形,没有选通的数码管就不会亮。通过分时轮流控制各个数码管的的COM端,就使各个数码管轮流受控显示,这就是动态驱动。在轮流显示过程中,每位数码管的点亮时间为1~2ms,由于人的视觉暂留现象及发光二极管的余辉效应,尽管实际上各位数码管并非同时点亮,但只要扫描的速度足够快,给人的印象就是一组稳定的显示数据,不会有闪烁感,动态显示的效果和静态显示是一样的,能够节省大量的I/O端口,而且功耗更低。————————————————————————————————————————————————————————————————————————由上面可以知道,数码管要显示得位码和段码都分别赋值(赋值前选通控制打开,赋值后选通关闭)才行,位码或段码赋值完成数值立即被锁存,只要不重新给位码或段码赋值则锁存的值不变。(注意,给锁存器赋值的是P0端口,只要不给P0重新赋值,则P0的值也不变)所以:

通常是 (1)清除位码 → (2)给锁存器赋下一位要显示的段码(字形码),开通段选,关闭段选 → (3)给锁存器赋下一位要显示的位码(位置码),开通位选,关闭位选

 1         P0   = 0xff;//消除重影,关闭所有位选 2     wela = 1; 3     wela = 0; 4     P0   = digitron_table[shi];//调用八段数码管代码表 5     dula = 1; 6     dula = 0; 7     P0   = 0xbf; 8     wela = 1; 9     wela = 0;10     delay(1);11     12     P0   = 0xff;//消除重影13     wela = 1;14     wela = 0;15     P0   = digitron_table[ge];//调用八段数码管代码表16     dula = 1;17     dula = 0;18     P0   = 0x7f;19     wela = 1;20     wela = 0;21     delay(1);

View Code

也可以 (1)清除段码 → (2)给锁存器赋下一位要显示的位码(位置码),开通位选,关闭位选→ (3)给锁存器赋下一位要显示的段码(字形码),开通段选,关闭段选

 1         P0   = 0x00;//消除重影,关闭段选 2     dula = 1; 3     dula = 0; 4     P0   = 0xbf; 5     wela = 1; 6     wela = 0; 7     P0   = digitron_table[shi];//调用八段数码管代码表 8     dula = 1; 9     dula = 0;10     delay(1);11     12     P0   = 0x00;//消除重影13     dula = 1;14     dula = 0;15     P0   = 0x7f;16     wela = 1;17     wela = 0;18     P0   = digitron_table[ge];//调用八段数码管代码表19     dula = 1;20     dula = 0;21     delay(1);

View Code

这样,不论多快的刷新频率都不会有重影。

————————————————————————————–

完整代码:

  1 //使用定时器1中断让8个LED循环右移,间隔500ms,同时使用定时器0中断方式让数码管前2位间隔1000ms从0显示到60,  2 //如果有外部中断产生则停止数码管走数(外部中断0低电平触发方式)  3    4 #include <reg52.h>  5 #include <intrins.h>  6    7 //宏定义,方便书写  8 #define uchar unsigned char  9 #define uint unsigned int 10  11 sbit dula = P2^6; 12 sbit wela = P2^7; 13 uchar counter_s; 14  15 //子函数声明 16 void interrupt_timer_init(); 17 void display(uchar i); 18 void delay(uint z); 19  20 //八段数码管代码表 21 uchar code digitron_table[] = {//LED单元 dp g f e  d c b a  22     0x3F,  //"0"  0011 1111 23     0x06,  //"1"  0000 0110 24     0x5B,  //"2"  0101 1011    * * * *  a  * * * * 25     0x4F,  //"3"  0100 1111    *                 * 26     0x66,  //"4"  0110 0110    *                 * 27     0x6D,  //"5"  0110 1101    *                 * 28     0x7D,  //"6"  0111 1101    f                 b 29     0x07,  //"7"  0000 0111    *                 * 30     0x7F,  //"8"  0111 1111    *                 * 31     0x6F,  //"9"  0110 1111    *                 * 32     0x77,  //"A"  0111 0111    * * * *  g  * * * * 33     0x7C,  //"B"  0111 1100    *                 * 34     0x39,  //"C"  0011 1001    *                 * 35     0x5E,  //"D"  0101 1110    *                 * 36     0x79,  //"E"  0111 1001    e                 c 37     0x71,  //"F"  0111 0001    *                 * 38     0x76,  //"H"  0111 0110    *                 * 39     0x38,  //"L"  0011 1000    *                 * 40     0x37,  //"n"  0011 0111    * * * *  d  * * * * * dp * * 41     0x3E,  //"u"  0011 1110 42     0x73,  //"P"  0111 0011 43     0x5C,  //"o"  0101 1100 44     0x40,  //"-"  0100 0000 45     0x00,  //熄灭 0000 0000 46     0x00   //自定义 47 }; 48  49 //主函数部分 50 void main() 51 { 52     interrupt_timer_init(); 53     while (1) { 54         display(counter_s); 55 } 56 } 57   58 //中断服务特殊功能寄存器配置和定时器初始化 59 void interrupt_timer_init() 60 { 61     TMOD = 0x11;//定时方式工作模式0和1,工作模式寄存器TMOD的地址是0x89,不能被8整除,只能对字节操作,不能位操作 62     TH1  = 0x4c;//公式:定时时间t = (2^16 - T1初值) * 振荡周期 * 12         (振荡周期 * 12 即机器周期) 63     TH0  = 0x4c; 64     TL1  = 0x00;//T1 = 2^16 - t * 11059200 / 12         (此定时时间为 50ms, T1 = 19456 = 0x4c00) 65     TL0  = 0x00; 66     TR1  = 1;    //定时器运行控制位置1,TCON的地址是0x88,可以对位操作 67     TR0  = 1; 68     ET1  = 1; //定时器/计数器T1的溢出中断允许位置1,允许T1中断, 中断允许寄存器IE(A8H) 69     ET0  = 1; 70     EX0  = 1; 71     IT0   = 0; 72     EA   = 1; //中断允许总控制位置1,CPU开放中断, 中断允许寄存器IE(A8H) 73     P1 = 0x7f; 74 }  75  76 // 77 void interrupt_program_INT0() interrupt 0 //(1)中断函数无返回值,会破坏栈 (2)不能向ISR传递参数,会破坏栈 (3)ISR应该尽可能的短小精悍 (4)中断函数不能被调用,硬件决定 78 { 79     TR0 = 0; 80 } 81  82 //T1中断服务程序 83 void interrupt_program_T1() interrupt 3 84 { 85     uchar counter; 86     counter++; 87     TH1  = 0x4c; 88     TL1  = 0x00; 89     if (counter == 10) {     90         P1 = _cror_(P1, 1); 91         counter = 0; 92     }     93 } 94  95 //T0中断服务程序 96 void interrupt_program_T0() interrupt 1 97 { 98     uchar counter_ms; 99     counter_ms++;100     TH1  = 0x4c;101     TL1  = 0x00;102     if (counter_ms == 20) {        103         counter_ms = 0;104         counter_s++;105         if (counter_s == 60) {106             counter_s = 0;107         }108     }    109 }110 111 //延时函数112 void delay(uint z)113 {114     uint x, y;115     for (x = 0; x < z; x++)116         for (y = 0; y < 114; y++);117 }118 119 //数码管显示函数120 void display(uchar i)121 {122      uchar shi,ge;123     shi = i / 10;//求模124     ge = i % 10;//求余125 //实际产品中,(1)关所有位选→(2)输出下一位要显示的段码→(3)开通下一位要显示的位选126 //其实也可以,(1)关所有段码→(2)开通下一位要显示的位选→(3)输出下一位要显示的段码127     P0   = 0x00;//消除重影,关闭段选128     dula = 1;129     dula = 0;130     P0   = 0xbf;131     wela = 1;132     wela = 0;133     P0   = digitron_table[shi];//调用八段数码管代码表134     dula = 1;135     dula = 0;136     delay(1);137     138     P0   = 0x00;//消除重影139     dula = 1;140     dula = 0;141     P0   = 0x7f;142     wela = 1;143     wela = 0;144     P0   = digitron_table[ge];//调用八段数码管代码表145     dula = 1;146     dula = 0;147     delay(1);148     149 /*150   P0   = 0xff;//消除重影,关闭所有位选151     wela = 1;152     wela = 0;153     P0   = digitron_table[shi];//调用八段数码管代码表154     dula = 1;155     dula = 0;156     P0   = 0xbf;157     wela = 1;158     wela = 0;159     delay(1);160     161     P0   = 0xff;//消除重影162     wela = 1;163     wela = 0;164     P0   = digitron_table[ge];//调用八段数码管代码表165     dula = 1;166     dula = 0;167     P0   = 0x7f;168     wela = 1;169     wela = 0;170     delay(1);171 */172 }

View Code

如有错误还请指出,如有侵权还请告知,如需转载请注明出处!

本人博客:http://www.cnblogs.com/yllinux/

相信成功的信念比成功本身更重要,

关于51单片机数码管消影

相关文章:

你感兴趣的文章:

标签云: