Feng HanXiu
Articles9
Tags0
Categories0

Archive

2024开源蓝桥系列(三):数码管的静态,动态显示以及消影原理

2024开源蓝桥系列(三):数码管的静态,动态显示以及消影原理

静态显示

1. 数码管的内部结构

LED数码管一般由多个LED灯组成,显示不同的数字或字符。在我们使用的板子中,数码管由7个长条状LED和1个圆形LED组成。常见的数码管有两种类型:共阳数码管(板子上的)和共阴数码管。

  • 共阳数码管:阳极连接到高电平(1),A、B、C、D等连接到低电平(0)时,LED灯点亮,显示数字。
  • 共阴数码管:与共阳数码管相反,阴极连接到低电平。图1 数码管的内部结构

2. 数码管的显示原理

数字是通过将特定的LED点亮来显示的。每个数字的显示可以用16进制编码表示。通常,在比赛中会提供数字0到9的16进制编码,我们不需要记住这些编码,只需要理解原理,并能够正确地显示所需的数字。

3. 数码管显示的原理图

在图2中,数码管连接了COM1-COM8,A1-DP1,表示8个数码管的控制信号。P0端口负责控制数码管的显示,573锁存器用于存储显示数据。

  • 当Y6C为高电平(1)时,P0口控制选择哪个数码管。
  • 当Y7C为高电平(1)时,P0口控制选中的数码管显示的数字。

图2 数码管原理图

4. 静态显示代码

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
44
45
46
47
48
49
50
51
52
53
54
55
#include <STC15F2K60S2.H>
#include <intrins.h>

unsigned char code SMG[10] = {0xc0, 0xf9, 0xa4, 0xb0, 0x99, 0x92, 0x82, 0xf8, 0x80, 0x90}; // 共阳极数码管段码表
// 0 1 2 3 4 5 6 7 8 9

/* 数码管静态显示 */
void slect_138_573(unsigned char channel, unsigned char dat) // 对P2与P0赋值
{
/* 选择通道并且输入数据 */
P0 = 0x00; /* 将原来P0口中的数据清0 */
P0 = dat; /* 这里用P0而不用其他端口是因为我们操作LED、数码管、继电器、蜂鸣器都是对P0进行操作 */
switch(channel) /* 选择通道 */
{
case 4: /* 使Y4输出低电平0,也就是操作LED */
P2 = (P2 & 0x1f) | 0x80; /* (P2 & 0x1f)就是将前3位清0,再操作前3位。将0x80转为2进制1000 0000,这里只看前3位100就是Y4 */
break;
case 5: /* 使Y5输出低电平0,也就是操作继电器和蜂鸣器 */
P2 = (P2 & 0x1f) | 0xa0;
break;
case 6: /* 使Y6输出低电平0,也就是操作8个数码管 */
P2 = (P2 & 0x1f) | 0xc0;
break;
case 7: /* 使Y7输出低电平0,也就是操作8个数码管中的1个数码管显示值 */
P2 = (P2 & 0x1f) | 0xe0;
break;
case 0: /* 关闭所有通道 */
P2 = (P2 & 0x1f) | 0x00;
break;
}
P2 = (P2 & 0x1f) | 0x00; /* 使用后,关闭所有通道 */
}

void SMG_Display_Bit(unsigned char pos, unsigned char value)
{
slect_138_573(6, 0x01 << pos - 1); // 选择哪个数码管亮
slect_138_573(7, value); // 亮的数码管显示什么
}

void System_init(void) // 关闭LED与蜂鸣器继电器
{
slect_138_573(4, 0xff); // 关LED
slect_138_573(5, 0x00); // 关继电器蜂鸣器
}

void main(void)
{
System_init();
while(1)
{
SMG_Display_Bit(1, SMG[0]);
}
}

/* 数码管静态显示 */

动态显示

1. 动态显示原理

动态显示的原理利用了人眼的视觉暂留效应和LED的余辉效应。尽管每个数码管并非同时点亮,但通过快速扫描数码管,给人以连续显示的效果。具体操作中,我们通过对数码管进行循环扫描,并加入一定的延迟,形成动态显示效果。

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
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
#include <STC15F2K60S2.H>
#include <intrins.h>

unsigned char code SMG[10] = {0xc0, 0xf9, 0xa4, 0xb0, 0x99, 0x92, 0x82, 0xf8, 0x80, 0x90}; // 共阳极数码管段码表
// 0 1 2 3 4 5 6 7 8 9

/* 数码管动态显示 */

void Delay1ms() //@12.000MHz
{
unsigned char i, j;

i = 12;
j = 169;
do
{
while (--j);
} while (--i);
}

void delay_ms(int x)
{
while(x--)
{
Delay1ms();
}
}

void slect_138_573(unsigned char channel, unsigned char dat)
{
/* 选择通道并且输入数据 */
P0 = 0x00; /* 将原来P0口中的数据清0 */
P0 = dat; /* 这里用P0而不用其他端口是因为我们操作LED、数码管、继电器、蜂鸣器都是对P0进行操作 */
switch(channel) /* 选择通道 */
{
case 4: /* 使Y4输出低电平0,也就是操作LED */
P2 = (P2 & 0x1f) | 0x80; /* (P2 & 0x1f)就是将前3位清0,再操作前3位。将0x80转为2进制1000 0000,这里只看前3位100就是Y4 */
break;
case 5: /* 使Y5输出低电平0,也就是操作继电器和蜂鸣器 */
P2 = (P2 & 0x1f) | 0xa0;
break;
case 6: /* 使Y6输出低电平0,也就是操作8个数码管 */
P2 = (P2 & 0x1f) | 0xc0;
break;
case 7: /* 使Y7输出低电平0,也就是操作8个数码管中的1个数码管显示值 */
P2 = (P2 & 0x1f) | 0xe0;
break;
case 0: /* 关闭所有通道 */
P2 = (P2 & 0x1f) | 0x00;
break;
}
P2 = (P2 & 0x1f) | 0x00; /* 使用后,关闭所有通道 */
}

void SMG_Display_Bit(unsigned char pos, unsigned char value)
{
slect_138_573(6, 0x01 << pos - 1);
slect_138_573(7, value);
delay_ms(2);
// delay_ms(50); // 延时太长数码管就做不到动态显示

// 消影
slect_138_573(6, 0x01 << pos - 1);
slect_138_573(7, 0xff);
}

void System_init(void)
{
slect_138_573(4, 0xff);
slect_138_573(5, 0x00);
}

void main(void)
{
System_init();
while(1)
{
SMG_Display_Bit(1, SMG[1]);
SMG_Display_Bit(8, SMG[6]);
}
}

/* 数码管动态显示 */

Author:Feng HanXiu
Link:http://example.com/2024/11/13/2024%E5%BC%80%E6%BA%90%E8%93%9D%E6%A1%A5%E7%B3%BB%E5%88%97%EF%BC%88%E4%B8%89%EF%BC%89%EF%BC%9A%E6%95%B0%E7%A0%81%E7%AE%A1%E7%9A%84%E9%9D%99%E6%80%81%EF%BC%8C%E5%8A%A8%E6%80%81%E6%98%BE%E7%A4%BA%E4%BB%A5%E5%8F%8A%E6%B6%88%E5%BD%B1%E5%8E%9F%E7%90%86/
版权声明:本博客采用由开源协会搭建