HAL STM32基于系统滴答定时器(SysTick)实现多任务时间片轮询

news2024/11/18 9:38:15

HAL STM32基于系统滴答定时器(SysTick)实现多任务时间片轮询


📑RTOS(实时操作系统)和定时器时间片轮询是两种不同的任务调度和执行方式的差异简介

🔖 以下部分内容,由AI给出的解答:

  • 🔖RTOS(实时操作系统):
  • 🌿RTOS是一种专门设计用于实时系统的操作系统,它可以有效地管理多个任务,提供任务调度、同步和通信等功能。
  • 🌿STM32可以使用多种RTOS,例如FreeRTOS、ChibiOS等,它们都提供了任务管理、信号量、消息队列等功能。
  • 🌿在RTOS中,每个任务都有自己的优先级,并且RTOS会根据任务的优先级进行调度。高优先级的任务将获得更多的CPU时间。
  • 🌿RTOS提供了更结构化的任务管理,使得编写和维护多任务应用程序变得更容易。
  • 🔖定时器时间片轮询:
  • 🌾定时器时间片轮询是一种基于定时器中断的任务调度方法,而不涉及RTOS的复杂性。
  • 🌾在这种方法中,任务的执行由定时器中断触发,每个任务都有一个预定的时间片来执行。
  • 🌾当定时器触发时,控制权将转移到下一个任务,如果当前任务没有执行完,它将在下一个时间片继续执行。
  • 🌾这种方式的调度对于简单的应用来说可能足够,但在复杂的多任务系统中,可能会导致任务之间的优先级管理和调度变得复杂。
  • 📺演示运行效果:
    在这里插入图片描述

🛠STM32CubeMX工程配置

  • 🔧在STM32CubeMX配置工程时,系统时基是默认配置的SysTick定时器。在这里插入图片描述
  • 🔱软件默认配置的系统滴答定时器的优先级是最低的,可以根据个人使用情况,进行调整。在这里插入图片描述- 🌿其他外设使用可以根据个人需求配置。

⛳业务代码完善

  • ✨STM32CubeMX所创建的工程,系统滴答定时器默认是没有启用中断的需要自行添加和补充。
    在这里插入图片描述

  • 🪓滴答定时器中断回调函数完善。

void HAL_SYSTICK_Callback(void)
{
    Sys_Tick_Count();

}

📗时间片轮询驱动

  • 🍁时间片轮询,主要有3部分组成:时基(sys_time)、任务管理(sys_task)、任务对象(TASK)组成:

  • 🌿sys_time.c

#include "sys_time.h"

static unsigned short  int sys_tick = 0;



/**
 * @brief 系统时基
 * 
 */
void Sys_Tick_Count(void)
{
    sys_tick += 1;
}



/**
 * @description: 获取系统滴答计时
 * @param {*}
 * @return {*}
 */
unsigned short int Get_Sys_Tick()
{
    return sys_tick;
}

/**
 * @description: 判断是否超时
 * @param {unsigned long int} start 计算开始的时间
 * @param {unsigned long int} timeout   超时时长
 * @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 系统任务
 * 
 * @param task 任务
 * @param handler 任务轮询函数
 * @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 启动任务
 * 
 * @param task  任务句柄
 */
void sys_task_start(sys_task_t *task)
{
    task->enable = 1;
}



/**
 * @brief 停止任务
 * 
 * @param task  任务句柄
 */
void sys_task_stop(sys_task_t *task)
{
    task->enable = 0;
}


/**
 * @brief 系统任务轮询
 * 
 */
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();                  // 运行
            task->tick_cnt =  Get_Sys_Tick();	   
        }
    }
}

  • 🌿Blink_TASK.c:(具体执行的任务可以根据个人实际使用进行添加配置,这里以驱动3个led对象为例)
#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中的内容:
  • 🍃添加所需运行的任务句柄,需要运行多少个任务就创建多少个对象。
// 控制LED1任务
sys_task_t Task1_Blink;

// 控制LED2任务
sys_task_t Task2_Blink;

// 控制LED3任务
sys_task_t Task3_Blink;
  • 🍃创建任务对象
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任务
sys_task_t Task1_Blink;

// 控制LED2任务
sys_task_t Task2_Blink;

// 控制LED3任务
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 */


