【51单片机】LED数码管显示
共阴极1亮0灭,共阳极0亮1灭。
【1】显示原理
LED数码管是常见的显示器件。LED数码管为“8”字型的,共计8段(包括小数点段在内)或者7段(不包括小数点段),每一段对应一个发光二极管,有共阴极和共阳极两种。如下图所示。

共阴极:数码管的阴极连接在一起,通常此公共阴极接地。当某个发光二极管的阳极接高电平时,该发光二极管被点亮,相应的段被显示。
共阳极:数码管的阳极连接在一起,公共阳极接到+5V上。当某个发光二极管的阴极接低电平时,该发光二极管被点亮,相应的段被显示。
编写程序时,共阴极1亮0灭,共阳极0亮1灭。
数码管的外形与各发光二极管对应的引脚,如下图所示。

在单片机开发的过程中,把数码管的某些段点亮,就能让其显示不同的字符。因此,我们通过编写程序,以“a”段作为最低位,并且按照“dp g f e d c b a”的顺序,为每个数码管提供总长为1字节(8位)的二进制代码,即段码。如果要在数码管上显示某一字符,只需将该字符的段码加到各段上即可。
当然,为了增加程序的可读性,避免冗余,通常使用2位十六进制数来表示数码管1字节的段码。例如,当共阴极数码管需要表示数字“0”时,段码“dp g f e d c b a”应该为“0011 1111”,即“0x3f”;当共阳极数码管需要表示数字“0”时,段码“dp g f e d c b a”应该为“1100 0000”,即“0xc0”。其他情况LED数码管的段码,如下表所示。
| 显示字符 |
共阴极字型码 (二进制) |
共阴极字型码 (十六进制) |
共阳极字型码 (二进制) |
共阳极字型码 (十六进制) |
| 0 | 0011 1111 | 0x3f | 1100 0000 | 0xc0 |
| 1 | 0000 0110 | 0x06 | 1111 1001 | 0xf9 |
| 2 | 0101 1011 | 0x5b | 1010 0100 | 0xa4 |
| 3 | 0100 1111 | 0x4f | 1011 0000 | 0xb0 |
| 4 | 0110 0110 | 0x66 | 1001 1001 | 0x99 |
| 5 | 0110 1101 | 0x6d | 1001 0010 | 0x92 |
| 6 | 0111 1101 | 0x7d | 1000 0010 | 0x82 |
| 7 | 0000 0111 | 0x07 | 1111 1000 | 0xf8 |
| 8 | 0111 1111 | 0x7f | 1000 0000 | 0x80 |
| 9 | 0110 1111 | 0x6f | 1001 0000 | 0x90 |
| A | 0111 0111 | 0x77 | 1000 1000 | 0x88 |
| b | 0111 1100 | 0x7c | 1000 0011 | 0x83 |
| C | 0011 1001 | 0x39 | 1100 0110 | 0xc6 |
| d | 0101 1110 | 0x5e | 1010 0001 | 0xa1 |
| E | 0111 1001 | 0x79 | 1000 0110 | 0x86 |
| F | 0111 0001 | 0x71 | 1000 1110 | 0x8e |
| “灭” | 0000 0000 | 0x00 | 1111 1111 | 0xff |
| …… | …… | …… | …… | …… |
在编程过程中,我们通常使用数组来存储和调用所需的数码管段码,并且将该数组定义为code类型,把数据存储在程序存储器。
代码示例:
uchar code seg[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f};
//共阴极数码管0-9
uchar code seg[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90};
//共阳极数码管0-9
【2】静态显示
静态显示是指无论多少位LED数码管,都同时处于显示状态。
优点:显示无闪烁,亮度较高,软件控制比较容易。
缺点:占用I/O口线较多,硬件资源利用率较低。
项目1
题目:用单片机控制一个8段LED数码管,先循环显示单个偶数:0、2、4、6、8,再显示单个奇数:1、3、5、7、9,如此反复循环显示。
原理图

| 关键字 | 元件名称 | 型号 | 数量(个) |
|---|---|---|---|
| AT89C51 | 单片机 | AT89C51 | 1 |
| CRYSTAL | 晶体振荡器 | 12MHZ | 1 |
| 7SEG-COM-ANODE | 共阳极7段数码管 | 红色 | 1 |
| CAP | 电容 | 30pF | 2 |
| CAP-ELEC | 电解电容 | 10uF | 1 |
| RES | 电阻 | 1kΩ | 1 |
| RES | 电阻 | 10kΩ | 1 |
| RES | 电阻 | 560Ω | 7 |
| BUTTON | 复位按键 | 1 |
代码
#include <reg52.h>
#define uchar unsigned char //宏定义无符号字符型变量方便书写
#define uint unsigned int //宏定义无符号整型变量方便书写
#define out P0 //宏定义P0口为out
uchar code seg[]={0xc0,0xa4,0x99,0x82,0x80,0xf9,0xb0,0x92,0xf8,0x90}; //共阳极段码表
void delay(uint n) //延时函数ms
{
uchar i;
uint j;
for(j=0;j<n;j++)
for(i=0;i<123;i++);
}
void main(void)
{
uchar i;
while(1)
{
out=seg[i];
delay(2000);
i++;
if(i>9)i=0;
}
}
实验现象
数码管项目1——静态显示实验现象
项目2
题目:单片机控制2位数码管,静态显示2个数字“2”和“7”。
原理图

