LED数码管的介绍

LED 小灯是一种简单的 LED,只能通过亮和灭来表达简单的信息。而这节课我们要来学习一种能表达更复杂信息的器件——LED 数码管。

先给大家提供一张原理图看一下,如图 5-3 所示。

图 5-3  数码管原理图


这是比较常见的数码管的原理图,我们板子上一共有 6 个数码管。前边有了 LED 小灯的学习,数码管学习就会轻松的多了。从图 5-3 可以看出来,数码管共有 a、b、c、d、e、f、g、dp 这么 8 个段,而实际上,这 8 个段每一段都是一个 LED 小灯,所以一个数码管就是由 8个 LED 小灯组成的。我们看一下数码管内部结构的示意图,如图 5-4。

图 5-4  数码管结构示意图


数码管分为共阳和共阴两种,共阴数码管就是 8 只 LED 小灯的阴极是连接在一起的,阴极是公共端,由阳极来控制单个小灯的亮灭。同理,共阳数码管就是阳极接在一起,大家可以认真研究下图 5-4。细心的同学会发现,图 5-3 的数码管上边有 2 个 com,这就是我们数码管的公共端。为什么有 2 个呢,一方面是 2 个可以起到对称的效果,刚好是 10 个引脚,另外一个方面,公共端通过的电流较大,我们初中就学过,并联电路电流之和等于总电流,用2 个 com 可以把公共电流平均到 2 个引脚上去,降低单条线路承受的电流。

从我们开发板的电路图上能看出来,我们所用的数码管都是共阳数码管,一共有 6 个,如图 5-5 所示。

图 5-5  KST-51 数码管电路


6 个数码管的 com 都是接到了正极上,当然了,和 LED 小灯电路一样,也是由 74HC138控制三极管的导通来控制整个数码管的使能。先来看最右边的 DS1 这个数码管,原理图上可以看出,控制 DS1 的三极管是 Q17,控制 Q17 的引脚是 LEDS0,对应到 74HC138 上边就是U3 的 Y0 输出,如图 5-6 所示。

图 5-6  74HC138 控制图


我们现在的目的是让 LEDS0 这个引脚输出低电平,相信大家现在可以根据前边学过的知识独立把 ADDR0、ADDR1、ADDR2、ADDR3、ENLED 这 4 个所需输入的值写出来了,现在大家不要偷懒,根据 74HC138 的手册去写一下,不需要你记住这些结论,但是遇到就写一次,锻炼过几次后,遇到同类芯片自己就知道如何去解决问题了。

数码管通常是用来显示数字的,我们板子上有 6 个数码管,习惯上称之为 6 位,那控制位选择的就是 74HC138 了。而数码管内部的 8 个 LED 小灯我们称之为数码管的段,那么数码管的段选择(即该段的亮灭)是通过 P0 口控制,经过 74HC245 驱动。

数码管的真值表数码管的 8 个段,我们直接当成 8 个 LED 小灯来控制,那就是 a、b、c、d、e、f、g、dp 一共 8 个 LED 小灯。我们通过图 5-3 可以看出,如果点亮 b 和 c 这两个 LED 小灯,也就是数码管的 b 段和 c 段,其他的所有的段都熄灭的话,就可以让数码管显示出一个数字 1,那么这个时候实际上 P0 的值就是 0b11111001,十六进制就是 0xF9。那么我们写一个程序进去,来看一看数码管显示的效果。

  • #include <reg52.h>

  • sbit ADDR0 = P1^0;
  • sbit ADDR1 = P1^1;
  • sbit ADDR2 = P1^2;
  • sbit ADDR3 = P1^3;
  • sbit ENLED = P1^4;

  • void main(){
  •     ENLED = 0;  //使能 U3,选择数码管 DS1
  •     ADDR3 = 1;
  •     ADDR2 = 0;
  •     ADDR1 = 0;
  •     ADDR0 = 0;
  •     P0 = 0xF9;  //点亮数码管段 b 和 c
  •     while (1);
  • }


