前后台系统,RTOS与定时器任务管理系统

前后台系统

  在裸机上写程序,通常把程序分为两部分:前台系统和后台系统。

  简单的小系统通常是前后台系统,这样的程序包括一个死循环和若干个中断服务程序:应用程序是一个无限循环,循环中调用API函数完成所需的操作,这个大循环就叫做后台系统。中断服务程序用于处理系统的异步事件,也就是前台系统。前台是中断级,后台是任务级。

写这个系统的目的:

  1. 为了能够充分利用cpu,不让他闲下来
  2. 可以实现多个功能同时发生

(前置条件):你需要知道只有一个cpu,他在物理的层面上是不可能同时发生的,但是他们可以欺骗人类,人类的视觉暂留有0.1s到0.4s
定时器分时操作系统-2024-04-19-23-10-06

  1. 只要这几个任务执行的频率足够高,那么对你而言,他们就是同时发生的.

  2. 第二个点就是(化delay为挂起).
    假设我们要执行一个跑马灯的操作,如果我们要设置他跑的慢一点,我们可以再他的每个灯显示后添加一个delay(time),但是在delay期间,我们的cpu是单纯的在等待,什么都没做. 于是我们可以设置一个时间任务,设置多少秒(只要设置和delay一样的时间就可以实现和delay一样的效果)而且在这些时间的间隔可以执行其他的任务

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    //原本的功能
    show(){
    SetLed(0,0);
    delay_ms(2);
    SetLed(1,1);
    delay_ms(2);
    SetLed(2,2);
    delay_ms(2);
    SetLed(3,3);
    delay_ms(2);
    }

    //修改后

    show(u8 w, u8 value){
    SetLed(w,value);
    }
    //每两秒执行一次
    per_2ms_conduct(){
    static int i = 0;
    show(i,i);
    }
    //这样子就没有delay出现了,你可以在同时执行其他的功能.

对于下面这部分的内容加了注解

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
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
//这个函数只做了一件事(时间到了,将flag标志置为1,表示可以做)
//这个Timer->uCount基于你设置的每次中断所消耗的时间,可以设置的很小,你可以自己调整
void updateTimerTask(TimerDef *Timer)

{

if (Timer->uCount >= 10) //0.5*10=5 ms到达

{

Timer->uCount = 0;



Timer->uFlag5ms = 1; //5 ms标志位置1

Timer->uCount10ms ++;

Timer->uCount50ms ++;

Timer->uCount100ms ++;

Timer->uCount1000ms ++;

}



if (Timer->uCount10ms >= 2)//10ms到达

{

Timer->uCount10ms = 0;

Timer->uFlag10ms = 1;

}

if (Timer->uCount50ms >= 10)//50ms到达

{

Timer->uCount50ms = 0;

Timer->uFlag50ms = 1;

}
}



时间任务管理

//大循环任务
//在大循环任务中放入你认为需要定时执行的耗时任务如(Per_5ms_tasks),在把这个大循环放在while(1)里头
void EverWhile_tasks()

{

}

//5ms 任务

void Per_5ms_tasks()

{

if(Timer.uFlag5ms != 1)//5ms未到达

return;//退出函数

task1();//用户函数

Timer.uFlag5ms = 0;//清空5ms标志位

}

//10ms 任务

void Per_10ms_tasks()

{

if(Timer.uFlag10ms != 1)

return;

task2();//用户函数

DIU.Timer.uFlag10ms = 0;

}

//50ms 任务

void Per_50ms_tasks()

{

if(Timer.uFlag50ms != 1)

return;

task3();//用户函数

Timer.uFlag50ms = 0;

}

//100ms 任务

void Per_100ms_tasks()

{

if(DIU.Timer.uFlag100ms != 1)

return;

task4();//用户函数

DIU.Timer.uFlag100ms = 0;// //

}

//1s 任务

void Per_1s_tasks()

{

if(DIU.Timer.uFlag1000ms != 1)

return;

task5();//用户函数

DIU.Timer.uFlag1000ms = 0;

}

以上,
你就可以实现:
例如(我每1ms执行一次显示任务,这样在我眼里他就是一直亮着的,
每3ms执行一次串口通信,每次访问完后都可以及时把内容输送给限时任务执行.
按键任务也是类似的(但是按键要考虑防抖问题,所以你设置的时间间隔需要有考究))

这个时候的cpu就和你一样,飞速运转,一点都没有闲着.