system/delay.c

149 lines
4.3 KiB
C
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/*
* @Author:
* @Date: 2023-04-11 18:31:07
* @LastEditors: xxx
* @LastEditTime: 2023-08-25 11:27:12
* @Description:
* email:
* Copyright (c) 2023 by xxx, All Rights Reserved.
*/
#include "delay.h"
// static uint16_t g_fac_ms = 0; // ms延时倍乘数,在os下,代表每个节拍的ms数
static uint32_t g_fac_us = 0; /* us延时倍乘数 */
void SysTick_Init(void)
{
NVIC_SetPriority(SysTick_IRQn, 3);
LL_SYSTICK_EnableIT();
}
/**
* @brief 初始化延迟函数
* @param sysclk: 系统时钟频率, 即CPU频率(rcc_c_ck)
* @retval 无
*/
void delay_init(uint16_t sysclk)
{
#if SYS_SUPPORT_OS /* 如果需要支持OS */
uint32_t reload;
#endif
// SysTick_Init();
// LL_SetSystemCoreClock(LL_SYSTICK_CLKSOURCE_HCLK); /* SYSTICK使用内核时钟源,同CPU同频率 */
g_fac_us = sysclk; /* 不论是否使用OS,g_fac_us都需要使用 */
// Remove the redundant assignment statement
#if SYS_SUPPORT_OS /* 如果需要支持OS. */
reload = sysclk; /* 每秒钟的计数次数 单位为M */
reload *= 1000000 / configTICK_RATE_HZ; /* 根据delay_ostickspersec设定溢出时间,reload为24位
* 寄存器,最大值:16777216,在168M下,约合0.099s左右
*/
g_fac_ms = 1000 / configTICK_RATE_HZ; // 代表OS可以延时的最少单位
SysTick->CTRL |= SysTick_CTRL_TICKINT_Msk; /* 开启SYSTICK中断 */
SysTick->LOAD = reload; /* 每1/delay_ostickspersec秒中断一次 */
SysTick->CTRL |= SysTick_CTRL_ENABLE_Msk; /* 开启SYSTICK */
#endif
}
/**
* @brief 延时nus
* @param nus: 要延时的us数.
* @note 注意: nus的值,不要大于34952us(最大值即2^24 / g_fac_us @g_fac_us = 168)
* @retval 无
*/
void delay_us(uint32_t nus)
{
uint32_t ticks;
uint32_t told, tnow, tcnt = 0;
uint32_t reload = SysTick->LOAD; /* LOAD的值 */
ticks = nus * g_fac_us; /* 需要的节拍数 */
told = SysTick->VAL; /* 刚进入时的计数器值 */
while (1)
{
tnow = SysTick->VAL;
if (tnow != told)
{
if (tnow < told)
{
tcnt += told - tnow; /* 这里注意一下SYSTICK是一个递减的计数器就可以了 */
}
else
{
tcnt += reload - tnow + told;
}
told = tnow;
if (tcnt >= ticks)
{
// __NOP();
break; /* 时间超过/等于要延迟的时间,则退出 */
}
}
}
}
/**
* @brief 对指定的硬件定时器进行微秒级延时
*
* 使用指定的硬件定时器进行延时操作,延时时间为微秒级。
*
* @param timer_us 指向硬件定时器的指针
* @param us 需要延时的微秒数
*/
void delay_hardware_us(TIM_TypeDef *timer_us, uint32_t us)
{
RESET_TIM_COUNT(timer_us);
while (LL_TIM_GetCounter(timer_us) < us)
; // 等待计数器达到指定值
}
/**
* @brief 延迟指定微秒数的硬件延迟函数
*
* 使用指定的定时器实现微秒级的硬件延迟。
*
* @param timer_us 指向定时器的指针,用于实现延迟功能
* @param us 需要延迟的微秒数
*/
void delay_hardware_ms(TIM_TypeDef *timer_us, uint32_t ms)
{
while (ms--)
{
delay_hardware_us(timer_us, 1000); // 每毫秒延时1000微秒
}
}
/**
* @brief 延时nms
* @param nms: 要延时的ms数 (0< nms <= 65535)
* @retval 无
*/
void delay_ms(uint16_t nms)
{
uint32_t repeat = nms / 30; /* 这里用30,是考虑到可能有超频应用 */
uint32_t remain = nms % 30;
while (repeat)
{
delay_us(30 * 1000); /* 利用delay_us 实现 1000ms 延时 */
repeat--;
}
if (remain)
{
delay_us(remain * 1000); /* 利用delay_us, 把尾数延时(remain ms)给做了 */
}
}
/**
* @brief 延时函数,用于模拟硬件延时。
* @param {uint32_t} ticks
* @return {*}
* @note: 请注意这个函数仅用于模拟硬件延时实际应用中可能需要使用其他延时函数如HAL_Delay或rt_delay。
*/
void delay_tick(uint32_t ticks)
{
while (ticks--)
{
__NOP();
}
}