欣欣学习网,老工程师带你学习单片机技术,欢迎来坐坐。
首  页 | 学习NIOSII | 学习C51 | 学习CPLD | 51+CPLD实验板 | | | MY-RTOS

 实验板首页
 安装QuartusII软件
 安装USB-Blaster驱动
 安装CH340C驱动
 安装Keil uVision软件
 运行Hello World例程
 新建Keil uVision工程
 在Flash中运行程序
 恢复CPLD中的出厂逻辑
 安装调试代理程序
 硬件架构分析
 实现LCD驱动接口
 实现数码管驱动接口
 实现4x2键盘接口
 使用ADC采集拟量
 使用EEPROM保存数据
 使用UART通信
 红外遥控信号解码
 用作USB转232/485
 相关软件与文档


实现LED数码管驱动


LED数码管在单片机系中属于常见的输出设备,在实验板上也集成有2位共阴极数码管。

数码管由多个数字显示位组成,而每个显示位又包含了8个笔划段,如图(1)所示。每个笔划段内安装有1个或多个LED二极管。这些LED二极管同时点亮或关闭,组成一个灯芯。当某个灯芯被点亮时,对应的笔划就显示出来,当它被关闭时对应的笔划处于隐藏状态。不同笔划内的灯芯是分开控制的,这样就可以有选择的点亮所需要的笔划,由它们组成一个数字或字符。

图(1)

为了减少对外的管脚数,把同一个显示位内不同段的灯芯的某个极性的管脚连接在一起用同一个管脚引出。如果所选择连在一起的管脚是灯芯的阴极,就构成了共阴极数码管。相对应的,如果把它们的阳极连在一起,就是共阳极数码管。

图(2)

于是,这个显示位内所有灯芯的公共引脚自然的形成了显示位的位选信号,类似存贮器的片选信号。同样为了节少管脚,将不同显示位的同名段的灯芯另一个极性的管脚连在一起,用同一个管脚引出,就形成了段信号管脚。段信号类似存贮器的数据位。通过位选信号选通某个显示位,再由段信号管脚送入段控制信号,就可以点亮这个显示位上的数码。很显然,不同显示位上的数码在微观时间上是不能同时点亮的,要分时使用段信号管脚,于是就形成的扫描控制。只要扫描控制的轮换速度足够快,那么在宏观时间上就形成了同时点亮的局面。共阳数数码管和共阴数码管控制极相反,但控制方法是类似的。

对数码的扫描驱动就是轮流向每个显示位发送段码的过程,如图(3)所示。段码随着位选信号的切换同步的更新。不过,在位选切换期间需要插入0段码。之所以插入0段码,是为了起到消隐作用,避免在相邻的显示位上产生影子字符。

图(3)

位选信号和段码信号对单片机来说都是输出信号,所以数码管驱动端口可以由两片74377来实现。如图(4)所示,两片挂在总线上的74377分别用来输出位选信号和段码信号。扫描的时序可以由软件产生。

图(4)

在EPM7128S中的出厂逻辑设计中,LED数码管的驱动接口就是使用两个74377逻辑单元实现的,如图(5)所示。两个74377的地址分别是0x8060和0x8061。

图(5)

对应的数码管驱动示例代码如下:

                        
const unsigned char     /*     dp  g   f   e   d   c   b   a   */
  LEDSecCode[]={ 0x3f,  /* 0:  0   0   1   1   1   1   1   1   */
                 0x06,  /* 1:  0   0   0   0   0   1   1   0   */
                 0x5b,  /* 2:  0   1   0   1   1   0   1   1   */
                 0x4f,  /* 3:  0   1   0   0   1   1   1   1   */
                 0x66,  /* 4:  0   1   1   0   0   1   1   0   */
                 0x6d,  /* 5:  0   1   1   0   1   1   0   1   */
                 0x7d,  /* 6:  0   1   1   1   1   1   0   1   */
                 0x27,  /* 7:  0   0   1   0   0   1   1   1   */
                 0x7f,  /* 8:  0   1   1   1   1   1   1   1   */
                 0x6f,  /* 9:  0   1   1   0   1   1   1   1   */
                 0x77,  /* a:  0   1   1   1   0   1   1   1   */
                 0x7c,  /* b:  0   1   1   1   1   1   0   0   */
                 0x39,  /* c:  0   0   1   1   1   0   0   1   */
                 0x5e,  /* d:  0   1   0   1   1   1   1   0   */
                 0x79,  /* e:  0   1   1   1   1   0   0   1   */
                 0x71,  /* f:  0   1   1   1   0   0   0   1   */
                 0x00,  /*  :  0   0   0   0   0   0   0   0   */
                 0x40   /* -:  0   1   0   0   0   0   0   0   */
               };

unsigned char LEDScanPos = 0;
unsigned char LEDBuffer[2];             // 显示缓冲区,存入待显示字符的代码

#define   DigAddr        0x8061         // 位选信号接口地址
#define   SecAddr        0x8060         // 段码信号接口地址

// 数码管扫描服务程序,在定时器中断内调用
void LEDScan(void)               
{
  XBYTE[SecAddr] = 0x00;                // 输出0段码,消除影子字符
  XBYTE[DigAddr] = LEDScanPos+1;        // 切换位选信号
  
  // 从显示缓冲区中读出字符的代码,然后译成段码,并送到段码接口上
  XBYTE[SecAddr] = LEDSecCode[LEDBuffer[LEDScanPos]]; 
  
  // 更新位选指针变量,以备下次调用
  LEDScanPos = (LEDScanPos+1)&0x01;
} 
          

完整的LED数码管驱动范例程序,可参见:Hello World 程序




管理员信箱: stonewayqi@hotmail.com

欣 欣 学 习 网

粤ICP备2023138008号