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

【经验分享】STM32F7使用SPI发送完成和接收中断

[复制链接]
STMCU小助手 发布时间:2021-12-17 12:04
虽然在平常的使用中,spi使用轮询等待发送完成或者接收完成就行了。0 H) V) U, @0 C: C" X0 k
但是在对时间有严格要求的设计中,假设我们需要发送完成后立马做xx事情,此时如果有低优先级的信号需要处理,我们的轮询方式就得不到及时的响应;
" i2 U) k! ]- l: q或者说比如需要定时从spi设备中采集数据,定时器中断来了我们就要马上调用接收函数,接收完成马上进行其他计算,同样此时应该保证数据的优先级。+ Y9 c3 w2 z& l+ ^( c
此时就需要用到发送完成和接收中断了。" w: K, I& {/ e
; S" h' M% g, R# G5 S1 Y
前面我们已经实现了SPI轮询的发送和接收,在前面的基础上进行修改。
8 m% v- k$ }( m1 x
! F9 m5 k' Y6 l( @4 T% z9 I, m接缓冲区满中断
( @6 s. E; i4 |9 T# Y新增发送和接收的回调函数,并在初始化的时候配置,使能SPI接收中断:
5 W. Y0 o! G2 e6 x. g9 z3 d! f7 s0 [. n- B) Z" z6 u
  1. SPI_HandleTypeDef SPI3_Handler;  //SPI2句柄1 h/ h! O0 c! O- z

  2. 7 x( G# Y# H4 K7 b0 ^6 V' T: g2 ?
  3. void rx_isr(SPI_HandleTypeDef *hspi)
    & `$ a$ p( B/ c# x- C/ Q3 M
  4. {6 U8 v4 v+ M! d& S: a: a9 n/ ]
  5.     if (__HAL_SPI_GET_FLAG(hspi, SPI_FLAG_TXE) == 1)
    2 l* l; I, {4 A8 ^- F0 C  p
  6.     {' O8 @# s  F. m: ?
  7.         u8 data = SPI3->DR;
    ; k% f) t' m% q8 j; m$ O- O
  8.                 printf("0x%X  ",data);
    1 Z4 _% M  H3 {
  9.     }
    8 J4 U% j, P+ V5 z
  10. }
    * j% N, s+ D$ [3 v2 ^( H* Q9 E
  11. void tx_isr(SPI_HandleTypeDef *hspi)! }/ }: H. k. p* P2 r  H: ?: t
  12. {1 I1 n1 s9 @. l7 V3 Q
  13.     if (__HAL_SPI_GET_FLAG(hspi, SPI_FLAG_TXE) == 1)& L+ r5 P! v5 @, p! M8 `) s
  14.     {
    6 W! \7 R( B, y$ f" T
  15. . I# u* I6 ~+ Y3 t+ a+ C; a+ l
  16.     }
    4 r, M/ ^. s4 b" E  b  b" M, g- s
  17. }1 f, M  j# i4 _' q/ |! ~) _
  18. void SPI3_Init(void)
    " O# y( e8 t# ]: t0 _* q
  19. {( o0 s' {1 _- h% P
  20.     HAL_NVIC_SetPriority(SPI3_IRQn, 0, 0);
    5 a5 ?$ ~+ \9 n. O4 |0 k
  21.     HAL_NVIC_EnableIRQ(SPI3_IRQn);
    . G* R) O  H# U

  22. 1 X2 J. L& J. `7 K2 o  i  j" M0 m
  23.     SPI3_Handler.Instance = SPI3;
    : A9 Z( o) \/ W7 \6 n, R
  24.     SPI3_Handler.Init.Mode = SPI_MODE_MASTER;
    0 H/ ?) L2 A0 M2 A% D1 q
  25.     SPI3_Handler.Init.Direction = SPI_DIRECTION_2LINES;) m9 {9 G% }# ?7 x* F, D6 i
  26.     SPI3_Handler.Init.DataSize = SPI_DATASIZE_8BIT;
    - Y- y, Z. R, m) _, r( ?1 v4 @6 X0 Y
  27.     SPI3_Handler.Init.CLKPolarity = SPI_POLARITY_LOW;/ ~$ i7 @, |1 A# _  e1 B! U( j
  28.     SPI3_Handler.Init.CLKPhase = SPI_PHASE_1EDGE;4 }4 {/ Q7 w. ]3 k4 E8 k, i, ~  l
  29.     SPI3_Handler.Init.NSS = SPI_NSS_SOFT;7 r1 M1 B: \0 `7 g! N8 h  S0 D
  30.     SPI3_Handler.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_128;
    ' L& j$ a% z3 e' P* E' K* [
  31.     SPI3_Handler.Init.FirstBit = SPI_FIRSTBIT_MSB;: S0 T& X- X' ]# v9 Q
  32.     SPI3_Handler.Init.TIMode = SPI_TIMODE_DISABLE;% i  I0 a& q/ Z& @# ]1 ]
  33.     SPI3_Handler.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE;: t% Q  E" g; |: ~( L. r% E. k
  34.     SPI3_Handler.Init.CRCPolynomial = 7;
    ' b7 g4 K  ^  l- y; v0 P6 m: V
  35.     SPI3_Handler.Init.CRCLength = SPI_CRC_LENGTH_DATASIZE;1 _1 n9 `  g( V
  36.     SPI3_Handler.Init.NSSPMode = SPI_NSS_PULSE_DISABLE;, |1 O1 q' u9 {7 Q+ N, R8 c

  37. , D3 E* d2 P1 b: E8 F, C
  38.     SPI3_Handler.RxISR = rx_isr;
    3 }3 c+ o& I3 ]- }
  39.     SPI3_Handler.TxISR = tx_isr;9 B+ m$ t3 `* C: d$ o; m/ {8 f
  40.                 ' P- \4 P7 o( `2 b: Z
  41.     HAL_SPI_Init(&SPI3_Handler);6 W7 S# Z1 }6 G+ k# T) z
  42. / I. z* ~! I# G
  43.     //__HAL_SPI_ENABLE_IT(&SPI3_Handler, SPI_IT_TXE);# |$ i$ V0 F" Q# y' o
  44.     __HAL_SPI_ENABLE_IT(&SPI3_Handler, SPI_IT_RXNE);' B+ T8 p& Q& {" T

  45. 4 D# y) x3 @8 \/ |* E- i8 ~
  46. }
    6 N0 n9 D4 {4 F; {: f
  47. void SPI3_IRQHandler(void)
    5 `% T7 v# u2 m# y
  48. {
    5 o; u; X: D) d9 S3 o' I4 K
  49.     HAL_SPI_IRQHandler(&SPI3_Handler);8 e$ g# D+ y5 ~$ x3 e5 Q7 ~
  50. }
复制代码

. Z0 y- N0 H4 L% e3 f) v. {" H对应的读写操作如下:9 B  J$ `$ Q- |
( [  z) {+ K" h% m/ n/ V$ l0 x
  1. u16 W25QXX_ReadID(void)
    : z& S3 O! S3 K: b$ s
  2. {
    * p7 C2 H2 u* O3 B
  3.     u16 Temp = 0;( j8 d4 v# ?/ l0 v3 |5 O

  4. % @1 S* x' _6 |+ j0 _
  5.     HAL_GPIO_WritePin(GPIOA, GPIO_PIN_4, GPIO_PIN_RESET);+ ~3 M0 S( p- H
  6.     SPI3_ReadWriteByte(0x90);//发送读取ID命令3 t% D' \9 d7 V0 y# Q) a9 _
  7.     SPI3_ReadWriteByte(0x00);
    7 D5 _0 Z& k) z! ]
  8.     SPI3_ReadWriteByte(0x00);
    3 k% l! o" j! O1 {& [; [
  9.     SPI3_ReadWriteByte(0x00);1 Y1 @" |' Y1 S+ Q& X7 x& u
  10.     Temp |= SPI3_ReadWriteByte(0xFF) << 8;' \; |7 k" u5 `9 g: x4 D% E
  11.     Temp |= SPI3_ReadWriteByte(0xFF);9 [! c- ?) r0 m. K5 d; L  U. T
  12.     HAL_GPIO_WritePin(GPIOA, GPIO_PIN_4, GPIO_PIN_SET);0 F2 ?: i1 j8 N9 p: k; Z
  13.     return Temp;" }6 s: b9 [2 }8 ?: s
  14. }
复制代码

' E* E* H: n; o显示结果如下:$ O; x  `# i! U/ V& w5 r
20200423172457741.png
0 A% D' Z' T7 A% Y
6 [2 G. V7 k, p, p% c& {2 B" S
其中前面4个0xFF是因为在写,写完4个byte同样会进入4次中断,但由于我们在接收中断就把数据接受了,所以SPI3_ReadWriteByte因为超时才退出的,可以明显看到几个数不是同时打印的,至于后面的ID没有显示也是同样的道理。, W4 |! k+ H$ H, w6 i

- I. u: _, E9 D3 M, w: m发送缓冲区空中断
: y" U/ Q- W6 u( j/ s同样在前面使能发送完成中断就可以了:: K! g0 n6 Y. v9 v& M' O

  R5 c2 C3 o" ]% @4 |8 @
  1. __HAL_SPI_ENABLE_IT(&SPI3_Handler, SPI_IT_TXE);
复制代码
- h: [- i0 z* Q1 l
但是由于发送完成了之后,发送缓冲区一直为空,所以会一直进入中断,所以我们使用发送完成中断的话,发送完成后除非再次填值或者关闭中断,否则会一直不停进入中断。3 R4 [. v$ K" H% f
+ ?# e6 e8 C1 J; R# j6 a
而实际上HAL库是提供了一个HAL_SPI_TransmitReceive_IT用于中断使用的发送接收函数,其中很重要的一部分内容:
6 g# v" G3 L- K+ U5 u; G' i, L6 F& d  P2 L7 ]$ O- z+ x0 }
  1.   hspi->ErrorCode   = HAL_SPI_ERROR_NONE;4 I1 Q4 T; W  y1 _0 f
  2.   hspi->pTxBuffPtr  = pTxData;
    3 f7 @. V, L( P; c, G
  3.   hspi->TxXferSize  = Size;
    ' |! Y, f  q6 i% q
  4.   hspi->TxXferCount = Size;) K1 I/ d$ F* p. |. u
  5.   hspi->pRxBuffPtr  = pRxData;! g9 h! ~/ q( {  y, u
  6.   hspi->RxXferSize  = Size;
    , j3 P6 `1 M. x3 T
  7.   hspi->RxXferCount = Size;, h: V4 @! `; \! O" o
  8. & \  s6 }2 G& V. [3 n9 Q8 _6 S
  9.   /* Set the function for IT treatment */
    * L% H6 l8 H' M7 p' R1 j* o
  10.   if(hspi->Init.DataSize > SPI_DATASIZE_8BIT )
    ; b" m. `8 h+ {& `
  11.   {
    0 G' M6 J* j$ c8 [9 U
  12.     hspi->RxISR = SPI_2linesRxISR_16BIT;7 i1 M8 p3 x+ F2 x" K) H
  13.     hspi->TxISR = SPI_2linesTxISR_16BIT;8 K$ j5 s4 D7 C  F5 i
  14.   }
    9 L0 |1 J1 b3 E7 R' X
  15.   else7 Z, ^4 j$ w: j- ~6 {* H# ~- |' T7 ?3 k
  16.   {0 v- C" S) f8 ^+ ~. j4 a, h3 ^
  17.     hspi->RxISR = SPI_2linesRxISR_8BIT;
    ; Z* W$ d2 w9 \+ z" q2 g: X
  18.     hspi->TxISR = SPI_2linesTxISR_8BIT;! m' `2 ]- F7 |, R+ ]$ N1 Q
  19.   }) _* K7 z) a& O3 M/ y$ X
  20.   __HAL_SPI_ENABLE_IT(hspi, (SPI_IT_TXE | SPI_IT_RXNE | SPI_IT_ERR));
复制代码

& A) @9 ?$ n& |6 q% L重新配置了中断函数,配置了发送和接收缓冲区为传入的数组,所以这里的数组要设置为全局变量,而前面设置的中断函数也失效了,而且使能了中断,所以我们前面所作的工作都是白费了。6 L9 [' Z, @- J0 G1 o. S9 {4 y

" }4 Z: n: i$ e* G4 l: I9 a
0 t: a" }, C! Y: C/ i& s2 t6 I2 U2 U/ M8 K# [; C
收藏 评论0 发布时间:2021-12-17 12:04

举报

0个回答

所属标签

相似技术帖

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