学习任务
1、四位数码管的电路结构与显示原理
(什么是位选、什么是段选、共阴与共阳的区别、显示4位数字,需要多少条口线?显示n位数字呢?)
2、Arduino直接连接四位数码管实现四位阿拉伯数字显示
(Friting绘制电路图(注意每个段都要加470欧姆限流电阻),程序原理说明,包含完整注释的源代码)
首先主要是介绍要完成四位数码管的动态扫描显示所需要了解并掌握的四位数码管的电路结构与显示原理。
一、位选与段选
以一位的7段数码管为例,如图1所示,一位的数码管加上小数点一共是8个需要控制的发光管,分别是a、b、c、d、e、f、g、dp,由8个引脚分别控制他们的亮灭,也就是说一个引脚控制一个发光管,那么这就是段选。发光的二极管是有两端的,那么这8个发光的二极管有一个公共端,这样就可以控制一位数码管整体,这就是位选。
由一位数码管延伸到四位数码管时,如图2所示,每一个发光管都有相应的引脚控制,每一位的数码管都有自己的公共端,通过公共端来控制哪一位的数码管亮或者是灭,这就是位选。
二、共阴与共阳的区别
一位的数码管相当于是由8个发光二极管拼成的,二极管有两个极,也就是阴极和阳极。
- 共阴数码管(如图4),也就是把所有组成这一位数码管的二极管的阴极都接在一起,想要点亮数码管中的某一段,就将com段(所有段的共同的阴极)接地,也就是低电平,然后把相应的阳极(a、b、c…….)接高电平,这样这一段就会被点亮。
- 共阳数码管(如图5),也就是把所有组成这一位数码管的二极管的阳极都接在一起,想要点亮数码管中的某一段,就将com段(所有段的共同的阳极)接高电平,然后把相应的阴极(a、b、c…….)接地或者是低电平,这样这一段就会被点亮。
当然,如果拿到一个数码管不知道是共阳还是共阴,可以用万用表的蜂鸣档测试一下或者高低电平接一下即可知道。
三、显示N位数字的口线数量规律
那么要想使四位数码管显示4位数字,需要多少条口线?显示n位数字呢?能总结出一个规律么?
-
以两位的共阴数码管为例(如图6),先观察段选,每一位数码管的相同的段并联在一起,最后由一个引脚控制,那么每一位有8个二极管,也就是需要并联8次,最后需要8个口线。对于位选,因为一共是两位数码管,所以需要两个公共端去控制每一位数码管。这样就是(8+2)条口线。
延伸到四位数码管(如图7),同理,对于段选,仍然是每一位数码管的相同的段并联在一起,最后由一个引脚控制,那么每一位有8个二极管,也就是需要并联8次,最后需要8个引脚。对于位选,因为一共是四位数码管,所以需要四个公共端去控制每一位数码管。这样就是(8+4)条口线。
可以看到,N位数码管,对于段选,不管是多少位的数码管,由于每一位相同的段都是并联,都是需要8个口线去控制段;对于位选,有几位数码管,就需要几个公共端去控制。所以N位数码管显示N位数字需要(8+N)条口线。
接下来介绍一下我们所使用的四位数码管主要会有哪些类型,并且他们之间有什么不同。
一、12个引脚的四位数码管
类型一
如图1,2所示,这种四位数码管是最常见的也是最简单的,每一位数码管中相同的段彼此并联,由8个引脚控制段选,其余4个引脚分别控制四个位选。
类型二
如图3,4所示,这种四位数码管在第二三位中间多了两点,这是属于时钟数码管,可以用它来显示时间。以共阴为例,这种的不同之处在于,它将增加的时钟点的阳极与其他四位的小数点(dp段)的阳极相并联,然后阴极也就是公共端,与第二位的数码管的公共端共享。也就是说可以看成是将这两个时钟点加入到了第二位的数码管中,成为它的一部分,这样使得四位数码管的引脚数量仍然不发生改变。
二、14个引脚的四位数码管
如图5,6,7,所示,以共阴极为例,这是我们所使用的四位数码管,也同样是属于时钟数码管,它之所以会增加两个引脚是因为它将两个时钟点单独拿出来,阳极并联使用一个引脚,再使用一个公共端,这个就可以看成是两个时钟点的一个位选。
在之前的四位数码管的显示原理学习的基础上,介绍的是利用Arduino直接连接四位数码管从而实现四位阿拉伯数字显示。以四位共阴数码管为例,显示数字1234。
一、实验器材
- Nano开发板
- 配套USB数据线
- 一个四位数码管
- 8个470Ω的电阻
- 若干导线
二、电路连接图
分析:四位数码管一共有8个引脚控制段选,所以需要每一个引脚串联一个电阻保证电流的正常流通,使得二极管正常显示。根据数码管的引脚图可对应段选和位选的引脚号,从而通过导线将引脚与nano板相连接,与电脑连接之后,在arduino中编写代码即可控制四位数码管。
三、编写代码
#define SEG_B 3 //Arduino Pin3--->SegLed Pin7
#define SEG_C 4 //Arduino Pin4--->SegLed Pin4
#define SEG_D 5 //Arduino Pin5--->SegLed Pin2
#define SEG_E 6 //Arduino Pin6--->SegLed Pin1
#define SEG_F 7 //Arduino Pin7--->SegLed Pin10
#define SEG_G 8 //Arduino Pin8--->SegLed Pin5
#define SEG_H 9 //Arduino Pin9--->SegLed Pin3
#define COM1 13 //Arduino Pin10--->SegLed Pin12
#define COM2 12 //Arduino Pin11--->SegLed Pin9
#define COM3 11 //Arduino Pin12--->SegLed Pin8
#define COM4 10 //Arduino Pin13--->SegLed Pin6
unsigned char table[10][8] =
{
{0, 0, 1, 1, 1, 1, 1, 1}, //0
{0, 0, 0, 0, 0, 1, 1, 0}, //1
{0, 1, 0, 1, 1, 0, 1, 1}, //2
{0, 1, 0, 0, 1, 1, 1, 1}, //3
{0, 1, 1, 0, 0, 1, 1, 0}, //4
{0, 1, 1, 0, 1, 1, 0, 1}, //5
{0, 1, 1, 1, 1, 1, 0, 1}, //6
{0, 0, 0, 0, 0, 1, 1, 1}, //7
{0, 1, 1, 1, 1, 1, 1, 1}, //8
{0, 1, 1, 0, 1, 1, 1, 1} //9
};
void setup()
{
pinMode(SEG_A,OUTPUT); //设置为输出引脚
pinMode(SEG_B,OUTPUT);
pinMode(SEG_C,OUTPUT);
pinMode(SEG_D,OUTPUT);
pinMode(SEG_E,OUTPUT);
pinMode(SEG_F,OUTPUT);
pinMode(SEG_G,OUTPUT);
pinMode(SEG_H,OUTPUT);
pinMode(COM1,OUTPUT);
pinMode(COM2,OUTPUT);
pinMode(COM3,OUTPUT);
pinMode(COM4,OUTPUT);
}
void loop()
{
Display(1,1); //第1位显示1
Delay(10);
Display(2,2); //第2位显示2
Delay(10);
Display(3,3); //第3位显示3
Delay(10);
Display(4,4); //第4位显示4
Delay(10);
}
void Display(unsigned char com, unsigned char num)
{
digitalWrite(SEG_A,LOW);
digitalWrite(SEG_B,LOW);
digitalWrite(SEG_C,LOW);
digitalWrite(SEG_D,LOW);
digitalWrite(SEG_E,LOW);
digitalWrite(SEG_F,LOW);
digitalWrite(SEG_G,LOW);
digitalWrite(SEG_H,LOW);
switch(com) //选通位选
{
case 1:
digitalWrite(COM1,LOW); //选择位1
digitalWrite(COM2,HIGH);
digitalWrite(COM3,HIGH);
digitalWrite(COM4,HIGH);
break;
case 2:
digitalWrite(COM1,HIGH);
digitalWrite(COM2,LOW); //选择位2
digitalWrite(COM3,HIGH);
digitalWrite(COM4,HIGH);
break;
case 3:
digitalWrite(COM1,HIGH);
digitalWrite(COM2,HIGH);
digitalWrite(COM3,LOW); //选择位3
digitalWrite(COM4,HIGH);
break;
case 4:
digitalWrite(COM1,HIGH);
digitalWrite(COM2,HIGH);
digitalWrite(COM3,HIGH);
digitalWrite(COM4,LOW); //选择位4
break;
default:break;
}
digitalWrite(SEG_A,table[num][7]); //a查询码值表
digitalWrite(SEG_B,table[num][6]);
digitalWrite(SEG_C,table[num][5]);
digitalWrite(SEG_D,table[num][4]);
digitalWrite(SEG_E,table[num][3]);
digitalWrite(SEG_F,table[num][2]);
digitalWrite(SEG_G,table[num][1]);
digitalWrite(SEG_H,table[num][0]);
}
四、代码分析
- 首先,定义数码管a段是接引脚2,b段是接引脚3……以此类推定义完段选,之后再定义位选,1位数码管的公共端接13……同样以此类推。
#define SEG_A 2 //Arduino Pin2--->SegLed Pin11
#define SEG_B 3 //Arduino Pin3--->SegLed Pin7
#define SEG_C 4 //Arduino Pin4--->SegLed Pin4
#define SEG_D 5 //Arduino Pin5--->SegLed Pin2
#define SEG_E 6 //Arduino Pin6--->SegLed Pin1
#define SEG_F 7 //Arduino Pin7--->SegLed Pin10
#define SEG_G 8 //Arduino Pin8--->SegLed Pin5
#define SEG_H 9 //Arduino Pin9--->SegLed Pin3
#define COM1 13 //Arduino Pin10--->SegLed Pin12
#define COM2 12 //Arduino Pin11--->SegLed Pin9
#define COM3 11 //Arduino Pin12--->SegLed Pin8
#define COM4 10 //Arduino Pin13--->SegLed Pin6
- 定义一个可以查询的码值表,因为使用的是共阴四位数码管,用0表示低电平,用1表示高电平,从而将0~9这10个数字显示时,数码管的阳极的一端的高低电平的状态表示出来。例如,当想要显示数字1时,那么a段与b段的阳极是高电平,那么a段与b段的二极管将会点亮,其余的是熄灭状态,那么就会显示数字1。
unsigned char table[10][8] =
{
{0, 0, 1, 1, 1, 1, 1, 1}, //0
{0, 0, 0, 0, 0, 1, 1, 0}, //1
{0, 1, 0, 1, 1, 0, 1, 1}, //2
{0, 1, 0, 0, 1, 1, 1, 1}, //3
{0, 1, 1, 0, 0, 1, 1, 0}, //4
{0, 1, 1, 0, 1, 1, 0, 1}, //5
{0, 1, 1, 1, 1, 1, 0, 1}, //6
{0, 0, 0, 0, 0, 1, 1, 1}, //7
{0, 1, 1, 1, 1, 1, 1, 1}, //8
{0, 1, 1, 0, 1, 1, 1, 1} //9
};
- 利用setup函数定义所连接的引脚为输出引脚
void setup()
{
pinMode(SEG_A,OUTPUT); //设置为输出引脚
pinMode(SEG_B,OUTPUT);
pinMode(SEG_C,OUTPUT);
pinMode(SEG_D,OUTPUT);
pinMode(SEG_E,OUTPUT);
pinMode(SEG_F,OUTPUT);
pinMode(SEG_G,OUTPUT);
pinMode(SEG_H,OUTPUT);
pinMode(COM1,OUTPUT);
pinMode(COM2,OUTPUT);
pinMode(COM3,OUTPUT);
pinMode(COM4,OUTPUT);
}
4.用loop函数来定义第一位显示1,第二位显示2,第三位显示3,第四位显示4,每一个显示后面都加了一个delay,用来表示显示延时10秒钟。又因为loop函数是一个死循环体,那么它会一直循环执行函数里面的内容。
void loop()
{
Display(1,1); //第1位显示1
Delay(10);
Display(2,2); //第2位显示2
Delay(10);
Display(3,3); //第3位显示3
Delay(10);
Display(4,4); //第4位显示4
Delay(10);
}
- 定义display这个函数,首先利用digitalWrite函数将共阴数码管的8个段的阳极设置为低电平,作用是为了将所有的二极管熄灭,起到置零的作用。
之后利用switch函数来定义位选,因为是以显示1234为例,那么当只让第一位亮起数字1时,就将第一位的公共端(com端)设置为低电平,其余设置为高电平;当只让第二位亮起数字2时,就将第二位的公共端(com端)设置为低电平……
最后,定义完位选后,用digitalWrite来定义段选,利用之前定义好的码值表,当显示数字1时,查询码值表找到相应的每一个段(a、b、c……)分别是高电平还是低电平,然后将这个信号发送到每一个段的对应的引脚上来控制二极管的亮灭状态。
void Display(unsigned char com, unsigned char num)
{
digitalWrite(SEG_A,LOW);
digitalWrite(SEG_B,LOW);
digitalWrite(SEG_C,LOW);
digitalWrite(SEG_D,LOW);
digitalWrite(SEG_E,LOW);
digitalWrite(SEG_F,LOW);
digitalWrite(SEG_G,LOW);
digitalWrite(SEG_H,LOW);
switch(com) //选通位选
{
case 1:
digitalWrite(COM1,LOW); //选择位1
digitalWrite(COM2,HIGH);
digitalWrite(COM3,HIGH);
digitalWrite(COM4,HIGH);
break;
case 2:
digitalWrite(COM1,HIGH);
digitalWrite(COM2,LOW); //选择位2
digitalWrite(COM3,HIGH);
digitalWrite(COM4,HIGH);
break;
case 3:
digitalWrite(COM1,HIGH);
digitalWrite(COM2,HIGH);
digitalWrite(COM3,LOW); //选择位3
digitalWrite(COM4,HIGH);
break;
case 4:
digitalWrite(COM1,HIGH);
digitalWrite(COM2,HIGH);
digitalWrite(COM3,HIGH);
digitalWrite(COM4,LOW); //选择位4
break;
default:break;
}
digitalWrite(SEG_A,table[num][7]); //a查询码值表
digitalWrite(SEG_B,table[num][6]);
digitalWrite(SEG_C,table[num][5]);
digitalWrite(SEG_D,table[num][4]);
digitalWrite(SEG_E,table[num][3]);
digitalWrite(SEG_F,table[num][2]);
digitalWrite(SEG_G,table[num][1]);
digitalWrite(SEG_H,table[num][0]);
}
五、实验现象
输入代码之后,观察四位数码管,先第一位10秒显示数字1,第二位10秒显示数字2,第三位10秒显示数字3,第一位10秒显示数字4,之后一次再循环点亮数字1,2,3,4……
六、实验总结
为什么不是直接显示数字1234的静态显示,而是数字循环出现?
- 首先,根据四位数码管的引脚图可以知道,每一位相同的段是并联在一起然后连到一个相同的引脚,信号会发送到每一个段的引脚上来控制段的点亮还是熄灭。假如是同时显示四位数字的话,那么引脚一次只能传递高电平和低电平的其中一种,会使每一位相同的段具有相同的电平,但是显示不同的数字,段的状态是不同的,这就产生了矛盾。所以四位数码管在显示的时候,是先将第一位的数码管的所有段的信号通过引脚传送之后,在传送第二位需要的信号,一直到第四位。
- 其次,要注意代码中使用loop函数来定义第一位显示1,第二位显示2,第三位显示3,第四位显示4,每一个显示后面都加了一个delay,用来表示显示延时10秒钟。又因为loop函数是一个死循环体,那么它会一直循环执行函数里面的内容。假如将delay去掉,实验的现象是看上去数字1234是同时显示的,其实仍是1234在循环显示,只是速度太快,产生视觉暂留效应给我们的眼睛产生了错觉。