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

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()
    ) F) p  }& v% {) W) {) b
  2. {
    " d* {/ z' c8 m% k6 e
  3.     ...........
    1 d5 q+ U' I7 j. O+ b7 p
  4.     LL_SYSTICK_SetClkSource(LL_SYSTICK_CLKSOURCE_HCLK);
    % T0 ], c8 U9 Q4 O, U7 U0 W
  5.     LL_SetSystemCoreClock(32000000);( E3 E6 V) x+ C- o
  6. #ifndef SYSTICK_IRQ: K/ A/ n. A: d4 {0 s& S! F& J# U
  7.     LL_Init1msTick(32000000); //使能systick但是不开启systick中断6 M* L2 i; I4 k+ r, x' N
  8. #else- C; z! |+ X5 g7 i5 H
  9.     SysTick_Config(SystemCoreClock / 1000);//使能systick同时开启systick中断
      X, z, D9 ]6 O2 P
  10. #endif
    " i% n) e5 |0 N: p; I: L! r
  11. }
复制代码
但是这里 需要注意的是,是不是需要开启 systick 中断!!!!
1、如果只是想用systick来作为延时用,程序不想被中断打断,就只需要使能systick而不用开启systick中断,调用 LL_Init1msTick 即可
  1. void LL_Init1msTick(uint32_t HCLKFrequency), C& M* i# M3 D: B& n
  2.     ---> LL_InitTick(HCLKFrequency, 1000U);
    $ u4 o8 |0 O' i3 X
  3.         ---> __STATIC_INLINE void LL_InitTick(uint32_t HCLKFrequency, uint32_t Ticks). i# ]2 Q6 X  T* ^+ U
  4.             {( w  P8 y' p# R& ?
  5.                   /* Configure the SysTick to have interrupt in 1ms time base */
    4 Z/ q, V( m4 _: ]- g/ A) o
  6.                   SysTick->LOAD  = (uint32_t)((HCLKFrequency / Ticks) - 1UL);  /* set reload register */8 q3 j: v3 W7 H" E& t6 e- x
  7.                   SysTick->VAL   = 0UL;  /* Load the SysTick Counter Value */
    # V* i7 i) h( Q8 |1 m6 E6 e3 ]
  8.                   SysTick->CTRL  = SysTick_CTRL_CLKSOURCE_Msk |8 o; c: D; Y$ X' F  c1 x) C4 S1 [
  9.                                    SysTick_CTRL_ENABLE_Msk; /* Enable the Systick Timer */5 Q/ B! S* x. d9 P' a1 p# E- e
  10.             }
