Arduino驱动4位数码管
-
昨天看到高中同学吐槽说被Arduino驱动数码管搞的满头大汗,不禁让我手痒痒。
-
突然想到自己好像也有4位数码管,翻了翻,果然有,于是就拿来玩了。
-
不过,好像驱动这个还是挺简单的吧!(确实挺简单的,只花了一个小时就封装好了函数)
参考网站:
基本原理
静态(只能保存单个数码管)
1.锁存器介绍
锁存器(Latch)是一种对脉冲电平敏感的存储单元电路,它们可以在特定输入脉冲电平作用下改变状态。锁存,就是把信号暂存以维持某种电平状态。锁存器的最主要作用是缓存,其次完成高速的控制器与慢速的外设的不同步问题,再其次是解决驱动的问题,最后是解决一个 I/O 口既能输出也能输入的问题。锁存器是利用电平控制数据的输入,它包括不带使能控制的锁存器和带使能控制的锁存器。
所谓锁存器,就是输出端的状态不会随输入端的状态变化而变化,仅在有锁存信号时输入的状态被保存到输出,直到下一个锁存信号到来时才改变。
2.138译码器(74HC138)介绍
74HC138是一款高速CMOS器件,74HC138引脚兼容低功耗肖特基TTL(LSTTL)系列。74HC138译码器可接受3位二进制加权地址输入(A0, A1和A2),并当使能时,提供8个互斥的低有效输出(Y0至Y7)。
74HC138特有3个使能输入端:两个低有效(E1和E2)和一个高有效(E3)。除非E1和E2置低且E3置高,否则74HC138将保持所有输出为高。
原理图:
动态显示
动态驱动显示就是使各个数码管轮流受控显示。在轮流显示过程中,每位数码管的点亮时间为1~2ms,由于人的视觉暂留现象及发光二极管的余辉效应,尽管实际上各位数码管并非同时点亮,但只要扫描的速度足够快态显示是一样的,能够节省大量的I/O端口,而且功耗更低。
一般的实例效果如下:
数码管引脚及接线
注意在共阳或共阴极引脚处要串联一个220欧姆(不要太大,不然灯不太亮)的电阻,再与Arduino的IO口相连,防止电流过大。
引脚定义
#define D_a 2
#define D_b 3
#define D_c 4
#define D_d 5
#define D_e 6
#define D_f 7
#define D_g 8
#define D_h 9
#define COM1 10
#define COM2 11
#define COM3 12
#define COM4 13
注意引脚要连续,一方面接线方便,一方面方便写代码
保存显示的数组
0表示亮灯,1表示熄灯,因为我的数码管为共阴极的,如果数码管不同的话,代码也可能不同。
bool型,减少内存。
后面如果有小数点则表示字母。
bool Digital_tube_number[18][8] = {
{0,0,0,0,0,0,1,1},//0
{1,0,0,1,1,1,1,1},//1
{0,0,1,0,0,1,0,1},//2
{0,0,0,0,1,1,0,1},//3
{1,0,0,1,1,0,0,1},//4
{0,1,0,0,1,0,0,1},//5
{0,1,0,0,0,0,0,1},//6
{0,0,0,1,1,1,1,1},//7
{0,0,0,0,0,0,0,1},//8
{0,0,0,0,1,0,0,1},//9
{0,0,0,1,0,0,0,0},//A10
{0,0,0,0,0,0,0,0},//B11
{0,1,1,0,0,0,1,0},//C12
{0,0,0,0,0,0,1,0},//D13
{0,1,1,0,0,0,0,0},//E14
{0,1,1,1,0,0,0,0},//F15
{0,1,0,0,0,0,1,0},//G16
{1,1,1,1,1,1,1,0},//小数点.
};
后来新增:
bool Digital_tube_number[37][8] = {
{0,0,0,0,0,0,1,1},//0
{1,0,0,1,1,1,1,1},//1
{0,0,1,0,0,1,0,1},//2
{0,0,0,0,1,1,0,1},//3
{1,0,0,1,1,0,0,1},//4
{0,1,0,0,1,0,0,1},//5
{0,1,0,0,0,0,0,1},//6
{0,0,0,1,1,1,1,1},//7
{0,0,0,0,0,0,0,1},//8
{0,0,0,0,1,0,0,1},//9
{0,0,0,1,0,0,0,1},//A10
{0,0,0,0,0,0,0,0},//B11
{0,1,1,0,0,0,1,0},//C12
{0,0,0,0,0,0,1,0},//D13
{0,1,1,0,0,0,0,0},//E14
{0,1,1,1,0,0,0,0},//F15
{0,1,0,0,0,0,1,0},//G16
{1,0,0,1,0,0,0,0},//H17
{1,1,1,1,0,0,1,0},//I18
{1,0,0,0,1,1,1,0},//J19
{1,1,0,1,0,0,0,0},//K20
{1,1,1,0,0,0,1,0},//L21
{0,0,0,1,0,0,1,0},//M22
{1,1,0,1,0,1,0,0},//N23
{0,0,0,0,0,0,1,1},//O24
{0,0,1,1,0,0,0,0},//P25
{0,0,0,0,0,0,1,0},//Q26
{0,0,0,1,0,0,0,0},//R27
{0,1,0,0,1,0,0,0},//S28
{0,1,1,1,0,0,1,0},//T29
{1,0,0,0,0,0,1,1},//U30
{1,0,0,0,0,0,1,0},//V31
{1,1,1,1,1,1,0,0},//W32
{1,1,1,1,1,1,0,0},//X33
{1,1,1,1,1,1,0,0},//Y34
{1,1,1,1,1,1,1,1},//不显示
{1,1,1,1,1,1,1,0},//小数点36.
};
初始化
for(int i=D_a;i<=D_h;i++){
pinMode(i,OUTPUT);
}
for(int i=COM1;i<=COM4;i++){
pinMode(i,OUTPUT);
}
显示
单个管教及其显示
void Digital_tube_display(int com,int number)
{
for(int i=COM1;i<=COM4;i++){
digitalWrite(i,LOW);
}
switch(com){
case 1:
digitalWrite(COM1,HIGH);
break;
case 2:
digitalWrite(COM2,HIGH);
break;
case 3:
digitalWrite(COM3,HIGH);
break;
case 4:
digitalWrite(COM4,HIGH);
break;
}
for(int i=0;i<8;i++){
digitalWrite(2+i,Digital_tube_number[number][i]);
}
}
多个数码管同时亮(最多支持4个)
多个数码管可以同时亮,但是这样每个数码管只能显示相同的数字.
下例:最后全显示2。
Digital_tube_display(1,5);
delay(200);
Digital_tube_display(2,14);
delay(200);
Digital_tube_display(3,1);
delay(200);
Digital_tube_display(4,2);//需要把Digital_tube_display里面的第一个循环(关闭所有COM)注释掉
另外一个例子:
void Digital_tube_display_sametime(int number)
{
digitalWrite(COM1,HIGH);
digitalWrite(COM2,HIGH);
digitalWrite(COM3,HIGH);
digitalWrite(COM4,HIGH);
for(int i=0;i<8;i++){
digitalWrite(2+i,Digital_tube_number[number][i]);
}
}
//调用一下这个函数
动态显示
/* 动态显示
* a数码管1显示,b数码管2显示,c数码管3显示,d数码管4显示,
* time1视觉暂留最短时间(最短为6,time2动态时间
*/
void Digital_tube_dynamic_display(int a,int b,int c,int d,int time1,float time2)
{
if(time1>6){
time1 = 6;
}
for(int i=0;i<time2*250/time1;i++){
Digital_tube_display(1,a);
delay(time1);
Digital_tube_display(2,b);
delay(time1);
Digital_tube_display(3,c);
delay(time1);
Digital_tube_display(4,d);
delay(time1);
}
}
动态调用实例:(1s改变一下)
Digital_tube_dynamic_display(1,2,3,4,6,1);
Digital_tube_dynamic_display(3,6,5,8,6,1);
Digital_tube_dynamic_display(10,11,12,13,6,1);
全代码
#define D_a 2
#define D_b 3
#define D_c 4
#define D_d 5
#define D_e 6
#define D_f 7
#define D_g 8
#define D_h 9
#define COM1 10
#define COM2 11
#define COM3 12
#define COM4 13
bool Digital_tube_number[18][8] = {
{0,0,0,0,0,0,1,1},//0
{1,0,0,1,1,1,1,1},//1
{0,0,1,0,0,1,0,1},//2
{0,0,0,0,1,1,0,1},//3
{1,0,0,1,1,0,0,1},//4
{0,1,0,0,1,0,0,1},//5
{0,1,0,0,0,0,0,1},//6
{0,0,0,1,1,1,1,1},//7
{0,0,0,0,0,0,0,1},//8
{0,0,0,0,1,0,0,1},//9
{0,0,0,1,0,0,0,0},//A10
{0,0,0,0,0,0,0,0},//B11
{0,1,1,0,0,0,1,0},//C12
{0,0,0,0,0,0,1,0},//D13
{0,1,1,0,0,0,0,0},//E14
{0,1,1,1,0,0,0,0},//F15
{0,1,0,0,0,0,1,0},//G16
{1,1,1,1,1,1,1,0},//小数点.
};
int delay_time = 2;
void setup() {
// put your setup code here, to run once:
for(int i=D_a;i<=D_h;i++){
pinMode(i,OUTPUT);
}
for(int i=COM1;i<=COM4;i++){
pinMode(i,OUTPUT);
}
Digital_tube_display_sametime(5);
}
void loop() {
// put your main code here, to run repeatedly:
/*Digital_tube_dynamic_display(1,2,3,4,6,1);
Digital_tube_dynamic_display(3,6,5,8,6,1);
Digital_tube_dynamic_display(10,11,12,13,6,1);*/
}
/* 动态显示
* a数码管1显示,b数码管2显示,c数码管3显示,d数码管4显示,
* time1视觉暂留最短时间,time2动态时间
*/
void Digital_tube_dynamic_display(int a,int b,int c,int d,int time1,float time2)
{
if(time1>6){
time1 = 6;
}
for(int i=0;i<time2*250/time1;i++){
Digital_tube_display(1,a);
delay(time1);
Digital_tube_display(2,b);
delay(time1);
Digital_tube_display(3,c);
delay(time1);
Digital_tube_display(4,d);
delay(time1);
}
}
void Digital_tube_display_sametime(int number)
{
digitalWrite(COM1,HIGH);
digitalWrite(COM2,HIGH);
digitalWrite(COM3,HIGH);
digitalWrite(COM4,HIGH);
for(int i=0;i<8;i++){
digitalWrite(2+i,Digital_tube_number[number][i]);
}
}
void Digital_tube_display(int com,int number)
{
for(int i=COM1;i<=COM4;i++){
digitalWrite(i,LOW);
}
switch(com){
case 1:
digitalWrite(COM1,HIGH);
break;
case 2:
digitalWrite(COM2,HIGH);
break;
case 3:
digitalWrite(COM3,HIGH);
break;
case 4:
digitalWrite(COM4,HIGH);
break;
}
for(int i=0;i<8;i++){
digitalWrite(2+i,Digital_tube_number[number][i]);
}
}