Preface
Not long ago, a friend of mine who was a tester switched to a development job. He encountered a question in the interview, and he didn't understand it, so he called me to ask. The question was roughly:
When developing a bare-metal microcontroller, the microcontroller has to handle multiple tasks. What is your program framework at this time?
This is actually a classic interview question, and I have been asked this question in interviews before.
Answer 1: Polling system
The code structure is as follows:
Swipe left and right to view all codes>>>
int main(void) { init_something(); while(1) { do_something1(); do_something2(); do_something3(); } }
This structure is probably the code structure when we first learn microcontrollers. It can be used better when there is no external event drive.
If you only answer this kind of question, your impression score will probably be low and you will most likely be a failure.
Answer 2: Front and back-end systems
The code structure is as follows (the code comes from the "RT-Thread Kernel Implementation and Application Development Practice Guide"):
Swipe left and right to view all codes>>>
int flag1 = 0; int flag2 = 0; int flag3 = 0; int main(void) { /* Hardware related initialization */ HardWareInit(); /* Infinite loop */ for (;;) { if (flag1) { /* Processing 1 */ DoSomething1(); } if (flag2) { /* Processing 2 */ DoSomethingg2(); } if (flag3) { /* Processing event 3 */ DoSomethingg3(); } } } void ISR1(void) { /* Set flag */ flag1 = 1; /* If the event processing time is very short, process it in the interrupt If the event processing time is long, return to the background processing */ DoSomething1(); } void ISR2(void) { /* Set flag */ flag2 = 2; /* If the event processing time is very short, process it in the interrupt If the event processing time is long, return to the background processing */ DoSomething2(); } void ISR3(void) { /* Set flag */ flag3 = 1; /* If the event processing time is very short, process it in the interrupt If the event processing time is long, return to the background processing */ DoSomething3(); }
Here, the interrupt is called the foreground, and the while loop in main is called the background. Compared with the loop system, this method can relatively improve the real-time response capability of external events.
If you can answer this question, you will get more than half of the impression points, and we will ask you in detail.
Answer 3: Upgraded front-end and back-end system (software timer method)
In the past, when I was learning C language, I often heard people say: pointers are the soul of C language, if you don’t learn pointers, you haven’t learned C language.
Later, when I was learning about single-chip microcomputers, I heard someone say: Interrupts and timers are the soul of single-chip microcomputers. If you don’t master interrupts and timers, you haven’t learned single-chip microcomputers.
The big guys have said that, so let's do something with the timer. Timers are full of treasures. In this note, we will introduce the bare metal framework made by using timers (system tick timers or other timers). There is another way to say the software timer method: time slice polling method.
If you can answer this question, you are likely to pass the interview.
Let's take the STM32 microcontroller as an example to see how this method is used.
Standing on the shoulders of giants
Open source project——MultiTimer, project repository address:
https://github.com/0x1abin/MultiTimer
1. Introduction to MultiTimer
MultiTimer is a software timer expansion module that can infinitely expand the timer tasks you need, replacing the traditional flag judgment method, and managing the program's time trigger timing more elegantly and conveniently.
2、MultiTimer的demo
Swipe left and right to view all codes>>>
#include "multi_timer.h" struct Timer timer1; struct Timer timer2; void timer1_callback() { printf("timer1 timeout!rn"); } void timer2_callback() { printf("timer2 timeout!rn"); } int main() { timer_init(&timer1, timer1_callback, 1000, 1000); //1s loop timer_start(&timer1); timer_init(&timer2, timer2_callback, 50, 0); //50ms delay timer_start(&timer2); while(1) { timer_loop(); } } void HAL_SYSTICK_Callback(void) { timer_ticks(); //1ms ticks }
3. Transplantation and analysis of MultiTimer
If you want to learn more about MultiTimer, you can read the project source code and the following article:
Issue 6 | MultiTimer, an infinitely scalable software timer
living comfortably without anybody's help
1. Code templates
Prepare a timer, which can be a system tick timer or a TIM timer, and use this timer to expand multiple software timers.
For example, our system has three tasks: LED flipping, temperature collection, and temperature display. At this time, we can use a hardware timer to expand three software timers and define the following macro definitions:
Swipe left and right to view all codes>>>
#define MAX_TIMER 3 // Maximum number of timers EXT volatile unsigned long g_Timer1[MAX_TIMER]; #define LedTimer g_Timer1[0] // LED flip timer #define GetTemperatureTimer g_Timer1[1] // Temperature acquisition timer #define SendToLcdTimer g_Timer1[2] // Temperature display timer #define TIMER1_SEC (1) // 秒 #define TIMER1_MIN (TIMER1_SEC*60) // 分
When the timer is initialized, the three software timers are also initialized:
Swipe left and right to view all codes>>>
/******************************************************************************************************** ** Function: TIM1_Init, general timer 1 initialization **------------------------------------------------------------------------------------------------------ ** Parameters: arr: auto-reload value psc: clock pre-scaling number ** Note: Timer overflow time calculation method: Tout=((arr+1)*(psc+1))/Ft ** Returns: void ********************************************************************************************************/ void TIM1_Init(uint16_t arr, uint16_t psc) { TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure; NVIC_InitTypeDef NVIC_InitStructure; RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM1, ENABLE); /* Timer TIM1 initialization */ TIM_TimeBaseStructure.TIM_Period = arr; TIM_TimeBaseStructure.TIM_Prescaler =psc; TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1; TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; TIM_TimeBaseStructure.TIM_RepetitionCounter=0; TIM_TimeBaseInit(TIM1, &TIM_TimeBaseStructure); TIM_ClearFlag(TIM1,TIM_FLAG_Update ); /* Interrupt enable */ TIM_ITConfig(TIM1,TIM_IT_Update, ENABLE ); /* Interrupt priority NVIC setting */ NVIC_InitStructure.NVIC_IRQChannel = TIM1_UP_IRQn; NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1; NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; NVIC_Init(&NVIC_InitStructure); TIM_Cmd(TIM1, ENABLE); // Initialize the global timer for(int i = 0; i < MAX_TIMER; i++) { g_Timer1[i] = 0; } }
In the timer interrupt, the timing values of these software timers are decremented:
Swipe left and right to view all codes>>>
/******************************************************************************************************** ** Function: TIM1_IRQHandler, Timer 1 interrupt service routine **------------------------------------------------------------------------------------------------------ ** Parameters: None ** Return: None ********************************************************************************************************/ void TIM1_UP_IRQHandler(void) //TIM1 interrupt { uint8 i; if (TIM_GetITStatus(TIM1, TIM_IT_Update) != RESET) // Check whether TIM1 update interrupt occurs { //------------------------------------------------------------------------------- // Various timers timing for (i = 0; i < MAX_TIMER; i++) // Timer time decreases if( g_Timer1[i] ) g_Timer1[i]-- ; TIM_ClearITPendingBit(TIM1, TIM_IT_Update); //Clear TIMx update interrupt flag } }
We assign timing values to these software timers in each scheduled task. When these timing values decrease to 0, the task will be triggered to execute, for example:
Swipe left and right to view all codes>>>
void Task_Led(void) { //---------------------------------------------------------------- // Wait for the timing time if(LedTimer) return; LedTimer = 1 * TIMER1_SEC; //---------------------------------------------------------------- //LED task body LedToggle(); } void Task_GetTemperature(void) { //---------------------------------------------------------------- // Wait for the timing time if(LedTimer) return; LedTimer = 2 * TIMER1_SEC; //---------------------------------------------------------------- // Temperature collection task body GetTemperature(); } void Task_SendToLcd(void) { //---------------------------------------------------------------- // Wait for the timing time if(LedTimer) return; LedTimer = 2 * TIMER1_SEC; //---------------------------------------------------------------- // Temperature display task body LcdDisplay(); }
In this way, the LED flipping task, temperature collection task, and temperature display task are triggered every 1, 2, and 4 seconds respectively.
The minimum timing unit configured here is 1 second. Of course, it should be configured according to actual needs (timer initialization). Timer initialization can be placed in the system unified initialization function:
Swipe left and right to view all codes>>>
/******************************************************************************************************** ** Function: SysInit, system power-on initialization **------------------------------------------------------------------------------------------------------ ** Parameters: ** illustrate: ** return: ********************************************************************************************************/ void SysInit(void) { CpuInit(); //Configure system information function SysTickInit(); // System tick timer initialization function UsartInit(115200); //Serial port initialization function, baud rate 115200 TIM1_Init(2000-1, 36000-1); // Timing period 1s LedInit(); // Led initialization TemperatureInit(); // Temperature sensor initialization LcdInit(); // LCD initialization }
Previous article:How to distinguish byte transfer and bit transfer in microcontroller instructions
Next article:MCU I/O control method (difference between UART interrupt and DMA interrupt)
- Popular Resources
- Popular amplifiers
Professor at Beihang University, dedicated to promoting microcontrollers and embedded systems for over 20 years.
- LED chemical incompatibility test to see which chemicals LEDs can be used with
- Application of ARM9 hardware coprocessor on WinCE embedded motherboard
- What are the key points for selecting rotor flowmeter?
- LM317 high power charger circuit
- A brief analysis of Embest's application and development of embedded medical devices
- Single-phase RC protection circuit
- stm32 PVD programmable voltage monitor
- Introduction and measurement of edge trigger and level trigger of 51 single chip microcomputer
- Improved design of Linux system software shell protection technology
- What to do if the ABB robot protection device stops
- Keysight Technologies Helps Samsung Electronics Successfully Validate FiRa® 2.0 Safe Distance Measurement Test Case
- Innovation is not limited to Meizhi, Welling will appear at the 2024 China Home Appliance Technology Conference
- Innovation is not limited to Meizhi, Welling will appear at the 2024 China Home Appliance Technology Conference
- Huawei's Strategic Department Director Gai Gang: The cumulative installed base of open source Euler operating system exceeds 10 million sets
- Download from the Internet--ARM Getting Started Notes
- Learn ARM development(22)
- Learn ARM development(21)
- Learn ARM development(20)
- Learn ARM development(19)
- Learn ARM development(14)
- EEWORLD University - Key Considerations for Isolated CAN Transceivers
- Looking for chips or modules---infrared photoelectric sensor switch, infrared human body sensor switch, gravity sensor switch
- Hiring embedded engineers
- 【Recruitment】Embedded Engineer Recruitment
- Application of Dacai UART screen in smart filing cabinet
- Optimizing DSP Power Budget by Adjusting Voltage Regulators
- MSP430 Series MCU System Engineering Design and Practice Source Code and PDF e-book download
- position2Go Review 3. Resources
- Please help me find out what circuit the box in the attached picture is.
- New content for the Dragon Boat Festival Core Points redemption! Selected Zongzi for everyone to redeem!