一、了解led数码管
普通数码管
每一块相当于一个led灯,注意块与引脚编号的对应关系即可。分为共阴极<上图>(公共端接地)和共阳极<下图>(非公共端接地)两种方式,给电平时要注意。
四位一体数码管
可以缩减引脚操作,通过上面的引脚来控制哪一块亮,再由下面的引脚来控制所选择的数组,单片机使用的就是四位一体的数码管
再来查看官方的单片机数码管模块图,使用的是共阴极连接,74HC245是一个双向缓冲器,既可以从左向右输入数据,也可以从右向左读回数据,可以提高驱动能力,解决由于是高电平输入驱动能力差导致灯光昏暗的问题。单片机中数码管还与74HC138译码器相互配合使用。
如下图所示,这个译码器可以让我们使用三个接口实现对8个引脚的操作。转换规则是ABC表示从低到高的三个二进制位,组合在一起的值所对的十进制数字就是要操作的led号码。
例如:ABC分别赋值001,十进制结果为4,即操作的是第四个led灯,即LED4也就是Y3接口。
二、实例
1.数码管的静态显示
以点亮led7为例,对照上面的74HC138译码器,需要分别给ABC赋值为011以点亮LED7,然后让其显示7,对照上面的数码管模块,则要给a、f、g、e、d、c高电平,给b、dp低电平,具体实现如下:
#include <REGX51.H>
void main(){
// 点亮LED7
P2_2 = 0;
P2_3 = 1;
P2_4 = 1;
// 显示的数字6
P0_0 = 1;
P0_1 = 0;
P0_2 = 1;
P0_3 = 1;
P0_4 = 1;
P0_5 = 1;
P0_6 = 1;
P0_7 = 0;
while(1){
}
}
为了方便书写,我们将显示操作封装为函数
#include <REGX51.H>
// 封装数码管显示函数
void Nixie_show(unsigned char position,unsigned char number){
// 先确定要显示的led块
switch(position){
case 1:
P2_4 = 1;P2_3 = 1;P2_2 = 1; // 7
break;
case 2:
P2_4 = 1;P2_3 = 1;P2_2 = 0; // 6
break;
case 3:
P2_4 = 1;P2_3 = 0;P2_2 = 1; // 5
break;
case 4:
P2_4 = 1;P2_3 = 0;P2_2 = 0; // 4
break;
case 5:
P2_4 = 0;P2_3 = 1;P2_2 = 1; // 3
break;
case 6:
P2_4 = 0;P2_3 = 1;P2_2 = 0; // 2
break;
case 7:
P2_4 = 0;P2_3 = 0;P2_2 = 1; // 1
break;
case 8:
P2_4 = 0;P2_3 = 0;P2_2 = 0; // 0
break;
}
// 确定显示的数字
// 注意,由a引脚到dp引脚的顺序是从低位到高位
switch(number){
case 0:
P0 = 0x3f; // 00111111
break;
case 1:
P0 = 0x06; // 00000110
break;
case 2:
P0 = 0x5b; // 01011011
break;
case 3:
P0 = 0x4f; // 01001111
break;
case 4:
P0 = 0x66; // 01100110
break;
case 5:
P0 = 0x6d; // 01101101
break;
case 6:
P0 = 0x7d; // 01111101
break;
case 7:
P0 = 0x07; // 00000111
break;
case 8:
P0 = 0x7f; // 01111111
break;
}
}
void main(){
Nixie_show(2,0);
while(1){
}
}
2.动态显示数据
可以看出我们每次都只能使对应的数码管显示对应的数字,如何动态的显示不同的数字呢?可以利用代码执行速度非常快的特性,使数码管之间的显示切换时间非常短,以人眼观察不到的速度达到动态显示的效果,但是这样会有一个问题,就是快速的切换(位选和段选)导致数码管的显示会错乱,对此我们还需要进行一个操作,消影操作,原理就是,我们在(位选 段选 位选 段选)时,由于速度过快,会导致前面段选显示到后面的位选这类问题导致显示错乱,所以我们要在每次位选段选操作后进行延时操作并暂时清零,与其他位选段选的操作隔开,代码如下:
#include <REGX51.H>
// 延时函数
void Delayms(unsigned char s) //@12.000MHz
{
while(s--){
unsigned char data i, j;
i = 12;
j = 169;
do
{
while (--j);
} while (--i);
}
}
// 封装数码管显示函数
void Nixie_show(unsigned char position,unsigned char number){
// 先确定要显示的led块
switch(position){
case 1:
P2_4 = 1;P2_3 = 1;P2_2 = 1; // 7
break;
case 2:
P2_4 = 1;P2_3 = 1;P2_2 = 0; // 6
break;
case 3:
P2_4 = 1;P2_3 = 0;P2_2 = 1; // 5
break;
case 4:
P2_4 = 1;P2_3 = 0;P2_2 = 0; // 4
break;
case 5:
P2_4 = 0;P2_3 = 1;P2_2 = 1; // 3
break;
case 6:
P2_4 = 0;P2_3 = 1;P2_2 = 0; // 2
break;
case 7:
P2_4 = 0;P2_3 = 0;P2_2 = 1; // 1
break;
case 8:
P2_4 = 0;P2_3 = 0;P2_2 = 0; // 0
break;
}
// 确定显示的数字
switch(number){
case 0:
P0 = 0x3f; // 00111111
break;
case 1:
P0 = 0x06; // 00000110
break;
case 2:
P0 = 0x5b; // 01011011
break;
case 3:
P0 = 0x4f; // 01001111
break;
case 4:
P0 = 0x66; // 01100110
break;
case 5:
P0 = 0x6d; // 01101101
break;
case 6:
P0 = 0x7d; // 01111101
break;
case 7:
P0 = 0x07; // 00000111
break;
case 8:
P0 = 0x7f; // 01111111
break;
}
// 进行消影操作,避免数码管显示错乱
//Delayms(1); 延时时间太长会导致闪烁
P0 = 0; // 消影核心操作
}
void main(){
while(1){
Nixie_show(1,1);
Nixie_show(2,3);
Nixie_show(3,1);
Nixie_show(4,4);
Nixie_show(5,5);
Nixie_show(6,2);
Nixie_show(7,0);
}
}
3.数码管的驱动方式
我们现在使用的就是直接扫描方式,会出现显示闪烁这类问题。
重点
- 数码管的两种连接方式
- 写程序要对照模块
- 消影操作