0%

八位数码管动态扫描

八位数码管动态扫描

实验工程可以在学习通上面下载

程序设计流程图

img

在程序启动的初期,需要对硬件有抽象的定义,这由我们的.h头文件表示,初始化硬件,实际是对一些寄存器的初始化,和上一个流水灯的init函数差不多。然后就是主要逻辑,扫描位选,并完成端口的赋值。

原理说明

什么是段选和位选

简单说:段选信号是选择数码管的那一段灯管亮起,位选信号是选择八个数码管的哪一个。

image-20220627143830272

如下图,由于这八个数码管是通用的同一个GND,也就是共地的。(一次只能一个开漏地级接给一个数码管,否则不同的二极管会冲突)因此,一次只能有一个数码管亮起,比如下图中八个数码管一次显示0-7,则只能够从左到右,D1先显示0,D1熄灭,D2再显示1,D2熄灭,…,然后轮流下去,如果速度够快,人眼看起来就像灯是一起亮着的。

image-20220627135806124

段选进一步说明

image-20220627142752484

image-20220627142912078

位选就是第几个数码管,段选是怎么来的?

比如我们要左起第3个(01234567)数码管显示6,因此位选就是2,也就是P2 = 2,当然也可以用程序中的方法(多此一举)P2 = weixuan[2]

然后段选要显示6根据上面的图,我们知道,显示6,需要“a, c, d, f, g, e”这些灯管亮起。所以位选信息如下

image-20220627144325373

所以因此段选信息就是:duanxuan[6] = 0b0111101 = 0x7d

所以对应P0.7-P0.0就是0x7d

类似上面的方法就可以枚举出所有的段选情况:

1
uchar duanxuan[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f};

代码说明

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
/* 对硬件各个端口的定义的头文件,直接使用即可 */
#include <STC15F2K60S2.h>
/* 重定义类型名,简写 */
#define uint unsigned int
#define uchar unsigned char

uint i=0;
// 段选:选择亮灯
uchar duanxuan[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f};
// 位选:选择哪一个数码管
uchar weixuan[]={0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07};

void Delay(int n) // 延时函数,单位毫秒
{
while(n--);
}

void main()
{
/* 设置推挽输出
* 和流水灯实验类似,对P0端口和P2端口进行设置
* 端口设置推挽输出,通道0设置“1”,通道0全0,具体见数据手册,流水灯也讲过了
* 端口0的0通道,是表示位选,八个位对应八个灯管,所以全部设成1
* 端口2的0通道,是表示段选,一次只能选一个数码管,由三位输入进行选择
* 分别是:P2.2 P2.1 P2.0
* 刚好是P2的第三位,所以赋值时候,只要P2 = weixuan[i]
* 就可以
* 这里简单将2的0通道全部设成1
*/
P2M0=0xff;
P2M1=0x00;
P0M0=0xff;
P0M1=0x00;
/* 循环扫描数码管
* 不断扫描数码管,使每一小段数码管都点亮一段时间
* 视觉上一直是亮的状态
*/
while(1)
{
for(i=0;i<8;i++)
{
P0=0;
P2=weixuan[i]; // 选择数码管的位数
P0=duanxuan[i+1]; // 选择对应的数值
Delay(600); // 延时
}
}
}