裸机程序设计模式

裸机程序的设计模式可以分为:轮询、前后台、定时器驱动、基于状态机。前面三种方法都无法解决一个问题:假设有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 并不容易拆分为多个状态,并且这
些状态执行的时间并不好控制。所以这并不是最优的解决方法,需要使用多任务系统。
 

上一篇:【Java】单例设计模式-2.单例设计模式设计方法


下一篇:算法金 | LSTM 原作者带队,一个强大的算法模型杀回来了