数码管动态扫描
作者:张庆奎
1.数码管介绍
数码管,其内部含有8个LED,其实是由LED组装而成的。
从图可以看出来,数码管共有 a、b、c、d、e、f、g、dp 这么 8 个段,而实际上,这 8 个段每一段都是一个 LED 小灯,所以一个数码管就是由 8个 LED 小灯组成的。注意 dp 这个段,它是表示一个小数点!
数码管分为共阴和共阳两种(对于我们使用的STC89C52RC是共阴的)。
共阴数码管就是8只LED灯的阴极是连在一起的,阴极是公共端,由阳极来控制单个小灯的亮灭。
同理,共阳数码管就是连在一起。
显示端:a, b, c, d, f, g, dp,这几个端口负责点亮数码管上相应的LED灯,比如a端口控制A这个lLED灯。
公共端(com):用于选择数码管。
举例说明:我们现在要使一个数码管显示数字”0“,那么”0“就是点亮A, B, C, D, E, F,对于共阴数码管,它的
相应的端口信号为:
数字 | dp | g | f | e | d | c | b | a | 二进制表示 | 十六进制表示 |
---|---|---|---|---|---|---|---|---|---|---|
0 | 0 | 0 | 1 | 1 | 1 | 1 | 1 | 1 | 00111111 | 0x3f |
2.STC89C52RC原理图
本单片机共有六个数码管,共阴
P2口的第六位DULA用于数码管的段锁存器,P2口的第七位WELA用于数码管的位锁存器,所以我们在点亮数码管的过程中要用到这两个锁存器。
由原理图可知显示端的信号,D0-D7分别对应a-h,在位选信号中(即选在哪一个数码管)D0对应WE1即当D0为低电平时第一个数码管亮,后面的D1...同理。
3. 数码管的动态扫描原理
- 由于开发板上所有的数码管都是由共用端和显示端连通的,显示端由某一个寄存器控制。
- 假设我们让第一个数码管显示1,之后我们还想让第二个数码管显示2,但是当第二个数码管显示2的时候,第一个数码管也会变成2,因为每个数码管的显示端都是由同一个寄存器控制的。
- 因此我们可以这样考虑,一次只点亮一个数码管,显示对应的值,点亮之后写一个延迟函数,这个延迟函数在1~2ms之间(1ms即可)。(延迟函数时间太长,就会变成静态效果,延迟函数时间太短,又会由于运行过快,没有稳定点亮就去执行下一语句而产生鬼影。)
- 由于人的视觉暂留现象及发光二极管的余辉效应,尽管实际上各位数码管并非同时点亮,但只要扫描的速度足够快,给人的印象就是一组稳定的显示数据,不会有闪烁感。
- 延迟时间必须相同,并且这些延迟时间不能过长,过长的话人眼会识别出来(过长的话人眼只认为第一个数码管点亮)。
4.实战:在数码管上同时显示012345
c
//overwhelm.h头文件
#define __OVERWHELM_H__
#ifdef CCNUIOT_51
#define uint_16 unsigned int
#define uint_8 unsigned char
#define int_16 int
#define int_8 char
#include <REG52.H>
#include "bsy_tube.h"
#include "bsp_delay.h"
#endif /*CCNUIOT_51*/
#endif /*__OVERWHELM_H__*/
1
2
3
4
5
6
7
8
9
10
11
12
13
2
3
4
5
6
7
8
9
10
11
12
13
c
//bsp_delay.h
#ifndef __BSP_DELAY_H__
#define __BSP_DELAY_H__
#include "overwhelm.h"
void Delay(uint_16 i);
#endif
1
2
3
4
5
6
7
8
2
3
4
5
6
7
8
c
//bsp_delay.c
#include "bsp_delay.h"
//延时函数delay
void Delay(unsigned int i)
{
unsigned int m,n;
for(m=i;m>0;m--)
for(n=90;n>0;n--);
}
1
2
3
4
5
6
7
8
9
10
2
3
4
5
6
7
8
9
10
c
//bsp_tube.h
//bsp_tube.h
#ifndef __BSP_TUBE_H__
#define __BSP_TUBE_H__
#include "overwhelm.h"
void Static_Display(uint_8 num, uint_8 i);//静态点亮数码管
void Dynamic_Display();
#endif
1
2
3
4
5
6
7
8
2
3
4
5
6
7
8
c
//bsp_tube.c
#include "bsy_tube.h"
#include "bsp_delay.h"
sbit dula=P2^6; //段选信号的锁存器控制
sbit wela=P2^7; //位选信号的锁存器控制
uint_8 code wei[] = {0xfe, 0xfd, 0xfb, 0xf7, 0xef, 0xdf};
//数码管各位的码表
uint_8 code duan[] = {0x3f,0x06,0x5b,0x4f,0x66,0x6d};
//0-5的码表
void Static_Display(uint_8 i, uint_8 num)//num是要显示的数字0-5,i是第几个数码管
{ //静态点亮数码管
P0 = wei[i];
wela = 1;
wela = 0;
P0 = duan[num];
dula = 1;
dula = 0;
}
void Dynamic_Display()//动态点亮数码管
{
Static_Display(0, 0);
Delay(2);
Static_Display(1, 1);
Delay(2);
Static_Display(2, 2);
Delay(2);
Static_Display(3, 3);
Delay(2);
Static_Display(4, 4);
Delay(2);
Static_Display(5, 5);
Delay(2);
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
c
//main.c
#include "overwhelm.h"//注意要包含这个头文件
void main(void)
{
while(1)
{
Dynamic_Display();//调用动态扫描数码管函数
}
}
1
2
3
4
5
6
7
8
9
10
2
3
4
5
6
7
8
9
10
在数字显示时,需要将不同的数字对应的段选信号和位选信号输出到数码管上,才能正确地显示出数字。而dula和wela这两个引脚则是控制这些信号传递的关键。
在实现数码管显示时,通常需要使用锁存器来保证数据稳定地传递到数码管上,避免闪烁和干扰。每当一个数字需要输出时,会先将该数字对应的位码和段码存储到锁存器中,然后通过控制dula和wela这两个引脚,将锁存器中的数据依次输出到数码管上。
5.思考:
- 如何在数码管上显示数字流0-F。
- 如何在数码管上显示一个时间,比如23.23.23分别对应时分秒,然后时间依次增加。