STM32延时函数原理详解
STM32延时函数原理详解
本文主要介绍了STM32微控制器中延时函数的实现原理,详细解释了使用SysTick定时器进行延时的具体方法。文章从代码实现入手,逐步解析了延时函数的各个部分,包括微秒级、毫秒级和秒级延时的实现方式。同时,文章还深入介绍了SysTick定时器的控制寄存器、装载寄存器和当前值寄存器的功能和使用方法,帮助读者理解延时函数背后的硬件原理。
STM32延时函数(查询定时器实现)
在STM32开发中,延时函数是一个常用的功能,但其具体实现原理却鲜为人知。本文将通过分析延时函数的代码实现,帮助读者理解其背后的硬件原理。
延时函数的实现主要依赖于STM32的系统定时器Systick Timer。以下是延时函数的具体实现代码:
#include "stm32f10x.h"
/**
* @brief 微秒级延时
* @param xus 延时时长,范围:0~233015
* @retval 无
*/
void Delay_us(uint32_t xus)
{
SysTick->LOAD = 72 * xus; //设置定时器重装值
SysTick->VAL = 0x00; //清空当前计数值
SysTick->CTRL = 0x00000005; //设置时钟源为HCLK并启动定时器
while(!(SysTick->CTRL & 0x00010000)); //等待计数到0
SysTick->CTRL = 0x00000004; //关闭定时器
}
/**
* @brief 毫秒级延时
* @param xms 延时时长,范围:0~4294967295
* @retval 无
*/
void Delay_ms(uint32_t xms)
{
while(xms--)
{
Delay_us(1000);
}
}
/**
* @brief 秒级延时
* @param xs 延时时长,范围:0~4294967295
* @retval 无
*/
void Delay_s(uint32_t xs)
{
while(xs--)
{
Delay_ms(1000);
}
}
控制及状态寄存器 (STK_CTRL)
Cortex-M3处理器有一个24位的系统定时器,这个定时器从计数值一直减到0,在下一个时钟边缘重新加载(包装到)LOAD寄存器中的值,然后计数下一个时钟。Systick Timer的CTRL寄存器(控制寄存器)如下:
- 第31
17位、第153位为保留位且必须被清除。 - 第16位COUNTFLAG,计数标志位,上一次该位被读取时,定时器倒计时计数到0,计数标志位为1。
- 第2位CLKSOURCE,时钟源选择,0:AHB的时钟8分频;1:处理器时钟(AHB时钟,即HCLK)
- 第1位TICKINT,是否开启SysTick异常请求。0:倒计时到零不断言SysTick异常请求;1:0:倒计时到零断言SysTick异常请求
- 第0位ENABLE,计数器启用。0:停止,1:启用
因此用Systick->CTRL = 0x00000005;
语句,实现HCLK作为SysTick Timer的时钟源并且启用定时器。
装载寄存器(STK_LOAD)
- 第31~24位为保留位
- 第23
0位共24位作为重载值,数值范围0x00FFFFFF
0x0000000 - 根据需要重载值要进行调整:
- 原文:To deliver a single SysTick interrupt after a delay of N processor clock cycles, use a RELOAD of value N. For example, if a SysTick interrupt is required after 400 clock pulses, set RELOAD to 400.
- 在N个处理器时钟周期要产生一次SysTick中断,重载值RELOAD就设置为N。例如需要在400个时钟周期后产生一次SysTick中断,重载值RELOAD就设置为400。
- 原文:To generate a multi-shot timer with a period of N processor clock cycles, use a RELOAD value of N-1. For example, if the SysTick interrupt is required every 100 clock pulses, set RELOAD to 99
- 要生成一个周期为N个处理器时钟周期的多触发定时器,请使用RELOADN-1的值。例如,如果每100个时钟脉冲需要SysTick中断,则设置重新加载到99(这时候用作实时操作系统RTOS)
因此用SysTick->LOAD = 72 * xus;
语句,设定重载值,STM32F10X系列系统时钟(SYSCLK)最大频率为72MHz,它是供STM32中绝大部分部件工作的时钟源,选择HCLK作为时钟源,HCLK最大频率72MHz,即时钟周期(clock cycle)为(\frac{1}{72000000})秒。当参数xus为1000时,延时了1000us=1ms。有关STM32F10X的时钟树参照:https://www.cnblogs.com/Darrick-Jan/p/11379913.html以及《STM32F10X参考手册》
当前值寄存器(STK_VAL)
- 第31位~24位作为保留位
- 余下24位作为当前值,写入任何值都会将字段清除为0,同时也会清除中的STK_CTRL寄存器中的计数标志位COUNTFLAG位为0。
语句SysTick->VAL = 0X00
,将当前值设为0,并将控制寄存器的COUNTFLAG位设为0。
总结
当计数器倒计时计数为0时,读取到控制寄存器STK_CTRL中的COUNTFLAG为1时,说明设定的时间到了,这时退出循环,将ENABLE位复位为0,于是有语句SysTick->CTRL = 0x00000004;
,用来关闭计数器。相对于定时器中断的方式实现延时,查询法上避免了频繁调用中断。