在STM32中实现精确的延迟功能

与传感器或模块总线通信时,通常需要使用精确的延迟。

通常,我们将封装几个常用的延迟函数。

让我们以STM32F103芯片为例,详细介绍STM32的下一个精确延迟功能。

实现:时钟树下图中紫色至Cortex System计时器(MHz)是Systick的时钟频率; SYSTICK原理SysTick是一个24位倒数计时器,当它计数到0时,它将自动从RELOAD寄存器中重新加载初始值并继续计数,并同时触发中断。

只要不清除SysTick控制和状态寄存器中的启用位,它就永远不会停止。

SysTick的最大任务是定期生成异常请求(作为系统的时基),以生成定期中断。

Systick计时器的四个寄存器:CTRL:Systick控制和状态寄存器LOAD:Systick重载寄存器VAL:Systick当前值寄存器CALIB:Systick标定值寄存器(不常用,可以忽略)/ ** @addtogroup CMSIS_CM3_SysTick CMSIS CM3 SysTick SysTick @ {* / typedef struct {__IO uint32_t CTRL;的内存映射结构; / *!& lt;偏移量:0x00 SysTick控制和状态寄存器* / __IO uint32_t LOAD; / *!& lt;偏移量:0x04 SysTick重载值寄存器* / __IO uint32_t VAL; / *!& lt;偏移量:0x08 SysTick当前值寄存器* / __I uint32_t CALIB; / *!& lt;偏移量:0x0C SysTick校准寄存器* /} SysTick_Type; SysTick-> CTRL寄存器:CLKSOURCE时钟源[2]:选择时钟源,0:AHB / 8:1:AHB。

0:STCLK =外部时钟源HCLK(AHB总线时钟)/ 8 = 72M / 8 = 9M 1:FCLK =核心时钟= 72M FCLK:空闲运行时钟。

LOAD寄存器:SysTick-> VAL寄存器:#include“ delay.h”静态u8 fac_us = 0; //我们的延迟乘法器静态u16 fac_ms = 0; // ms延迟乘法器//初始化延迟功能// SYSTICK时钟固定为HCLK时钟1/8,即SYSTICK = SYSCLK / 8 // SYSCLK:系统时钟void delay_init(){SysTick_CLKSourceConfig(SysTick_CLKSource_HCLK_Div8); //选择外部时钟HCLK / 8 fac_us = SystemCoreClock / 8000000; // SYSTICK时钟为9M(即8点频率),fac_us = 9,即SysTick的9倒数,需要1us fac_ms =(u16)fac_us * 1000; //在OS中,它表示每个ms所需的系统时钟的数量} // Query SysTick-& gt; CTRL寄存器的bit0是否为1(为1)表示倒计时时间已到; //在整个延迟方法中,不输入SysTick中断; // delay nus // nus是我们要延迟的人数。

void delay_us(u32 nus)(u32 temp; SysTick-& gt = LOAD = nus * fac_us; //加载SysTick-& gt; VAL = 0x00的延迟时间; //清除计数器SysTick-> CTRL | = SysTick_CTRL_ENABLE_Msk; //开始倒计时// do while判断是当操纵杆启用(bit0)位为1并且(bit16)为1时等待结束做{temp = SysTick-& gt; CTRL;} while(( ; amp; 0x01)& amp !!(temp&(1& lt;& lt; 16))); //等待时间达到SysTick-> CTRL& amp; =〜 SysTick_CTRL_ENABLE_Msk; //关闭计数器SysTick-& gt; VAL = 0X00; //清空计数器)//延迟nms //注意nms范围// SysTick-> LOAD是一个24位寄存器,因此最大延迟为:// nms& lt = 0xffffff * 8 * 1000 / SYSCLK // SYSCLK单位为Hz,nms单位为ms //在72M条件下,nms< = 1864无效delay_ms(u16 nms) {u32 temp; SysTick-> LOAD =(u32)nms * fac_ms; //时间加载(SysTick-> LOAD为24位)SysTick-> VAL = 0x00; //清空计数器SysTick-> CTRL | = SysTick_CTRL_ENABLE_Msk; //开始倒计时,执行{temp = SysTick-& gt; CTRL; } while((temp& amp; amp; amp; amp; amp; !!(temp& amp;(1& lt& lt; 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时,表示SysTick已被递减50 * 9,这意味着50us的延迟增加了。

参考资料:[准时原子] MiniSTM32开发板信息如果您愿意,请关注微信公众号:程序员Xiaoha,如果您有任何要玩的模块,请给我留言,让我们玩