复制代码
) C; L8 [4 S. J) h6 }! Y7 C
但是需要自己编写延时函数,不能使用HAL库提供的HAL_Delay()。原因如下:HAL_Delay的实现是依靠一个uwTickFreq变量,uwTickFreq是在HAL_IncTick中累加的,需要在 SysTick_Handler中断函数中周期调用,这样HAL_Delay才会有一个基准
  1. __weak void HAL_IncTick(void)
    $ p9 v7 N3 ?9 W/ }! Q
  2. {
    3 n) L. O9 ^% C9 ?& w; U$ ?
  3.   uwTick += uwTickFreq;
    / e% x7 I2 s2 Q* ~3 b0 N. u; m
  4. }
    4 h1 X& F2 _3 p& T2 x# z3 P9 u$ q9 s
  5. __weak uint32_t HAL_GetTick(void)" B4 Y0 Q! a' P5 s4 n2 k
  6. {
    8 U& z. R7 P7 i5 l9 k7 x) i  M. P# Y  s
  7.   return uwTick;
    - u" D, [5 P6 W' X; A8 a
  8. }
    , |, s4 }0 X1 p
  9. __weak void HAL_Delay(uint32_t Delay)
    ; T& X  Y, p" e
  10. {
    4 x% M) l& s0 |4 [' n+ E6 b
  11.   uint32_t tickstart = HAL_GetTick();
    * ]( f3 A5 O3 G8 }
  12.   uint32_t wait = Delay;% Q% B. N- ^  S3 N$ p+ p
  13. . F7 {( H; G+ _( I5 V
  14.   /* Add a period to guaranty minimum wait */; T' _2 _: n% r5 [
  15.   if (wait < HAL_MAX_DELAY)
    2 ~! j  t# F0 r  I; [+ s4 E$ G$ A+ i% r
  16.   {
    % _% F' E! Z+ {8 c
  17.     wait += (uint32_t)(uwTickFreq);( b$ V' R; N# \3 P9 i
  18.   }7 V- L9 a8 r8 g# _

  19. / G) {$ T# M4 A
  20.   while((HAL_GetTick() - tickstart) < wait)
    8 U$ s7 w2 X  C
  21.   {
    ' {" C8 X8 t+ j6 l0 J
  22.   }% o* R4 N% R# p% P
  23. }
复制代码
自定义的us延时
  1. void my_delay_us(uint32_t nus)2 k9 U8 k, z3 M5 n
  2. {   
    5 \. i9 h3 k2 a, H$ `' i
  3.   uint32_t temp;  0 F+ p8 B* L. E9 D: l7 L
  4.   uint32_t fac_us = SystemCoreClock/1000000;    //为系统时钟的1/1000000    $ d; O0 e) r. r' Y
  5.   SysTick->LOAD   = nus*fac_us;             //时间加载         # ~3 c8 U$ V0 N" r
  6.   SysTick->VAL    = 0x00;                    //清空计数器
    0 v7 ^- w6 Z/ ]9 }, a% p
  7.   SysTick->CTRL  |= SysTick_CTRL_ENABLE_Msk ;    //开始倒数    8 m1 ~' M8 d& ?, G$ o+ Y$ n% g
  8.   do' i  k  J+ l1 T  T! t, [
  9.   {
    2 R# D  i6 K+ K# z- v
  10.     temp = SysTick->CTRL;5 R( D! ]8 m/ T3 E4 i3 w2 a
  11.   }8 Z3 _$ j6 R4 T/ T. n
  12.   while((temp & 0x01) &&! (temp&(1 << 16)));   //等待时间到达   1 J. e7 O" }7 P8 X
  13.   SysTick->CTRL &= ~ SysTick_CTRL_ENABLE_Msk;   //关闭计数器
    ' L, j) W9 R& v
  14.   SysTick->VAL = 0X00;                 //清空计数器   
    ' {, t5 T5 j5 J( i
  15. }
复制代码
, U0 _2 n: X% P! @9 D
2、如果想用systick座系统的时钟节拍,需要开启systick中断,可以直接调用 SysTick_Config 来配置,也可以使用 HAL_Init 来配置,HAL_Init 配置最终也会调用 SysTick_Config 函数
  1. HAL_Init(void)
    9 h, j) j3 g+ o! J+ R+ H
  2.     ---> HAL_InitTick(uint32_t TickPriority)
    ) p1 q2 [  q' O5 ]+ `
  3.         ---> SysTick_Config(uint32_t ticks)$ C& {, g3 f* U1 o% t
  4.             {
    , B( `" P* N$ \3 a2 d1 U2 {
  5.               if ((ticks - 1UL) > SysTick_LOAD_RELOAD_Msk)
    - F) b* K% }; G! }% H9 _; j% S" b+ i
  6.               {4 x! y4 L- d6 J; D- X
  7.                 return (1UL);                                                   /* Reload value impossible */8 V7 X* `' ~8 S* G
  8.               }2 f, W, Q7 h# t0 t
  9.             
    + x, p9 P5 j6 E% L+ @( `
  10.               SysTick->LOAD  = (uint32_t)(ticks - 1UL);                         /* set reload register */$ i: C- e% n% A4 @6 M+ \
  11.               NVIC_SetPriority (SysTick_IRQn, (1UL << __NVIC_PRIO_BITS) - 1UL); /* set Priority for Systick Interrupt */
    , Y: t& ~: l/ l/ d
  12.               SysTick->VAL   = 0UL;                                             /* Load the SysTick Counter Value */
    , l! L' s# j+ ?2 W; k( o; G4 Y
  13.               SysTick->CTRL  = SysTick_CTRL_CLKSOURCE_Msk |) x/ q8 f" U( q: e/ ^
  14.                                SysTick_CTRL_TICKINT_Msk   |
    6 d2 U7 t. W5 l' ?
  15.                                SysTick_CTRL_ENABLE_Msk;                         /* Enable SysTick IRQ and SysTick Timer */2 O( E: ?0 C; R, C
  16.               return (0UL);                                                     /* Function successful */) B5 C, a4 \' Z5 h4 e& |: L8 y8 ]
  17.             }
复制代码

7 V" R9 ~5 S( [8 r# `1 V
这样配置完成之后,还需要再systick的中断中调用 osSystickHandler 和 HAL_IncTick
  1. void SysTick_Handler(void)9 r( D; O/ p2 P6 k
  2. {
    8 a9 f$ b; N. }5 t6 Z/ L+ I0 S
  3.   osSystickHandler();//为OS提供系统时钟节拍: f) d* E8 _! o
  4.   HAL_IncTick();//为HAL库提供时钟基准
    ! \, G# S/ \5 ]* o2 L
  5. }
复制代码
/ O/ r3 h2 {$ j; G
转载此文目的在于传递更多信息,版权归原作者所有,如涉及侵权,请联系小编删除。
文章出处: MCU开发加油站
( i. I- V& {. f, l- o0 N
收藏 评论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 手机版