stm32怎么计算延时时间?STM32中精确延时函数的实现
在与传感器或者模块的总线进行通信的时候,常常需要使用到精确延时,一般我们会封装几个常用延时函数,下面我们以STM32F103芯片为例,详细介绍一下STM32下一种精确延时函数的实现:
时钟树
下图中紫色的 to Cortex System timer(MHz)就是Systick的时钟频率;
SYSTICK原理
SysTick 是一个24位的倒计数定时器,当计到0时,将从RELOAD寄存器中自动重装载定时初值并继续计数,且同时触发中断。只要不把它在SysTick控制及状态寄存器中的使能位清除,就永不停息。
SysTick 的最大使命,就是定期地产生异常请求,作为系统的时基,产生一个周期性的中断。
Systick定时器的四个寄存器:
CTRL:Systick控制和状态寄存器
LOAD:Systick重装载寄存器
VAL:Systick当前值寄存器
CALIB:Systick校准值寄存器 (不常用,可忽略)
/** @addtogroup CmsIS_CM3_SysTick CMSIS CM3 SysTickmemory mapped structure for SysTick@{*/typedef struct{__IO uint32_t CTRL;/*!< Offset: 0x00SysTick Control and Status Register */__IO uint32_t LOAD;/*!< Offset: 0x04SysTick Reload Value Register*/__IO uint32_t VAL;/*!< Offset: 0x08SysTick Current Value Register*/__Iuint32_t CALIB;/*!< Offset: 0x0CSysTick Calibration Register*/} SysTick_Type;
SysTick->CTRL寄存器:
CLKSOURCE-时钟源[2]: select the clock soruce, 0 : AHB / 8, 1 : AHB.
0:STCLK=外部时钟源HCLK(AHB总线时钟)/8=72M/8 = 9M
1:FCLK=内核时钟=72M
FCLK:空闲运行时钟
SysTick-> LOAD寄存器:
SysTick-> VAL寄存器:
#include "delay.h"static u8fac_us=0;//us延时倍乘数static u16 fac_ms=0;//ms延时倍乘数//初始化延迟函数//SYSTICK的时钟固定为HCLK时钟的1/8,即SYSTICK=SYSCLK/8//SYSCLK:系统时钟void delay_init(){SysTick_CLKSourceConfig(SysTick_CLKSource_HCLK_Div8);//选择外部时钟HCLK/8fac_us=SystemCoreClock/8000000; //SYSTICK时钟为9M(即8分频)时,fac_us=9,即SysTick倒数9个数,耗时1usfac_ms=(u16)fac_us*1000; //非OS下,代表每个ms需要的systick时钟数}//查询SysTick->CTRL寄存器bit0是否为1,当为1时,说明倒计时时间到;//整个延时方法中,不进入SysTick中断;//延时nus//nus为要延时的us数.void delay_us(u32 nus){u32 temp;SysTick->LOAD=nus*fac_us; //延时时间加载SysTick->VAL=0x00; //清空计数器SysTick->CTRL|=SysTick_CTRL_ENABLE_Msk ; //开始倒数 //do while 判断就是 systick 使能(bit0)位为 1 且(bit16)为1的时候等待结束 do{temp=SysTick->CTRL;}while((temp&0x01)&&!(temp&(1<<16))); //等待时间到达SysTick->CTRL&=~SysTick_CTRL_ENABLE_Msk; //关闭计数器SysTick->VAL =0X00; //清空计数器}//延时nms//注意nms的范围//SysTick->LOAD为24位寄存器,所以,最大延时为://nms<=0xffffff*8*1000/SYSCLK//SYSCLK单位为Hz,nms单位为ms//对72M条件下,nms<=1864void delay_ms(u16 nms){u32 temp;SysTick->LOAD=(u32)nms*fac_ms;//时间加载(SysTick->LOAD为24bit)SysTick->VAL =0x00;//清空计数器SysTick->CTRL|=SysTick_CTRL_ENABLE_Msk ;//开始倒数do{temp=SysTick->CTRL;}while((temp&0x01)&&!(temp&(1<<16)));//等待时间到达SysTick->CTRL&=~SysTick_CTRL_ENABLE_Msk;//关闭计数器SysTick->VAL =0X00;//清空计数器}
有了上面函数实现,我们就可以在程序中进行精准延时了,比如delay_us(50);
在刚进入delay_us函数的时候,先计算好这段延时需要等待的SysTick计数次数,这里为50*9(假设系统时钟为72MHz,因为systick的频率为系统时钟频率的1/8,那么systick每增加1,就是1/9us),然后我们就一直读取SysTick->CTRL寄存器,当该寄存器bit16的值为1时,说明倒计时了50*9个SysTick,即说明延时50us时间到了。
参考资料:
【正点原子】MiniSTM32开发板资料
喜欢请关注微信公众号:程序员小哈
有啥想玩的模块,留言给我,咱们一起玩
推荐
宠物
- 1适合新手养的不容易病的龟:龟的天性,龟的天敌以及龟饲养方面的心得381
- 2姑娘血流不止民众接力救人,女子慌慌张张大喊,赶快去救人116
- 3这15种食物不要给狗狗吃,这几种水果不要给狗狗吃321
- 4适合新手养的仓鼠好上手的有哪些?新手适合养什么种类的仓鼠197
- 5宠物掉毛怎么解决小妙招?宠物掉毛如何清洁日常毛发清理就买479
- 6鱼肠炎最佳治疗时间:鱼类肠炎病的病症及防治方法288
- 7贵宾犬为什么不能一起睡觉?为什么贵宾犬偏不睡狗窝160
- 8虎毒不食子为什么猫却食子呢?不都说,虎毒不食子吗329
- 9狗身上蜱虫怎么消灭最彻底的方法?4月到10月蜱虫活跃期你的狗驱虫了吗453
- 10二哈笼子里咬东西:二哈闯祸把邻家鸭子都咬了389