51单片机_数码管显示
51单片机_数码管显示
在51单片机的应用中,数码管显示是一项基础且常见的功能。数码管能够显示数字和一些字符,通过内部的发光二极管(LED)来实现。根据公共端的不同,数码管分为共阳极和共阴极两种类型。在共阴极数码管中,所有LED的阴极连接在一起,而阳极则分别通过不同的引脚控制。要点亮特定的LED,只需在相应的阳极引脚上提供高电平信号。


数码管字符编码表(共阴/共阳对照)
| 字符 | 共阴极段码(HEX) | 共阳极段码(HEX) | 说明 | 二进制显示(abcdefg dp) |
|---|---|---|---|---|
| 数字 | ||||
| 0 | 0x3F | 0xC0 | 数字0 | 0011 1111 / 1100 0000 |
| 1 | 0x06 | 0xF9 | 数字1 | 0000 0110 / 1111 1001 |
| 2 | 0x5B | 0xA4 | 数字2 | 0101 1011 / 1010 0100 |
| 3 | 0x4F | 0xB0 | 数字3 | 0100 1111 / 1011 0000 |
| 4 | 0x66 | 0x99 | 数字4 | 0110 0110 / 1001 1001 |
| 5 | 0x6D | 0x92 | 数字5 | 0110 1101 / 1001 0010 |
| 6 | 0x7D | 0x82 | 数字6 | 0111 1101 / 1000 0010 |
| 7 | 0x07 | 0xF8 | 数字7 | 0000 0111 / 1111 1000 |
| 8 | 0x7F | 0x80 | 数字8 | 0111 1111 / 1000 0000 |
| 9 | 0x6F | 0x90 | 数字9 | 0110 1111 / 1001 0000 |
| 大写字母 | ||||
| A | 0x77 | 0x88 | 字母A | 0111 0111 / 1000 1000 |
| C | 0x39 | 0xC6 | 字母C | 0011 1001 / 1100 0110 |
| E | 0x79 | 0x86 | 字母E | 0111 1001 / 1000 0110 |
| F | 0x71 | 0x8E | 字母F | 0111 0001 / 1000 1110 |
| G | 0x3D | 0xC2 | 字母G | 0011 1101 / 1100 0010 |
| H | 0x76 | 0x89 | 字母H | 0111 0110 / 1000 1001 |
| I | 0x06 | 0xF9 | 字母I | 0000 0110 / 1111 1001 |
| J | 0x1E | 0xE1 | 字母J | 0001 1110 / 1110 0001 |
| L | 0x38 | 0xC7 | 字母L | 0011 1000 / 1100 0111 |
| O | 0x3F | 0xC0 | 字母O | 0011 1111 / 1100 0000 |
| P | 0x73 | 0x8C | 字母P | 0111 0011 / 1000 1100 |
| S | 0x6D | 0x92 | 字母S | 0110 1101 / 1001 0010 |
| U | 0x3E | 0xC1 | 字母U | 0011 1110 / 1100 0001 |
| Y | 0x66 | 0x99 | 字母Y | 0110 0110 / 1001 1001 |
| 小写字母 | ||||
| b | 0x7C | 0x83 | 小写b | 0111 1100 / 1000 0011 |
| c | 0x58 | 0xA7 | 小写c | 0101 1000 / 1010 0111 |
| d | 0x5E | 0xA1 | 小写d | 0101 1110 / 1010 0001 |
| h | 0x74 | 0x8B | 小写h | 0111 0100 / 1000 1011 |
| n | 0x54 | 0xAB | 小写n | 0101 0100 / 1010 1011 |
| o | 0x5C | 0xA3 | 小写o | 0101 1100 / 1010 0011 |
| r | 0x50 | 0xAF | 小写r | 0101 0000 / 1010 1111 |
| t | 0x78 | 0x87 | 小写t | 0111 1000 / 1000 0111 |
| u | 0x1C | 0xE3 | 小写u | 0001 1100 / 1110 0011 |
| y | 0x6E | 0x91 | 小写y | 0110 1110 / 1001 0001 |
| 特殊字符 | ||||
| - | 0x40 | 0xBF | 减号/负号 | 0100 0000 / 1011 1111 |
| . | 0x80 | 0x7F | 小数点 | 1000 0000 / 0111 1111 |
| _ | 0x08 | 0xF7 | 下划线 | 0000 1000 / 1111 0111 |
| = | 0x48 | 0xB7 | 等号 | 0100 1000 / 1011 0111 |
| 空格 | 0x00 | 0xFF | 全灭 | 0000 0000 / 1111 1111 |
| 全亮 | 0xFF | 0x00 | 所有段亮 | 1111 1111 / 0000 0000 |
普中51开发板使用的是两个4位的共阴极数码管,详细介绍如下:
74HC138译码器简介
作用:节省单片机I/O口


