3.6节 滴答延时实验使用SysTick实现时间戳
有时候,我们需要控制程序运行的频率,比如每隔一秒打印一行,这时候需要用到延时函数。本节介绍使用SysTick实现延时。
a.实验准备:USB转串口模块,ST-Llink下载器,CHEAPX机器人控制板
b.实验目的:STM32 SysTick实现时间戳
c.相关知识点:
SysTick滴答定时器,内部是一个24 位的倒计数计时器,我们设置计数的频率,就可以根据读取到的计数大小知道时间是多少。
d.编程及运行
(1)初始化SysTick并编写中断。定义三个32位的全局变量_TimeStampH,_TimeStampL分别存储程序运行的多少秒和微秒。
volatile u32 _TimeStampH=0; //单位unit:s volatile u32 _TimeStampL=0; //单位unit:1/9us volatile static u32 sysTimeStamp=0; //单位unit:1/9us void initSysTick(void) { SysTick_CLKSourceConfig(SysTick_CLKSource_HCLK_Div8); //8分频,72M/8=9M SysTick->CTRL|=SysTick_CTRL_TICKINT_Msk; //使能 SYSTICK IR SysTick->LOAD=9000000; //重装数,最大2^24=16777216 SysTick->VAL =0; //清零 SysTick->CTRL|=SysTick_CTRL_ENABLE_Msk; //开启 SYSTICK } void SysTick_Handler(void)//SysTick中断函数 { _TimeStampH++; }
(2)实现延时函数
void delay_ms(u16 nms) { u32 endTime=nms*9000; if(SysTick->VAL>=endTime) { endTime=SysTick->VAL-endTime+4;//4为补偿值,因为执行函数内语句也存在耗时 if(endTime<10)endTime=10; while(SysTick->VAL>endTime);//每次循环,需要执行一次空语句和一次while判断语句SysTick->VAL>endTime,该过程存在耗时,若endTime太小,可能下一轮判断SysTick->VAL已恢复9000000导致延时出错 } else { endTime=9000000-(endTime-SysTick->VAL); if(endTime>8999990)endTime=8999990; //保证一定存在 endTime> SysTick->VAL while(endTime> SysTick->VAL); if(endTime<10)endTime=10; while(SysTick->VAL>endTime);//每次循环,需要执行一次空语句和一次while判断语句SysTick->VAL>endTime,该过程存在耗时,若endTime太小,可能下一轮判断SysTick->VAL已恢复9000000导致延时出错 } } void delay_us(u16 nus) { u32 endTime=nus*9; if(SysTick->VAL>=endTime) { endTime=SysTick->VAL-endTime+4;//4为补偿值,因为执行函数内语句也存在耗时,5,差值为1 if(endTime<10)endTime=10; while(SysTick->VAL>endTime);//每次循环,需要执行一次空语句和一次while判断语句SysTick->VAL>endTime,该过程存在耗时,若endTime太小,可能下一轮判断SysTick->VAL已恢复9000000导致延时出错 } else { endTime=9000000-(endTime-SysTick->VAL); if(endTime>8999990)endTime=8999990;//保证一定存在 endTime> SysTick->VAL while(endTime> SysTick->VAL); if(endTime<10)endTime=10; while(SysTick->VAL>endTime);//每次循环,需要执行一次空语句和一次while判断语句SysTick->VAL>endTime,该过程存在耗时,若endTime太小,可能下一轮判断SysTick->VAL已恢复9000000导致延时出错 } }
(3)主函数
//滴答延时实验 int main(void) { NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); //PriorityGroupConfig NVIC中断分组设置 组2(2位抢占优先级,2位响应优先级) initDebugSerial(500000); initSysTick(); showVersion();//显示版本 while(1) { printf("运行时间:%4us ",_TimeStampH); delay_ms(1000); } }
(4)实验结果: