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

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()
    3 {4 P7 k: G' N9 U4 d1 M' g; e
  2. {
    * [# a; l! q# U
  3.     ...........; x% Y3 q' x. b! Q
  4.     LL_SYSTICK_SetClkSource(LL_SYSTICK_CLKSOURCE_HCLK);
    - q* G% n0 @; Z% t! K1 g
  5.     LL_SetSystemCoreClock(32000000);% J# T2 a7 }# ]2 K+ R' U
  6. #ifndef SYSTICK_IRQ
    5 ~3 |3 t5 R5 U8 g
  7.     LL_Init1msTick(32000000); //使能systick但是不开启systick中断
    " V2 m* ^$ J+ Z0 |5 w% p: Q8 \
  8. #else
    2 X0 ?. u* e! e5 N( D
  9.     SysTick_Config(SystemCoreClock / 1000);//使能systick同时开启systick中断$ a2 @: E# b6 C5 O4 P0 v7 n/ x) I
  10. #endif% E) c* f8 H0 k1 [* E: {
  11. }
复制代码
但是这里 需要注意的是,是不是需要开启 systick 中断!!!!
1、如果只是想用systick来作为延时用,程序不想被中断打断,就只需要使能systick而不用开启systick中断,调用 LL_Init1msTick 即可
  1. void LL_Init1msTick(uint32_t HCLKFrequency)
    3 c2 T! s7 R5 U& R8 k
  2.     ---> LL_InitTick(HCLKFrequency, 1000U);$ D6 k$ }  X* U* y8 m
  3.         ---> __STATIC_INLINE void LL_InitTick(uint32_t HCLKFrequency, uint32_t Ticks)' D/ L$ U  F- G2 r; A
  4.             {
    0 W8 f1 R9 U5 \/ `: ^' q
  5.                   /* Configure the SysTick to have interrupt in 1ms time base */
    8 a7 O0 r+ k4 O. \+ W
  6.                   SysTick->LOAD  = (uint32_t)((HCLKFrequency / Ticks) - 1UL);  /* set reload register */
    / I% o1 M. ]) N; J, Q
  7.                   SysTick->VAL   = 0UL;  /* Load the SysTick Counter Value */
      V  e5 J2 w9 M  Q- q0 f
  8.                   SysTick->CTRL  = SysTick_CTRL_CLKSOURCE_Msk |
    ( x) n* a5 z! S; ~3 i- V$ [: ~
  9.                                    SysTick_CTRL_ENABLE_Msk; /* Enable the Systick Timer */
    8 S6 p' E) ^: ?4 _( Y
  10.             }
复制代码

8 L" `. f. Y" p
但是需要自己编写延时函数,不能使用HAL库提供的HAL_Delay()。原因如下:HAL_Delay的实现是依靠一个uwTickFreq变量,uwTickFreq是在HAL_IncTick中累加的,需要在 SysTick_Handler中断函数中周期调用,这样HAL_Delay才会有一个基准
  1. __weak void HAL_IncTick(void)
    7 B0 B; {6 L6 |" e& _
  2. {
    6 c7 ^4 A( B$ {" B) }! h: L
  3.   uwTick += uwTickFreq;+ b+ p) h/ z  i# Z: L+ V7 N
  4. }, m2 ]' b$ j9 e1 W9 C- d
  5. __weak uint32_t HAL_GetTick(void)7 F2 g+ h/ D" t- h- P1 T
  6. {
    ' Y# I) p; u/ V- H2 d2 V
  7.   return uwTick;7 X6 _2 F  a3 j7 J
  8. }6 |  N1 J" w6 l
  9. __weak void HAL_Delay(uint32_t Delay)7 d6 q2 u# F  f
  10. {  A7 d8 k0 }8 I
  11.   uint32_t tickstart = HAL_GetTick();! C1 F9 y% E) A7 X# W
  12.   uint32_t wait = Delay;
    4 ~$ X8 C; k& o. A$ x: a

  13. 9 O) O; J3 c+ Q* U  T0 A7 j" Y
  14.   /* Add a period to guaranty minimum wait */7 d% a  h1 J! f1 b; Y5 K( v
  15.   if (wait < HAL_MAX_DELAY)
    # k- s- G  B+ X% f9 b
  16.   {
    8 l& j, f- @9 T2 I& R5 m" n
  17.     wait += (uint32_t)(uwTickFreq);
    9 @9 p9 q8 [5 b
  18.   }0 v$ o, t; @( p4 i

  19. 4 U3 H! N# v+ ?% Q
  20.   while((HAL_GetTick() - tickstart) < wait)% L0 i# E3 H1 V3 v0 `% Z
  21.   {
    % S& |8 n; L* N, H, ]& S
  22.   }  _) _+ A2 O% Y/ E5 `: o, `: N
  23. }
复制代码
自定义的us延时
  1. void my_delay_us(uint32_t nus)
    * d& }4 {# V7 T9 V7 z) Y
  2. {    ) U7 V' F# ]& [& n$ i& O6 w
  3.   uint32_t temp;  
    ) v* X* ~, m; f* M! B. a8 g& ?  |
  4.   uint32_t fac_us = SystemCoreClock/1000000;    //为系统时钟的1/1000000   
    ! w4 G) P' R# r5 _; x! V. U
  5.   SysTick->LOAD   = nus*fac_us;             //时间加载         
    4 v! C7 v3 I1 T
  6.   SysTick->VAL    = 0x00;                    //清空计数器9 ?" X% d* u7 C0 x' l' l
  7.   SysTick->CTRL  |= SysTick_CTRL_ENABLE_Msk ;    //开始倒数    + X" a. W% y) i
  8.   do
    6 ^/ w5 H, m# C9 v' b6 L6 H
  9.   {) ~( @8 x* h2 W3 Z, t; B1 Q& A
  10.     temp = SysTick->CTRL;6 g' d6 j# n7 C- j3 u6 s
  11.   }3 L6 A" ^1 F4 @
  12.   while((temp & 0x01) &&! (temp&(1 << 16)));   //等待时间到达   
    / h1 {+ s. |' u9 ]
  13.   SysTick->CTRL &= ~ SysTick_CTRL_ENABLE_Msk;   //关闭计数器7 u" h: W) [/ o+ j' ~" i, Z  a* C
  14.   SysTick->VAL = 0X00;                 //清空计数器   
    : h; t- y9 f# t( V5 r" \
  15. }
