STM32F103标准外设库——SysTick系统定时器(八)

简介: STM32F103标准外设库——SysTick系统定时器(八)

一、SysTick 简介

       SysTick:系统定时器,24位,只能递减,存在于内核,嵌套在NVIC中,所有的Cortex-M内核的单片机都具有这个定时器。

       SysTick—系统定时器有 4 个寄存器,简要介绍如下。在使用 SysTick 产生定时的时候,只需要配置前三个寄存器,最后一个校准寄存器不需要使用。

二、SysTick功能框图

       counter在时钟的驱动下,从reload初值开始往下递减计数到0,产生中断和置位COUNTFLAG标志。然后又从reload值开始重新递减计数,如此循环。

SysTick定时时间计算

t : 一个计数循环的时间,跟reload和CLK有关

CLK : 72M或者9M,由CTRL寄存器配置

RELOAD :24位,用户自己配置

t = reload * ( 1/clk )

Clk = 72M时,t = (72)*(1/72 M)= 1U

SClk = 72M时,t = (72000)*(1/72 M)= 1MS时间单位换算:

1s = 1000ms = 1000 000 us = 1000 000 000ns

三、SysTick 定时实验

       利用 SysTick 产生 1s 的时基,LED 以 1s 的频率闪烁

1.硬件设计

       SysTick 属于单片机内部的外设,不需要额外的硬件电路,剩下的只需一个 LED 灯即可。

2.软件设计

       我们创建了两个文件:bsp_SysTick.c 和 bsp_ SysTick.h 文件用来存放 SysTick 驱动程序及相关宏定义,中断服务函数放在 stm32f10x_it.c 文件中。SysTick 属于内核的外设,有关的寄存器定义和库函数都在内核相关的库文件 core_cm3.h 中。

3.编程要点

       设置重装载寄存器的值

       清除当前数值寄存器的值

       配置控制与状态寄存器

(1)SysTick 配置库函数

// 这个 固件库函数 在 core_cm3.h中
static __INLINE uint32_t SysTick_Config(uint32_t ticks)
{ 
  // reload 寄存器为24bit,最大值为2^24
  if (ticks > SysTick_LOAD_RELOAD_Msk)  return (1);
  
  // 配置 reload 寄存器的初始值  
  SysTick->LOAD  = (ticks & SysTick_LOAD_RELOAD_Msk) - 1;
  
  // 配置中断优先级为 1<<4-1 = 15,优先级为最低
  NVIC_SetPriority (SysTick_IRQn, (1<<__NVIC_PRIO_BITS) - 1); 
  
  // 配置 counter 计数器的值
  SysTick->VAL   = 0;
  
  // 配置systick 的时钟为 72M
  // 使能中断
  // 使能systick
  SysTick->CTRL  = SysTick_CTRL_CLKSOURCE_Msk | 
                   SysTick_CTRL_TICKINT_Msk   | 
                   SysTick_CTRL_ENABLE_Msk;                    
  return (0); 
}

       用固件库编程的时候我们只需要调用库函数 SysTick_Config() 即可,SysTick_Config() 库函数主要配置了 SysTick 中的三个寄存器:LOAD、VAL 和 CTRL,有关具体的部分看代码注释即可。

(2)配置 SysTick 中断优先级

       在 SysTick_Config() 库函数还调用了固件库函数 NVIC_SetPriority() 来配置系统定时器的中断优先 级,该库函数也在 core_m3.h 中定义,原型如下:

__STATIC_INLINE void NVIC_SetPriority(IRQn_Type IRQn, uint32_t priority)
{
    if ((int32_t)IRQn < 0) {
        SCB->SHP[(((uint32_t)(int32_t)IRQn) & 0xFUL)-4UL] =
        (uint8_t)((priority << (8 - __NVIC_PRIO_BITS)) & (uint32_t)0xFFUL);
    } 
    else {
        NVIC->IP[((uint32_t)(int32_t)IRQn)] =
        (uint8_t)((priority << (8 - __NVIC_PRIO_BITS)) & (uint32_t)0xFFUL);
    }
}

        如果要修改内核外设的优先级,只需要修改下面三个寄存器对应的某个字段即可。

(3)SysTick 初始化函数

/**
  * @brief  启动系统滴答定时器 SysTick
  * @param  无
  * @retval 无
  */
void SysTick_Init(void)
{
  /* SystemFrequency / 1000    1ms中断一次
   * SystemFrequency / 100000  10us中断一次
   * SystemFrequency / 1000000 1us中断一次
   */
//  if (SysTick_Config(SystemFrequency / 100000)) // ST3.0.0库版本
  if (SysTick_Config(SystemCoreClock / 100000)) // ST3.5.0库版本
  { 
    /* Capture error */ 
    while (1);
  }
}

       SysTick 初始化函数由用户编写,里面调用了 SysTick_Config() 这个固件库函数,通过设置该固件库函数的形参,就决定了系统定时器经过多少时间就产生一次中断。

SysTick 中断时间的计算

SysTick_Config(SystemCoreClock / 100000)

       SysTick_Config()的形我们配置为 SystemCoreClock / 100000=72M/100000=720,从刚刚分析我们 知道这个形参的值最终是写到重装载寄存器 LOAD 中的,从而可知我们现在把 SysTick 定时器中 断一次的时间 TINT=720/72M=10us。

(4)SysTick 定时函数

/**
  * @brief   us延时程序,10us为一个单位
  * @param  
  *   @arg nTime: Delay_us( 1 ) 则实现的延时为 1 * 10us = 10us
  * @retval  无
  */
