STM32的SysTick定时器初体验


注:本文属博主学习时所作笔记,内容源大参考于野火的《零死角玩转STM32F103》以及部分网络资料,笔记内容仅作为自己参考,免去频繁查询参考手册的麻烦,如有错误,还请指出!

SysTick介绍

SysTick 属于CM3内核的外设,它可以产生非常精确的延时,一般用于操作系统,用于产生一个单独的时钟节拍,相当于操作系统的心脏。

SysTick是一个24bit的向下递减的计数器,计数器每计数一次的时间为$1 \over SYSCLK$,Stm32中一般设置系统时钟为72M。当重载数值寄存器递减到0时,系统定时器则会产生中断。

SysTick—系统定时器有 4 个寄存器,一般配置时,大多操作前三个。

寄存器名称 寄存器描述
CTRL SysTick 控制及状态寄存器
LOAD SysTick 重装载数值寄存器
VAL SysTick 当前数值寄存器
CALIB SysTick 校准数值寄存器
  • CTRL

    位段 名称 类型 复位值 描述
    16 COUNTFLAG R/W 0 如果在上次读取本寄存器后, SysTick 已经计到了 0,则该位为 1。
    2 CLKSOURCE R/W 0 时钟源选择位,0=AHB/8,1=处理器时钟 AHB
    1 TICKINT R/W 0 1=SysTick 倒数计数到 0 时产生 SysTick 异常请
    求,0=数到 0 时无动作。也可以通过读取
    COUNTFLAG 标志位来确定计数器是否递减到0。
    0 ENABLE R/W 0 SysTick 定时器的使能位
  • LOAD

    位段 名称 类型 复位值 描述
    23:0 RELOAD R/W 0 当倒数计数至零时,将被重装载的值
  • VAL

    位段 名称 类型 复位值 描述
    23:0 CURRENT R/W 0 读取时返回当前倒计数的值,写它则使之清零,
    同时还会清除在 SysTick 控制及状态寄存器中的 COUNTFLAG 标志。

代码分析

static __INLINE uint32_t SysTick_Config(uint32_t ticks){ 
  if (ticks > SysTick_LOAD_RELOAD_Msk)                          /* 重装载值判断 */
      return (1);                               
  SysTick->LOAD  = (ticks & SysTick_LOAD_RELOAD_Msk) - 1;       /* 设置重装载寄存器 */
  NVIC_SetPriority (SysTick_IRQn, (1<<__NVIC_PRIO_BITS) - 1);   /* 设置中断优先级 __NVIC_PRIO_BITS为4 */
  SysTick->VAL   = 0;                                           /* 设置当前数值寄存器 */
  SysTick->CTRL  = SysTick_CTRL_CLKSOURCE_Msk |                 /* 设置系统定时器的时钟源为 AHBCLK=72M */
                   SysTick_CTRL_TICKINT_Msk   |                 /* 使能系统定时器中断 */
                   SysTick_CTRL_ENABLE_Msk;                     /* 使能定时器 */
  return (0);                                                 
}

固件库编程时,我们通过SysTick_Config()配置系统定时器,形参 ticks 用来设置重装载寄存器的值,最大不能超过重装载寄存器的值$2^{24}$,固件库中的宏定义提供了我们参考值:

#define SYSCLK_FREQ_72MHz  72000000

uint32_t SystemCoreClock = SYSCLK_FREQ_72MHz;

SysTick_Config(SystemFrequency / 1000);            //1ms中断一次
SysTick_Config(SystemFrequency / 100000);         //10us中断一次
SysTick_Config(SystemFrequency / 1000000);         //1us中断一次

延时函数设计

  • 无中断函数类型延时

    //微秒级延时
    void Systick_Delay_us(uint32_t us){
        uint32_t i;
        SysTick_Config(SystemFrequency / 1000000);        //1us中断一次
        for (i = 0; i<us;i++){
            while(!((SysTick->CTRL)&(1<<16)));            //读取16位COUNTFLAG,定时器一个中断周期1us结束while循环
        } 
        SysTick->CTRL &= ~SysTick_CTRL_ENABLE_Msk;        //关闭SysTick定时器
    }
    
    //毫秒级延时
    void Systick_Delay_ms(uint32_t ms){
        uint32_t i;
        SysTick_Config(SystemFrequency / 1000);        //1us中断一次
        for (i = 0; i<us;i++){
            while(!((SysTick->CTRL)&(1<<16)));            //读取16位COUNTFLAG,定时器一个中断周期1ms结束while循环
        } 
        SysTick->CTRL &= ~SysTick_CTRL_ENABLE_Msk;        //关闭SysTick定时器
    }
    
  • 含中断函数类型延时

//固件库宏定义
#define    __IO    volatile        /*!< defines 'read / write' permissions   */
static __IO uint32_t TimingDelay;

void Delay_us(__IO uint32_t nTime){ 
    TimingDelay = nTime;     
      SysTick->CTRL |=  SysTick_CTRL_ENABLE_Msk;    // 使能SysTick定时器
      while(TimingDelay != 0);
}

void SysTick_Init(void){
  if (SysTick_Config(SystemCoreClock / 1000)){         //1ms中断一次,计数周期为1ms
      while (1);                                        //防止定时器配置错误产生一些未知的连锁的错误
  }
 }

void TimingDelay_Decrement(void){
    if (TimingDelay != 0x00){        //判断是否计时结束
          TimingDelay--;
      }
}
//文件stm32f10x_it.c内
void SysTick_Handler(void){
    TimingDelay_Decrement();    

有关volatile的细节可参考我的这篇博文:盘点C语言中你不知道的小细节,技术尚浅,仅供参考

需要延时的时候,我们可以调用函数Delay_us()并传入具体的参数, 当然之前还需要对SysTick进行初始化,将参数传给全局变量TimingDelay,当一个计数递减周期完成,产生异常(中断),自动调用中断服务函数SysTick_Handler(void),这个函数我们可以在文件==stm32f10x_it.c==中编程,再声明一个函数用于控制多少个计时周期,每完成一个计时周期减一,直至延时完成。

延时实例:

  void main(){
      SysTick_Init();        //计时器初始化
      Delay_us(1000);        //延时1000ms,1s
      {    }                //用户代码
  }

文章作者: Mahoo Huang
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 Mahoo Huang !
评论
 上一篇
盘点C语言中你不知道的小细节 盘点C语言中你不知道的小细节
0UL/1UL0UL 表示 无符号长整型 01UL 表示 无符号长整型 1 一般的 1 没有后缀,系统默认指定的类型为int,即有符号的整型数。 除此之外还可以将l,u自由组合形成多种后缀(不区分大小写),单独添加也没问题,
2019-11-12
下一篇 
Hexo个人博客SEO优化指南 Hexo个人博客SEO优化指南
安装sitemap Windows环境下直接在博客根目录打开Git Bash,运行命令: npm install hexo-generator-sitemap --save # sitemap.xml 提交给谷歌搜素引擎 np
2019-11-06
  目录