HAL STM32基于系統(tǒng)滴答定時(shí)器(SysTick)實(shí)現(xiàn)多任務(wù)時(shí)間片輪詢
??RTOS(實(shí)時(shí)操作系統(tǒng))和定時(shí)器時(shí)間片輪詢是兩種不同的任務(wù)調(diào)度和執(zhí)行方式的差異簡(jiǎn)介
?? 以下部分內(nèi)容,由AI給出的解答:
- ??RTOS(實(shí)時(shí)操作系統(tǒng)):
- ??RTOS是一種專(zhuān)門(mén)設(shè)計(jì)用于實(shí)時(shí)系統(tǒng)的操作系統(tǒng),它可以有效地管理多個(gè)任務(wù),提供任務(wù)調(diào)度、同步和通信等功能。
- ??STM32可以使用多種RTOS,例如FreeRTOS、ChibiOS等,它們都提供了任務(wù)管理、信號(hào)量、消息隊(duì)列等功能。
- ??在RTOS中,每個(gè)任務(wù)都有自己的優(yōu)先級(jí),并且RTOS會(huì)根據(jù)任務(wù)的優(yōu)先級(jí)進(jìn)行調(diào)度。高優(yōu)先級(jí)的任務(wù)將獲得更多的CPU時(shí)間。
- ??RTOS提供了更結(jié)構(gòu)化的任務(wù)管理,使得編寫(xiě)和維護(hù)多任務(wù)應(yīng)用程序變得更容易。
- ??定時(shí)器時(shí)間片輪詢:
- ??定時(shí)器時(shí)間片輪詢是一種基于定時(shí)器中斷的任務(wù)調(diào)度方法,而不涉及RTOS的復(fù)雜性。
- ??在這種方法中,任務(wù)的執(zhí)行由定時(shí)器中斷觸發(fā),每個(gè)任務(wù)都有一個(gè)預(yù)定的時(shí)間片來(lái)執(zhí)行。
- ??當(dāng)定時(shí)器觸發(fā)時(shí),控制權(quán)將轉(zhuǎn)移到下一個(gè)任務(wù),如果當(dāng)前任務(wù)沒(méi)有執(zhí)行完,它將在下一個(gè)時(shí)間片繼續(xù)執(zhí)行。
- ??這種方式的調(diào)度對(duì)于簡(jiǎn)單的應(yīng)用來(lái)說(shuō)可能足夠,但在復(fù)雜的多任務(wù)系統(tǒng)中,可能會(huì)導(dǎo)致任務(wù)之間的優(yōu)先級(jí)管理和調(diào)度變得復(fù)雜。
- ??演示運(yùn)行效果:
??STM32CubeMX工程配置
- ??在STM32CubeMX配置工程時(shí),系統(tǒng)時(shí)基是默認(rèn)配置的SysTick定時(shí)器。
- ??軟件默認(rèn)配置的系統(tǒng)滴答定時(shí)器的優(yōu)先級(jí)是最低的,可以根據(jù)個(gè)人使用情況,進(jìn)行調(diào)整。
- ??其他外設(shè)使用可以根據(jù)個(gè)人需求配置。
?業(yè)務(wù)代碼完善
-
?STM32CubeMX所創(chuàng)建的工程,系統(tǒng)滴答定時(shí)器默認(rèn)是沒(méi)有啟用中斷的需要自行添加和補(bǔ)充。
-
??滴答定時(shí)器中斷回調(diào)函數(shù)完善。
void HAL_SYSTICK_Callback(void)
{
Sys_Tick_Count();
}
??時(shí)間片輪詢驅(qū)動(dòng)
-
??時(shí)間片輪詢,主要有3部分組成:時(shí)基(sys_time)、任務(wù)管理(sys_task)、任務(wù)對(duì)象(TASK)組成:
-
文章來(lái)源:http://www.zghlxwxcb.cn/news/detail-833462.html
-
??sys_time.c文章來(lái)源地址http://www.zghlxwxcb.cn/news/detail-833462.html
#include "sys_time.h"
static unsigned short int sys_tick = 0;
/**
* @brief 系統(tǒng)時(shí)基
*
*/
void Sys_Tick_Count(void)
{
sys_tick += 1;
}
/**
* @description: 獲取系統(tǒng)滴答計(jì)時(shí)
* @param {*}
* @return {*}
*/
unsigned short int Get_Sys_Tick()
{
return sys_tick;
}
/**
* @description: 判斷是否超時(shí)
* @param {unsigned long int} start 計(jì)算開(kāi)始的時(shí)間
* @param {unsigned long int} timeout 超時(shí)時(shí)長(zhǎng)
* @return {*}
*/
unsigned short int Is_Timeout(unsigned short int start, unsigned short int timeout)
{
return ((unsigned short int)(Get_Sys_Tick() - start)) > timeout ? 1: 0;
}
- ??sys_task.c
#include "sys_task.h"
#include "sys_time.h"
#include "string.h"
sys_task_t *sys_task_head = NULL;
/**
* @brief 系統(tǒng)任務(wù)
*
* @param task 任務(wù)
* @param handler 任務(wù)輪詢函數(shù)
* @param interval 輪詢間隔
*/
void sys_task_create(sys_task_t *task, void (*handler)(void), unsigned int interval)
{
sys_task_t *sys_task_tail = NULL;
memset(task, 0, sizeof(sys_task_t));
task->enable = 0;
task->interval = interval;
task->tick_cnt = Get_Sys_Tick();
task->task_handler = handler;
task->sys_task_next = NULL;
if (sys_task_head == NULL)
{
sys_task_head = task;
return ;
}
sys_task_tail = sys_task_head;
while (sys_task_tail->sys_task_next != NULL)
{
sys_task_tail = sys_task_tail->sys_task_next;
}
sys_task_tail->sys_task_next = task;
}
/**
* @brief 啟動(dòng)任務(wù)
*
* @param task 任務(wù)句柄
*/
void sys_task_start(sys_task_t *task)
{
task->enable = 1;
}
/**
* @brief 停止任務(wù)
*
* @param task 任務(wù)句柄
*/
void sys_task_stop(sys_task_t *task)
{
task->enable = 0;
}
/**
* @brief 系統(tǒng)任務(wù)輪詢
*
*/
void sys_task_process()
{
sys_task_t *task = NULL;
for (task = sys_task_head; task != NULL; task = task->sys_task_next)
{
if (task->enable && Is_Timeout(task->tick_cnt, task->interval))
{
task->task_handler(); // 運(yùn)行
task->tick_cnt = Get_Sys_Tick();
}
}
}
- ??Blink_TASK.c:(具體執(zhí)行的任務(wù)可以根據(jù)個(gè)人實(shí)際使用進(jìn)行添加配置,這里以驅(qū)動(dòng)3個(gè)led對(duì)象為例)
#include "Blink_TASK.h"
#include "usb_printf.h"
void Blink_Task1(void){
HAL_GPIO_TogglePin(LED_GPIO_Port, LED_Pin);
usb_printf("This Blink_Task1\r\n");
HAL_Delay(1000);
}
void Blink_Task2(void){
HAL_GPIO_TogglePin(LED2_GPIO_Port, LED2_Pin);
usb_printf("This Blink_Task2\r\n");
HAL_Delay(800);
}
void Blink_Task3(void){
HAL_GPIO_TogglePin(LED3_GPIO_Port, LED3_Pin);
usb_printf("This Blink_Task3\r\n");
HAL_Delay(600);
}
- main.c中的內(nèi)容:
- ??添加所需運(yùn)行的任務(wù)句柄,需要運(yùn)行多少個(gè)任務(wù)就創(chuàng)建多少個(gè)對(duì)象。
// 控制LED1任務(wù)
sys_task_t Task1_Blink;
// 控制LED2任務(wù)
sys_task_t Task2_Blink;
// 控制LED3任務(wù)
sys_task_t Task3_Blink;
- ??創(chuàng)建任務(wù)對(duì)象
void task_start()
{
sys_task_create(&Task1_Blink, Blink_Task1, 50);
sys_task_start(&Task1_Blink);
sys_task_create(&Task2_Blink, Blink_Task2, 20);
sys_task_start(&Task2_Blink);
sys_task_create(&Task3_Blink, Blink_Task3, 30);
sys_task_start(&Task3_Blink);
}
- ??main.c所有代碼
/* USER CODE BEGIN Header */
/**
******************************************************************************
* @file : main.c
* @brief : Main program body
******************************************************************************
* @attention
*
* Copyright (c) 2024 STMicroelectronics.
* All rights reserved.
*
* This software is licensed under terms that can be found in the LICENSE file
* in the root directory of this software component.
* If no LICENSE file comes with this software, it is provided AS-IS.
*
******************************************************************************
*/
/* USER CODE END Header */
/* Includes ------------------------------------------------------------------*/
#include "main.h"
#include "usart.h"
#include "usb_device.h"
#include "gpio.h"
/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
#include "usb_printf.h"
//Timer Task Manage
#include "sys_time.h"
#include "sys_task.h"
#include "Blink_TASK.h"
/* USER CODE END Includes */
/* Private typedef -----------------------------------------------------------*/
/* USER CODE BEGIN PTD */
/* USER CODE END PTD */
/* Private define ------------------------------------------------------------*/
/* USER CODE BEGIN PD */
/* USER CODE END PD */
/* Private macro -------------------------------------------------------------*/
/* USER CODE BEGIN PM */
/* USER CODE END PM */
/* Private variables ---------------------------------------------------------*/
/* USER CODE BEGIN PV */
// 控制LED1任務(wù)
sys_task_t Task1_Blink;
// 控制LED2任務(wù)
sys_task_t Task2_Blink;
// 控制LED3任務(wù)
sys_task_t Task3_Blink;
/* USER CODE END PV */
/* Private function prototypes -----------------------------------------------*/
void SystemClock_Config(void);
/* USER CODE BEGIN PFP */
/* USER CODE END PFP */
/* Private user code ---------------------------------------------------------*/
/* USER CODE BEGIN 0 */
// 任務(wù)創(chuàng)建
void task_start()
{
sys_task_create(&Task1_Blink, Blink_Task1, 50);
sys_task_start(&Task1_Blink);
sys_task_create(&Task2_Blink, Blink_Task2, 20);
sys_task_start(&Task2_Blink);
sys_task_create(&Task3_Blink, Blink_Task3, 30);
sys_task_start(&Task3_Blink);
}
/* USER CODE END 0 */
/**
* @brief The application entry point.
* @retval int
*/
int main(void)
{
/* USER CODE BEGIN 1 */
/* USER CODE END 1 */
/* MCU Configuration--------------------------------------------------------*/
/* Reset of all peripherals, Initializes the Flash interface and the Systick. */
HAL_Init();
/* USER CODE BEGIN Init */
/* USER CODE END Init */
/* Configure the system clock */
SystemClock_Config();
/* USER CODE BEGIN SysInit */
/* USER CODE END SysInit */
/* Initialize all configured peripherals */
MX_GPIO_Init();
MX_USART1_UART_Init();
MX_USB_DEVICE_Init();
/* USER CODE BEGIN 2 */
uint32_t Main_Fosc = HAL_RCC_GetSysClockFreq();
// HAL_GetTick();
usb_printf("Main_Fosc:%d \r\n", Main_Fosc);
task_start();
/* USER CODE END 2 */
/* Infinite loop */
/* USER CODE BEGIN WHILE */
while(1) {
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
sys_task_process();
}
/* USER CODE END 3 */
}
/**
* @brief System Clock Configuration
* @retval None
*/
void SystemClock_Config(void)
{
RCC_OscInitTypeDef RCC_OscInitStruct = {0};
RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};
/** Configure the main internal regulator output voltage
*/
__HAL_RCC_PWR_CLK_ENABLE();
__HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE2);
/** Initializes the RCC Oscillators according to the specified parameters
* in the RCC_OscInitTypeDef structure.
*/
RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;
RCC_OscInitStruct.HSEState = RCC_HSE_ON;
RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
RCC_OscInitStruct.PLL.PLLM = 4;
RCC_OscInitStruct.PLL.PLLN = 168;
RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV4;
RCC_OscInitStruct.PLL.PLLQ = 7;
if(HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK) {
Error_Handler();
}
/** Initializes the CPU, AHB and APB buses clocks
*/
RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK | RCC_CLOCKTYPE_SYSCLK
| RCC_CLOCKTYPE_PCLK1 | RCC_CLOCKTYPE_PCLK2;
RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV2;
RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;
if(HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_2) != HAL_OK) {
Error_Handler();
}
}
/* USER CODE BEGIN 4 */
void HAL_SYSTICK_Callback(void)
{
Sys_Tick_Count();
}
/* USER CODE END 4 */
/**
* @brief This function is executed in case of error occurrence.
* @retval None
*/
void Error_Handler(void)
{
/* USER CODE BEGIN Error_Handler_Debug */
/* User can add his own implementation to report the HAL error return state */
__disable_irq();
while(1) {
}
/* USER CODE END Error_Handler_Debug */
}
#ifdef USE_FULL_ASSERT
/**
* @brief Reports the name of the source file and the source line number
* where the assert_param error has occurred.
* @param file: pointer to the source file name
* @param line: assert_param error line source number
* @retval None
*/
void assert_failed(uint8_t *file, uint32_t line)
{
/* USER CODE BEGIN 6 */
/* User can add his own implementation to report the file name and line number,
ex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */
/* USER CODE END 6 */
}
#endif /* USE_FULL_ASSERT */
- ??本示例中所使用的是USB CDC作為調(diào)試信息輸出,
usb_printf.c、h
代碼:
#include "usb_printf.h"
void usb_printf(const char *fmt, ...) {
char buf[128];//自定義緩沖區(qū)大小
va_list args;
va_start(args, fmt);
vsnprintf(buf, sizeof(buf), fmt, args);
va_end(args);
CDC_Transmit_FS((uint8_t *)buf, strlen(buf));
}
#ifndef _USB_PRINTF_H
#define _USB_PRINTF_H
#include "stdio.h"
#include <stdarg.h>
#include "usbd_cdc_if.h"
void usb_printf(const char *fmt, ...);
#endif
??示例工程源碼
- ??基于stm32f401創(chuàng)建。固件版本:
STM32Cube FW_F4 V1.28.0
鏈接:https://pan.baidu.com/s/1ouPVpfv9E_2paunmgrOMRg?pwd=r3xk
提取碼:r3xk
到了這里,關(guān)于HAL STM32基于系統(tǒng)滴答定時(shí)器(SysTick)實(shí)現(xiàn)多任務(wù)時(shí)間片輪詢的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!