// 任务创建
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作为调试信息输出,usb_printf.c、h代码:
#include "usb_printf.h"



void usb_printf(const char *fmt, ...) {
    char buf[128];//自定义缓冲区大小
    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创建。固件版本:STM32Cube FW_F4 V1.28.0
链接:https://pan.baidu.com/s/1ouPVpfv9E_2paunmgrOMRg?pwd=r3xk 
提取码:r3xk

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1413628.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

中科星图——MOD11A1 V6是由Aqua中分辨率成像光谱仪获取的地表温度/发射率(LST/E)数据集

数据名称&#xff1a; MYD11A1.006 数据来源&#xff1a; NASA 时空范围&#xff1a; 2000-2022年 空间范围&#xff1a; 全国 数据简介&#xff1a; MOD11A1 V6数据集是由Aqua星搭载的中分辨率成像光谱仪获取的地表温度/发射率(LST/E)产品&#xff0c;以分片方式组织…

SpringBoot activemq收发消息、配置及原理

SpringBoot集成消息处理框架 Spring framework提供了对JMS和AMQP消息框架的无缝集成&#xff0c;为Spring项目使用消息处理框架提供了极大的便利。 与Spring framework相比&#xff0c;Spring Boot更近了一步&#xff0c;通过auto-configuration机制实现了对jms及amqp主流框架…

《动手学深度学习(PyTorch版)》笔记4.5

注&#xff1a;书中对代码的讲解并不详细&#xff0c;本文对很多细节做了详细注释。另外&#xff0c;书上的源代码是在Jupyter Notebook上运行的&#xff0c;较为分散&#xff0c;本文将代码集中起来&#xff0c;并加以完善&#xff0c;全部用vscode在python 3.9.18下测试通过。…

spring-boot-starter-validation常用注解

文章目录 一、使用二、常用注解三、Valid or Validated &#xff1f;四、分组校验1. 分组校验的基本概念2. 定义验证组3. 应用分组到模型4. 在控制器中使用分组5. 总结 一、使用 要使用这些注解&#xff0c;首先确保在你的 Spring Boot 应用的 pom.xml 文件中添加了 spring-bo…

Facebook 广告帐户:多账号运营如何防止封号?

Facebook目前是全球最受欢迎的社交媒体平台之一&#xff0c;拥有超过27亿活跃用户。因此&#xff0c;它已成为个人和企业向全球受众宣传其产品和服务的重要平台。 然而&#xff0c;Facebook 制定了广告商必须遵守的严格政策和准则&#xff0c;以确保其广告的质量和相关性&…

项目风采展示【TRDa】

桌面功能介绍&#xff1a; 1&#xff1a;支持本地音乐、三方音乐控制播放展示功能&#xff1b; 2&#xff1a;支持陀螺仪 3&#xff1a;支持蓝牙列表显示。

【QT+QGIS跨平台编译】之十二:【libpng+Qt跨平台编译】(一套代码、一套框架,跨平台编译)

文件目录 一、libpng介绍二、文件下载三、文件分析四、pro文件五、编译实践一、libpng介绍 PNG(Portable Network Graphics,便携式网络图形),是一种采用无损压缩算法的位图格式,支持索引、灰度、RGB三种颜色方案以及Alpha通道等特性。 PNG使用从LZ77派生的无损数据压缩算…

RectMask2D的合批情况验证

1.经过实际测试&#xff0c;RectMask2D在裁剪区域完全相同且位置完全重合的情况下能够合批 但是当RectMask2D位置不重合时&#xff0c;就不能合批 注意&#xff0c;虽然此处被RectMask2D裁剪了&#xff0c;但是有部分是被渲染的&#xff0c;在计算深度时属于需要渲染…

20240126请问在ubuntu20.04.6下让GTX1080显卡让whisper工作在large模式下?

20240126请问在ubuntu20.04.6下让GTX1080显卡让whisper工作在large模式下&#xff1f; 2024/1/26 21:19 问GTX1080模式使用large该如何配置呢&#xff1f; 这个问题没有完成&#xff0c;可能需要使用使用显存更大的显卡了&#xff01; 比如GTX1080Ti 11GB&#xff0c;更猛的可…

hex 尽然可以 设置透明度,透明度参数对比图 已解决

还不知道CSS Color Module Level 4标准早在2014年就推出8位hex和4位hex来支持设置alpha值&#xff0c;以实现hex和rgba的互转。这个办法可比6位HEX转RGBA简洁多了&#xff0c;先来简单解释一下&#xff1a; 8位hex是在6位hex基础上加后两位来表示alpha值&#xff0c;00表示完全…

计算机网络——TCP协议

&#x1f4a1;TCP的可靠不在于它是否可以把数据100%传输过去&#xff0c;而是 1.发送方发去数据后&#xff0c;可以知道接收方是否收到数据&#xff1b;2.如果接收方没收到&#xff0c;可以有补救手段&#xff1b; 图1.TCP组成图 TCP的可靠性是付出代价的&#xff0c;即传输效率…

gitee仓库使用中的警告

当 Git 执行 git pull 命令时&#xff0c;有时候会出现类似下面的警告信息&#xff1a; warning: ----------------- SECURITY WARNING ---------------- warning: | TLS certificate verification has been disabled! | warning: ------------------------------------------…

光耦固态继电器在军工行业的全面应用分析

光耦固态继电器是一种集成了光耦隔离和固态继电器功能于一体的电子元件。它通过光电耦合技术实现输入和输出之间的电气隔离&#xff0c;同时利用固态开关控制输出电流。在军工行业&#xff0c;这一技术的应用正在逐渐得到广泛认可。 光耦固态继电器在军工设备中的电气隔离应用 …

FFMPEG解析ts流

三篇相关联的文章&#xff1a; ffmpeg下HLS解析过程-CSDN博客TS文件格式详解及解封装过程-CSDN博客 FFMPEG解析ts流-CSDN博客 一、简介 关于TS格式解析&#xff0c;可以参考《TS文件格式详解及解封装过程-CSDN博客》&#xff0c;本文主要代码部分解读。建议大家熟读iso138…

企业职能部门员工忙闲不均,如何调动积极性?

案例企业背景&#xff1a; 某企业隶属于中国航天科技集团公司&#xff0c;致力于光纤陀螺系统、微机电惯性系统、光纤传感系统等高新技术产品的研发。公司具有雄厚的新型惯导和光电传感技术基础&#xff0c;多年来开创了我国光纤陀螺技术在武器、卫星和载人飞船等多个任务上的…

深入浅出 diffusion(4):pytorch 实现简单 diffusion

1. 训练和采样流程 2. 无条件实现 import torch, time, os import numpy as np import torch.nn as nn import torch.optim as optim from torchvision.datasets import MNIST from torchvision import transforms from torch.utils.data import DataLoader from torchvision.…

Flink 集成 Debezium Confluent Avro ( format=debezium-avro-confluent )

博主历时三年精心创作的《大数据平台架构与原型实现:数据中台建设实战》一书现已由知名IT图书品牌电子工业出版社博文视点出版发行,点击《重磅推荐:建大数据平台太难了!给我发个工程原型吧!》了解图书详情,京东购书链接:https://item.jd.com/12677623.html,扫描左侧二维…

Hadoop-MapReduce-MRAppMaster启动篇

一、源码下载 下面是hadoop官方源码下载地址&#xff0c;我下载的是hadoop-3.2.4&#xff0c;那就一起来看下吧 Index of /dist/hadoop/core 二、上下文 在上一篇<Hadoop-MapReduce-源码跟读-客户端篇>中已经将到&#xff1a;作业提交到ResourceManager&#xff0c;那…

Bitbucket第一次代码仓库创建/提交/创建新分支/合并分支/忽略ignore

1. 首先要在bitbucket上创建一个项目&#xff0c;这个我没有权限创建&#xff0c;是找的管理员创建的。 管理员创建之后&#xff0c;这个项目给了我权限&#xff0c;我就可以创建我的代码仓库了。 2. 点击这个Projects下的具体项目名字&#xff0c;就会进入这样一个页面&#…

EG-2121CA (晶体振荡器 低抖动表面声波(SAW)振荡器)

在当今高度数字化的时代&#xff0c;稳定的信号传输显得尤为重要。若要实现信号的稳定传输&#xff0c;晶体振荡器必不可少。EG-2121CA&#xff0c;它是一款低抖动表面声波&#xff08;SAW&#xff09;振荡器设计的产品&#xff0c;凭借其出色的频率范围、稳定的电源电压和可靠…