基于CubeMX+STM32的简单任务调度的实现

概要

CubeMX STM32 SystemTimer 简单任务调度

本文主要介绍一下使用CubeMX+Stm32芯片运行简单的任务调度系统的实现过程。

STM32中任务调度的意义

1、提高系统实时性
定时任务调度允许STM32以精确的时间间隔执行特定任务,满足实时系统的严格要求。例如,在工业控制中,传感器数据采集和电机控制需要严格的时间同步,定时调度确保这些任务按时执行,避免延迟导致的系统不稳定。

2、优化资源利用率
通过合理调度任务,STM32可以避免CPU资源浪费。空闲时间可用于低优先级任务或进入低功耗模式,从而提升整体能效。例如,在电池供电设备中,定时唤醒和任务调度可显著延长电池寿命。

3、简化复杂任务管理
对于多任务系统,定时调度器(如FreeRTOS的定时器功能)能简化任务协调。周期性任务(如数据上传、状态检测)无需手动管理时序,只需配置调度器即可自动执行,降低代码复杂度。

实现思路

硬件定时器配置
使用STM32的硬件定时器(如SystemTimer)配合HAL库实现任务调度。配置定时器基础中断频率(如1ms),在中断回调函数或main函数中维护任务队列。

CubeMX配置图

如图所示,正常配置时钟树和系统定时器即可。

在这里插入图片描述
在这里插入图片描述

代码实现

Task.c

/****************************************************************************************
* @file         Task.c
* @brief        时间片轮询
* @author       lwz
* @date         2025/10/24
* @version      V1.0.0
* @note         
****************************************************************************************/
/*头文件添加区*/
#include "Task.h"

/*宏定义定义区*/

/*外部变量引用区*/

/*全局变量定义区*/
TaskList g_taskList = {0};//任务列表

/*函数声明区*/

/*函数定义区*/

/***************************************************************************************
* @brief        时间片轮询的主要调度任务
* @param        void
* @retval       void
* @note         
***************************************************************************************/
void TaskScheduler(void)
{
	uint8_t taskId = 0;
	if(g_taskList.taskNum == 0)
		return;
	for(; taskId<g_taskList.taskNum; taskId++)
	{
		if(HAL_GetTick() - g_taskList.taskListArr[taskId].lastRunTick >= g_taskList.taskListArr[taskId].taskCycTime)
		{//当前时间与上次任务结束时间差值大于该任务的运行周期就运行该任务
			g_taskList.taskListArr[taskId].lastRunTick = HAL_GetTick();//记录当前最后一次运行时间
			g_taskList.taskListArr[taskId].TaskFunc();
		}
	}
};

/***************************************************************************************
* @brief        添加任务至任务表
* @param        taskFunc 要添加的任务结构体
                taskCycTime 任务执行周期
* @retval       成功返回1 失败返回0
* @note         
***************************************************************************************/
uint8_t AddTaskToList(void (*taskFunc)(void), uint16_t taskCycTime)
{
	if(g_taskList.taskNum >= MAX_TASK_NUM)
    {
		return 0;
    }
	g_taskList.taskListArr[g_taskList.taskNum].TaskFunc = taskFunc;
	g_taskList.taskListArr[g_taskList.taskNum].lastRunTick = 0;
	g_taskList.taskListArr[g_taskList.taskNum].taskCycTime = taskCycTime;
	g_taskList.taskNum++;
	g_taskList.taskListArr[g_taskList.taskNum].taskId = g_taskList.taskNum;
	return 1;
}

Task.h

#ifndef _TASK_H
#define _TASK_H

#include "main.h"

#define MAX_TASK_NUM	32

typedef void (*TaskFunc)(void);

//任务结构体
typedef struct
{
	uint8_t taskId;             //任务编号
	uint16_t taskCycTime;       //任务执行频率
	void (*TaskFunc)(void);     //要执行的任务
	uint32_t lastRunTick;       //上次运行结束时间
}TaskType;

//任务列表结构体
typedef struct
{
	TaskType taskListArr[MAX_TASK_NUM];     //任务数组
	uint8_t taskNum;                        //当前列表中的任务数量
}TaskList;

void TaskScheduler(void);
uint8_t AddTaskToList(void (*TaskFunc)(void), uint16_t taskCycTime);
#endif

main.c

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();
  /* USER CODE BEGIN 2 */
  AddTaskToList(TaskFunc1, TIME4MS);//添加执行周期为4MS的定时任务
  
  /* USER CODE END 2 */

  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
  while (1)
  {
    /* USER CODE END WHILE */
    TaskScheduler();//任务调度
    /* USER CODE BEGIN 3 */
  }
  /* USER CODE END 3 */
}
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小李学不懂C

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值