当前位置:   article > 正文

STM32(四):Systick (标准库函数)_stm32 标准库函数 配置systick

stm32 标准库函数 配置systick

前言

上一篇文章已经介绍了如何用外部中断的方式进行点灯,实现了点灯的第三种方式。这篇文章我们来介绍一下如何用STM32单片机中的Systick嘀嗒定时器来控制LED灯的交替闪烁以及如何使用系统滴答定时器实现精准的 ms 和 μs 延时。

一、实验原理

1.Systick的定义

Systick定时器是一个24bit的倒计数(向下计数)定时器,功能就是实现简单的延时。当计数到 0 时,将从RELOAD 寄存器中自动重装载定时初值。只要不把它在SysTick 控制及状态寄存器 中的使能位清除,就永不停息,即使在睡眠模式下也能工作。SysTick定时器被捆绑在NVIC中,用于产生SYSTICK异常。

例如:计数初值为10,经过一个时钟周期后,计数值减一,即9,8,7……1,0;计数至0后,又重新开始从10开始倒计数至0。​ 可以借此做精准延时。

2.Systick的寄存器

SysTick包含四个寄存器,都是24位的寄存器。

 Systick的四个寄存器:

  • CTRL         SysTick 控制和状态寄存器(地址:0xE000_E010)
  • LOAD         SysTick 自动重装载除值寄存器(地址:0xE000_E014)
  • VAL            SysTick 当前值寄存器(地址:0xE000_E018)
  • CALIB        SysTick 校准值寄存器(地址:0xE000_E01C)

2.1 Systick的寄存器构成

1.控制及状态寄存器(CTRL)

SysTick控制及状态寄存器 (地址:0xE000_E010)

2.重装载数值寄存器(LOAD)

SysTick重装载数值寄存器(地址:0xE000_E014)

 3.当前数值寄存器(VAL)

SysTick当前数值寄存器(地址:0xE000_E018)

  4.校准数值寄存器(CALIB)

SysTick校准数值寄存器(地址:0xE000_E01C)

二、实验步骤

1.Systick初始化

首先是对Systick的初始化,SystemCoreClock是对系统时钟源的宏定义,然后选择中断频率。进行时钟情况判定,若系统时钟正常,那么就先关闭嘀嗒定时器,等待延时后再开启;若系统时钟异常,那么直接进入while循环,起到一个捕获异常的作用。

  1. void SysTick_Init(void)
  2. {
  3. /* SystemFrequency / 1000 1ms中断一次
  4. * SystemFrequency / 1000000 1us中断一次
  5. */
  6. if (SysTick_Config(SystemCoreClock / 1000000))
  7. {
  8. /* Capture error */
  9. while (1);
  10. }
  11. /* 关闭系统滴答定时器:初始化先不用开启,等需要延时时才开启定时器 */
  12. SysTick->CTRL &= ~ SysTick_CTRL_ENABLE_Msk;
  13. }

2.Systick_Config配置

 SysTick_Config的参数,其实就是一个时钟次数,叫systick重装定时器的值。若已知预装载值和时钟频率,那么可以求出进入一次中断的时间,例如

(SystemCoreClock / 1000U)/ (SystemCoreClock)s 

就是说进入一次中断,也就是1ms进入一次,我们还可以修改其中的Systic寄存器配置,达到我们自己想要的效果。

  1. static __INLINE uint32_t SysTick_Config(uint32_t ticks)
  2. {
  3. if (ticks > SysTick_LOAD_RELOAD_Msk) return (1); /* Reload value impossible */
  4. SysTick->LOAD = (ticks & SysTick_LOAD_RELOAD_Msk) - 1; /* set reload register */
  5. NVIC_SetPriority (SysTick_IRQn, (1<<__NVIC_PRIO_BITS) - 1); /* set Priority for Cortex-M0 System Interrupts */
  6. SysTick->VAL = 0; /* Load the SysTick Counter Value */
  7. SysTick->CTRL = SysTick_CTRL_CLKSOURCE_Msk |
  8. SysTick_CTRL_TICKINT_Msk |
  9. SysTick_CTRL_ENABLE_Msk; /* Enable SysTick IRQ and SysTick Timer */
  10. return (0); /* Function successful */
  11. }

3.Systick中断

首先是是得有一个节拍程序,实质上就是TimingDelay的自减。

  1. void TimingDelay_Decrement(void)
  2. {
  3. if (TimingDelay != 0x00)
  4. {
  5. TimingDelay--;
  6. }
  7. }

但到这里我们的中断配置还没结束!!重点!!易踩坑!!

我们还需要在stm32f10x_it.c的文件里面的中断服务函数 SysTick_Handler()里加上我们的节拍程序,大概在134行,记得加上头文件,例如:

  1. #include "bsp/systick/bsp_SysTick.h"
  2. void SysTick_Handler(void)
  3. {
  4. TimingDelay_Decrement();
  5. }

4.延时函数

其中nTime代表要延时的微秒数,并通过上述的TimingDelay_Decrement()函数进行自减直至到0,停止延时。

  1. void Delay_us(__IO u32 nTime)
  2. {
  3. TimingDelay = nTime;
  4. /* 使能滴答定时器 */
  5. SysTick->CTRL |= SysTick_CTRL_ENABLE_Msk;
  6. while(TimingDelay != 0);
  7. /* 关闭系统滴答定时器 */
  8. SysTick->CTRL &= ~ SysTick_CTRL_ENABLE_Msk;
  9. }

