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

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

[复制链接]
STMCU小助手 发布时间:2021-12-17 12:04
虽然在平常的使用中,spi使用轮询等待发送完成或者接收完成就行了。
8 j- }8 l! r4 Z/ m6 D3 ~但是在对时间有严格要求的设计中,假设我们需要发送完成后立马做xx事情,此时如果有低优先级的信号需要处理,我们的轮询方式就得不到及时的响应;
2 l' H- Q  d/ m2 h或者说比如需要定时从spi设备中采集数据,定时器中断来了我们就要马上调用接收函数,接收完成马上进行其他计算,同样此时应该保证数据的优先级。
3 s, O( S- _. x: }此时就需要用到发送完成和接收中断了。
  |6 v$ d5 X3 r! \8 F  i: a+ {% b& G1 \" |/ ^  I" X7 K+ W/ t; l
前面我们已经实现了SPI轮询的发送和接收,在前面的基础上进行修改。
; C8 z0 T6 p8 x, P# R9 U4 L! _7 X3 z' z) W) h+ O/ ^! c3 I- G6 _
接缓冲区满中断
- W4 w( V2 k4 p* V6 L新增发送和接收的回调函数,并在初始化的时候配置,使能SPI接收中断:
# w/ `3 ?6 T* W- j: I0 ~
7 k4 s- z, L/ V- E2 U% A4 d
  1. SPI_HandleTypeDef SPI3_Handler;  //SPI2句柄
    / p. ?( N' D4 Y
  2. 5 E6 `# o, k' H, g; g: f
  3. void rx_isr(SPI_HandleTypeDef *hspi)
    ) b9 h' W& a9 Z, D% B- R
  4. {
    . O  {! Z$ \$ B0 k
  5.     if (__HAL_SPI_GET_FLAG(hspi, SPI_FLAG_TXE) == 1)
    $ p* L) B* A' a
  6.     {
    % ]# f; t( q9 o  K8 c
  7.         u8 data = SPI3->DR;
    ( J. }: R# o. g  G% D( N
  8.                 printf("0x%X  ",data);' j) a# g% q$ ~( z' G
  9.     }
    ! F7 i9 g& g9 |: W% I; `9 m7 C
  10. }! \# g' {! r* e( N
  11. void tx_isr(SPI_HandleTypeDef *hspi)3 [: ]; O. U; S* k3 r4 l
  12. {* S) ^$ J3 l* U3 q1 K: z
  13.     if (__HAL_SPI_GET_FLAG(hspi, SPI_FLAG_TXE) == 1)
    7 W$ ~) X- p5 H- n7 L$ k+ c
  14.     {; ~5 Z3 i1 q+ }6 K" k) U
  15. ' e5 r" x% G& S+ {0 N1 K) |! C
  16.     }/ u  `- L- {9 y: ~+ |
  17. }  D- q0 Y- T# C
  18. void SPI3_Init(void)( @# t- c& _1 J" }+ [
  19. {
    7 e- F! i, P- B6 \$ v+ A6 i0 f
  20.     HAL_NVIC_SetPriority(SPI3_IRQn, 0, 0);7 V1 y3 i  t5 z7 k% Q2 X
  21.     HAL_NVIC_EnableIRQ(SPI3_IRQn);. H& w: Y- X5 S* v7 h" H5 o

  22. 4 z5 K* ^/ {- c9 Z! j1 |: c
  23.     SPI3_Handler.Instance = SPI3;" @* v" o/ K0 f  y) T3 i# j
  24.     SPI3_Handler.Init.Mode = SPI_MODE_MASTER;
    1 Z, a8 _1 ?8 }6 h5 N+ L" d. X
  25.     SPI3_Handler.Init.Direction = SPI_DIRECTION_2LINES;
    + U# s( q- u1 F4 N5 R+ R8 Y
  26.     SPI3_Handler.Init.DataSize = SPI_DATASIZE_8BIT;
    6 ^3 M% K3 x5 j0 ^' q
  27.     SPI3_Handler.Init.CLKPolarity = SPI_POLARITY_LOW;5 }, i1 |- h1 w
  28.     SPI3_Handler.Init.CLKPhase = SPI_PHASE_1EDGE;2 ]  ^/ V* N/ `! W
  29.     SPI3_Handler.Init.NSS = SPI_NSS_SOFT;: [1 D5 U$ z8 K% }
  30.     SPI3_Handler.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_128;) r$ r# ]7 S- w7 i; `. |3 _
  31.     SPI3_Handler.Init.FirstBit = SPI_FIRSTBIT_MSB;9 U. ?$ ?! V7 ]# l! a+ }
  32.     SPI3_Handler.Init.TIMode = SPI_TIMODE_DISABLE;
    ' G; S+ @& X6 `8 C5 K1 ?
  33.     SPI3_Handler.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE;$ z3 q, B* a, B; m" k4 y: ?
  34.     SPI3_Handler.Init.CRCPolynomial = 7;4 Z; Y; d% V, Z
  35.     SPI3_Handler.Init.CRCLength = SPI_CRC_LENGTH_DATASIZE;" ~! N" D2 U- B1 t+ M  F* t( G8 i
  36.     SPI3_Handler.Init.NSSPMode = SPI_NSS_PULSE_DISABLE;
    2 ^. `2 R1 M; I1 M

  37. 1 S/ t) q% b+ b# j1 G( s  J6 d* Q
  38.     SPI3_Handler.RxISR = rx_isr;
    4 e/ R! W2 h- H) Z7 r( J& H' T
  39.     SPI3_Handler.TxISR = tx_isr;# N+ p+ ]/ ?, c: V  ]1 k9 y
  40.                
    ' F4 l: |5 l& d3 z
  41.     HAL_SPI_Init(&SPI3_Handler);) l# F/ D) ]' W; C
  42.   f' S9 l3 u# O
  43.     //__HAL_SPI_ENABLE_IT(&SPI3_Handler, SPI_IT_TXE);2 d& z$ @% i* E: e" {9 @- S" J+ q; K
  44.     __HAL_SPI_ENABLE_IT(&SPI3_Handler, SPI_IT_RXNE);
    2 V7 ?. ?5 r- g
  45. ) B" b3 C+ |- q4 t1 t
  46. }
    - f& S: f' w& b9 u& F( D% Y! G# e/ K
  47. void SPI3_IRQHandler(void)3 r/ i3 L" t+ D4 y7 h7 E' V; n+ q: j
  48. {
    ; q9 _% t( K) [# f
  49.     HAL_SPI_IRQHandler(&SPI3_Handler);
    % a+ J  g. Q$ J$ y; d
  50. }
复制代码
  N8 p& V9 E, |7 N+ |- |
对应的读写操作如下:
& |, P+ s0 o" i5 l; R/ m: a/ P$ z" S
  1. u16 W25QXX_ReadID(void)
    ) f0 V$ v- W& {
  2. {
    0 E4 v+ z8 C- T5 s3 }1 ^
  3.     u16 Temp = 0;
    * E2 A  _9 L' H

  4. ; n7 G0 C% |7 h5 M
  5.     HAL_GPIO_WritePin(GPIOA, GPIO_PIN_4, GPIO_PIN_RESET);
      l6 W* E5 \! m1 T3 t, S
  6.     SPI3_ReadWriteByte(0x90);//发送读取ID命令
    / @. D  Y. O* X$ t3 x7 d( E' L
  7.     SPI3_ReadWriteByte(0x00);
    # [: A" S4 |! o' w4 R7 f8 u  v1 m
  8.     SPI3_ReadWriteByte(0x00);/ o+ f: J0 L: E" n4 L5 C  O
  9.     SPI3_ReadWriteByte(0x00);- u" W) Y  g4 y6 {
  10.     Temp |= SPI3_ReadWriteByte(0xFF) << 8;
    3 A2 A7 Y  f9 W' c
  11.     Temp |= SPI3_ReadWriteByte(0xFF);9 Y6 N! d$ S. b4 H) g, k+ Z
  12.     HAL_GPIO_WritePin(GPIOA, GPIO_PIN_4, GPIO_PIN_SET);+ l, ^# j5 l6 ~4 u% M) B  ]# d* ~
  13.     return Temp;- B+ k! B- V, z8 q7 O
  14. }
复制代码

+ \& h: N3 F, x: B( d显示结果如下:
) T: \8 |/ ^/ E0 H/ l  k+ \
20200423172457741.png

1 U) a, ~; k: ?9 I! I) J1 D& T  R( J- ?( q* ?- B! X
其中前面4个0xFF是因为在写,写完4个byte同样会进入4次中断,但由于我们在接收中断就把数据接受了,所以SPI3_ReadWriteByte因为超时才退出的,可以明显看到几个数不是同时打印的,至于后面的ID没有显示也是同样的道理。: S/ j& C( y8 r* Y" W! {
1 ^! M6 ^! T" S; k, k" f( r
发送缓冲区空中断3 ~% [& U* }6 }! R& w5 l) w
同样在前面使能发送完成中断就可以了:
4 c! }3 Y1 u9 D; X# ~( s. I
& p5 c7 F+ ]6 M. J  I
  1. __HAL_SPI_ENABLE_IT(&SPI3_Handler, SPI_IT_TXE);
复制代码

, Y# I, K; e/ s6 d7 ?但是由于发送完成了之后,发送缓冲区一直为空,所以会一直进入中断,所以我们使用发送完成中断的话,发送完成后除非再次填值或者关闭中断,否则会一直不停进入中断。2 e  i* f  o$ _% ]1 O% i" L
  j& f( m: C6 r; i7 W: A9 H" N& }
而实际上HAL库是提供了一个HAL_SPI_TransmitReceive_IT用于中断使用的发送接收函数,其中很重要的一部分内容:
0 M2 Z7 _$ N* U; `6 U9 y( X+ }/ `7 h+ f6 ~; J7 X' K
  1.   hspi->ErrorCode   = HAL_SPI_ERROR_NONE;% X/ z/ Z% s: S: p) A
  2.   hspi->pTxBuffPtr  = pTxData;
    % G$ p  k0 z$ W: v- F. J
  3.   hspi->TxXferSize  = Size;
    " w. Z: k5 l: ?0 }% P. _
  4.   hspi->TxXferCount = Size;
    + h' v/ _* M5 R1 w$ r2 ?
  5.   hspi->pRxBuffPtr  = pRxData;
    4 Z# G: j$ r1 J/ u$ _6 H6 y
  6.   hspi->RxXferSize  = Size;
    & M7 L0 V9 b0 ]4 a+ h0 S, g0 f2 ~
  7.   hspi->RxXferCount = Size;0 s( C2 Y6 [1 q8 W0 w
  8. 4 g5 E/ W8 S; w. L1 ^1 h
  9.   /* Set the function for IT treatment */
    & v; s. ~, N3 `- b. ?& p5 ?
  10.   if(hspi->Init.DataSize > SPI_DATASIZE_8BIT )
    / v+ E7 l! \" U! X% Z% S
  11.   {3 f6 f3 n2 Z3 V" s
  12.     hspi->RxISR = SPI_2linesRxISR_16BIT;
    4 c- f2 R- g/ `; Z: H2 [2 C
  13.     hspi->TxISR = SPI_2linesTxISR_16BIT;
    5 @* U2 C/ e/ k0 R
  14.   }8 W. S. R# A3 L
  15.   else" Y0 ]* C# ^* S! s5 e7 E% N
  16.   {
    6 G9 @5 C. E* {9 r: a
  17.     hspi->RxISR = SPI_2linesRxISR_8BIT;
    - [+ s5 R: Y) A2 ^" \
  18.     hspi->TxISR = SPI_2linesTxISR_8BIT;
    * C2 ?6 ?$ i. C* W
  19.   }
    4 @, ^* P$ P$ b6 E
  20.   __HAL_SPI_ENABLE_IT(hspi, (SPI_IT_TXE | SPI_IT_RXNE | SPI_IT_ERR));
复制代码

7 R1 z1 ]; a: l7 S' g重新配置了中断函数,配置了发送和接收缓冲区为传入的数组,所以这里的数组要设置为全局变量,而前面设置的中断函数也失效了,而且使能了中断,所以我们前面所作的工作都是白费了。  {7 O8 J& R) B7 H2 w

4 E( y! X( }3 r: C" w! I/ h4 [! |( d$ V

1 Z0 T0 h1 b. v& I
赞 收藏 评论0 发布时间:2021-12-17 12:04

举报

0个回答

所属标签

相似技术帖

官网相关资源

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