//这里结合两张图片一起介绍
// P2_4 = 1;P2_3 = 1;P2_2 = 1; 控制LED8
// P2_4 = 1;P2_3 = 1;P2_2 = 0; 控制LED7
// P2_4 = 1;P2_3 = 0;P2_2 = 1; 控制LED6
// P2_4 = 1;P2_3 = 0;P2_2 = 0; 控制LED5
// P2_4 = 0;P2_3 = 1;P2_2 = 1; 控制LED4
// P2_4 = 0;P2_3 = 1;P2_2 = 0; 控制LED3
// P2_4 = 0;P2_3 = 0;P2_2 = 1; 控制LED2
// P2_4 = 0;P2_3 = 0;P2_2 = 0; 控制LED1


数码管静态显示
#include <REGX52.H>
void Delay(unsigned int xms);
//数码管段码表
unsigned char NixieTable[]={0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x6F};
//数码管显示子函数
void Nixie(unsigned char Location,Number)
{
switch(Location) //位码输出
{
case 1:P2_4=1;P2_3=1;P2_2=1;break;
case 2:P2_4=1;P2_3=1;P2_2=0;break;
case 3:P2_4=1;P2_3=0;P2_2=1;break;
case 4:P2_4=1;P2_3=0;P2_2=0;break;
case 5:P2_4=0;P2_3=1;P2_2=1;break;
case 6:P2_4=0;P2_3=1;P2_2=0;break;
case 7:P2_4=0;P2_3=0;P2_2=1;break;
case 8:P2_4=0;P2_3=0;P2_2=0;break;
}
P0=NixieTable[Number]; //段码输出
}
void main()
{
Nixie(1,6); //在数码管的第1位置显示6
while(1)
{
}
}
// 延时1ms
void Delay(unsigned int xms) //@12.000MHz
{
unsigned char i, j;
while(xms)
{
i = 2;
j = 239;
do
{
while (--j);
} while (--i);
xms--;
}
}
// 现象:数码管的第1位置显示6
让数码管数字动起来:0 ~ 9 循环显示
#include <REGX52.H>
void Delay(unsigned int xms);
//数码管段码表
unsigned char NixieTable[]={0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x6F};
//数码管显示子函数
void Nixie(unsigned char Location,Number)
{
switch(Location) //位码输出
{
case 1:P2_4=1;P2_3=1;P2_2=1;break;
case 2:P2_4=1;P2_3=1;P2_2=0;break;
case 3:P2_4=1;P2_3=0;P2_2=1;break;
case 4:P2_4=1;P2_3=0;P2_2=0;break;
case 5:P2_4=0;P2_3=1;P2_2=1;break;
case 6:P2_4=0;P2_3=1;P2_2=0;break;
case 7:P2_4=0;P2_3=0;P2_2=1;break;
case 8:P2_4=0;P2_3=0;P2_2=0;break;
}
P0=NixieTable[Number]; //段码输出
}
void main()
{
unsigned char i;
while(1)
{
for(i = 0; i <= 9; i++)
{
Nixie(1,i); //在数码管的第1位置显示6
Delay(1000);
}
}
}
// 延时1ms
void Delay(unsigned int xms) //@12.000MHz
{
unsigned char i, j;
while(xms)
{
i = 2;
j = 239;
do
{
while (--j);
} while (--i);
xms--;
}
}
数码管动态显示
看似同时点亮的多个数字,背后是一场精密的“视觉骗局”。
动态扫描是解决多位独立数码管显示时,节省I/O口、降低功耗的核心技术。其本质是利用人眼的视觉暂留效应(Persistence of Vision)和数码管的余晖特性,通过快速轮流点亮每个数码管,使其在宏观上看起来像是同时稳定显示。
单片机通过循环执行以下步骤实现动态显示:
- 关闭所有位选:进行消隐,防止切换时的“鬼影”(下面的例子采用关闭段选方式实现消影,具体介绍见最后)。
- 输出段码:将当前位要显示的数字(如‘3’)对应的段码(如共阴
0x4F)送到段选线。 - 打开当前位选:接通当前位数码管的公共端,使其点亮。
- 短暂延时:保持点亮约 1-5ms。
- 切换至下一位:重复上述步骤,点亮下一个数码管。
当整个循环的扫描频率高于50Hz(即所有数码管轮流点亮一遍的时间小于20ms)时,人眼就无法分辨其闪烁,会认为所有数码管在稳定、同时发光。
- 优点:极大节省单片机I/O口和硬件成本。
- 缺点:程序设计稍复杂,且每个数码管实际是间歇发光,亮度低于静态驱动。
简单来说,动态扫描就像一位敏捷的灯光师在几盏灯之间飞速切换,因为速度极快,在你的眼睛看来,所有灯都是常亮的。这是嵌入式显示设计中一项经典而高效的资源优化技术。