三、实操代码

程序分为3个文件:bsp_SysTick.c、bsp_SysTick.h、main.c

1.bsp_SysTick.c

  1. /* 包含头文件 ----------------------------------------------------------------*/
  2. #include "bsp/systick/bsp_SysTick.h"
  3. static __IO u32 TimingDelay;
  4. /**
  5.   * 函数功能: 初始化配置系统滴答定时器 SysTick
  6.   * 输入参数: 无
  7.   * 返 回 值: 无
  8.   * 说    明:无
  9.   */
  10. void SysTick_Init(void)
  11. {
  12.     /* SystemFrequency / 1000    1ms中断一次
  13.      * SystemFrequency / 1000000 1us中断一次
  14.      */
  15.     if (SysTick_Config(SystemCoreClock / 1000000))
  16.     { 
  17.         /* Capture error */ 
  18.         while (1);
  19.     }
  20.     /* 关闭系统滴答定时器:初始化先不用开启,等需要延时时才开启定时器  */
  21.     SysTick->CTRL &= ~ SysTick_CTRL_ENABLE_Msk;
  22. }
  23. /**
  24.   * 函数功能: us延时程序
  25.   * 输入参数: nTime:延时时间
  26.   * 返 回 值: 无
  27.   * 说    明:无
  28.   */
  29. void Delay_us(__IO u32 nTime)
  30.     TimingDelay = nTime;    
  31.     /* 使能滴答定时器 */ 
  32.     SysTick->CTRL |=  SysTick_CTRL_ENABLE_Msk;
  33.     while(TimingDelay != 0);
  34.   
  35.   /* 关闭系统滴答定时器 */
  36.     SysTick->CTRL &= ~ SysTick_CTRL_ENABLE_Msk;
  37. }
  38. /**
  39.   * 函数功能: 节拍程序
  40.   * 输入参数: 无
  41.   * 返 回 值: 无
  42.   * 说    明:需要在 SysTick 中断函数 SysTick_Handler()调用
  43.   */
  44. void TimingDelay_Decrement(void)
  45. {
  46.     if (TimingDelay != 0x00)
  47.     { 
  48.         TimingDelay--;
  49.     }
  50. }

2.bbsp_SysTick.h

  1. #ifndef __BSP_SYSTICK_H__
  2. #define __BSP_SYSTICK_H__
  3. /* 包含头文件 ----------------------------------------------------------------*/
  4. #include <stm32f10x.h>
  5. /* 类型定义 ------------------------------------------------------------------*/
  6. /* 宏定义 --------------------------------------------------------------------*/
  7. #define Delay_ms(x) Delay_us(1000*x) //单位ms
  8. /* 扩展变量 ------------------------------------------------------------------*/
  9. /* 函数声明 ------------------------------------------------------------------*/
  10. void SysTick_Init(void);
  11. void TimingDelay_Decrement(void);
  12. void Delay_us(__IO u32 nTime);
  13. #endif /* __BSP_SYSTICK_H__ */

3.main.c

  1. /* 包含头文件 ----------------------------------------------------------------*/
  2. #include "stm32f10x.h"
  3. #include "bsp/led/bsp_led.h"
  4. #include "bsp/key/bsp_key.h"
  5. #include "bsp/delay/delay.h"
  6. #include "bsp/systick/bsp_SysTick.h"
  7. /* 函数体 --------------------------------------------------------------------*/
  8. static uint16_t timecount;
  9. /**
  10. * 函数功能: 主函数.
  11. * 输入参数: 无
  12. * 返 回 值: 无
  13. * 说 明: 无
  14. */
  15. int main(void)
  16. {
  17. LED_GPIO_Init();
  18. /* 初始化系统滴答定时器 */
  19. SysTick_Init();
  20. /* 清零时间计数 */
  21. timecount=0;
  22. while (1)
  23. {
  24. /* 延时10ms */
  25. Delay_ms(10);
  26. /* 每10ms计数值增加1 */
  27. timecount++;
  28. /* 计数到50,延时时间为500ms */
  29. if(timecount==50)
  30. {
  31. LED1_ON;
  32. LED2_OFF;
  33. LED3_OFF;
  34. }
  35. /* 计数到100,延时时间为1s */
  36. if(timecount==100)
  37. {
  38. LED1_OFF;
  39. LED2_ON;
  40. LED3_OFF;
  41. }
  42. /* 计数到150,延时时间为1.5s */
  43. if(timecount==150)
  44. {
  45. LED1_OFF;
  46. LED2_OFF;
  47. LED3_ON;
  48. /* 清零时间计数 */
  49. timecount=0;
  50. }
  51. }
  52. }

四、实验效果

Systick点灯

结束语

本文以STM32VET6为例讲解了用Systick定时器控制按键点灯的实现方法,并指出其中的易坑点。希望对大家有所帮助!如果还有什么问题,欢迎评论区留言,谢谢!

声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:【wpsshop博客】
推荐阅读
相关标签
  

闽ICP备14008679号