| 关键字 | 元件名称 | 型号 | 数量(个) |
|---|---|---|---|
| AT89C51 | 单片机 | AT89C51 | 1 |
| CRYSTAL | 晶体振荡器 | 12MHZ | 1 |
| 7SEG-COM-ANODE | 共阳极7段数码管 | 红色 | 2 |
| CAP | 电容 | 30pF | 2 |
| CAP-ELEC | 电解电容 | 10uF | 1 |
| RES | 电阻 | 1kΩ | 1 |
| RES | 电阻 | 10kΩ | 1 |
| RES | 电阻 | 470Ω | 14 |
| BUTTON | 复位按键 | 1 |
代码
#include <reg52.h>
#define uchar unsigned char //宏定义无符号字符型变量方便书写
#define uint unsigned int //宏定义无符号整型变量方便书写
uchar code seg[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90}; //共阳极段码表
void main(void)
{
P0=seg[2]; //将数字“2”的段码送到P0口
P1=seg[7]; //将数字“7”的段码送到P1口
while(1); //无限循环
; //因为后续未对数码管进行熄灭的操作,数码管一直处于点亮的状态,所以while循环可有可无
}
实验现象

【3】动态显示
动态显示是将所有LED数码管显示器的段码线的相应段都并联在一起,由一个8位I/O端口控制,而各显示位的公共端分别由另外单独的I/O端口线控制。
其实质是,每一个时刻选中一位显示,其余各位均不显示,每隔一定的时间逐位点亮各数码管,利用数码管的余晖和人眼的“视觉暂留”作用,造成“多位同时亮”的假象,达到4位或者多位同时显示的效果。
优点:占用I/O口线较少,硬件利用率较高。
缺点:占用单片机时间较多。显示可能有闪烁,亮度较低,软件编程比较复杂。
项目3
题目:单片机控制8只数码管,分别滚动显示单个数字1~8。
原理图

原理图绘制技巧:蓝色粗线是总线。
1、右键→“放置”→“总线”(或者单击左侧主工具栏“总线模式”的图标)。

2、总线不能出现90°角的转折,可以在需要转折处先单击鼠标“左键”→按住“Ctrl”寻找合适的角度→延长斜线到合适位置后单击鼠标“左键”→继续绘制直线即可。

3、总线分支需要画成与总线成45°角的相互平行的一组斜线,从外设或者单片机需要与总线相连的引脚出发,鼠标“左键”单击开始绘制,转折的处理与总线相同,也是借助“Ctrl”。

4、在外设与单片机IO口相对应的总线分支上,需要添加“网络标号”,保障其正常的电气连接。
在英文模式下,点击键盘上的字母“A”→将字符串(S)更改为“NET=P#”或者“NET=P0#”或者“NET=#”(前面“NET=”不变,如果标号是P0~P7,则为“NET=P#”;如果标号是P00~P07,则为“NET=P0#”;如果标号是1~8,则为“NET=#”)→根据实际需要调节“计数初值(C)”,即上述“P#”、“P0#”和“#”中“#”的起始值→在合适的位置放置网络标号即可。

