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

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

[复制链接]
STMCU小助手 发布时间:2021-12-17 12:04
虽然在平常的使用中,spi使用轮询等待发送完成或者接收完成就行了。
& A. U) @7 G+ u, l/ e6 b: h但是在对时间有严格要求的设计中,假设我们需要发送完成后立马做xx事情,此时如果有低优先级的信号需要处理,我们的轮询方式就得不到及时的响应;
+ n% d- A8 [0 @! p7 T# D" Q或者说比如需要定时从spi设备中采集数据,定时器中断来了我们就要马上调用接收函数,接收完成马上进行其他计算,同样此时应该保证数据的优先级。% _5 R/ i8 I. O# O/ p
此时就需要用到发送完成和接收中断了。
7 w" s$ W% C) u1 E
, W' @- a6 O* o1 ]  L- N7 `+ v6 k8 ~前面我们已经实现了SPI轮询的发送和接收,在前面的基础上进行修改。
1 a9 ?/ }2 z/ u0 _8 B( n4 D8 \6 \) N7 K# S: ^) V
接缓冲区满中断" i& S. L9 @1 P: m9 T  s
新增发送和接收的回调函数,并在初始化的时候配置,使能SPI接收中断:
6 ~& K' r' n9 E1 l* X6 N
3 a& v6 P6 f/ l8 M; P6 L% \  P
  1. SPI_HandleTypeDef SPI3_Handler;  //SPI2句柄
    ; ~4 V% ]( O& G, z+ e; t7 j
  2. 1 z- a/ o) N& ]6 s# l7 B5 I  `
  3. void rx_isr(SPI_HandleTypeDef *hspi). t7 x- v, X3 k
  4. {) u, d: B# ?$ |& G+ I5 ]2 m& n( w
  5.     if (__HAL_SPI_GET_FLAG(hspi, SPI_FLAG_TXE) == 1)
    % e6 ^8 X6 @. c; G9 W& q+ V7 C4 U
  6.     {0 X6 v/ E9 o' W/ s8 U+ m& @
  7.         u8 data = SPI3->DR;/ Z4 p  \) ~, m; |% V7 q% @
  8.                 printf("0x%X  ",data);
    + `9 d& b# i2 b$ T1 Z, M
  9.     }. R; I0 X1 p3 w
  10. }& c6 q  v# ?! |% f: H
  11. void tx_isr(SPI_HandleTypeDef *hspi). `# T* _. H$ @, j1 ~8 J: S& c
  12. {  J4 D3 M: b% \1 W0 K8 W
  13.     if (__HAL_SPI_GET_FLAG(hspi, SPI_FLAG_TXE) == 1)1 m) `1 ]" E8 |4 F, q- J& W
  14.     {
    * K# _" O9 v( Z& Y1 r8 c5 T

  15. : J1 O  G2 h9 _4 Y$ g; J
  16.     }
    + m/ z. P  {2 k+ g; {0 b; m3 R! I
  17. }- J: y4 u% g. N) V. i& {
  18. void SPI3_Init(void)
    * s! J) E" ~& s2 o* P
  19. {
    / B5 S+ |7 y; I2 y3 E
  20.     HAL_NVIC_SetPriority(SPI3_IRQn, 0, 0);
    # q" d9 U6 Z$ O' V$ q
  21.     HAL_NVIC_EnableIRQ(SPI3_IRQn);
    % Q( D$ N8 b* n4 K4 f; P- [: w
  22.   l, @6 n4 C4 D. ~
  23.     SPI3_Handler.Instance = SPI3;4 F7 `1 i3 M& ~8 E+ B
  24.     SPI3_Handler.Init.Mode = SPI_MODE_MASTER;) r+ D0 b* h* s* X3 k7 c+ C% R
  25.     SPI3_Handler.Init.Direction = SPI_DIRECTION_2LINES;
    1 V. Q: i1 b9 g; B* J! y
  26.     SPI3_Handler.Init.DataSize = SPI_DATASIZE_8BIT;# k& H# j$ W) J9 r. Y: }( A
  27.     SPI3_Handler.Init.CLKPolarity = SPI_POLARITY_LOW;
    6 P- G% G& B* s/ ^$ S8 W- }
  28.     SPI3_Handler.Init.CLKPhase = SPI_PHASE_1EDGE;/ Z4 Z/ n6 A" k- U" W
  29.     SPI3_Handler.Init.NSS = SPI_NSS_SOFT;) P3 g9 T  T$ s9 z" w$ Q2 q$ p, E
  30.     SPI3_Handler.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_128;5 L$ W8 i* {0 a; i0 a1 m  b8 p! B
  31.     SPI3_Handler.Init.FirstBit = SPI_FIRSTBIT_MSB;% ^) W# O- L6 B0 J# a
  32.     SPI3_Handler.Init.TIMode = SPI_TIMODE_DISABLE;
    ( a7 e5 H+ u& H- v8 u$ e
  33.     SPI3_Handler.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE;
    # x& q4 y  r) }. E+ s0 O. f
  34.     SPI3_Handler.Init.CRCPolynomial = 7;8 T2 T9 m' M+ G
  35.     SPI3_Handler.Init.CRCLength = SPI_CRC_LENGTH_DATASIZE;
    * y3 q, X/ S: a6 V$ Q- N5 ]8 m. ^
  36.     SPI3_Handler.Init.NSSPMode = SPI_NSS_PULSE_DISABLE;
    5 c( Y9 g" U7 n
  37. ' J5 G3 f8 _  v
  38.     SPI3_Handler.RxISR = rx_isr;
    7 g7 e( [. p9 n4 V6 s1 n! G
  39.     SPI3_Handler.TxISR = tx_isr;
    ! Z) }" [6 A* F3 O
  40.                 1 c1 D" r# ^/ k  S( z' _
  41.     HAL_SPI_Init(&SPI3_Handler);$ O( `4 e& C/ E) p6 w$ `
  42. . i- |3 u2 C9 h! P
  43.     //__HAL_SPI_ENABLE_IT(&SPI3_Handler, SPI_IT_TXE);" K, j- {( }" M% R$ e% l) k; E8 p
  44.     __HAL_SPI_ENABLE_IT(&SPI3_Handler, SPI_IT_RXNE);9 }) ~! }$ l4 {

  45. ' C& K! Y4 @4 R6 `, ?3 u' B2 \
  46. }
    + i% z/ b4 k' }, w& q0 ?  e
  47. void SPI3_IRQHandler(void)! O- U" N! h# M
  48. {# ^& Z6 U- s5 H8 W: s
  49.     HAL_SPI_IRQHandler(&SPI3_Handler);
    ( `! P' L7 w* V3 }5 t
  50. }
复制代码
0 z2 L' A4 p" h  T; z7 [
对应的读写操作如下:
  u; s6 p% `3 E$ B  _2 L, k+ d- D5 q7 s% B
  1. u16 W25QXX_ReadID(void)
    * F5 V  g# ?8 ~: T
  2. {9 p9 v* `; F9 H
  3.     u16 Temp = 0;
    $ N5 r7 x( A, v5 A; V1 M

  4. 2 \% q( Q7 [3 x8 O
  5.     HAL_GPIO_WritePin(GPIOA, GPIO_PIN_4, GPIO_PIN_RESET);
    : H% ?: m3 P$ B
  6.     SPI3_ReadWriteByte(0x90);//发送读取ID命令
    % n3 b% u+ j+ ~1 V7 v- f
  7.     SPI3_ReadWriteByte(0x00);4 U) u: ]& O/ s% V
  8.     SPI3_ReadWriteByte(0x00);
    ) t  I9 l& S5 R- j' D; U
  9.     SPI3_ReadWriteByte(0x00);2 S! b+ T# a' e3 `1 m0 z0 C3 m
  10.     Temp |= SPI3_ReadWriteByte(0xFF) << 8;6 A( }0 [9 y) F+ b& E
  11.     Temp |= SPI3_ReadWriteByte(0xFF);
      I! O, W8 S$ w# p' H8 T3 Q
  12.     HAL_GPIO_WritePin(GPIOA, GPIO_PIN_4, GPIO_PIN_SET);
    3 U; s  B: o: K3 T: g/ w
  13.     return Temp;
    . {  Q* S7 s, D* g- I3 X7 m
  14. }
复制代码
2 g" ^* K" ]& g9 _
显示结果如下:
3 P/ _$ {9 _4 E# @1 m( R
20200423172457741.png

5 `9 |$ t, S( _) ]' R8 j7 r2 |2 k. V- _3 _9 r
其中前面4个0xFF是因为在写,写完4个byte同样会进入4次中断,但由于我们在接收中断就把数据接受了,所以SPI3_ReadWriteByte因为超时才退出的,可以明显看到几个数不是同时打印的,至于后面的ID没有显示也是同样的道理。
! r9 {7 n, k5 D- V) _4 |7 k; h! i% B& D. S$ E7 I
发送缓冲区空中断
5 y; W' r* L: @" |- X  O& O同样在前面使能发送完成中断就可以了:' W& b4 g/ e1 T( l  X9 P
5 e& S; j7 i7 v
  1. __HAL_SPI_ENABLE_IT(&SPI3_Handler, SPI_IT_TXE);
复制代码

( g" [# h+ f) C' ~0 T7 p但是由于发送完成了之后,发送缓冲区一直为空,所以会一直进入中断,所以我们使用发送完成中断的话,发送完成后除非再次填值或者关闭中断,否则会一直不停进入中断。
# V: G( k8 v# }+ P) R; F* |% \* @4 L0 F: c
而实际上HAL库是提供了一个HAL_SPI_TransmitReceive_IT用于中断使用的发送接收函数,其中很重要的一部分内容:
# B# }& I2 j2 v$ B& [8 ^) e5 w8 o# k" C' t& F( j" M" h
  1.   hspi->ErrorCode   = HAL_SPI_ERROR_NONE;2 U0 |8 L0 o" j6 v/ ]
  2.   hspi->pTxBuffPtr  = pTxData;  H. G' b" Y7 Y& G5 W
  3.   hspi->TxXferSize  = Size;
    . X* {! e/ t' I1 s8 i! z
  4.   hspi->TxXferCount = Size;
    1 I1 u% U1 \5 T  c0 w/ N
  5.   hspi->pRxBuffPtr  = pRxData;
    ( f0 O" L) u# x2 b
  6.   hspi->RxXferSize  = Size;+ d% R/ b$ t; r. @% u5 H. d) b
  7.   hspi->RxXferCount = Size;
    4 q. _2 u* J+ J# e4 @. {* K. C1 |
  8. 5 T' y" O. N4 X4 J, b
  9.   /* Set the function for IT treatment */
    0 I' P3 F- O0 }/ ~1 ?4 \1 P/ n9 J
  10.   if(hspi->Init.DataSize > SPI_DATASIZE_8BIT )
    , |+ M# U8 Z$ S- i- E+ e- h
  11.   {' T  e6 ~: @7 b9 W# P& f
  12.     hspi->RxISR = SPI_2linesRxISR_16BIT;
    9 \$ B5 G( ?8 O8 ^4 }& t
  13.     hspi->TxISR = SPI_2linesTxISR_16BIT;
    & i4 C: {; Z& d- _& r
  14.   }; n6 A3 F' H" o6 j
  15.   else! c( M$ n' g  M: m9 s# b
  16.   {
    2 D, s, Y( g0 O+ w
  17.     hspi->RxISR = SPI_2linesRxISR_8BIT;
    6 E- |/ |7 `$ Q6 t5 a
  18.     hspi->TxISR = SPI_2linesTxISR_8BIT;
    # B! H4 Y7 F7 k
  19.   }
    - R7 v& Z2 u" m( Z7 I
  20.   __HAL_SPI_ENABLE_IT(hspi, (SPI_IT_TXE | SPI_IT_RXNE | SPI_IT_ERR));
复制代码

( i" c  ^/ {+ l! \/ m重新配置了中断函数,配置了发送和接收缓冲区为传入的数组,所以这里的数组要设置为全局变量,而前面设置的中断函数也失效了,而且使能了中断,所以我们前面所作的工作都是白费了。
9 U8 b6 y) f4 g, P& u+ a; N1 Q- c. C  H( g: g

# s' ]; w# v% P4 o4 G& h0 M; R, H2 b% E
收藏 评论0 发布时间:2021-12-17 12:04

举报

0个回答
关于意法半导体
我们是谁
投资者关系
意法半导体可持续发展举措
创新和工艺
招聘信息
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
关注我们
st-img 微信公众号
st-img 手机版