zoukankan      html  css  js  c++  java
  • 关于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/

  • 相关阅读:
    poj 2187 Beauty Contest(旋转卡壳)
    poj 2540 Hotter Colder(极角计算半平面交)
    poj 1279 Art Gallery(利用极角计算半平面交)
    poj 3384 Feng Shui(半平面交的联机算法)
    poj 1151 Atlantis(矩形面积并)
    zoj 1659 Mobile Phone Coverage(矩形面积并)
    uva 10213 How Many Pieces of Land (欧拉公式计算多面体)
    uva 190 Circle Through Three Points(三点求外心)
    zoj 1280 Intersecting Lines(两直线交点)
    poj 1041 John's trip(欧拉回路)
  • 原文地址:https://www.cnblogs.com/yllinux/p/6935590.html
Copyright © 2011-2022 走看看