问小白 wenxiaobai
资讯
历史
科技
环境与自然
成长
游戏
财经
文学与艺术
美食
健康
家居
文化
情感
汽车
三农
军事
旅行
运动
教育
生活
星座命理

STM32延时函数原理详解

创作时间:
作者:
@小白创作中心

STM32延时函数原理详解

引用
1
来源
1.
https://www.cnblogs.com/qianxiaohan/p/18275930

本文主要介绍了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寄存器(控制寄存器)如下:

  • 第3117位、第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位为保留位
  • 第230位共24位作为重载值,数值范围
    0x0000000
    0x00FFFFFF
  • 根据需要重载值要进行调整:
  • 原文: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;
,用来关闭计数器。相对于定时器中断的方式实现延时,查询法上避免了频繁调用中断。

© 2023 北京元石科技有限公司 ◎ 京公网安备 11010802042949号