/* * @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" #if USE_OS == 1 #include "os.h" // 确保包含了 vPortSetupTimerInterrupt 函数的声明 extern void vPortSetupTimerInterrupt(void); #endif // 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 } #if USE_OS == 1 void delay_us(uint32_t nus) { uint32_t ticks; uint32_t told, tnow, reload, tcnt = 0; if ((0x0001 & (SysTick->CTRL)) == 0) { // 定时器未工作,初始化定时器 vPortSetupTimerInterrupt(); } reload = SysTick->LOAD; // 获取重装载寄存器值 ticks = nus * g_fac_us; // 计算延时所需的SysTick计数 vTaskSuspendAll(); // 阻止OS调度,防止打断us延时 told = SysTick->VAL; // 获取当前数值寄存器值(开始时数值) while (1) { tnow = SysTick->VAL; // 获取当前数值寄存器值 if (tnow != told) { // 当前值不等于开始值说明已在计数 if (tnow < told) { tcnt += told - tnow; // 计数值 = 开始值 - 当前值 } else { tcnt += reload - tnow + told; // 计数值 = 重装载值 - 当前值 + 开始值 } told = tnow; // 更新开始值 if (tcnt >= ticks) { break; // 时间超过/等于要延迟的时间,则退出 } } } xTaskResumeAll(); // 恢复OS调度 } #else /** * @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; /* 时间超过/等于要延迟的时间,则退出 */ } } } } #endif /** * @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(); } }