裸机多任务系统:不是freertos类系统,是将任务切片放到一个while循环里去执行,把任务的执行时间切片得足够小,然后在一个while循环里去执行,以达到像是“多个while循环一起”的多线程操作。

我们如果执行闪灯代码,传统上是这样的,亮-delay-灭-delay-亮

但是delay函数会大大阻塞我们的运行时间,由于要适配逻辑多任务模型切片时间短的需求,这里就不能使用delay函数了

羊哥的delay函数可以保证吧时间切片到几us,适用于逻辑多任务模型,由于羊哥的delay函数是自己编写的且为标准库,这里用HAL库不太方便,于是我自己写了一个方便大家复制(其实主要是AI的功劳)

---------------------------------------------------------------------------------------------------------------------------------

.c:

#include "delay.h"

// 用于微秒延时的校准值,根据实际时钟频率调整
static uint32_t us_ticks_per_us = 0;

/**
  * @brief  初始化延迟函数。
  * @param  None
  * @retval None
  */
void Delay_Init(void)
{
    // 启用DWT单元
    CoreDebug->DEMCR |= CoreDebug_DEMCR_TRCENA_Msk;
    // 清空CYCCNT计数器
    DWT->CYCCNT = 0;
    // 启用CYCCNT计数器
    DWT->CTRL |= DWT_CTRL_CYCCNTENA_Msk;

    // 计算每个微秒对应的CYCCNT计数值
    // SystemCoreClock 是HAL库定义的系统核心时钟频率,对于STM32F103C8T6通常是72000000
    us_ticks_per_us = SystemCoreClock / 1000000;
}

/**
  * @brief  毫秒级延迟函数。
  * @param  ms: 延迟的毫秒数。
  * @retval None
  */
void Delay(uint32_t ms)
{
    // 直接调用HAL库的毫秒延迟函数
    HAL_Delay(ms);
}

/**
  * @brief  获取当前系统运行时间(毫秒)。
  * @param  None
  * @retval 当前时间(毫秒)。
  */
uint32_t GetTick(void)
{
    // 直接调用HAL库的获取时间函数
    return HAL_GetTick();
}

/**
  * @brief  获取当前高精度时间(微秒)。
  * @param  None
  * @retval 当前时间(微秒)。
  */
uint64_t GetUs(void)
{
    uint32_t ms = HAL_GetTick();
    uint32_t us = DWT->CYCCNT / us_ticks_per_us;

    // 处理在读取ms和us之间,HAL_GetTick()刚好溢出(+1)的情况
    // 如果当前CYCCNT的计数值很小,但ms却比上次大很多,说明发生了溢出
    if ((DWT->CYCCNT < (SystemCoreClock / 2)) && (ms > GetTick()))
    {
        ms--;
    }

    return ((uint64_t)ms * 1000) + us;
}

/**
  * @brief  微秒级延迟函数。
  * @param  us: 延迟的微秒数。
  * @retval None
  */
void DelayUs(uint32_t us)
{
    uint64_t start_time = GetUs();
    while ((GetUs() - start_time) < us);
}

---------------------------------------------------------------------------------------------------------------------------------

.h:

#ifndef __DELAY_H
#define __DELAY_H

#include "stm32f1xx_hal.h"

void      Delay_Init(void);
void      Delay(uint32_t ms);
uint32_t  GetTick(void);
uint64_t  GetUs(void);
void      DelayUs(uint32_t us);

#endif

---------------------------------------------------------------------------------------------------------------------------------

Keil代码编写部分:

这里我们新建两个文件,新建文件的方法在上一节已经提到这里就不再多说了

代码也很简单这里不再过多解释,具体可以看山哥标准库的视频

接着放到main.c里作为切片

Logo

有“AI”的1024 = 2048,欢迎大家加入2048 AI社区

更多推荐