复制代码
2 X5 R& D1 o2 b% ?; x! h7 t4 R% T6 h
2、如果想用systick座系统的时钟节拍,需要开启systick中断,可以直接调用 SysTick_Config 来配置,也可以使用 HAL_Init 来配置,HAL_Init 配置最终也会调用 SysTick_Config 函数
  1. HAL_Init(void)' F$ _6 _3 u3 s, ?0 B
  2.     ---> HAL_InitTick(uint32_t TickPriority)) T" D  R- Y) f$ [) I8 \5 F
  3.         ---> SysTick_Config(uint32_t ticks)" d2 L' U0 v" G' J" q$ G
  4.             {" H  c1 ?7 b) l( ^9 z
  5.               if ((ticks - 1UL) > SysTick_LOAD_RELOAD_Msk)( h+ {& ?3 E0 `- ]5 |0 l6 f6 l/ x
  6.               {
    ! Y7 w8 Z4 K# C/ Z; R/ H
  7.                 return (1UL);                                                   /* Reload value impossible */
    2 z7 X/ e) l! Z( K$ @: c" b. e# o
  8.               }
    2 H4 s- I9 ^* Q! F3 y& J" x" S
  9.             
    " G! H& j2 |, H( f3 ~- ~0 V
  10.               SysTick->LOAD  = (uint32_t)(ticks - 1UL);                         /* set reload register */3 M% u% u# u1 W# q9 u
  11.               NVIC_SetPriority (SysTick_IRQn, (1UL << __NVIC_PRIO_BITS) - 1UL); /* set Priority for Systick Interrupt *// |& {2 H# N" Y# C3 O2 f4 Y
  12.               SysTick->VAL   = 0UL;                                             /* Load the SysTick Counter Value */& P! L% N$ D1 T7 k' z8 V, m
  13.               SysTick->CTRL  = SysTick_CTRL_CLKSOURCE_Msk |# {& n% h; y6 T! s2 s
  14.                                SysTick_CTRL_TICKINT_Msk   |. a4 S; N# Z& D; w; y$ o
  15.                                SysTick_CTRL_ENABLE_Msk;                         /* Enable SysTick IRQ and SysTick Timer */
    2 r0 N* B% \- I  v# |
  16.               return (0UL);                                                     /* Function successful */- l1 _5 @9 x0 W9 p" E
  17.             }
复制代码

3 c9 A- B; i2 P9 ^; L4 N! ~% V
这样配置完成之后,还需要再systick的中断中调用 osSystickHandler 和 HAL_IncTick
  1. void SysTick_Handler(void)
    # I% e$ w+ [1 N) U7 v' h7 x
  2. {
    8 o0 p. f# R& X5 n
  3.   osSystickHandler();//为OS提供系统时钟节拍8 S) X8 r: c4 y6 x9 a2 M5 Z
  4.   HAL_IncTick();//为HAL库提供时钟基准
    ) c9 N$ G" k3 j) p. x2 L
  5. }
复制代码
. m  M' N! K% H1 w% j% y1 w
转载此文目的在于传递更多信息,版权归原作者所有,如涉及侵权,请联系小编删除。
文章出处: MCU开发加油站

% T1 q; v4 H. V
赞 收藏 评论1 发布时间:2021-1-18 14:57

举报

1个回答
AG5JZ 回答时间:2021-1-19 08:05:03
学习了,感谢分享!
关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
人形机器人运动控制、感知与智能配电
半导体创新技术与应用方向
EE架构与软件定义汽车
12V/48V 汽车智能配电(SPD)
区域控制单元(ZCU)与分区架构
关注我们
st-img 微信公众号
st-img 手机版