/** * @file delay.c * @author Nations * @version v1.0.0 * * @copyright Copyright (c) 2019, Nations Technologies Inc. All rights reserved. */ #include "delay.h" #include /** * @brief 基于SysTick定时器的微秒级延时函数 * * @param nus 延时的微秒数 * * @note 该函数使用SysTick定时器实现微秒级的延时。它首先配置SysTick定时器使用系统时钟, * 然后根据需要延时的微秒数和系统核心时钟计算重载值,开始倒计时,并在每次循环中读取 * 定时器的控制寄存器值,直到倒计时结束。延时结束后,关闭定时器并清除其值。 */ void systick_delay_us(u32 nus) { u32 temp; // 选择系统时钟作为SysTick定时器的时钟源 SysTick_CLKSourceConfig(SysTick_CLKSource_HCLK); // 根据需要延时的微秒数和系统核心时钟计算SysTick定时器的重载值 SysTick->LOAD=nus*(SystemCoreClock/1000000); // 清除SysTick定时器的当前值 SysTick->VAL=0x00; // 启动SysTick定时器的倒计时 SysTick->CTRL|=SysTick_CTRL_ENABLE_Msk; // 等待直到SysTick定时器倒计时结束 do { temp=SysTick->CTRL; } while(temp&0x01&&!(temp&(1<<16))); // 关闭SysTick定时器的倒计时 SysTick->CTRL&=~SysTick_CTRL_ENABLE_Msk; // 再次清除SysTick定时器的当前值 SysTick->VAL =0X00; } /** * @brief 延时指定的毫秒数 * * 本函数通过SysTick定时器实现精确的毫秒级延时。在延时期间,处理器将进入等待状态, * 直到SysTick定时器计数达到预设的毫秒数。此函数阻塞程序的执行直到延时结束。 * * @param nms 要延时的毫秒数 */ void systick_delay_ms(u16 nms) { u32 temp; // 选择系统时钟作为SysTick定时器的时钟源 SysTick_CLKSourceConfig(SysTick_CLKSource_HCLK); // 根据输入的毫秒数和系统时钟频率计算SysTick定时器的重载值 // 注意SysTick->LOAD是24位的 SysTick->LOAD=(u32)nms*((SystemCoreClock/1000000)*1000); // 清除SysTick定时器的当前值,即重置计数器 SysTick->VAL =0x00; // 启动SysTick定时器计数 SysTick->CTRL|=SysTick_CTRL_ENABLE_Msk; // 等待直到延时结束 do { temp=SysTick->CTRL; } while(temp&0x01&&!(temp&(1<<16))); // 检查定时器状态,确保延时完成 // 关闭SysTick定时器计数 SysTick->CTRL&=~SysTick_CTRL_ENABLE_Msk; // 再次清除定时器值,为下一次延时做准备 SysTick->VAL =0X00; } // void delay_ms(u16 nms) // { // u16 count = nms/100; // while(count--) { // systick_delay_ms(100); // } // systick_delay_ms(nms%100); // } /** * delay_ms_test函数用于实现指定毫秒数的延时。 * * @param nms 延时的毫秒数。 * * 该函数通过编译级的忙等待实现延时,适合于对延时精度要求不高的场合。 * 注意:这种延时方法并不是精确的延时,其延时的精度会受到处理器速度和当前负载的影响。 */ void delay_ms(u16 nms) { // 初始化计数变量 u16 i = 0, j = 0, k = 0; // 设置计数变量i,j,k的初始值 i = 0; j = 0; k = 0; // 根据指定的毫秒数nms进行延时 for(i = 0; i < nms; i++) { k = 0; // 内层循环用于增加延时的总循环次数,以达到近似的延时效果 for(j = 0; j < 9600; j++) { k++; } } }