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

STM32Cube HAL库中断处理机制,回调函数实现原理

[复制链接]
STMCU小助手 发布时间:2020-12-28 10:06
STM32Cube HAL库中断处理机制,回调函数实现原理
STM32Cube HAL出来六七年了,还是有很多初学者没有适应,今天就分享一个读者问到的关于中断处理的问题。
很多人都知道STM32CubeMX这套工具的一个目的:减少开发者对STM32底层驱动的开发时间,把重心放在应用代码上。
但是,STM32CubeMX只是生成了底层驱动的初始化代码。所以,我们还需要掌握:应用层代码如何调用HAL库函数(API接口),以及HAL库中断处理机制等相关知识。
HAL库牵涉的内容较多,下面简单描述一下HAL库中断处理,以及相关的回调函数。
1  HAL库中断处理机制
之前使用标准外设库开发时,中断程序(函数)由我们自己实现。
而HAL库的中断处理函数是按照HAL处理机制来实现,如USART1,统一由HAL_UART_IRQHandler来进行处理,如下图:
1.1.jpg
其它大部分外设(TIM、SPI、CAN...)中断都类似,HAL进行统一处理。
也就是说,HAL已经帮我们把中断处理函数写好了,我们只需要调用相应函数来编写应用程序就行了。
HAL_xxx_IRQHandler里面做了哪些处理? 我们以STM32F1的HAL_UART_IRQHandler为例:
  1. <p class="MsoNormal"><span lang="EN-US">void HAL_UART_IRQHandler(UART_HandleTypeDef/ E" \) T- x4 p. g/ t5 x! W
  2. *huart)<o:p></o:p></span></p>
    * P0 r$ Q- g! @

  3. 1 x4 i/ @; O* m5 m6 j1 W( Q/ P
  4. <p class="MsoNormal"><span lang="EN-US">{<o:p></o:p></span></p>. D$ R, h" V  {5 [; A
  5. 1 y" w' R: f$ [/ q
  6. <p class="MsoNormal"><span lang="EN-US">  9 P, L! x- }- G. @
  7. uint32_t isrflags   =1 `) W  P( u# ~1 G! ^& q0 Q) k3 R5 o1 G
  8. READ_REG(huart->Instance->SR);<o:p></o:p></span></p>
    5 h6 @# C" Y. \7 T! d! t
  9. / h$ C7 z) a# s$ v
  10. <p class="MsoNormal"><span lang="EN-US">  $ H$ y( p( g3 ^$ [
  11. uint32_t cr1its     =) u: {# b( c* Q7 h# ~
  12. READ_REG(huart->Instance->CR1);<o:p></o:p></span></p>
    $ x! A8 L+ I, _1 _( y$ M

  13. 8 \) R, e# F8 R; `7 E3 N1 T/ }
  14. <p class="MsoNormal"><span lang="EN-US">  
    8 C) p0 U1 S, `  @8 k
  15. uint32_t cr3its     =  Z  M! V0 o5 E2 ?
  16. READ_REG(huart->Instance->CR3);<o:p></o:p></span></p>
    & q4 n- a1 @) z" A2 J
  17. 9 R  z& w9 H7 d6 H
  18. <p class="MsoNormal"><span lang="EN-US">  
    ' @- F7 N# M5 Z$ i  H
  19. uint32_t errorflags = 0x00U;<o:p></o:p></span></p>
    : @4 m/ B. L7 E$ m3 y0 m

  20. $ ~% H& r% `, {) ]# c: z
  21. <p class="MsoNormal"><span lang="EN-US">  8 }- T, D, [4 `6 l" I
  22. uint32_t dmarequest = 0x00U;<o:p></o:p></span></p>3 z8 f, T4 ^. q+ l& M6 T+ w

  23. : c, s! k' Y; F6 }. t& n
  24. <p class="MsoNormal"><span lang="EN-US"> </span></p>
    ) h  D; H  m) K5 A! V) a

  25. 8 v0 Q$ c% u  ?' ^( D9 x  ~: `+ p
  26. <p class="MsoNormal"><span lang="EN-US">  /*
    / L  Y' a# k% C' n+ d0 H7 T
  27. If no error occurs */<o:p></o:p></span></p>
    4 R9 L6 Q& \! i; C! @# g9 J6 Z

  28. 4 k6 ^3 K( H" B; U" ~" `# K
  29. <p class="MsoNormal"><span lang="EN-US"> 4 N9 y# R5 k8 L, k8 k7 |
  30. errorflags = (isrflags & (uint32_t)(USART_SR_PE | USART_SR_FE |/ u% A$ M6 n: m; p
  31. USART_SR_ORE | USART_SR_NE));<o:p></o:p></span></p>
    . x, C& }+ Y; z+ Y
  32. : s$ q3 }; F: R7 N1 ^
  33. <p class="MsoNormal"><span lang="EN-US"> 4 M, L! ?3 c6 q6 y" K. M+ \
  34. if(errorflags == RESET)<o:p></o:p></span></p>7 T# M7 J; u' }" M" U8 `8 B

  35. - D, \7 a2 i' L6 e/ l# n7 R
  36. <p class="MsoNormal"><span lang="EN-US">  {<o:p></o:p></span></p>, |# A1 J7 {& |" p: |+ Q% ^; `
  37. % B$ X$ ^4 Q! _
  38. <p class="MsoNormal"><span lang="EN-US">   & v" P0 Z6 Y7 _, F: R
  39. /* UART in mode Receiver# P( a: r9 {2 }; [+ X
  40. -------------------------------------------------*/<o:p></o:p></span></p>" G# m# W) M* ]& {2 H( c
  41. * \# o( }: ~$ C) i: m
  42. <p class="MsoNormal"><span lang="EN-US">   ( x/ J2 o+ a5 F+ d* V3 }9 E0 i; x
  43. if(((isrflags & USART_SR_RXNE) != RESET) && ((cr1its &
    ' a! k2 y. P' a, [! f
  44. USART_CR1_RXNEIE) != RESET))<o:p></o:p></span></p>6 X& {! p2 h8 D$ Y6 n0 h% u! S7 R
  45. # y$ ]# }1 [, J# y
  46. <p class="MsoNormal"><span lang="EN-US">    {<o:p></o:p></span></p>
    / d' c# r. s( j5 W6 o3 S9 S; X
  47. & S+ P/ d, ^% v1 j" I$ e
  48. <p class="MsoNormal"><span lang="EN-US">     
    : E8 e: f% ^2 O1 q
  49. UART_Receive_IT(huart);<o:p></o:p></span></p>
    8 C/ F# U% _4 X  C0 ?
  50. 8 u' U- C" M+ B5 t1 |- c& o
  51. <p class="MsoNormal"><span lang="EN-US">     
    7 R, N# W6 b, S5 Y" s( Z0 ^
  52. return;<o:p></o:p></span></p>
    : J  Z' F  l9 w$ m" i4 y
  53. , }3 J. J5 F- p
  54. <p class="MsoNormal"><span lang="EN-US">    }<o:p></o:p></span></p>
    . w% _/ D' @. z1 `$ A  G
  55. ( N. {  z% e1 o: k+ Z
  56. <p class="MsoNormal"><span lang="EN-US">  }<o:p></o:p></span></p>
    * L* B' h! w) c6 O/ X3 k4 }# R
  57. ) B' Q$ f+ A2 X( Q; P
  58. <p class="MsoNormal"><span lang="EN-US"> </span></p>: g4 L) P; p" h1 w9 p

  59. 6 R; G: L) b2 c6 s4 ?! g
  60. <p class="MsoNormal"><span lang="EN-US">  /*
    6 q5 E8 t0 Y; Z# J
  61. If some errors occur */<o:p></o:p></span></p>
    0 R  Z2 I4 O  O

  62. " x7 Y- }5 d2 O( ~; ]# y) Z
  63. <p class="MsoNormal"><span lang="EN-US">
    % [& W! ^. W# R# p$ @9 Q
  64. if((errorflags != RESET) && (((cr3its & USART_CR3_EIE) !=4 S* D/ {6 G5 w/ `/ ^8 b. w
  65. RESET) || ((cr1its & (USART_CR1_RXNEIE | USART_CR1_PEIE)) != RESET)))<o:p></o:p></span></p>. P" d  B+ T2 ^" h; b. ~
  66. 3 Z$ F. A3 ]7 A1 H0 N- S
  67. <p class="MsoNormal"><span lang="EN-US">  {<o:p></o:p></span></p>
    2 [$ Y5 @; a- b4 G
  68. 7 Z% j# T8 K$ t8 }4 y- v$ T
  69. <p class="MsoNormal"><span lang="EN-US">  /*<o:p></o:p></span></p>
    ! @0 h- D6 N5 G- v; ^

  70. 3 ^* W% P! U6 |0 Z, V
  71. <p class="MsoNormal"><span lang="EN-US">  ·<o:p></o:p></span></p>! c8 V7 D5 K) C. j
  72. , p/ W3 a* K, v5 d; ^0 U
  73. <p class="MsoNormal"><span lang="EN-US">  ·</span>删减了部分代码<span lang="EN-US"><o:p></o:p></span></p>7 b; P$ l( y; N- A

  74. & T/ E! H: p5 a* P- x& G+ a9 F$ Z
  75. <p class="MsoNormal"><span lang="EN-US">  ·<o:p></o:p></span></p>8 V6 g% o/ J% ~: y( P' k$ f  a
  76. ' t/ Y8 r( u1 ]+ k% U. D3 V, I
  77. <p class="MsoNormal"><span lang="EN-US">  */<o:p></o:p></span></p>& g. h+ g$ U; S# w5 `9 Q
  78. ( |, s! s* c1 C6 ^% s; V
  79. <p class="MsoNormal"><span lang="EN-US">  }6 ~, V1 h& g9 G" l9 V% g' l
  80. /* End if some error occurs */<o:p></o:p></span></p>
    * ~+ W5 L2 W8 @# i

  81. $ `( @" b) g4 x! E: C
  82. <p class="MsoNormal"><span lang="EN-US"> </span></p>
      t  x% D! \& e9 U: S

  83. 2 ?+ i  x0 ~  M/ M
  84. <p class="MsoNormal"><span lang="EN-US">  /*
    ( _* J9 A0 y/ d+ }( y) U, w6 L0 r
  85. UART in mode Transmitter ------------------------------------------------*/<o:p></o:p></span></p>
    / g$ U. W& p/ t* L; v* I1 {

  86. ( E& g" D7 T& a
  87. <p class="MsoNormal"><span lang="EN-US">
    . r) k  i+ l. S. I; a# v/ ]* H
  88. if(((isrflags & USART_SR_TXE) != RESET) && ((cr1its &4 h1 W  }; J; K& o/ n
  89. USART_CR1_TXEIE) != RESET))<o:p></o:p></span></p>
    6 ?9 J* D+ k3 j* k/ @
  90. ' `( W9 [: _8 Y* C0 r* q- x
  91. <p class="MsoNormal"><span lang="EN-US">  {<o:p></o:p></span></p>
    " i0 E6 a* {) J# l. p0 f
  92. 8 b$ `: `2 I. l/ ~. r& V6 W! X
  93. <p class="MsoNormal"><span lang="EN-US">   - F) d" e! H- j0 N5 [" o3 u6 g% k" v
  94. UART_Transmit_IT(huart);<o:p></o:p></span></p>
    9 A, @. y5 u4 z& Y

  95.   P+ }) F) m- I0 E
  96. <p class="MsoNormal"><span lang="EN-US">   " a6 G. S) v1 i. x6 G6 J
  97. return;<o:p></o:p></span></p># z! ^1 }" i5 u" A2 V
  98. 3 t! k' t5 }# @4 C
  99. <p class="MsoNormal"><span lang="EN-US">  }<o:p></o:p></span></p>4 b: c* J. Y( e0 _  T
  100. - A# V8 K1 V# E0 f3 V
  101. <p class="MsoNormal"><span lang="EN-US">  /*1 P; }% c3 Q: }
  102. UART in mode Transmitter end --------------------------------------------*/<o:p></o:p></span></p>3 X+ v- K- D& Y; E8 K3 j# _

  103. $ z! X! }4 j0 w+ Q0 `
  104. <p class="MsoNormal"><span lang="EN-US">
    " s, b, D# @' h; f
  105. if(((isrflags & USART_SR_TC) != RESET) && ((cr1its &8 X6 P. ?9 N. f  f
  106. USART_CR1_TCIE) != RESET))<o:p></o:p></span></p>
      }  A2 p: }4 K. w- ^3 u- }' d
  107. 6 |. u+ O7 t- I4 Q& Q2 V( z
  108. <p class="MsoNormal"><span lang="EN-US">  {<o:p></o:p></span></p>1 k  T7 ]3 d! _: T2 x5 [2 f( Q
  109. ( h% t7 [! a- k/ F. n- t: X$ {
  110. <p class="MsoNormal"><span lang="EN-US">   
    . z; Q2 M. p" x6 R/ V7 g; m
  111. UART_EndTransmit_IT(huart);<o:p></o:p></span></p>. v2 ^5 N; t4 i9 Y

  112. 6 M+ Z% R; H$ v1 Q6 Q
  113. <p class="MsoNormal"><span lang="EN-US">   
    $ F8 v) \4 h! C2 k- j
  114. return;<o:p></o:p></span></p>
    7 Y0 E; w% Q$ F$ f
  115. 8 @2 {* F3 J# N3 n* i, n
  116. <p class="MsoNormal"><span lang="EN-US">  }<o:p></o:p></span></p>
    % y( i7 e& Y' s: v2 S- m
  117. + E+ n, k0 {* Z! c& K
  118. <p class="MsoNormal"><span lang="EN-US">}</span></p>
复制代码

- d2 [! B5 `. `' H7 h2 n
其实,大家认真看一下代码应该能明白,这些和我们编写的中断处理函数是不是有类似之处?
这是无非就是接收中断、发送中断、错误中断等一系列处理。只是这里又进行了再次封装,比如接收中断UART_Receive_IT。
当然,这个UART_Receive_IT接收中断实现方式又可能存在不同。像F0、F1...就是直接调用这个接收中断函数来进一步处理。
像L0、G0...是通过执行指针函数RxISR来进一步处理。G0的接收中断处理为:huart->RxISR(huart);
  1. <p class="MsoNormal"><span lang="EN-US">void HAL_UART_IRQHandler(UART_HandleTypeDef
    , {: C7 e3 D: j( f, o
  2. *huart)<o:p></o:p></span></p>; b# n+ Y2 Z% C( i  e: [0 Q' O& A
  3. ; J( X3 F- c2 A" f+ N
  4. <p class="MsoNormal"><span lang="EN-US">{<o:p></o:p></span></p>- s7 b1 Z- c1 `  z: a
  5. % f! m3 \& J! ?
  6. <p class="MsoNormal"><span lang="EN-US">  //</span>删除了前面代码<span lang="EN-US"><o:p></o:p></span></p>2 B0 W$ q' H! N  O+ m
  7. 5 }! X2 _. G* K. S1 m
  8. <p class="MsoNormal"><span lang="EN-US">  /*
    . F1 F0 c! {; X9 A0 z' S* j2 X
  9. If no error occurs */<o:p></o:p></span></p>
    & N% P# Y& ~1 }6 u0 w, L2 ^2 P0 s
  10. 3 E6 N/ n( i1 y
  11. <p class="MsoNormal"><span lang="EN-US">
    8 B, D2 P  Y2 I1 ^1 n$ Y) q
  12. errorflags = (isrflags & (uint32_t)(USART_ISR_PE | USART_ISR_FE |
    , J! c2 i3 ^& t
  13. USART_ISR_ORE | USART_ISR_NE));<o:p></o:p></span></p>
    1 c4 z% C* y$ h6 I0 S2 S

  14. , X+ D) ~" ~6 w( j+ M: P  s
  15. <p class="MsoNormal"><span lang="EN-US">  if8 j; L, O/ t3 A* K& T3 V
  16. (errorflags == 0U)<o:p></o:p></span></p>
    * x1 f6 `; b( f) @; K! S/ _0 v$ A8 t
  17. 4 V7 @' i5 A( _9 }& s8 @+ U
  18. <p class="MsoNormal"><span lang="EN-US">  {<o:p></o:p></span></p>6 P, D) w6 p  Y# q

  19. " U6 u. \# ^) c) d9 |
  20. <p class="MsoNormal"><span lang="EN-US">   
    4 ?! l1 S' }2 f$ A6 {
  21. /* UART in mode Receiver
    + [4 }5 j8 A' ~6 L% K6 _9 v
  22. ---------------------------------------------------*/<o:p></o:p></span></p>' o; e* }7 \+ H4 l
  23. 1 _. [1 o! M* Z- w$ p6 R2 U
  24. <p class="MsoNormal"><span lang="EN-US">   ' L* {1 I, L: ]' ~  h8 P' M  W
  25. if (((isrflags & USART_ISR_RXNE_RXFNE) != 0U)<o:p></o:p></span></p>/ V! f* |/ w( R( E+ n. s: x6 ^
  26. # s; h6 E1 A9 G% ]# s, N
  27. <p class="MsoNormal"><span lang="EN-US">      
    ' V8 N) a; N( _+ R2 a* Q7 U3 y+ b8 H
  28. && (((cr1its & USART_CR1_RXNEIE_RXFNEIE) != 0U)<o:p></o:p></span></p>
    . e4 [$ h* W8 Z5 ]

  29. . D& S, Y$ m) M$ U6 i$ D
  30. <p class="MsoNormal"><span lang="EN-US">           
    ! U# T4 w; V3 Y3 L
  31. || ((cr3its & USART_CR3_RXFTIE) != 0U)))<o:p></o:p></span></p>
    7 \% u; D7 }9 N9 |. d  ~
  32. $ E3 }' }$ s/ m( J
  33. <p class="MsoNormal"><span lang="EN-US">    {<o:p></o:p></span></p>) D8 G3 F  W/ D' u; C6 n5 `
  34. 5 t( R2 W* t* q0 j$ q' y9 g) Y) e8 G
  35. <p class="MsoNormal"><span lang="EN-US">     / I, `6 p9 U! V: G8 D: A
  36. if (huart->RxISR != NULL)<o:p></o:p></span></p>
    . R# O$ O- d$ V8 c9 H

  37. 8 v5 D. t, N: q: R, t0 d
  38. <p class="MsoNormal"><span lang="EN-US">     
    3 P" ^% I: [6 e) x" C
  39. {<o:p></o:p></span></p>
    - K9 p6 W7 v& z- ]
  40. ; y+ o# s7 h' Z$ ?0 |, l; j
  41. <p class="MsoNormal"><span lang="EN-US">       1 F5 ~* Z/ M  h: e+ `. q
  42. huart->RxISR(huart);<o:p></o:p></span></p>" g( t7 d; U4 u: a) m
  43. 8 s" \7 J! b& N1 I& R; S; o4 B/ Q2 f" D
  44. <p class="MsoNormal"><span lang="EN-US">     . d. P0 I& N1 n6 c  x: Y" O& p
  45. }<o:p></o:p></span></p>& [( d, M2 H/ s& }( p/ x) d( C& n

  46. ! `% l2 t6 d3 [3 O7 h# a3 y
  47. <p class="MsoNormal"><span lang="EN-US">     * r; H( i0 ?& O2 e6 X
  48. return;<o:p></o:p></span></p>5 N# F, T- O* i3 d, Q8 Y8 P

  49. 9 E" {/ T! b2 V# a. R
  50. <p class="MsoNormal"><span lang="EN-US">    }<o:p></o:p></span></p>
    . p5 \8 y; X! H

  51. ' T" R- s; s& m
  52. <p class="MsoNormal"><span lang="EN-US">  }<o:p></o:p></span></p>7 n$ _/ w! S2 b, W/ ~
  53. ' |! }2 _/ M1 Q+ \# \2 ^2 d, v
  54. <p class="MsoNormal"><span lang="EN-US">  //</span>删除了后面代码<span lang="EN-US"><o:p></o:p></span></p>' D) W* s8 N8 T2 g5 s2 N

  55. & f; j5 @4 s% ^7 J/ I" G1 ~
  56. <p class="MsoNormal"><span lang="EN-US">}</span></p>
复制代码
看了上面USART中断处理的函数,大家有没有得到什么启发?
其实,HAL库里面处理机制基本一致,只是实现方式上有所不同。
如果你摸清楚了HAL库基本原理,相信阅读HAL库源码,或者使用HAL库编写应用代码不是问题。
2  回调函数实现原理
在HAL库中存在大量类似HAL_XXX_XXXCallback这样的函数,这些都是回调函数。
回调函数就是一个通过函数指针调用的函数。如果你把函数的指针(地址)作为参数传递给另一个函数,当这个指针被用来调用其所指向的函数时,我们就说这是回调函数。
回调函数不是由该函数的实现方直接调用,而是在特定的事件或条件发生时由另外的一方调用的,用于对该事件或条件进行响应。
---来自百度百科
HAL库中断处理使用了较多的回调函数,还是拿UART接收中断来举例说明。
初始化配置好UART中断接收,如果有中断请求,就会执行回调函数HAL_UART_RxCpltCallback。
看上面回调函数的定义,通过特定条件调用『回调函数』,这里触发的条件就是中断。
3  扩展说明
这里也简单说几点:
1.初学者想直接使用HAL不是不行,需要有一定C语言功底
针对大部分初学者来说,是不建议直接上手HAL。但是,有部分C功底较好的,还是建议直接上手。
2.学HAL,建议参看官网例程
很多人不知道如何找资源,我不止一次强调,官方的才是最好。在HAL库中Projects目录下就有很多例程Examples。
3.我们追求效率,可以HAL库源码
如果你想修改HAL库源码,允许修改少部分。如果要大量修改,还是别折腾了。
4.实际项目需做一定修改
STM32CubeMX仅仅是生成初始化代码和工程,你实际项目中一般都有自己的软件架构。
特别是项目越大,软件架构就需要更加规范。
比如:生成的gpio.c文件名,你需要修改成bsp_gpio.c.
再比如:函数MX_USART2_UART_Init改成MX_DEBUG_UART_Init.
------------END ------------
文章出处: strongerHuang

" e2 o/ V- e& K+ r+ ~
赞 收藏 评论0 发布时间:2020-12-28 10:06

举报

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