| 关键字 | 元件名称 | 型号 | 数量(个) |
|---|---|---|---|
| AT89C51 | 单片机 | AT89C51 | 1 |
| CRYSTAL | 晶体振荡器 | 12MHZ | 1 |
| 7SEG-MPX8-CA-BLUE | 8位8段共阳极数码管 | 蓝色 | 1 |
| CAP | 电容 | 30pF | 2 |
| CAP-ELEC | 电解电容 | 10uF | 1 |
| RES | 电阻 | 1kΩ | 1 |
| RES | 电阻 | 10kΩ | 1 |
| RX8 | 双向排阻 | 220Ω | 1 |
| 2N2222A | NPN型三极管 | 8 | |
| BUTTON | 复位按键 | 1 |
代码
#include <reg52.h>
#include <intrins.h> //包含循环移位函数的头文件
#define uchar unsigned char //宏定义无符号字符型变量方便书写
#define uint unsigned int //宏定义无符号整型变量方便书写
uchar code seg[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90}; //共阳极段码表
void delay(uint n) //延时函数ms
{
uchar i;
uint j;
for(j=0;j<n;j++)
for(i=0;i<123;i++);
}
void main(void)
{
uchar i,j=0x80;
while(1)
{
for(i=1;i<=8;i++)
{
j=_crol_(j,1); //循环移位函数_crol_(j,1)将j循环左移1位
P2=j; //P2口输出位控码
P0=seg[i]; //P0口输出段码
delay(1000); //延时,控制每位显示的时间
P0=0xff; //消影
}
}
}
代码重点解析:
1、循环移位函数功能分析
j的初始值为0x80(即0b1000 0000),每执行一次for循环,循环移位函数_crol_(j,1)都将j循环左移1位。例如:当第一次执行for循环时,i=1,j循环左移1位,由初始值0x80(即0b1000 0000)变为0x01(即0b0000 0001);当第二次执行for循环时,i=2,则由0x01(即0b0000 0001)变为0x02(即0b0000 0010)……具体情况如下表所示。
| i | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 |
| j |
0x01 0b0000 0001 |
0x02 0b0000 0010 |
0x04 0b0000 0100 |
0x08 0b0000 1000 |
0x10 0b0001 0000 |
0x20 0b0010 0000 |
0x40 0b0100 0000 |
0x80 0b1000 0000 |
| 点亮位置 | 第1位 | 第2位 | 第3位 | 第4位 | 第5位 | 第6位 | 第7位 | 第8位 |
| 显示数字 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 |
2、先输出位码(即位控码、位选码),再输出段码,否则数码管某些位会出现乱码。
P2=j; //P2口输出位控码
P0=seg[i]; //P0口输出段码
3、消影:消除上一个数码管段选对下一个数码管的影响,同时也可以提高数码管的亮度。
P0=0xff; //消影
实验现象
数码管项目3——滚动显示单个数字1~8实验现象
【4】数码管的驱动
因为单片机IO口的驱动电流较小,驱动能力很弱,主要用于对外设传感器的控制,所以数码管显示需要增加驱动模块。驱动模块的选择主要有三极管驱动和数字芯片驱动两种方式。
三极管驱动
如图所示,NPN三极管的发射极(有箭头的那个极)连接到共阳极数码管的位选引脚,基极与单片机的IO口相连,集电极连接的是VCC(+5V)。
在软件编程时,如果要让共阳极数码管的第1位工作,单片机的P20引脚向NPN三极管Q1的基极输入高电平,这样数码管1号引脚的电压略低于5V,数码管第1位实现共阳极连接,输入段码即可完成显示。

74HC245数字芯片驱动
74HC245是方向可控的八路缓冲器,主要用于提高电流驱动。在ptoteus仿真中,可以理解为从A端输入B端输出后,单片机的IO口便可以驱动数码管等大功率外设。
接线方式如图所示,引脚1接VCC,引脚19接GND,A端引脚连接单片机控制外设的引脚,B端引脚与外设相连。

项目四
题目:单片机控制8只数码管,同时显示数字1~8。
原理图:由于proteus仿真软件与实物存在细微差别,动态显示时采用三极管驱动数码管显示不稳定,所以使用74HC245芯片作为驱动,完成动态数码管的实验。

| 关键字 | 元件名称 | 型号 | 数量(个) |
|---|---|---|---|
| AT89C51 | 单片机 | AT89C51 | 1 |
| CRYSTAL | 晶体振荡器 | 12MHZ | 1 |
| 7SEG-MPX8-CA-BLUE | 8位8段共阳极数码管 | 蓝色 | 1 |
| CAP | 电容 | 30pF | 2 |
| CAP-ELEC | 电解电容 | 10uF | 1 |
| RES | 电阻 | 1kΩ | 1 |
| RES | 电阻 | 10kΩ | 1 |
| RX8 | 双向排阻 | 220Ω | 1 |
| 74HC245 | 8位双向总线驱动器 | 1 | |
| BUTTON | 复位按键 | 1 |
代码:只需将项目三代码中的延时函数由“delay(1000);”改为“delay(10);”即可。
#include <reg52.h>
#include <intrins.h> //包含循环移位函数的头文件
#define uchar unsigned char //宏定义无符号字符型变量方便书写
#define uint unsigned int //宏定义无符号整型变量方便书写
uchar code seg[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90}; //共阳极段码表
void delay(uint n) //延时函数ms
{
uchar i;
uint j;
for(j=0;j<n;j++)
for(i=0;i<123;i++);
}
void main(void)
{
uchar i,j=0x80;
while(1)
{
for(i=1;i<=8;i++)
{
j=_crol_(j,1); //循环移位函数_crol_(j,1)将j循环左移1位
P2=j; //P2口输出位控码
P0=seg[i]; //P0口输出段码
delay(10); //延时,控制每位显示的时间
P0=0xff; //消影
}
}
}
实验现象

【5】Proteus8.13 新建工程详细教程
1、桌面新建文件夹→重命名为“项目名”。(也可以在计算机的其他位置新建文件夹)
2、双击打开Proteus 8 Professional软件

3、【文件】→新建工程

4、更改工程名称为“项目名”;点击“浏览”→找到并打开第1步新建的文件夹→点击“选择文件夹”。


5、点击“Next”

6、保持默认选项,一直点击“Next”,最后选择“Finish”。




更多推荐



所有评论(0)