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

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

[复制链接]
STMCU小助手 发布时间:2021-12-17 12:04
虽然在平常的使用中,spi使用轮询等待发送完成或者接收完成就行了。  ^: k# F: K" d2 Q2 L1 J  n
但是在对时间有严格要求的设计中,假设我们需要发送完成后立马做xx事情,此时如果有低优先级的信号需要处理,我们的轮询方式就得不到及时的响应;
" d9 \) x: W; y& U' B( @: {或者说比如需要定时从spi设备中采集数据,定时器中断来了我们就要马上调用接收函数,接收完成马上进行其他计算,同样此时应该保证数据的优先级。
( u6 h  `! y8 p8 [/ J& p8 E. \" ?! l此时就需要用到发送完成和接收中断了。
1 R6 H' ^- K) f
' m* g$ I# R$ n0 V. }2 \! r+ P前面我们已经实现了SPI轮询的发送和接收,在前面的基础上进行修改。/ Y) `  ]; e2 T( g! A# Z1 U

( ~( N) L7 t5 ]3 e2 J接缓冲区满中断
1 P' |$ j( C; S新增发送和接收的回调函数,并在初始化的时候配置,使能SPI接收中断:' v% {/ K! s7 J& t: d

: D4 ?4 D2 y5 {; [! Z: |( u
  1. SPI_HandleTypeDef SPI3_Handler;  //SPI2句柄3 g  T) L9 i% Y2 v
  2. - W1 m& I: V7 `; X5 z. M# k
  3. void rx_isr(SPI_HandleTypeDef *hspi)
    ( K/ q$ U% G4 J" R7 _
  4. {
    & _1 Z/ R3 D" F5 J% e. e9 ~
  5.     if (__HAL_SPI_GET_FLAG(hspi, SPI_FLAG_TXE) == 1)
    8 t8 U4 B* u5 s) |, l1 B4 p5 ~+ {
  6.     {
    ( M+ K$ `5 {4 D! p
  7.         u8 data = SPI3->DR;
    ) A3 b$ H! ]+ g# b+ O) D, W% ^
  8.                 printf("0x%X  ",data);
    0 t* }0 K, j' V2 }
  9.     }9 m, F! G1 W$ x$ [
  10. }6 q8 x" u) {3 j9 }
  11. void tx_isr(SPI_HandleTypeDef *hspi)9 i: F' J" ?! w% w+ \
  12. {% K( e, c, w, r/ r; y4 N: ^! a, s
  13.     if (__HAL_SPI_GET_FLAG(hspi, SPI_FLAG_TXE) == 1); d" [6 p* H- W4 G$ ?
  14.     {
    3 j: e  r% x8 s7 u1 M

  15. / E! ^/ O4 M9 m. ]8 w3 \
  16.     }: I$ j1 ~. C$ Z1 [- W3 Y9 k/ v: J0 Z
  17. }
    . S8 S' b7 }# H0 L/ I8 m& t
  18. void SPI3_Init(void)1 t, [5 i% g- L% l3 `4 }
  19. {
    6 K- K/ J- B" S  [3 t
  20.     HAL_NVIC_SetPriority(SPI3_IRQn, 0, 0);
    6 T9 O) v: A. K" N% `0 w2 m
  21.     HAL_NVIC_EnableIRQ(SPI3_IRQn);- L4 Q1 ^; q' T0 X5 Z$ B, J
  22. * k$ T( o7 g. O  @* T6 P4 ~
  23.     SPI3_Handler.Instance = SPI3;
    ! R, L2 N. x- m( H- D# G0 {
  24.     SPI3_Handler.Init.Mode = SPI_MODE_MASTER;
    6 U. J- r9 U/ ^# `6 v
  25.     SPI3_Handler.Init.Direction = SPI_DIRECTION_2LINES;, O# ?! `2 b# ^& g6 _
  26.     SPI3_Handler.Init.DataSize = SPI_DATASIZE_8BIT;
    4 V! V6 i) x4 r5 v1 E
  27.     SPI3_Handler.Init.CLKPolarity = SPI_POLARITY_LOW;7 t% j9 w, I& ?" J. c
  28.     SPI3_Handler.Init.CLKPhase = SPI_PHASE_1EDGE;! Y2 D  ^& R5 }6 P" ~) M8 K- A
  29.     SPI3_Handler.Init.NSS = SPI_NSS_SOFT;
    2 w& T4 c# B& |; s! w# j
  30.     SPI3_Handler.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_128;
    % E$ e3 P* X; @  {
  31.     SPI3_Handler.Init.FirstBit = SPI_FIRSTBIT_MSB;4 o. U: P5 |9 _6 r+ {& d
  32.     SPI3_Handler.Init.TIMode = SPI_TIMODE_DISABLE;
    * F: P2 K$ b4 B4 t) ?( \
  33.     SPI3_Handler.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE;8 [" u7 G# f# c" C( Y* N
  34.     SPI3_Handler.Init.CRCPolynomial = 7;3 ^- m* ^0 {" R9 `
  35.     SPI3_Handler.Init.CRCLength = SPI_CRC_LENGTH_DATASIZE;, \0 ?7 v: p3 ?3 n
  36.     SPI3_Handler.Init.NSSPMode = SPI_NSS_PULSE_DISABLE;2 |& e8 d3 j4 N9 t$ I  I

  37. : E) U: `# a$ [6 R: X: q
  38.     SPI3_Handler.RxISR = rx_isr;: S, K5 m: U" N" V5 e
  39.     SPI3_Handler.TxISR = tx_isr;/ d5 Y3 z! v7 A+ ~; c% M$ ]
  40.                 " l0 q& o& a$ V
  41.     HAL_SPI_Init(&SPI3_Handler);! Q  o9 [; r, C

  42. 5 }; u6 Z, Y$ ~- S% _$ U
  43.     //__HAL_SPI_ENABLE_IT(&SPI3_Handler, SPI_IT_TXE);
    6 l& h5 Q) @9 q6 z9 R+ g. E
  44.     __HAL_SPI_ENABLE_IT(&SPI3_Handler, SPI_IT_RXNE);
    8 C# y0 h+ L; i" `! q

  45. , t. `2 q" _9 S* f) j- R5 J
  46. }( b7 V0 S8 N6 d& H1 p! E+ M# `
  47. void SPI3_IRQHandler(void)' J. ^- |! X4 ]5 u' W& c+ d; b/ c
  48. {
    / W+ j, `! ~6 Y# N& f! |
  49.     HAL_SPI_IRQHandler(&SPI3_Handler);  l0 d; k9 W' w8 M' R
  50. }
复制代码
  b$ k# Q& H; ^9 I# ?" d. a& W3 l
对应的读写操作如下:8 N; |( l4 Z+ ^$ _9 e7 J6 F, Q

/ k+ h' {: W5 w3 B
  1. u16 W25QXX_ReadID(void)6 j! O0 i2 ]: u
  2. {
    ) U  O% i) ?: K& J5 N/ |2 C
  3.     u16 Temp = 0;
    ( A9 O2 D  |' R5 T1 a8 [

  4. ( ^: P+ G" W3 B
  5.     HAL_GPIO_WritePin(GPIOA, GPIO_PIN_4, GPIO_PIN_RESET);/ i$ `1 i! g% N: |' M7 ]  `1 E6 ?
  6.     SPI3_ReadWriteByte(0x90);//发送读取ID命令6 E$ q$ r0 ?. M
  7.     SPI3_ReadWriteByte(0x00);5 G( Q0 ~, V" H" p( r3 r# I0 c* y3 i
  8.     SPI3_ReadWriteByte(0x00);
    * N0 \* W- ~3 w5 H  o
  9.     SPI3_ReadWriteByte(0x00);+ V, w. D5 b; }
  10.     Temp |= SPI3_ReadWriteByte(0xFF) << 8;
    ( E* `9 C8 t6 V3 {! ~& z
  11.     Temp |= SPI3_ReadWriteByte(0xFF);
    8 M1 z0 O7 Y1 S! f
  12.     HAL_GPIO_WritePin(GPIOA, GPIO_PIN_4, GPIO_PIN_SET);
    5 k' G, F2 `0 D4 S% V# b  ^
  13.     return Temp;( J" {: j8 ?  [+ q3 T6 U. D
  14. }
复制代码

' M! y  z! O5 N: }* ]9 k显示结果如下:
; Z6 z2 Q2 e% D/ n7 ?; v
20200423172457741.png

3 u; O" o1 R7 @4 [, ^) J0 k& P* k; P8 X
其中前面4个0xFF是因为在写,写完4个byte同样会进入4次中断,但由于我们在接收中断就把数据接受了,所以SPI3_ReadWriteByte因为超时才退出的,可以明显看到几个数不是同时打印的,至于后面的ID没有显示也是同样的道理。1 Y* T' P: s* z! U, X9 b- _

0 H0 w; ~, q# d* T( f发送缓冲区空中断
5 i6 m* y8 W7 i+ p& r- Q同样在前面使能发送完成中断就可以了:
+ t2 C; Q+ y, r  u/ [* o# z- R% Y' p6 u& ~. Z0 g* R
  1. __HAL_SPI_ENABLE_IT(&SPI3_Handler, SPI_IT_TXE);
复制代码
7 q9 }/ w) _9 Y$ S) w7 J; @* U
但是由于发送完成了之后,发送缓冲区一直为空,所以会一直进入中断,所以我们使用发送完成中断的话,发送完成后除非再次填值或者关闭中断,否则会一直不停进入中断。9 z. _* a, j3 V6 P: q- D  t
6 g, i' ]5 I4 O7 k. s
而实际上HAL库是提供了一个HAL_SPI_TransmitReceive_IT用于中断使用的发送接收函数,其中很重要的一部分内容:9 L; n9 d) v0 V, t% d
7 k2 N: L# v# k: L! X
  1.   hspi->ErrorCode   = HAL_SPI_ERROR_NONE;
    6 N5 J5 V4 E, Q) \& c3 c: c
  2.   hspi->pTxBuffPtr  = pTxData;
    6 m7 x2 }8 F/ E
  3.   hspi->TxXferSize  = Size;
    3 d1 z2 ~  f# H) }$ g
  4.   hspi->TxXferCount = Size;
    0 Q4 V5 H( \9 s* u
  5.   hspi->pRxBuffPtr  = pRxData;3 V. V3 s+ z' V3 }) e# `
  6.   hspi->RxXferSize  = Size;
    3 U3 B: |" n. J- A0 `
  7.   hspi->RxXferCount = Size;1 Z6 A# X2 c$ x3 w4 {9 j: H
  8. ) L! V& o- k5 r7 z" n
  9.   /* Set the function for IT treatment */
    - v! ^' b$ u% r& o$ Y/ R3 y) t9 O
  10.   if(hspi->Init.DataSize > SPI_DATASIZE_8BIT )
    : y3 c1 H' x7 p* [6 D
  11.   {1 d7 B) p: Q0 L" }
  12.     hspi->RxISR = SPI_2linesRxISR_16BIT;
    6 d) A: m' ~% D7 K8 N
  13.     hspi->TxISR = SPI_2linesTxISR_16BIT;
    5 w- o* t0 V# B2 e! w  R7 z
  14.   }
    $ l. `/ G5 x0 s4 J5 n
  15.   else
    ! O8 x5 z7 `$ X. m% v0 G
  16.   {( `! T5 S$ h0 l: Y1 S2 w7 ^
  17.     hspi->RxISR = SPI_2linesRxISR_8BIT;) p! _+ @' \' Q
  18.     hspi->TxISR = SPI_2linesTxISR_8BIT;! g5 O5 P  R6 C4 o4 {2 L4 l
  19.   }+ o2 t" e' z. B* c3 _
  20.   __HAL_SPI_ENABLE_IT(hspi, (SPI_IT_TXE | SPI_IT_RXNE | SPI_IT_ERR));
复制代码
6 `$ H2 l6 p9 p1 w6 Z+ z3 a+ {
重新配置了中断函数,配置了发送和接收缓冲区为传入的数组,所以这里的数组要设置为全局变量,而前面设置的中断函数也失效了,而且使能了中断,所以我们前面所作的工作都是白费了。
% g; Q: t/ u2 C. V4 L- |2 ~# `0 z$ m9 n2 ?8 G; `: [; {/ M
$ Y" }) r' p6 m8 l  Q/ R, N' _
7 J/ T& Y( v0 C
赞 收藏 评论0 发布时间:2021-12-17 12:04

举报

0个回答

所属标签

相似技术帖

官网相关资源

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