Write in the front: it's purely personal opinion. If you don't agree, you're right! If it helps you, congratulations.
Introduction to embedded MCU programming - Thinking
Following the above, thinking is the foundation. On the basis of thinking, it will be easier to understand the structure. If you haven't read the previous article, you can take a few minutes to read the above to better understand this article.
First set up a Flag. The function of program architecture is to make the thinking more organized, and make the program easy to read, transplant and inherit. You can write programs without architecture, run well, and make products, which is easy to make others' eggs hurt. After a long time, if you pick up the ancestral code, it will hurt yourself. Therefore, it is best for beginners to learn architecture at the beginning, and the road will be much smoother in the future.
Let's start with thinking. The first part said that any program is discretized in time. Let's discretize it regularly, that is, the architecture. In short, it is the regular and periodic execution.
On this basis, there are two branches. There is no difference between good and bad. It depends on which one you are happy to choose. One is heavy event, which is called event driven; One is retiming, which is called timing drive. No matter which architecture, there is a basic time timer. We are very familiar with it. The commonly used one is 1ms. The differences between the two are explained in detail below:
1, Event driven: it means that each task counts and cycles independently. It is mainly based on task classification, and each task processes the cycle according to its own time interval. The advantage is that the events are independent without considering the impact between tasks.
2, Timing drive: process various tasks in priority order at several special time intervals. Tasks are classified by processing time interval. For example, all tasks with an interval of 20ms are processed together in order, and tasks with an interval of 100ms are processed together in order. The advantage is that at a certain time node, the tasks are processed centrally, the synchronization is relatively strong, and the subsequent time can be directly dormant, which is more suitable for low-power occasions. The disadvantage is that the order of precedence will cause some coverage, which needs to be avoided.
First explain with examples, and then code.
For example, there is an LED flashing task and a key scanning task.
The event driven processing method is that the time base of 1ms is reached, and each task is executed once. LED flashing task has a timing accumulator, which is off when it reaches 500, on when it reaches 1000, and then cleared. Keep cycling like this. The key scanning task also has an accumulator. When it reaches 20, it performs a scanning, and then the counter is cleared. It keeps cycling like this.
The processing method of timing drive is 1ms time base. According to this time base, there is a timing accumulator. When the accumulator is divided by 20, there is a 20ms mark, when it is divided by 500, there is a 500ms mark, and when it is divided by 1000, there is a 1s mark, and the timing accumulator is cleared at the same time. Put the key scanning task under the 20ms mark. Under the 500ms mark, put in the off led command, and under the 1s mark, put in the on LED command.
Both achieve the same effect. The literal expression is rather obscure and is coded.
Event driven schema Code:
LED_Flash_Event(void) { static uint16_t led_timer_counter; if(led_1ms_flag) { led_1ms_flag = 0; led_timer_counter++; if(led_timer_counter>=1000) led_timer_counter = 0; if(led_timer_counter<500) LED1_TURNON(); if(led_timer_counter<1000) LED1_TURNOFF(); } } void main(void) { Init(); while(1) { Intrrupt_Process(); LED_Flash_Event(); KEY_Scan_Event(); Sensor_Collent_Event(); } }
In the above code, if the timer interrupts and sets the flag of 1ms, the code will not be pasted. Just understand. This is the common architecture of event driven, which is roughly the same.
The timing drive architecture code is as follows:
void main(void) { static uint8_t TimerCounter; Init(); while(1) { Intrrupt_Process(); if(TimerFlag&TIMER_20MS_FLAG) { TimerFlag&=~TIMER_20MS_FLAG; TimerCounter++; if(TimerCounter>=50) TimerCounter= 0; if(0=(TimerCounter%5)) TimerFlag|=TIMER_100MS_FLAG; if(0=(TimerCounter%25)) TimerFlag|=TIMER_500MS_FLAG; if(0=(TimerCounter%50)) TimerFlag|=TIMER_1000MS_FLAG; { //20ms loop KEY_Scan_Event(); Sensor_Collent_Event(); } if(TimerFlag&TIMER_100MS_FLAG) { TimerFlag&=~TIMER_100MS_FLAG; LED_Flash_Event(); Sensor_Process_Event(); } if(TimerFlag&TIMER_500MS_FLAG) { TimerFlag&=~TIMER_500MS_FLAG; } if(TimerFlag&TIMER_1000MS_FLAG) { TimerFlag&=~TIMER_1000MS_FLAG; RTC_Timer_Process(); } } Enter_Sleep(); } }
The timing driven framework, such as the above code, can be improved by ourselves. I prefer to use the timing driven framework, because I know that the architecture of the assembly is the same as this. If I write it according to this framework, the program flow is very clear and easy to read. When it comes to low power consumption, this framework is also very comfortable.
This is the bare metal framework. The real-time operating system program is also a similar framework. It can combine events with timing drive. For unique events, events drive you to do a task. For others that are not very important, use a task to make a minimum time base and do it with timing drive.
This is probably the case with the framework. The other is how to fit in. It is suggested that beginners must use the framework to program. Don't write a program to the end. All kinds of tasks are mixed together. At that time, it can't be changed. It's not easy to transplant.