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

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

[复制链接]
STMCU小助手 发布时间:2021-12-17 12:04
虽然在平常的使用中,spi使用轮询等待发送完成或者接收完成就行了。( Q- b9 x; H8 n: Y. L, n
但是在对时间有严格要求的设计中,假设我们需要发送完成后立马做xx事情,此时如果有低优先级的信号需要处理,我们的轮询方式就得不到及时的响应;
& ^( Y% ?, H2 g2 C0 R7 }或者说比如需要定时从spi设备中采集数据,定时器中断来了我们就要马上调用接收函数,接收完成马上进行其他计算,同样此时应该保证数据的优先级。5 z8 `. e; ]) f4 @% {
此时就需要用到发送完成和接收中断了。# R  \( ], P+ |% L4 ~" [4 r1 `

* f0 P% y9 [3 I. s. ^4 V& c) n" h前面我们已经实现了SPI轮询的发送和接收,在前面的基础上进行修改。0 F) w9 ^! \9 o( V, s
5 f6 s/ Q) ]/ b8 E( S
接缓冲区满中断
7 }" a$ e: l; s3 K. k$ y3 W新增发送和接收的回调函数,并在初始化的时候配置,使能SPI接收中断:8 ]+ \# I6 N: v# G+ V( ]
$ M3 x. _2 F, Y; K9 L. D& X0 r6 M: o/ v
  1. SPI_HandleTypeDef SPI3_Handler;  //SPI2句柄5 k* l0 s# W9 A1 \/ q

  2. 4 N5 E4 h( |& C% t! x
  3. void rx_isr(SPI_HandleTypeDef *hspi)
    9 `3 T/ t! d7 ^* s" F  g9 T
  4. {
    3 B. M# O0 c' Z0 t0 J  ^) s
  5.     if (__HAL_SPI_GET_FLAG(hspi, SPI_FLAG_TXE) == 1)
    ) y, i4 }- B9 Y, r  |" }' P
  6.     {1 [- X  [$ q3 k% A+ B9 r
  7.         u8 data = SPI3->DR;
    ; ~& c; b3 o! y! Q3 O
  8.                 printf("0x%X  ",data);/ D! @, E* W5 W8 ~/ ^
  9.     }
    , s) Z) W6 G4 R* u# R& }3 P' H
  10. }
    : z. ^# x9 _- D( a. _6 Y9 q
  11. void tx_isr(SPI_HandleTypeDef *hspi). y$ E. q* d. b1 I
  12. {6 h, F6 n  r0 g
  13.     if (__HAL_SPI_GET_FLAG(hspi, SPI_FLAG_TXE) == 1)
    2 E$ C5 c  Y9 n" W$ g
  14.     {( w% P9 G; g8 ]3 c- I. a  j! v
  15. 9 s/ ^' J8 s7 f7 |+ ~
  16.     }
      |. K. D4 T) t% }
  17. }
    ; J2 r! n: C0 \& Y
  18. void SPI3_Init(void)2 }8 i" r; d: C( o/ I( }& G
  19. {
    6 w9 N6 m, z5 ?- x1 E. C9 S1 V
  20.     HAL_NVIC_SetPriority(SPI3_IRQn, 0, 0);
    4 u- `3 b) w% X  ~) j
  21.     HAL_NVIC_EnableIRQ(SPI3_IRQn);. Y: s) b+ \+ ?

  22. & D$ i3 m) o; J9 A* e& }; ^; V. l" U
  23.     SPI3_Handler.Instance = SPI3;5 H# y) t, X% U/ J! W) Y7 P; z
  24.     SPI3_Handler.Init.Mode = SPI_MODE_MASTER;
    3 U. j! c0 d8 @
  25.     SPI3_Handler.Init.Direction = SPI_DIRECTION_2LINES;
    ) M, h6 c2 c5 @) t
  26.     SPI3_Handler.Init.DataSize = SPI_DATASIZE_8BIT;3 k! F3 U! L( m! O
  27.     SPI3_Handler.Init.CLKPolarity = SPI_POLARITY_LOW;
    2 a9 {4 `& ~/ S5 C$ |7 I2 C
  28.     SPI3_Handler.Init.CLKPhase = SPI_PHASE_1EDGE;
    : Y$ b: ?4 A9 `. W: ?8 O$ x) Y3 C
  29.     SPI3_Handler.Init.NSS = SPI_NSS_SOFT;# X+ f& L5 X4 z5 x
  30.     SPI3_Handler.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_128;9 g7 R9 v1 h0 S
  31.     SPI3_Handler.Init.FirstBit = SPI_FIRSTBIT_MSB;
    0 B3 X$ g! d5 ^) p8 V
  32.     SPI3_Handler.Init.TIMode = SPI_TIMODE_DISABLE;( j# p; e# T6 g9 P
  33.     SPI3_Handler.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE;
    : `/ D4 V1 d/ D
  34.     SPI3_Handler.Init.CRCPolynomial = 7;
    3 d# w2 @4 F% L
  35.     SPI3_Handler.Init.CRCLength = SPI_CRC_LENGTH_DATASIZE;- g, q1 d/ E/ s- N; K& Q5 w
  36.     SPI3_Handler.Init.NSSPMode = SPI_NSS_PULSE_DISABLE;, X7 p9 u9 t( x

  37. + N9 I# q$ C  r
  38.     SPI3_Handler.RxISR = rx_isr;
    : O  x0 e5 F  m. A* t: ^
  39.     SPI3_Handler.TxISR = tx_isr;# u4 D  Z3 w: S+ o
  40.                 # n' b: m4 i  p! ]9 d; A2 b9 Y
  41.     HAL_SPI_Init(&SPI3_Handler);3 y/ m" a# X5 y" ~
  42. 2 w/ C# n1 `0 l" _4 e
  43.     //__HAL_SPI_ENABLE_IT(&SPI3_Handler, SPI_IT_TXE);' b4 d! v3 y. R) U* {4 T
  44.     __HAL_SPI_ENABLE_IT(&SPI3_Handler, SPI_IT_RXNE);
    2 S+ q0 s  i6 S7 h

  45. ( W5 x, x& D4 c. a9 ^, |/ [
  46. }9 z& T2 u( a8 E! F# l
  47. void SPI3_IRQHandler(void). f9 `1 E7 u6 T6 c
  48. {( o5 a8 |+ s. ~1 y! X5 H
  49.     HAL_SPI_IRQHandler(&SPI3_Handler);
    : k: W3 c7 a0 ?# w( \8 P
  50. }
复制代码

8 Y$ `# I6 @" v& J- [. z, q& B对应的读写操作如下:
6 B. T8 R8 K7 S+ k* W! C& h* J8 H9 n; f+ L0 p9 ^; H) W5 W
  1. u16 W25QXX_ReadID(void)
    * `2 T$ r$ i8 R$ @; Q. y
  2. {
    3 w; k" J2 [3 S8 g3 c$ x8 Z5 M
  3.     u16 Temp = 0;
    9 v6 ^! D" n) A  d% A% _2 \

  4. + P. R/ A& `" t7 n7 b. B8 A2 J
  5.     HAL_GPIO_WritePin(GPIOA, GPIO_PIN_4, GPIO_PIN_RESET);
    " I' N5 [& C+ Y0 K; Q
  6.     SPI3_ReadWriteByte(0x90);//发送读取ID命令
    * B2 {  j7 o9 p. u' M) q
  7.     SPI3_ReadWriteByte(0x00);
    + }1 Z( N) g* n5 i7 Z9 ~1 n
  8.     SPI3_ReadWriteByte(0x00);
    7 Z7 ~/ y; Z$ ?5 e6 a
  9.     SPI3_ReadWriteByte(0x00);
    9 w+ g9 r: L% a4 u
  10.     Temp |= SPI3_ReadWriteByte(0xFF) << 8;
    : X- e/ j+ m. C, `0 m
  11.     Temp |= SPI3_ReadWriteByte(0xFF);
    4 Q* F7 h! E5 ~9 ?" n6 P
  12.     HAL_GPIO_WritePin(GPIOA, GPIO_PIN_4, GPIO_PIN_SET);
    - |* D0 K' W; u; k1 G+ k$ _7 Z
  13.     return Temp;8 y0 Y+ q  J# u
  14. }
复制代码

8 y# ?' A- n. b2 ]7 F3 M/ C& Y' g% m: t显示结果如下:
6 v6 R, B( f, B$ m3 p" f
20200423172457741.png
0 y" n  x# V3 d  z
6 k$ f) z  a/ t! p. Z0 }
其中前面4个0xFF是因为在写,写完4个byte同样会进入4次中断,但由于我们在接收中断就把数据接受了,所以SPI3_ReadWriteByte因为超时才退出的,可以明显看到几个数不是同时打印的,至于后面的ID没有显示也是同样的道理。6 T# x0 @1 {; M; y
6 j& v  j% v$ z5 d# R
发送缓冲区空中断
/ [3 `; F& s/ |同样在前面使能发送完成中断就可以了:
( H  ^% o" u8 m0 |' @' Q) N2 T, w, |: ~7 ]; r7 G/ M+ E& _
  1. __HAL_SPI_ENABLE_IT(&SPI3_Handler, SPI_IT_TXE);
复制代码
5 y, t! f' ]: h3 h7 s7 n# p4 s+ h% k
但是由于发送完成了之后,发送缓冲区一直为空,所以会一直进入中断,所以我们使用发送完成中断的话,发送完成后除非再次填值或者关闭中断,否则会一直不停进入中断。! W) i7 R0 {; Q
/ P% u/ H8 E; I
而实际上HAL库是提供了一个HAL_SPI_TransmitReceive_IT用于中断使用的发送接收函数,其中很重要的一部分内容:
' _1 t* z* u. Z+ E, M* x" c
2 N, |7 \5 j/ S  e8 |2 F
  1.   hspi->ErrorCode   = HAL_SPI_ERROR_NONE;
    8 S8 M3 j, k& M% q/ `& B( F
  2.   hspi->pTxBuffPtr  = pTxData;
    " h  Y6 n3 ?0 n' C6 D
  3.   hspi->TxXferSize  = Size;4 f8 N0 {* a; @7 g# Y, y9 ~( G
  4.   hspi->TxXferCount = Size;
    ! B; e* V0 Y% H$ d
  5.   hspi->pRxBuffPtr  = pRxData;1 t% B- e' q1 F; R9 m
  6.   hspi->RxXferSize  = Size;
    ! |' J: h9 i3 r5 x9 N: ^1 {- m6 F
  7.   hspi->RxXferCount = Size;
    - C2 [& S( ?! @( \! w9 Y" E

  8. ' w- y1 t/ @8 a3 n+ ^
  9.   /* Set the function for IT treatment */
    : r( k$ R8 _) I( p: ^! m7 J( ]
  10.   if(hspi->Init.DataSize > SPI_DATASIZE_8BIT )" x3 R7 h( D. C7 H) w0 L, ~
  11.   {
    ) W% |' K- i" H/ V$ u
  12.     hspi->RxISR = SPI_2linesRxISR_16BIT;
    ! n* H/ y+ j  r8 t
  13.     hspi->TxISR = SPI_2linesTxISR_16BIT;# G- E% b, a% Y# p" D0 }: n
  14.   }
    1 f) S6 ^+ _- i" Y% _  f
  15.   else
    $ r0 @; }0 \2 F# F2 {! Z
  16.   {
    5 {3 M/ ?; r7 h6 r7 C' \$ @/ y9 w
  17.     hspi->RxISR = SPI_2linesRxISR_8BIT;
    : x+ P7 |" Y; Q
  18.     hspi->TxISR = SPI_2linesTxISR_8BIT;6 X6 j$ }9 x8 n
  19.   }
    + H4 e+ o4 c' t5 J; c& \$ t& E
  20.   __HAL_SPI_ENABLE_IT(hspi, (SPI_IT_TXE | SPI_IT_RXNE | SPI_IT_ERR));
复制代码

2 m. e. x6 h: T  J% e6 Q重新配置了中断函数,配置了发送和接收缓冲区为传入的数组,所以这里的数组要设置为全局变量,而前面设置的中断函数也失效了,而且使能了中断,所以我们前面所作的工作都是白费了。& H( B$ ~; J/ u; v" z2 ~+ l

: [* o, ]# N9 P% y
1 J- V" t4 q+ O  y+ f
7 c5 e) H! ]) d1 G& n+ ^2 R
收藏 评论0 发布时间:2021-12-17 12:04

举报

0个回答
关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
STM32Cube扩展软件包
意法半导体边缘AI套件
ST - 理想汽车豪华SUV案例
ST意法半导体智能家居案例
STM32 ARM Cortex 32位微控制器
关注我们
st-img 微信公众号
st-img 手机版