大家把这个程序编译一下,并下载到单片机中,就可以看到程序运行的结果是在最右侧的数码管上显示了一个数字 1。

用同样的方法,我们可以把其他的数字字符都在数码管上显示出来,而数码管显示的数字字符对应给 P0 的赋值,我们叫做数码管的真值表。我们来列一下我们这个电路图的数码管真值表,注意,这个真值表里显示的数字都不带小数点的,如表 5-7。

表 5-7 数码管真值表字符01234567
数值0xC00xF90xA40xB00x990x920x820xF8
字符89ABCDEF
数值0x800x900x880x830xC60xA10x860x8E
大家可以把上边那个用数码管显示数字 1 程序中的 P0 的赋值随便修改成表 5-7 真值表中的数值,看看显示的数字的效果。

数码管的静态显示
在第三章我们学习了 74HC138,了解到 74HC138 在同一时刻只能让一个输出口为低电平,也就是说在一个时刻内,我们只能使能一个数码管,并根据我们给出的 P0 的值来改变这个数码管的显示字符,我们可以将此理解为数码管的静态显示。

数码管静态显示是对应动态显示而言的,静态显示对于一两个数码管还行,多个数码管,静态显示实现的意义就没有了。这节课我们先用一个数码管的静态显示来实现一个简单的秒表,为下节课的动态显示打下基础。

先来介绍一个 51 单片机的关键字 code。我们前边课程定义变量的时候,一般用到unsigned char 或者 unsigned int 这两个关键字,这样定义的变量都是放在我们的单片机的 RAM中,我们在程序中可以随意去改变这些变量的值。但是还有一种数据,我们在程序中要使用,但是却不会改变它的值,定义这种数据时可以加一个 code 关键字修饰一下,这个数据就会存储到我们的程序空间 Flash 中,这样可以大大节省单片机的 RAM 的使用量,毕竟我们的单片机 RAM 空间比较小,而程序空间则大的多。那么现在要使用的数码管真值表,我们只会使用它们的值,而不需要改变它们,就可以用 code 关键字把它放入 Flash 中了,具体程序代码如下。纯文本复制

  • #include <reg52.h>

  • sbit ADDR0 = P1^0;
  • sbit ADDR1 = P1^1;
  • sbit ADDR2 = P1^2;
  • sbit ADDR3 = P1^3;
  • sbit ENLED = P1^4;

  • //用数组来存储数码管的真值表,数组将在下一章详细介绍
  • unsigned char code LedChar[] = {
  •     0xC0, 0xF9, 0xA4, 0xB0, 0x99, 0x92, 0x82, 0xF8,
  •     0x80, 0x90, 0x88, 0x83, 0xC6, 0xA1, 0x86, 0x8E
  • };

  • void main(){
  •     unsigned char cnt = 0;  //记录 T0 中断次数
  •     unsigned char sec = 0;  //记录经过的秒数

  •     ENLED = 0;  //使能 U3,选择数码管 DS1
  •     ADDR3 = 1;
  •     ADDR2 = 0;
  •     ADDR1 = 0;
  •     ADDR0 = 0;
  •     TMOD = 0x01;  //设置 T0 为模式 1
  •     TH0 = 0xB8;  //为 T0 赋初值 0xB800
  •     TL0 = 0x00;
  •     TR0 = 1;  //启动 T0

  •     while (1){
  •         if (TF0 == 1){  //判断 T0 是否溢出
  •             TF0 = 0;  //T0 溢出后,清零中断标志
  •             TH0 = 0xB8;  //并重新赋初值

  •             TL0 = 0x00;
  •             cnt++;  //计数值自加 1
  •             if (cnt >= 50){  //判断 T0 溢出是否达到 50 次
  •                 cnt = 0;  //达到 50 次后计数值清零
  •                 P0 = LedChar[sec]; //当前秒数对应的真值表中的值送到 P0 口
  •                 sec++;  //秒数记录自加 1
  •                 if (sec >= 16){  //当秒数超过 0x0F(15)后,重新从 0 开始
  •                    sec = 0;
  •                 }
  •             }
  •         }
  •     }
  • }