#include "Delay.h" #if MODE == USE_SYS_TICK //初始化延迟函数 //SYSTICK的时钟固定为AHB时钟的1/8 //SYSCLK:系统时钟频率 void vDelayInit(void) { uint8_t ucSYSCLK; SysTick_CLKSourceConfig(SysTick_CLKSource_HCLK_Div8); xUcFacInit.ucFacUs=ucSYSCLK/8; xUcFacInit.usFacMs=(uint16_t)xUcFacInit.ucFacUs*1000; } //延时nus //nus为要延时的us数. void vDelayUs(uint32_t ulNus) { uint32_t ulTemp; SysTick->LOAD=ulNus*xUcFacInit.ucFacUs; //时间加载 SysTick->VAL=0x00; //清空计数器 SysTick->CTRL|=SysTick_CTRL_ENABLE_Msk ; //开始倒数 do { ulTemp=SysTick->CTRL; } while((ulTemp&0x01)&&!(ulTemp&(1<<16))); //等待时间到达 SysTick->CTRL&=~SysTick_CTRL_ENABLE_Msk; //关闭计数器 SysTick->VAL =0x00; //清空计数器 } /** * @brief 毫秒级延时函数 * @note 由于Systick定时器为24位定时器,其装载的最大值为0xFFFFFF,也就是16777215,如果加载的值超过0xFFFFFF,则实际加载的值是取模后的值,导致延时时间缩短, * usNms<=0xFFFFFF*8*1000/SYSCLK。所以在72M条件下,超过1.864s的延时会导致计数器溢出,从而导致定时为xms-16777215的结果。 * @note 如下函数会判断延时是否超过最大延时,若超过则分成多次1000ms处理。 * @param None * @retval None */ void vDelayMs(uint16_t usNms) { uint32_t ulTemp; while (usNms) { uint16_t current = (usNms > 1000) ? 1000 : usNms; usNms -= current; SysTick->LOAD = (uint32_t)current * xUcFacInit.usFacMs; SysTick->VAL = 0x00; SysTick->CTRL |= SysTick_CTRL_ENABLE_Msk; do { ulTemp = SysTick->CTRL; } while ((ulTemp & 0x01) && !(ulTemp & (1 << 16))); SysTick->CTRL &= ~SysTick_CTRL_ENABLE_Msk; SysTick->VAL = 0x00; } } #elif MODE == USE_DWT void vDelayInit(void) { DEMCR |= (uint32_t)TRCENA; // 使能DWT外设 DWT_CYCCNT = (uint32_t)0u; // DWT CYCCNT寄存器计数清0 DWT_CTRL |= (uint32_t)DWT_CTRL_CYCCNTENA; // 使能Cortex-M3 DWT CYCCNT寄存器 } // 微秒延时 void vDelayUs(uint32_t ulNus) { if(ulNus > 10000) ulNus = 10000; uint32_t ulTicksStart, ulTicksEnd, ulTicksDelay; ulTicksStart = DWT_CYCCNT; ulTicksDelay = ( ulNus * ( SystemCoreClock / (1000000) ) ); // 将微秒数换算成滴答数 ulTicksEnd = ulTicksStart + ulTicksDelay; if ( ulTicksEnd >= ulTicksStart ) // ulTicksEnd没有溢出 { if(DWT_CYCCNT > ulTicksStart) // DWT_CYCCNT在上述计算的这段时间中没有溢出 { while( DWT_CYCCNT < ulTicksEnd ); } // DWT_CYCCNT溢出 else { return; // 已经超时,直接退出 } } else // ulTicksEnd溢出 { // DWT_CYCCNT在上述计算的这段时间中没有溢出 if(DWT_CYCCNT > ulTicksStart) { // 等待DWT_CYCCNT的值溢出 while( DWT_CYCCNT > ulTicksEnd ); } // 等待溢出后的DWT_CYCCNT到达ulTicksEnd while( DWT_CYCCNT < ulTicksEnd ); } } void vDelayMs(uint16_t usNms) { for(uint16_t i = 0; i < usNms; i++) { // delay 1 ms vDelayUs(1000); } } #else #endif