当前位置:宠物百科>综合>资讯>正文

stm32怎么计算延时时间?STM32中精确延时函数的实现

人气:110 ℃/2023-12-06 01:08:13

在与传感器或者模块的总线进行通信的时候,常常需要使用到精确延时,一般我们会封装几个常用延时函数,下面我们以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开发板资料

喜欢请关注微信公众号:程序员小哈

有啥想玩的模块,留言给我,咱们一起玩

搜索更多有关“stm32怎么计算延时时间?STM32中精确延时函数的实现”的信息 [百度搜索] [SoGou搜索] [头条搜索] [360搜索]
CopyRight © 2021-2024 宠物百科 All Rights Reserved. 手机版