I/O输出——实例3:数码管动态扫描显示

 I/O输出—— 实例3:数码管动态扫描显示

一、实例目的
      通过本实例,我们应:
      1. 了解多位数码管的结构及引脚;
      2. 了解多位数码管驱动电路;
      3.掌握数码管动态扫描程序设计。
      本例重点介绍多位数码管的驱动电路和程序设计,关于单个数码管的结构和驱动原理,请参见《 I/O输出——实例2:数码管静态驱动 》。
二、多位数码管结构及引脚
      多位数码管用于显示更多的数值信息,其由多个数码管组成,这些数码管的段(a~h)一一对应连接在一起,公共极独立。4位数码管外观如图1所示。
           
                    图1   4位数码管
    注:图1来源自Wikipedia,原文链接: https://en.wikipedia.org/wiki/Seven-segment_display
   
 四位数码管引脚见表1。
   表1 四位数码管引脚

引脚
功能
a~h
多位数码管的段控制端,输入,决定数码管的显示内容
com0~com3
数码管的公共端,即共阴极或共阳极,又称位选

二、多位数码管驱动原理
        因为多位数码管的a~h段在内部连接在一起,为了让数码管显示不同的内容,只能采用动态扫描方式,即按照一定方向(例如从左到右)逐一选中数码管,单片机输出相应的显示数据,并保持一定的时间,如此循环。由于人眼的视觉暂留效应,我们看到多位显示内容是同时显示的,这与动画由一幅幅图片动态快速切换的原理是类似的。 根据经验,当帧率为15fps以上,则动画是连贯的(一帧就是一幅图像)。帧率越高动画越流畅,一般动画要求帧数在24帧以上。对于四位数码管,显示四位数字为一帧,按25fps计算,则每位数字的显示时间为10ms左右(1s/25/4)(帧率取25fps,4为数码管的位数)。 但是,经过实测,每位数字显示10ms,明显看到辉光闪烁,刷新频率不够,改为5ms则稳定显示。 
        8位数码管的驱动电路如图2所示。一个74HC573锁存器用于提供数码管 驱动 电流,一个74LS138译码器用于片选8位数码管,任意时刻仅有一个数码管是选中的。
        
                                                           图2 8位数码管动态扫描驱动电路
       下面简单介绍74HC573和74LS138芯片的功能和引脚。
       74HC573是8位锁存器(时序电路,输出不仅仅取决于输入,还与电路之前的状态有关,具有记忆(存储)功能),用于锁存8位数据,其引脚见表2。
                                                       表2  74HC573引脚
引脚
功能
D0~D7
输入,8位待锁存的数据
Q0~Q7
输出,三态,内部8位锁存器的输出
提示:三态指高电平、低电平和高阻态。高阻态相当于与其它电路断开。通常总线(地址线、数据线都是三态的)
输入,输出使能,低电平有效
输入高电平时,Q0~Q7呈高阻态;输入低电平时,Q0~Q7为内部8位锁存器输出
提示:如果管脚带帽(名称上有一个横线),表示该引脚低电平有效,否则为高电平有效。
LE
输入,锁存使能端,高电平有效。
LE = 1时,D0~D7能够进入到内部的8位锁存器
LE = 0时, 内部的8位锁存器保持,即D0~D7无法进入到锁存器内部
74LS138是38译码器(组合电路,输出由输入决定,无记忆(存储)功能),其引脚见表3,功能表见表4。
表3 74LS138引脚
引脚
功能
C,B,A
输入,译码输入,C为最高位,A为最低位,共8种状态
Y0~Y7
输出,38译码器输出,低电平有效
提示:如果管脚后有一个圆圈。,表示该引脚有效时,输出低电平。
E1
输入,使能端,高电平有效
E2、E3
输入,使能端,低电平有效
提示:如果管脚前有一个圆圈。且引脚名称未带帽(—),表示该引脚低电平有效,否则为高电平有效。
表4   74LS138 引脚功能表
注:  G2=E2+E3, G1=E1                                            

三、多位数码管动态扫描程序设计
       下面以使用4位数码管显示“2016”为例进行介绍。
 动态扫描程序主流程图如图3所示。

         图3   4位数码管动态扫描显示流程图

       采用结构式编程,将数码管动态扫描相关的函数写在一个7seg.h头文件里,便于移植和嵌入。当工程用到数码管动态扫描时,仅需引用7seg.h和修改相关的硬件接口定义即可。
  1. 新建一个工程LEDDynamic。
  2. 新建两个文件,一个main.c,一个7seg.h,添加到本工程。文件内容如下:
    
//main.c
#include"7seg.h"
//显示数据存在一个数组里
unsigned char num[] = {2,0,1,6};
/****************************
*函数:delayMS
*功能:ms级延时函数@12MHz主频
*参数:ms:unsinged int,延时时间,单位:ms
*返回值:无
*****************************/
void delayMS(unsigned int ms)
{
   unsigned int i,j;
   for(i=0;i<ms;i++)
    for(j=0;j<150;j++);
}
//main是主程序
void main()
{
   unsigned char i;
   while(1)
   {
      for(i=0;i<4;i++)  //4位数码管,逐个扫描,共四次
         {
           led_display(i,num[i]); //显示2016
           delayMS(10);
         }

   }

//7seg.h
#include"reg51.h"
#define led_seg P0 //段控制a~h
#define led_com P2 //P2.2~P2.0控制74LS138译码的输入(C,B,A)
//共阴极段码表code table for 0-9,A-F, and off
unsigned char LED_CODE[] = {0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,
                          0x7F,0x6F,0x77,0x7C,0x39,0x5E,0x79,0x71,0x00};

/****************************
*函数:led_display
*功能:片选某位数码管,显示指定数字
*参数:com:unsigned char,数码管位选;number:unsigned char,显示的数字
*返回值:无
*****************************/
void led_display(unsigned char com, unsigned char number)
{
         led_com  = com;
        led_seg = LED_CODE[number];    
}

       7seg.h的 led_display 函数即为动态扫描的函数,选中某位数码管,显示指定内容。要显示多少位,则调用多少次。注意,每位数码管显示间隔时间不能太大也不能太小,太大则显示结果出现逐位显示现象,太小可能导致每位数码管显示时间过短,亮度不够。原则上,N位数码管,每位数码管显示时间T=1s/(25*N)。

3.编译并生成.hex。
4.在Proteus进行仿真。
仿真结果如下:
图4 数码管动态扫描显示2016(每位数码管保持10ms)

图5 数码管动态扫描显示2016(每位数码管保持16ms,约15fps)

       可见,当扫描间隔超过16ms时,明显看出显示不连贯。 
       但是,经过实测,每位数字显示10ms,明显看到辉光闪烁,刷新频率不够,改为5ms则稳定显示。

     至此,数码管动态扫描驱动电路和程序已经学完。上面例子是在main函数里进行数码管动态扫描显示,如果存在其他延时(如按键延时,呼吸灯延时),则这些延时过程中,数码管只能显示最后一个扫描的数码管的内容,这是很糟糕的。有没有好的解决办法呢?当然有,改为使用定时器中断周期地去刷新显示内容。 

  • 20
    点赞
  • 128
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值