#include <REGX52.H>
//数码管段码表
unsigned char NixieTable[]={0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x6F};
//延时子函数
void Delay(unsigned int xms)
{
unsigned char i, j;
while(xms--)
{
i = 2;
j = 239;
do
{
while (--j);
} while (--i);
}
}
//数码管显示子函数
void Nixie(unsigned char Location,Number)
{
switch(Location) //位码输出
{
case 1:P2_4=1;P2_3=1;P2_2=1;break;
case 2:P2_4=1;P2_3=1;P2_2=0;break;
case 3:P2_4=1;P2_3=0;P2_2=1;break;
case 4:P2_4=1;P2_3=0;P2_2=0;break;
case 5:P2_4=0;P2_3=1;P2_2=1;break;
case 6:P2_4=0;P2_3=1;P2_2=0;break;
case 7:P2_4=0;P2_3=0;P2_2=1;break;
case 8:P2_4=0;P2_3=0;P2_2=0;break;
}
P0=NixieTable[Number]; //段码输出
Delay(1); //显示一段时间
P0=0x00; //段码清0,消影
}
void main()
{
while(1)
{
Nixie(1,1); //在数码管的第1位置显示1
// Delay(20);
Nixie(2,2); //在数码管的第2位置显示2
// Delay(20);
Nixie(3,3); //在数码管的第3位置显示3
// Delay(20);
}
}
// 段选决定显示内容,位选决定数码管
// 共阴极数码管,段选高电平点亮
// P0=0x00; //段码清0,消影
// 这段的原理是:把段选全部置零(关闭所有二极管),达到消影目的
这是通过关闭段选来实现消影效果,但我实践发现依旧存在重影现象(不严重),如果想要关闭位选,需要对74HC138译码器进行操作:
使用74HC138关闭所有位选(即让所有输出端无效)核心在于控制其使能端。对于共阴极数码管电路,这会使所有数码管的公共阴极断开,从而达到完全消影和关闭的目的。
74HC138有三个使能引脚,它们是控制芯片是否工作的总开关:
G2A和G2B:低电平有效 (L)G1:高电平有效 (H)
芯片只有同时满足 G1=0, G2A=0, G2B=1 时,才会根据地址输入(A,B,C)进行译码输出。破坏这三个条件中的任意一个,芯片即被禁用,所有输出端(Y0-Y7)将变为高电平。
对于共阴极数码管,位选有效信号是低电平(0)。当74HC138所有输出为高电平(1)时,没有任何一个数码管的阴极被拉低,因此所有数码管均被关闭。

观察原理图发现,G1=0, G2A=0, G2B=1 都是焊上去的,无法使用单片机进行控制,所以这里消影只能使用关闭段选来实现。

浙公网安备 33010602011771号