(1)实验平台:普中51单片机开发板-A2&A3&A4
前面章节我们已经介绍了如何控制 51 单片机的 IO 口输出高低电平, 本章我们通过另外一个实验来讲述 51 单片机 IO 口的输出。 通过单片机的 IO 口控制板载数码管显示。 学习本章可以参考前面的实验章节内容。 本章分为如下几部分内容:
11.1 数码管介绍
11.1.1 数码管简介
11.1.2 数码管显示原理
11.1.3 数码管静态显示原理
11.2 硬件设计
11.3 软件设计
11.4 实验现象
11.1 数码管介绍
11.1.1 数码管简介
数码管是一种半导体发光器件, 其基本单元是发光二极管。 数码管也称 LED数码管, 不同行业人士对数码管的称呼不一样, 其实都是同样的产品。 数码管按段数可分为七段数码管和八段数码管, 八段数码管比七段数码管多一个发光二极管单元, 也就是多一个小数点(DP) , 这个小数点可以更精确的表示数码管想要显示的内容; 按能显示多少个(8) 可分为 1 位、 2 位、 3 位、 4 位、 5 位、6 位、 7 位等数码管。 按发光二极管单元连接方式可分为共阳极数码管和共阴极数码管。
共阳数码管是指将所有发光二极管的阳极接到一起形成公共阳极(COM)的数码管, 共阳数码管在应用时应将公共极 COM 接到+5V, 当某一字段发光二极管的阴极为低电平时, 相应字段就点亮, 当某一字段的阴极为高电平时, 相应字段就不亮。
共阴数码管是指将所有发光二极管的阴极接到一起形成公共阴极(COM)的数码管, 共阴数码管在应用时应将公共极 COM 接到地线 GND 上, 当某一字段发光二极管的阳极为高电平时, 相应字段就点亮, 当某一字段的阳极为低电平时, 相应字段就不亮。
不同位数的数码管实物图如下所示:
11.1.2 数码管显示原理
不管将几位数码管连在一起, 数码管的显示原理都是一样的, 都是靠点亮内部的发光二极管来发光, 下面我们就来讲解一个数码管是如何亮起来的。 数码管内部电路如下图所示:
从上图可看出, 一位数码管的引脚是 10 个, 显示一个 8 字需要 7 个小段,另外还有一个小数点, 所以其内部一共有 8 个小的发光二极管, 最后还有一个公共端, 多数生产商为了封装统一, 单位数码管都封装 10 个引脚, 其中第 3 和第 8 引脚是连接在一起的。 而它们的公共端又可分为共阳极和共阴极, 图中间为共阳极内部原理图, 右图为共阴极内部原理图。
对共阴极数码来说, 其 8 个发光二极管的阴极在数码管内部全部连接在一起,所以称“共阴” , 而它们的阳极是独立的, 通常在设计电路时一般把阴极接地。当我们给数码管的任意一个阳极加一个高电平时, 对应的这个发光二极管就点亮了。 如果想要显示出一个 8 字, 并且把右下角的小数点也点亮的话, 可以给 8个阳极全部送高电平, 如果想让它显示出一个 0 字, 那么我们可以除了给第“g, dp” 这两位送低电平外, 其余引脚全部都送高电平, 这样它就显示出 0 字了。
如果使用共阴数码管, 需要注意增加单片机 IO 口驱动电流, 因为共阴数码管是要靠单片机 IO 口输出电流来点亮的, 但单片机 I/O 口难以输出稳定的、 如此大的电流, 所以数码管与单片机连接时需要加驱动电路, 可以用上拉电阻的方法或使用专门的数码管驱动芯片, 比如 74HC573、 74HC245 等, 其输出电流较大,电路接口简单。
共阳极数码管其内部 8 个发光二极管的所有阳极全部连接在一起, 电路连接时, 公共端接高电平, 因此我们要点亮哪个发光管二极管就需要给阴极送低电平,此时显示数字的编码与共阴极编码是相反的关系, 数码管内部发光二极管点亮时, 也需要 5mA 以上的电流, 而且电流不可过大, 否则会烧坏发光二极管。 因此不仅要防止数码管电流过大, 同时要防止流经数码管的电流集中到单片机时电流不能过大, 否则会损坏主芯片。
一般共阳极数码管更为常用, 为什么呢? 这是因为数码管的非公共端往往接在 IC 芯片的 I/O 上, 而 IC 芯片的驱动能力往往是比较小的, 如果采用共阴极数码管, 它的驱动端在非公共端, 就有可能受限于 IC 芯片输出电流不够而显示昏暗, 要外加上拉电阻或者是增加三极管加大驱动能力。 但是 IC 芯片的灌电流,即输入电流范围比较大。 所以使用共阳极数码管的好处是: 将驱动数码管的工作交到公共端(一般接驱动电源) , 加大驱动电源的功率自然要比加大 IC 芯片 I/O口的驱动电流简单许多。 另一方面, 这样也能减轻主芯片的负担。
我们开发板上使用的数码管是 2 个四位一体的共阴极数码管(即 8 个 LED的阳极全部并联一起引出, 阴极分别引出如 A、 B...DP) , 本章实验也是在该数码管上实现单个的静态显示。 如果要让共阴数码管显示数字 0, 即对应的段ABCDEF 要点亮即给它高电平, 其他的段熄灭即给它低电平。 其他的数字显示方式一样, 这里就不多说。 下面给出共阴和共阳数码管的 0-F 段码数据表, 如下所示:
①共阴数码管码表
0x3f, 0x06, 0x5b, 0x4f, 0x66, 0x6d,
0 1 2 3 4 5
0x7d, 0x07, 0x7f, 0x6f, 0x77, 0x7c,
6 7 8 9 A B
0x39, 0x5e, 0x79, 0x71, 0x00,
C D E F 无显示
②共阳数码管码表
0xC0, 0xF9, 0xA4, 0xB0, 0x99, 0x92,
0 1 2 3 4 5
0x82, 0xF8, 0x80, 0x90, 0x88, 0x83,
6 7 8 9 A B
0xC6, 0xA1, 0x86, 0x8E, 0xFF,
C D E F 无显示
从上述共阳和共阴码表中不难发现, 它们的数据正好是相互取反的值。 比如共阴数码管数字 0 段码: 0x3f, 其二进制是: 0011 1111, 取反后为: 1100 0000,转换成 16 进制即为 0XC0。 其他段码依此类推。 该段码数据由来, 是将 a 段作为最低位, b 段作为次低位, 其他按顺序类推, dp 段为最高位, 共 8 位, 正好和51 单片机的一组端口数一样, 因此可以直接使用某一组端口控制数码管的段选数据口, 比如 P0 口。
11.1.3 数码管静态显示原理
LED 数码管显示器工作方式有两种: 静态显示方式和动态显示方式。 静态显示的特点是每个数码管的段选必须接一个 8 位数据线来保持显示的字形码。 当送入一次字形码后, 显示字形可一直保持, 直到送入新字形码为止。 这种方法的优点是占用 CPU 时间少, 显示便于监测和控制。 缺点是硬件电路比较复杂, 成本较高, 比如使用 4 个静态数码管, 那么就得 32 个 IO 来控制, 这对 51 单片机来说是无法承受的, 正因为如此才会有后面章节动态数码实验的讲解。
动态显示的特点是将所有数码管的段选线并联在一起, 由位选线控制是哪一位数码管有效。 选亮数码管采用动态扫描显示。 所谓动态扫描显示即轮流向各位数码管送出字形码和相应的位选, 利用发光管的余辉和人眼视觉暂留作用, 使人的感觉好像各位数码管同时都在显示。 动态显示的亮度比静态显示要差一些, 所以在选择限流电阻时应略小于静态显示电路中的。
本章实验使用的数码管虽然是动态数码管电路, 但我们依然可以使用数码管其中一位来学习静态数码管知识。 本章实验主要介绍静态数码管的控制, 有关动态数码管控制将在下一章节介绍。 有关静态数码管的详细介绍, 大家可以在百度上查找了解。
11.2 硬件设计
开发板上的静态数码管模块电路如下图所示:
上图电路实际上是动态数码管电路, 使用的是 2 个四位一体的共阴数码管组成, 即 8 位数码管的段选数据 a-dp 全部并联一起引出, 每位数码管的位选即公共端引出, 前面我们也说了, 虽然开发板上没有单个的静态数码管, 但依然可以在动态数码管电路中使用其中一个来学习静态数码管显示。 本实验使用 SMG1 最左边那个数码管作为静态数码管, 因为单片机 IO 口外部都增加了外部上拉电阻,因此 P22、 P23、 P24 引脚默认就是高电平, 根据 38 译码器输出特点, 此时 Y7脚(LED8) 输出有效, 即低电平。 而数码管的段选 a-dp 连接在 74HC245 驱动芯片输出口, 由 P0 端口控制。 所以只要控制 P0 口输出高电平, SMG1 最左边那个数码管默认就可以显示。 此处暂时不去理会 38 译码器的工作原理, 后面动态数码管实验会专门介绍。 74HC245 作为驱动芯片使用, 目的是让数码管能获得更大的电流, 为防止因电流过大烧坏数码管, 在 74HC245 芯片输出管脚又串联了 2个 4 位的 100 欧排阻后连接数码管段码 a-dp 脚。 本章暂时不必了解 74HC245 芯片使用, 只要知道 P0 口输出什么, 74HC245 芯片就输出什么。
11.3 软件设计
本章所要实现的功能是: 控制静态数码管显示数字 0, 即让 P0 端口输出数字0 的段码 0x3f(共阴) 。
我们打开“\4--实验程序\1--基础实验\6-静态数码管实验” 工程, 控制代码全部都在 main.c 中, 代码如下:
/************************************************************************************** 深圳市普中科技有限公司(PRECHIN 普中) 技术支持:www.prechin.net PRECHIN 普中 实验名称:静态数码管实验 接线说明: 实验现象:下载程序后“数码管模块”最左边数码管显示数字0 注意事项: ***************************************************************************************/ #include "reg52.h" typedef unsigned int u16; //对系统默认数据类型进行重定义 typedef unsigned char u8; #define SMG_A_DP_PORT P0 //使用宏定义数码管段码口 //共阴极数码管显示0~F的段码数据 u8 gsmg_code[17]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07, 0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71}; /******************************************************************************* * 函 数 名 : main * 函数功能 : 主函数 * 输 入 : 无 * 输 出 : 无 *******************************************************************************/ void main() { SMG_A_DP_PORT=gsmg_code[0];//将数组第1个数据赋值给数码管段选口 while(1) { } }main.c 文件内代码非常少也很简单, 首先将 51 单片机的头文件包含进来,然后定义一个全局数组变量 gsmg_code 存放共阴数码管 0-F 段码数据。 主函数功能也很简单, 首先将数组的第 1 个数据赋值给 SMG_A_DP_PORT, 因为数组内定义的是共阴数码管段码, 数组角标为0存储的就是第一个数据0X3F。然后进入while循环, 单片机此时一直在 while 内循环操作。 当然该条语句也可以放在 while循环语句内, 同样会让静态数码管显示 0。
11.4 实验现象
使用 USB 线将开发板和电脑连接成功后(电脑能识别开发板上 CH340 串口) ,把编译后产生的.hex 文件烧入到芯片内, 实现现象如下: 最左边那位数码管显示数字 0。