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

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()
    ( r- r# I  c0 ?; F/ Y
  2. {  ~- E& D# t0 F! G/ @: \4 e
  3.     ...........
    9 _/ A  _6 Q5 U/ h9 e/ v* B
  4.     LL_SYSTICK_SetClkSource(LL_SYSTICK_CLKSOURCE_HCLK);5 Y, f; G+ y- e4 g: X! h% j
  5.     LL_SetSystemCoreClock(32000000);" m$ m+ |* k4 e9 O2 X# W
  6. #ifndef SYSTICK_IRQ6 M% Q* B# a3 j) K
  7.     LL_Init1msTick(32000000); //使能systick但是不开启systick中断
    ' D2 V0 m8 ~: f
  8. #else1 ]* K, H1 ]8 n5 @  J
  9.     SysTick_Config(SystemCoreClock / 1000);//使能systick同时开启systick中断
    / l) X1 X% I7 a9 ^8 ]: Z
  10. #endif
    9 }+ _* @9 W. m, n! F
  11. }
复制代码
但是这里 需要注意的是,是不是需要开启 systick 中断!!!!
1、如果只是想用systick来作为延时用,程序不想被中断打断,就只需要使能systick而不用开启systick中断,调用 LL_Init1msTick 即可
  1. void LL_Init1msTick(uint32_t HCLKFrequency)
    ; K  X# R% g  K* K! J8 W
  2.     ---> LL_InitTick(HCLKFrequency, 1000U);
    ; a0 N/ a: ?$ J  x& d
  3.         ---> __STATIC_INLINE void LL_InitTick(uint32_t HCLKFrequency, uint32_t Ticks)  z8 [3 e! _9 F. B/ {8 ~
  4.             {. M6 D8 ^* N. S/ z
  5.                   /* Configure the SysTick to have interrupt in 1ms time base */0 N$ O) W; b+ v( H- a5 j& `, q" W, {
  6.                   SysTick->LOAD  = (uint32_t)((HCLKFrequency / Ticks) - 1UL);  /* set reload register */& N4 Y# R1 ]% y7 C9 B$ j
  7.                   SysTick->VAL   = 0UL;  /* Load the SysTick Counter Value */# K0 }, P% {% H  X  e! l, [7 Q; t
  8.                   SysTick->CTRL  = SysTick_CTRL_CLKSOURCE_Msk |
    , L1 i/ g" K: Y! I6 _1 H$ g3 |) |
  9.                                    SysTick_CTRL_ENABLE_Msk; /* Enable the Systick Timer */6 Y2 B- V/ S4 J- \- [; }4 O
  10.             }
复制代码
; x. M/ l" ?- l- Z7 N$ F
但是需要自己编写延时函数,不能使用HAL库提供的HAL_Delay()。原因如下:HAL_Delay的实现是依靠一个uwTickFreq变量,uwTickFreq是在HAL_IncTick中累加的,需要在 SysTick_Handler中断函数中周期调用,这样HAL_Delay才会有一个基准
  1. __weak void HAL_IncTick(void)
    - X' U  `. R0 E: T
  2. {
    1 S' B0 c6 d+ n  I4 O
  3.   uwTick += uwTickFreq;
    2 X' t# Q3 H- x% Y% {& v
  4. }
    & a' ~0 l" s* j
  5. __weak uint32_t HAL_GetTick(void)( V! m" I: i+ R' u+ ~* D1 b! i* b; }# ]
  6. {
    9 y7 L; f2 J' j( p
  7.   return uwTick;+ S: S& p/ A0 f- }7 `" L8 [9 l
  8. }
    , O0 b$ c! `- C! K
  9. __weak void HAL_Delay(uint32_t Delay)
    4 W0 B3 \# f, H
  10. {
    , m9 a5 ~3 f. m/ B0 V
  11.   uint32_t tickstart = HAL_GetTick();( V& y" Z4 n' Z3 L1 Y. G( ^
  12.   uint32_t wait = Delay;
    2 V9 U2 h- W# E# ^& {. o" ]7 h. ?

  13. # i1 m' \0 _7 b1 t5 S) e7 ?
  14.   /* Add a period to guaranty minimum wait */3 a0 U, u& _( S: S
  15.   if (wait < HAL_MAX_DELAY)7 D- D0 s) g  L4 c( @5 B
  16.   {+ ]$ t9 C1 @' k4 l
  17.     wait += (uint32_t)(uwTickFreq);5 X5 Q: u1 c- q/ G! v: w& k
  18.   }/ d# A1 q7 I1 V# O8 u; m

  19. ( T$ L/ S  V3 v4 `5 Y. E2 j0 m9 `' N
  20.   while((HAL_GetTick() - tickstart) < wait); E/ p# V9 ]; |/ v
  21.   {  S/ ^. H6 }% ?- @
  22.   }
    $ ]/ \# x0 X2 _5 K. Y$ {+ U
  23. }
复制代码
自定义的us延时
  1. void my_delay_us(uint32_t nus)8 u; ^! w* r: y: X+ A" q- _
  2. {   
    ' B; A$ p; D) b* |( V
  3.   uint32_t temp;  2 c# F+ N$ P7 j% G, A
  4.   uint32_t fac_us = SystemCoreClock/1000000;    //为系统时钟的1/1000000    % O: i. {% d2 G( O! Y
  5.   SysTick->LOAD   = nus*fac_us;             //时间加载         - s( d( w% o& k4 m# t
  6.   SysTick->VAL    = 0x00;                    //清空计数器
    # U; \5 I( b9 E- O; D* V$ ~
  7.   SysTick->CTRL  |= SysTick_CTRL_ENABLE_Msk ;    //开始倒数   
    % Z! i- o0 ?3 z* f
  8.   do
    0 Q9 }5 s& m0 p0 p( s
  9.   {& h, g- p! ]6 j- n6 \( y
  10.     temp = SysTick->CTRL;. ?' f! E9 y1 S, o3 Z. G/ A' W
  11.   }3 Z6 b5 H& f& E& F- J
  12.   while((temp & 0x01) &&! (temp&(1 << 16)));   //等待时间到达   
    5 s  L* e" |' {8 O" O
  13.   SysTick->CTRL &= ~ SysTick_CTRL_ENABLE_Msk;   //关闭计数器
    1 ]* d" ^. x6 c( H
  14.   SysTick->VAL = 0X00;                 //清空计数器   
    1 r  ~& D: y* h/ z/ n8 m# O4 P9 x+ }
  15. }
复制代码
+ `! U. H, ~: D& M8 I' {/ ^3 S
2、如果想用systick座系统的时钟节拍,需要开启systick中断,可以直接调用 SysTick_Config 来配置,也可以使用 HAL_Init 来配置,HAL_Init 配置最终也会调用 SysTick_Config 函数
  1. HAL_Init(void)
    1 b4 L" U; @$ U$ e% u
  2.     ---> HAL_InitTick(uint32_t TickPriority)
    + F- N' T3 D/ E2 ]
  3.         ---> SysTick_Config(uint32_t ticks)
    ; x6 r; M1 [; k2 K
  4.             {
    + A" r+ w* v7 ]1 k' Z8 t
  5.               if ((ticks - 1UL) > SysTick_LOAD_RELOAD_Msk)
    ) r  ^# N9 Q* B4 x' s6 Z& W
  6.               {
    / M, t6 l1 ]/ E* H6 N! o
  7.                 return (1UL);                                                   /* Reload value impossible */% h' B1 ^+ u% L
  8.               }. b5 X2 ?% X$ r! c$ i
  9.             
    6 A2 N! v* n' s% I3 ~$ T# q: y
  10.               SysTick->LOAD  = (uint32_t)(ticks - 1UL);                         /* set reload register */% y2 s/ J2 b& \9 l4 U
  11.               NVIC_SetPriority (SysTick_IRQn, (1UL << __NVIC_PRIO_BITS) - 1UL); /* set Priority for Systick Interrupt */8 Y! B( g, I8 E6 ^  k( {* N5 u1 }
  12.               SysTick->VAL   = 0UL;                                             /* Load the SysTick Counter Value */, C! {: W# N+ k4 o( m! |0 L
  13.               SysTick->CTRL  = SysTick_CTRL_CLKSOURCE_Msk |
    2 l' Q9 p! E$ o. S; P, B; ~
  14.                                SysTick_CTRL_TICKINT_Msk   |
    4 ]# U0 e) `3 e" M/ t
  15.                                SysTick_CTRL_ENABLE_Msk;                         /* Enable SysTick IRQ and SysTick Timer */: b- a. @: [0 e, w+ {
  16.               return (0UL);                                                     /* Function successful */
    9 M7 |# i3 l. U1 c
  17.             }
复制代码
  v0 g5 c( k1 E! S/ c1 w
这样配置完成之后,还需要再systick的中断中调用 osSystickHandler 和 HAL_IncTick
  1. void SysTick_Handler(void)+ S5 D7 H- b4 G$ A. W
  2. {0 H* i4 z% L9 {7 Z  ~8 s
  3.   osSystickHandler();//为OS提供系统时钟节拍
    * X9 ?+ i7 u& ]3 g" p
  4.   HAL_IncTick();//为HAL库提供时钟基准
    ) Z. A$ ?* a9 e  p
  5. }
复制代码

: ]8 m7 p* R$ y+ q! B! ^) r; j
转载此文目的在于传递更多信息,版权归原作者所有,如涉及侵权,请联系小编删除。
文章出处: MCU开发加油站
7 h8 V5 n3 |: J
收藏 评论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 手机版