裸机程序的设计模式可以分为:轮询、前后台、定时器驱动、基于状态机。前面三种方法都无法解决一个问题:假设有A、B两个都很耗时的函数,无法降低他们互相之间的影响。第4中方法可以解决这个问题,但是实践起来有难度。
1、轮询模式
// 经典单片机程序: 轮询
02 void main()
03 {
04 while (1)
05 {
06 喂一口饭();
07 回一个信息();
08 }
09 }
while循环里有两个函数,这两个函数之间有影响,一个函数运行时间较长,另一个函数就迟迟无法运行。
2、前后台
所谓前后台,就是指使用中断程序。
// 前后台程序
02 void main()
03 {
04 while (1)
05 {
06 // 后台程序
07 喂一口饭();
08 }
09 }
10
11 // 前台程序
12 void 滴_中断()
13 {
14 回一个信息();
15 }
while循环里面的是后台程序,中断里是前台程序,中断程序的执行是非常及时的,但是如果中断函数执行很长,就会造成后台程序运行不及时。
// 前后台程序
02 void main()
03 {
04 while (1)
05 {
06 // 后台程序
07 }
08 }
09
10 // 前台程序
11 void 滴_中断()
12 {
13 回一个信息();
14 }
15
16 // 前台程序
17 void 啊_中断()
18 {
19 喂一口饭();
20 }
改进后,将两个程序都写成前台程序(中断程序),但是如果两个程序同时需要执行,那么就会受影响。
3、定时器驱动
定时器驱动模式,是前后台模式的一种,可以按照不用的频率执行各种函数。比如需要
每 2 分钟给小孩喂一口饭,需要每 5 分钟给同事回复信息。那么就可以启动一个定时器,让
它每 1 分钟产生一次中断,让中断函数在合适的时间调用对应函数。示例代码如下:
// 前后台程序: 定时器驱动
02 void main()
03 {
04 while (1)
05 {
06 // 后台程序
07 }
08 }
09
10 // 前台程序: 每 1 分钟触发一次中断
11 void 定时器_中断()
12 {
13 static int cnt = 0;
14 cnt++;
15 if (cnt % 2 == 0)
16 {
17 喂一口饭();
18 }
19 else if (cnt % 5 == 0)
20 {
21 回一个信息();
22 }
23 }
每发生2次中断,就执行一次喂饭程序,每发生5次中断,就执行一次回一个信息。这种模式适合调用周期性的函数,并且每一个函数执行的时间不能超过一个定时器周期。如果函数执行时间超过定时器周期,那么函数之间就会受影响。
4、基于状态机
当“喂一口饭”、“回一个信息”都需要花很长的时间,无论使用前面的哪种设计模式,
都会退化到轮询模式的缺点:函数相互之间有影响。可以使用状态机来解决这个缺点,示例
代码如下:
// 状态机
02 void main()
03 {
04 while (1)
05 {
06 喂一口饭();
07 回一个信息();
08 }
09 }
01 void 喂一口饭(void)
02 {
03 static int state = 0;
04 switch (state)
05 {
06 case 0:
07 {
08 /* 舀饭 */
09 /* 进入下一个状态 */
10 state++;
11 break;
12 }
13 case 1:
14 {
15 /* 喂饭 */
16 /* 进入下一个状态 */
17 state++;
18 break;
19 }
20 case 2:
21 {
22 /* 舀菜 */
23 /* 进入下一个状态 */
24 state++;
25 break;
26 }
27 case 3:
28 {
29 /* 喂菜 */
30 /* 恢复到初始状态 */
31 state = 0;
32 break;
33 }
34 }
35 }
36
37 void 回一个信息(void)
38 {
39 static int state = 0;
40
41 switch (state)
42 {
43 case 0:
44 {
45 /* 查看信息 */
46 /* 进入下一个状态 */
47 state++;
48 break;
49 }
50 case 1:
51 {
52 /* 打字 */
53 /* 进入下一个状态 */
54 state++;
55 break;
56 }
57 case 2:
58 {
59 /* 发送 */
60 /* 恢复到初始状态 */
61 state = 0;
62 break;
63 }
64 }
65 }
使用状态机模式,可以解决裸机程序的难题:假设有 A、 B 两个都很耗时的函数,怎样
降低它们相互之间的影响。但是很多场景里,函数 A、 B 并不容易拆分为多个状态,并且这
些状态执行的时间并不好控制。所以这并不是最优的解决方法,需要使用多任务系统。