0%

八位数码管+流水灯(BSP版本)

八位数码管+流水灯(BSP版本)

因为不是专业的单片机专家,所以既然提供了带有BSP库的版本,自然就用BSP版本。这里介绍一下BSP版本的代码。

文件说明

image-20220629151028369

文件的主题部分如上图,除了main函数以外,我们看到STC15F2K60S2.H和前面一样是端口的地址定义的头文件

然后是displayer.h头文件,

image-20220629151443888

这一部分就是显示功能的相关接口,STC单片机上的显示主要是数码管和LED灯。

  • DisplayerInit是显示模块初始化函数,会对对应的函数的硬件,以及相关针脚进行初始化,具体可以看看前面的博文,就是作P0、P2端口等以及其他相关寄存器的初始化
  • SetDisplayerArea是设置有效显示区域,根据[begin, end]设置数码管显示范围。如果begin = 0,end = 7,显示的就是所有的数码管。但是范围不仅仅是这样,如果你的end大于7,比如是255,这也是能够正常工作的,只是硬件地址只有0-7,但是其他的无效地址会消耗一定的时间,这样总体显示时间变长了,由于是动态扫描的,所以8个有效数码管显示会出现闪烁,亮度下降的现象。
  • Seg7Print参数是输入8个要显示的数据,这个可以根据输入的参数作为在decode_table[]中的索引,可以显示对应灯管的组合
  • LedPrint控制8个数码管开关,一个位对应一个数码管,1是亮,0是暗。

还有一个文件是sys.h,这个是用来执行系统级别的操作,旨在对于用户以及系统的事件做出响应

image-20220629155718409

image-20220629155747086

上面是系统相关的函数,注释写的很清楚,主要是初始化系统,并且定义了事件,以及响应事件的函数。这里不详细展开,用到的时候再进行说明。

上面头文件涉及的函数,在STCBSP_V3.6.LIB静态库中进行定义,因此可以直接使用。

image-20220629154235232

主函数逻辑说明

image-20220629160509448

main.c中需要将SysClock设置成和下载的IRC一样的频率

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
/* 显示数码管和LED等需要的头文件,其中前面两个是必须的 */
#include "STC15F2K60S2.H" // 端口地址定义
#include "sys.H" // 使用系统的函数定义
#include "displayer.H" // 数码管显示

/* 必须。定义系统工作时钟频率(Hz),用户要修改成和实际工作频率(下载时)一致,如上图 */
code unsigned long SysClock=11059200; // code是告诉单片机这个变量的值刷写入ROM,不再改变

/* 用户可以进行自定义数码管显示,主要是通过decode_table */
#ifdef _displayer_H_
code char decode_table[]={ /* 值 */
0x3f, // 0
0x06, // 1
0x5b, // 2
0x4f, // 3
0x66, // 4
0x6d, // 5
0x7d, // 6
0x07, // 7
0x7f, // 8
0x6f, // 9
0x00, // 无
0x08, // 下-
0x40, // 中-
0x01, // 上-
0x41, // 上中-
0x48, // 中下-
0x3f|0x80, // 带小数点0
0x06|0x80, // 带小数点1
}; // 也可以采用上面的拼接方式进行段选信息的构造
#endif

/* LED显示函数,可回调 */
void my100mS_callback()
{
// 定义一个LED寄存器类型
unsigned char a;
// LED显示左移
if(a != 0) a=a<<1;
// 超出了,重置
else a=0x01;
// 显示寄存器值
LedPrint(a);
/**
* 这里仅仅进行一次打印操作
* 但是每一次a的值从上一次继承下来,实现了移位操作
* a是局部变量
* 从局部变量声明的时候,它就在堆栈空间了,而不是调用函数的时候,才让它入栈的。
*/
}
void main()
{
// 使用显示设备,需要进行初始化
DisplayerInit();
// 设置显示范围为0-64,实际有效只有0-7,因此有无效地址消耗时间,数码管会出现闪烁变暗
SetDisplayerArea(0,64);
// 八个数码管分别显示1-8
Seg7Print(1,2,3,4,5,6,7,8);
// 利用回调函数,每100ms,就调用一次函数,这么做是为了节省栈空间,因为单片机的栈很小
SetEventCallBack(enumEventSys100mS, my100mS_callback);
/* 这里是初始化系统并循环等待事件,如果没有下面这部分,程序运行结束,板子就死了 */
MySTC_Init();
while(1) {
MySTC_OS();
}
}

C语言版本

整体和上一个版本差不多,这里不做赘述。

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
/**********************
:八位数码管+流水灯
型号:STC15F2K60S2 主频:11.0592MHz
************************/
#include <STC15F2K60S2.h>
#define uint unsigned int
#define uchar unsigned char

uchar arrSeg7Select[] = {0x3f, 0x06, 0x5b, 0x4f, 0x66, 0x6d, 0x7d, 0x07, 0x7f}; //显示0-8
uchar arrDigitSelect[] = {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07}; //数码管0-7

/*---------引脚别名定义---------*/
sbit sbtLedSel = P2 ^ 3; //数码管与LED灯切换引脚

/*---------变量定义---------*/
uchar uiLed = 0x01; //LED灯值寄存
uint uiLedCnt = 0; //LED灯累计计数器
uchar i = 0; //数码管扫描显示循环

/*---------初始化函数---------*/
void Init()
{
P0M1 = 0x00;
P0M0 = 0xff;
P2M1 = 0x00;
P2M0 = 0x08;
sbtLedSel = 0; //先选择数码管亮
}

/*---------延时函数---------*/
//下为生成1ms的延时函数,通过传入参数n,函数可以延时n毫秒
void delay_ms( uint n )
{
while( n )
{
uchar i, j;
i = 11;
j = 190;
do
{
while ( --j );
}
while ( --i );
n--;
}
}

/*---------主函数---------*/
void main()
{
Init();
while( 1 )
{
sbtLedSel = 0;
for( i = 0; i < 8; i++ )
{
P0 = 0;
P2 = arrDigitSelect[i]; //选择数码管的位数
P0 = arrSeg7Select[i + 1]; //显示对应的数值
delay_ms( 1 );
}
uiLedCnt++;
sbtLedSel = 1;
P0 = uiLed; //LED显示
delay_ms( 1 ); //延时200ms
if( uiLedCnt == 50 )
{
if( uiLed == 0x80 ) //value等于0x80时,重新赋初值0x01
uiLed = 0x01;
else
uiLed = uiLed << 1; //value值逐一左移
uiLedCnt = 0;
}
}
}