void Delay_us(__IO u32 nTime)
{ 
  TimingDelay = nTime;  
 
  // 使能滴答定时器  
  SysTick->CTRL |=  SysTick_CTRL_ENABLE_Msk;
 
  while(TimingDelay != 0);
}

       函数 Delay_us() 中我们等待 TimingDelay 为 0,当 TimingDelay 为 0 的时候表示延时时间到。变量 TimingDelay 在中断函数中递减,即 SysTick 每进一次中断即 10us 的时间 TimingDelay 递减一次。

(5)SysTick 中断服务函数

void SysTick_Handler(void)
{
    TimingDelay_Decrement();
}

       中断服务函数调用了另外一个函数 TimingDelay_Decrement(),原型如下:

/**
  * @brief  获取节拍程序
  * @param  无
  * @retval 无
  * @attention  在 SysTick 中断函数 SysTick_Handler()调用
  */
void TimingDelay_Decrement(void)
{
  if (TimingDelay != 0x00)
  { 
    TimingDelay--;
  }
}

(6)主函数

/*
 * t : 定时时间 
 * Ticks : 多少个时钟周期产生一次中断 
 * f : 时钟频率 72000000
 * t = Ticks * 1/f = (72000000/100000) * (1/72000000) = 10us 
 */ 
 
/**
  * @brief  主函数
  * @param  无  
  * @retval 无
  */
int main(void)
{ 
  /* LED 端口初始化 */
  LED_GPIO_Config();
 
  /* 配置SysTick 为10us中断一次 */
  SysTick_Init();
 
//  for(;;)
//  {
 
//    LED1( ON ); 
//      Delay_us(100000);     // 100000 * 10us = 1000ms
//    //Delay_ms(100);
//    LED1( OFF );
//    
//    LED2( ON );
//      Delay_us(100000);   // 100000 * 10us = 1000ms
//    //Delay_ms(100);
//    LED2( OFF );
//  
//    LED3( ON );
//      Delay_us(100000);   // 100000 * 10us = 1000ms
//    //Delay_ms(100);
//    LED3( OFF );
//  }     
 
  for(;;)
  {
 
    LED1( ON ); 
    SysTick_Delay_Ms( 1000 );
    LED1( OFF );
    
    LED2( ON );
    SysTick_Delay_Ms( 1000 );
    LED2( OFF );
  
    LED3( ON );
    SysTick_Delay_Ms( 1000 );
    LED3( OFF );
  } 
  
}

       主函数中初始化了 LED 和 SysTick,然后在一个 while 循环中以 1s 的频率让 LED 闪烁。

4.systick 微秒级延时

void SysTick_Delay_Us( __IO uint32_t us)
{
  uint32_t i;
  SysTick_Config(SystemCoreClock/1000000);
  
  for(i=0;i<us;i++)
  {
    // 当计数器的值减小到0的时候,CRTL寄存器的位16会置1 
    while( !((SysTick->CTRL)&(1<<16)) );
  }
  // 关闭SysTick定时器
  SysTick->CTRL &=~SysTick_CTRL_ENABLE_Msk;
}

5.systick 毫秒级延时

void SysTick_Delay_Ms( __IO uint32_t ms)
{
  uint32_t i; 
  SysTick_Config(SystemCoreClock/1000);
  
  for(i=0;i<ms;i++)
  {
    // 当计数器的值减小到0的时候,CRTL寄存器的位16会置1
    // 当置1时,读取该位会清0
    while( !((SysTick->CTRL)&(1<<16)) );
  }
  // 关闭SysTick定时器
  SysTick->CTRL &=~ SysTick_CTRL_ENABLE_Msk;
}


目录
相关文章
|
传感器 存储
STM32--TIM定时器(3)
STM32--TIM定时器(3)
STM32--TIM定时器(3)
|
编解码 芯片
STM32--TIM定时器(2)
STM32--TIM定时器(2)
|
1月前
|
传感器
STM32--TIM定时器(1)
STM32--TIM定时器(1)
|
2月前
|
芯片
STM32F103标准外设库——中断应用/事件控制器(七)
STM32F103标准外设库——中断应用/事件控制器(七)
43 0
STM32F103标准外设库——中断应用/事件控制器(七)
|
2月前
|
监控 前端开发
STM32F103标准外设库——RCC时钟(六)
STM32F103标准外设库——RCC时钟(六)
70 0
STM32F103标准外设库——RCC时钟(六)
|
2月前
|
C++ 芯片 编译器
STM32F103标准外设库—— 新建工程与库函数(四)
STM32F103标准外设库—— 新建工程与库函数(四)
44 0
STM32F103标准外设库—— 新建工程与库函数(四)
|
2月前
|
存储
STM32F103标准外设库——GPIO 输入、输出 (五)
STM32F103标准外设库——GPIO 输入、输出 (五)
70 0
STM32F103标准外设库——GPIO 输入、输出 (五)
|
1月前
|
存储 C语言 芯片
C/C++ stm32基础知识超详细讲解(系统性学习day14)
C/C++ stm32基础知识超详细讲解(系统性学习day14)
|
1月前
STM32定时器的使用
STM32定时器的使用
15 1
|
2月前
|
传感器 芯片 内存技术
STM32F103标准外设库——认识STM32(一)
STM32F103标准外设库——认识STM32(一)
107 0
STM32F103标准外设库——认识STM32(一)