
The time-slice polling method is often mentioned alongside operating systems, meaning it is frequently used in operating systems:RTOS in STM32 microcontroller development. The following will reference others’ code to demonstrate how to establish a time-slice polling architecture program.Timer Reuse Executing other functions while one function is delayed makes full use of CPU time, doesn’t it resemble an operating system? The delay here is implemented using a timer, and we will first introduce the timer reuse function. Using one timer, which can be any timer, we will not specify further. Assuming there are three tasks, we should do the following:1 Initialize the Timer Here we assume the timer’sinterrupt period is 1ms. Of course, you can change it to 10ms; similar to operating systems, if interrupts are too frequent, efficiency decreases, and if interrupts are too long, real-time performance suffers.2 Define a Value:
#define TASK_NUM (3) // The number of tasks defined here is 3, indicating that three tasks will use this timer for timing. uint16 TaskCount[TASK_NUM]; // Here we define three variables to store timing values for the three tasks uint8 TaskMark[TASK_NUM]; // Similarly, three flags corresponding to the three tasks, 0 indicates time not reached, 1 indicates timing completed.
3 Add in the Timer Interrupt Service Function:
Code Explanation: The timer interrupt service function checks each task one by one; if the timing value is 0, it indicates that this timer is not being used or has completed its timing, and no action is taken. Otherwise, the timer decrements until it reaches zero, at which point the corresponding flag is set to 1, indicating that the timing for this task has been reached.4 In our application program, add the following code where timing is needed: Below is an example for task 1.
TaskCount[0] = 20; // Delay 20ms TaskMark[0] = 0x00; // Start the timer for this task
At this point, we only need to check if TaskMark[0] is 0x01 in the task. Other tasks can be added similarly, thus achieving the reuse of a single timer. Friends who need it can give it a try; the effect is good. From the above, we can see that while waiting for a timer to arrive, we can loop to check the flag and also execute other functions.Establishing the Time-Slice Polling Architecture The following will detail the implementation process of the time-slice polling method.1 Design a Structure:
// Task Structure typedef struct _TASK_COMPONENTS{ uint8 Run; // Program running flag: 0-not running, 1-running uint8 Timer; // Timer uint8 ItvTime; // Task running interval time void (*TaskHook)(void); // Task function to run} TASK_COMPONENTS; // Task definition
2 Task Flag Processing The task flag processing function is equivalent to the interrupt service function and needs to be called in the timer’s interrupt service function.
3 Task Processing:
/********************************************************* FunctionName : TaskProcess()* Description : Task processing* EntryParameter : None* ReturnValue : None*********************************************************/void TaskProcess(void){ uint8 i; for (i=0; i < TASKS_MAX; i++) // Process each task's timing { if (TaskComps[i].Run) // Time is not 0 { TaskComps[i].TaskHook(); // Run task TaskComps[i].Run = 0; // Clear flag to 0 } }}
This function determines when to execute which task, managing the tasks. The user only needs to call this function in the main() function without needing to call and handle each task function separately. Thus, a time-slice polling application program architecture is established, requiring only two functions and one structure. For convenience, we will also establish anenumerationvariable.Application of the Time-Slice Polling Architecture Assume we have three tasks: clock display, key scanning, and working status display.1 Define a Structure Variable:
/********************************************************* Variable definition *********************************************************/static TASK_COMPONENTS TaskComps[] = { {0, 60, 60, TaskDisplayClock}, // Display clock {0, 20, 20, TaskKeySan}, // Key scanning {0, 30, 30, TaskDispStatus}, // Display working status // Add your tasks here....};
When defining the structure variable, we have already initialized the values, which relate to specific execution time priorities, etc. Here are three tasks, and the four elements in the structure are the program running flag, timer, running time interval, and task function name.2 Task List:
// Task List typedef enum _TASK_LIST{ TAST_DISP_CLOCK, // Display clock TAST_KEY_SAN, // Key scanning TASK_DISP_WS, // Display working status // Add your tasks here.... TASKS_MAX // Total number of available timed tasks} TASK_LIST;
The defined task list, except for the value of TASKS_MAX, has no specific meaning; it is only to clearly indicate the relationship between tasks.3 Write Task Functions:
/******************************************************** FunctionName : TaskDisplayClock()* Description : Display task* EntryParameter : None* ReturnValue : None********************************************************/void TaskDisplayClock(void){}/******************************************************** FunctionName : TaskKeySan()* Description : Scan task* EntryParameter : None* ReturnValue : None********************************************************/void TaskKeySan(void){}/******************************************************** FunctionName : TaskDispStatus()* Description : Display working status* EntryParameter : None* ReturnValue : None********************************************************/void TaskDispStatus(void){}// Add other tasks here....
Now you can write tasks according to your needs.4 Main Function:
/******************************************************** FunctionName : main()* Description : Main function* EntryParameter : None* ReturnValue : None********************************************************/int main(void) { InitSys(); // Initialize while (1) { TaskProcess(); // Task processing function }}
The main function is simple; it just needs to execute the task processing function in a loop. Two points to note:
-
Data transfer between tasks should use global variables.
-
Reasonably divide tasks and their execution times to ensure tasks complete quickly, avoiding congestion.


Some screenshots from electronic books

Some screenshots from courseware PPTs

【Complete Set of Hardware Learning Materials】
