你的浏览器版本过低,可能导致网站不能正常访问!
为了你能正常使用网站功能,请使用这些浏览器。

STM32单片机systick使用注意事项

[复制链接]
STMCU小助手 发布时间:2021-1-18 14:57
STM32单片机systick使用注意事项
前言
CM4内核的处理和CM3一样,内部都包含了一个SysTick定时器,SysTick 是一个24 位的倒计数定时器,当计到0 时,将从RELOAD 寄存器中自动重装载定时初值。只要不把它在SysTick 控制及状态寄存器中的使能位清除,就永不停息。这样可以用systick来实现延时定时功能,不用再占用系统定时器。systick也多用做系统的时钟节拍,如freeRTOS等OS,再启动调度器的时候,就会将systick配置成其系统时钟,给系统提供心跳。
systick中有4个寄存器
CTRL
LOAD
VAL
CALIB
5.1.png
systick配置注意事项
使用CubeMX配置生成的代码中,会自动生成一个 SystemClock_Config() 的函数,用于配置单片机时钟,其中就会配置systick
  1. void SystemClock_Config()
  2. {
  3.     ...........
  4.     LL_SYSTICK_SetClkSource(LL_SYSTICK_CLKSOURCE_HCLK);
  5.     LL_SetSystemCoreClock(32000000);
  6. #ifndef SYSTICK_IRQ
  7.     LL_Init1msTick(32000000); //使能systick但是不开启systick中断
  8. #else
  9.     SysTick_Config(SystemCoreClock / 1000);//使能systick同时开启systick中断
  10. #endif
  11. }
复制代码
但是这里 需要注意的是,是不是需要开启 systick 中断!!!!
1、如果只是想用systick来作为延时用,程序不想被中断打断,就只需要使能systick而不用开启systick中断,调用 LL_Init1msTick 即可
  1. void LL_Init1msTick(uint32_t HCLKFrequency)
  2.     ---> LL_InitTick(HCLKFrequency, 1000U);
  3.         ---> __STATIC_INLINE void LL_InitTick(uint32_t HCLKFrequency, uint32_t Ticks)
  4.             {
  5.                   /* Configure the SysTick to have interrupt in 1ms time base */
  6.                   SysTick->LOAD  = (uint32_t)((HCLKFrequency / Ticks) - 1UL);  /* set reload register */
  7.                   SysTick->VAL   = 0UL;  /* Load the SysTick Counter Value */
  8.                   SysTick->CTRL  = SysTick_CTRL_CLKSOURCE_Msk |
  9.                                    SysTick_CTRL_ENABLE_Msk; /* Enable the Systick Timer */
  10.             }
复制代码

但是需要自己编写延时函数,不能使用HAL库提供的HAL_Delay()。原因如下:HAL_Delay的实现是依靠一个uwTickFreq变量,uwTickFreq是在HAL_IncTick中累加的,需要在 SysTick_Handler中断函数中周期调用,这样HAL_Delay才会有一个基准
  1. __weak void HAL_IncTick(void)
  2. {
  3.   uwTick += uwTickFreq;
  4. }
  5. __weak uint32_t HAL_GetTick(void)
  6. {
  7.   return uwTick;
  8. }
  9. __weak void HAL_Delay(uint32_t Delay)
  10. {
  11.   uint32_t tickstart = HAL_GetTick();
  12.   uint32_t wait = Delay;

  13.   /* Add a period to guaranty minimum wait */
  14.   if (wait < HAL_MAX_DELAY)
  15.   {
  16.     wait += (uint32_t)(uwTickFreq);
  17.   }

  18.   while((HAL_GetTick() - tickstart) < wait)
  19.   {
  20.   }
  21. }
复制代码
自定义的us延时
  1. void my_delay_us(uint32_t nus)
  2. {   
  3.   uint32_t temp;  
  4.   uint32_t fac_us = SystemCoreClock/1000000;    //为系统时钟的1/1000000   
  5.   SysTick->LOAD   = nus*fac_us;             //时间加载         
  6.   SysTick->VAL    = 0x00;                    //清空计数器
  7.   SysTick->CTRL  |= SysTick_CTRL_ENABLE_Msk ;    //开始倒数   
  8.   do
  9.   {
  10.     temp = SysTick->CTRL;
  11.   }
  12.   while((temp & 0x01) &&! (temp&(1 << 16)));   //等待时间到达   
  13.   SysTick->CTRL &= ~ SysTick_CTRL_ENABLE_Msk;   //关闭计数器
  14.   SysTick->VAL = 0X00;                 //清空计数器   
  15. }
复制代码

2、如果想用systick座系统的时钟节拍,需要开启systick中断,可以直接调用 SysTick_Config 来配置,也可以使用 HAL_Init 来配置,HAL_Init 配置最终也会调用 SysTick_Config 函数
  1. HAL_Init(void)
  2.     ---> HAL_InitTick(uint32_t TickPriority)
  3.         ---> SysTick_Config(uint32_t ticks)
  4.             {
  5.               if ((ticks - 1UL) > SysTick_LOAD_RELOAD_Msk)
  6.               {
  7.                 return (1UL);                                                   /* Reload value impossible */
  8.               }
  9.             
  10.               SysTick->LOAD  = (uint32_t)(ticks - 1UL);                         /* set reload register */
  11.               NVIC_SetPriority (SysTick_IRQn, (1UL << __NVIC_PRIO_BITS) - 1UL); /* set Priority for Systick Interrupt */
  12.               SysTick->VAL   = 0UL;                                             /* Load the SysTick Counter Value */
  13.               SysTick->CTRL  = SysTick_CTRL_CLKSOURCE_Msk |
  14.                                SysTick_CTRL_TICKINT_Msk   |
  15.                                SysTick_CTRL_ENABLE_Msk;                         /* Enable SysTick IRQ and SysTick Timer */
  16.               return (0UL);                                                     /* Function successful */
  17.             }
复制代码

这样配置完成之后,还需要再systick的中断中调用 osSystickHandler 和 HAL_IncTick
  1. void SysTick_Handler(void)
  2. {
  3.   osSystickHandler();//为OS提供系统时钟节拍
  4.   HAL_IncTick();//为HAL库提供时钟基准
  5. }
复制代码

转载此文目的在于传递更多信息,版权归原作者所有,如涉及侵权,请联系小编删除。
文章出处: MCU开发加油站

收藏 评论1 发布时间:2021-1-18 14:57

举报

1个回答
AG5JZ 回答时间:2021-1-19 08:05:03
学习了,感谢分享!

所属标签

关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
STM32N6 AI生态系统
STM32MCU,MPU高性能GUI
ST ACEPACK电源模块
意法半导体生物传感器
STM32Cube扩展软件包
关注我们
st-img 微信公众号
st-img 手机版