HAL库使用嘀嗒计时器(SysTick)写延时

简介

要用SysTick计时器写延时函数,首先要了解SysTick是怎么工作的。

SysTick是位于单片机内核上的外设,只要是Cortex M内核的单片机,都拥有SysTick计时器,并且SysTick计时器是一个递减计时器。

SysTick定时器介绍

在不同的微处理器或系统中,SysTick定时器的时钟频率可能会有不同的设置,但是一般情况下STM32(除H7外)SysTick的时钟频率默认是系统时钟SystemCoreClock的1/8(开始我也试着去找,但是没有找到。查阅资料了解到,HAL库中似乎并没有明确的提到SysTick时钟频率为SystemCoreClock的1/8,SysTick定时器的时钟频率的设置是在内部自动完成的,也不需要用户手动配置。)

SysTick定时器寄存器介绍

以下时STM32固件库中提到SysTick的几个寄存器,

CTRL -> 控制和状态寄存器,它用于配置和控制SysTick定时器的行为,CTRL寄存器是一个32位的寄存器,寄存器位介绍如下:

  • Bit 0(ENABLE):启用/禁用SysTick定时器。设置为1时启用定时器,设置为0时禁用定时器。
  • Bit 1(TICKINT):定时器中断使能位。设置为1时,当SysTick定时器到达零时,会触发SysTick中断;设置为0时,不触发中断。
  • Bit 2(CLKSOURCE):定时器时钟源选择位。设置为1时,选择外部时钟源作为SysTick定时器的时钟;设置为0时,选择内部时钟作为SysTick定时器的时钟。
  • Bit 16(COUNTFLAG):定时器溢出标志位。当SysTick定时器计数器溢出时,该位被置为1。在软件读取该位后,它将被自动清除。

通过配置CTRL寄存器的不同位来控制SysTick定时器的启用与禁用、中断使能、时钟源选择以及

读取定时器溢出标志。

LOAD -> 重装载寄存器,它用于设置SysTick定时器的初始计数值。LOAD寄存器是一个32位的

寄存器,当VAL递减到0时,它存储的值会重新加载到计数器VAL中。从而实现循环计数的效果。

所以,我们就可以通过设置LOAD寄存器的值,达到控制SysTick定时器的周期定时效果。

具体计算方法如下:

定时周期T = (LOAD寄存器的值 + 1) × 时钟周期;

而SysTick的时钟频率 f = SystemCoreClock/8;

所以,SysTick时钟周期 = 1/(SystemCoreClock/8);

定时周期T = (LOAD寄存器的值 + 1)/(SystemCoreClock/8);

而我们需要1us的延时,就相当于是LOAD里的值给到VAL之后,VAL递减到0的时间刚好是1us,

所以LOAD寄存器的值 = 1us * (SystemCoreClock/8)-1;

这样就算到了延时1us,我们需要赋予SysTick重载寄存器的值了。

VAL -> SysTick定时器的当前值寄存器,SysTick递减就是指VAL寄存器里的值递减;

CALIB -> SysTick定时器的校准寄存器,用于提供SysTick定时器的校准值和特征信息。

程序

知道这些,我么就可以开始编写延时程序了:

寄存器版us延时程序

void delay_us(uint16_t us)
{
    SysTick->LOAD = (us * (SystemCoreClock/8000000))-1;    //设置1us所需要的重装载值
	SysTick->CTRL = 0;        //关闭定时器
	SysTick->VAL = 0;        //清空计数值
    SysTick->CTRL |= 1<<0;        //开启定时器
    while(!(SysTick->CTRL & (1<<16)));   //等待VAL递减到0
    SysTick->CTRL &= ~(1<<0);    //关闭定时器
    SysTick->VAL = 0;        
}

HAL库版us延时程序:

HAL库的话,有专门的掩码控制对应寄存器,跟寄存器类似,只是用一大串英文字母替换了几个数字 

void delay_us(uint16_t us)
{
    SysTick->LOAD = (us * (SystemCoreClock/8000000))-1; 
    SysTick->VAL = 0;
    SysTick->CTRL = 0;
    SysTick->CTRL |= SysTick_CTRL_ENABLE_Msk;
    while (!(SysTick->CTRL & SysTick_CTRL_COUNTFLAG_Msk));
    SysTick->CTRL &= ~SysTick_CTRL_ENABLE_Msk;
}

根据HAL库core_cm3.h第700行;

SysTick_CTRL_ENABLE_Msk:CTRL寄存器使能掩码
SysTick_CTRL_COUNTFLAG_Msk:CTRL溢出标志位掩码

至于ms延时,我们都已经知道us延时了,ms嘛  /手动滑稽:

void delay_ms(uint16_t ms)

{for(int i = ms;i>0;i--)delay_us(1000);}

不好意思,之前寄存器那个while循环里面少加了一个否定符,导致延时卡死,现在改正过来了。 

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值