23、STM32 上系统精确延时与获取 micro 时间函数的实现(FreeRTOS 中也能移植)


        在编程中经常需要精确的延时,或者需要精确的统计一段代码的执行时间,亦或者是需要精确的保证某段代码被

调用的频率。比如需要统计某个函数的执行时间,从而判断开销,又比如在飞控中需要精确的保证每隔 2m 调用一

次读取传感器的函数,可以使用定时器去实现。在 STM32 平台上,我们可以充分的利用 systick 去实现。

static volatile uint32_t sysTickMillis = 0;
static const    uint32_t sysTickPerUs  = 72;   /* 系统时钟频率 - 72MHz */

/* 检查是否溢出 */
static int systick_check_underflow(void)
{
   return SysTick->CTRL & SysTick_CTRL_COUNTFLAG_Msk;
}

/* systick 中断服务程序 */ 
void SysTick_Handler(void)
{
   __disable_irq();
 
   systick_check_underflow();
   
   sysTickMillis++;
 
   __enable_irq();
}
 
/* systick 初始化 */ 
void systick_init(void)
{
   sysTickPerUs = SystemCoreClock / 1000000;
   
   SysTick_Config(SystemCoreClock / 1000);
}
 
/* 获取系统当前的 micro 数值 */
uint32_t micros(void)
{
   uint32_t cycle, timeMs;
 
   do
    {
       timeMs = sysTickMillis;
       cycle  = SysTick->VAL;
       
       __ASM volatile("nop");
       
   }while (timeMs != sysTickMillis);
 
   if (systick_check_underflow())
   {
       timeMs++;
       
       cycle = SysTick->VAL;
   }
 
   return (timeMs * 1000) + (SysTick->LOAD + 1 - cycle) / sysTickPerUs;
}
 
 
uint32_t millis(void)
{
   return sysTickMillis;
}
 
 /* 微秒延时函数 */
void delay_us(u32 us) 
{
    staticint currentTime, lastTime = 0;
 
    lastTime= micros();
        
    while(1)
    {       
         currentTime= micros();
 
         if ( currentTime - lastTime >=  us )
         {
            break;
         }
    }
}

/* 毫秒延时函数 */
void delay_ms(u32 ms)  
{
    staticint currentTime, lastTime = 0;
 
    lastTime= millis();
        
    while(1)
    {       
        currentTime= millis();
 
        if( currentTime - lastTime >=  ms )
        {
            break;
        }
    }
}

使用方法 :

在 main 函数中调用 systick_init() 进行初始化

调用 delay_us 函数实现 us 级延时

调用 delay_ms 函数实现 ms 级延时


计算代码的执行时间 :

last = micro();

...  /* 需要被统计的代码/函数 */

cur = micro();

usetime = cur  - last;


在 FreeRTOS 下的移植

由于在 FreeRTOS 下,systick 被系统占用,因此不能直接使用该方式去实现,需要稍作修改。

A、 将原来的 sysTickMillis变量声明为全局变量, 以便于在其他地方可以调用

B、 将 systick_check_underflow();函数声明为外部,可以在port.c 中被调用

C、 删除原来的 Systick中断处理函数,并将函数中的处理代码添加到 port.c 的 xPortSysTickHandler 

    函数中去

    systick_check_underflow();

    sysTickMillis++;

D、删除 systick_init 函数

E、 micros 以及 delay_ms 等函数保持不变即可



你可能感兴趣的:(STM32F1,开发)