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

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

[复制链接]
STMCU小助手 发布时间:2021-12-17 12:04
虽然在平常的使用中,spi使用轮询等待发送完成或者接收完成就行了。
- @; {5 v" \, d0 s/ ]" P但是在对时间有严格要求的设计中,假设我们需要发送完成后立马做xx事情,此时如果有低优先级的信号需要处理,我们的轮询方式就得不到及时的响应;5 h& ~' W" M( V
或者说比如需要定时从spi设备中采集数据,定时器中断来了我们就要马上调用接收函数,接收完成马上进行其他计算,同样此时应该保证数据的优先级。
: P' Y8 c7 l  f. V此时就需要用到发送完成和接收中断了。
  q) M1 o: `# o+ Z: N" u8 Y
. L5 o( H& A: Q, n! ~: _7 U. J: ~前面我们已经实现了SPI轮询的发送和接收,在前面的基础上进行修改。$ s! g- y, i/ r) X9 b

" o" b- b! ~6 r5 v接缓冲区满中断2 J. k! G  o4 M1 S$ @- A
新增发送和接收的回调函数,并在初始化的时候配置,使能SPI接收中断:1 c2 v  }, Z! w- Q/ p$ }0 f  {
4 S4 X, X6 B; j: }
  1. SPI_HandleTypeDef SPI3_Handler;  //SPI2句柄; P+ l" W( r/ h2 b+ q: r
  2. / e" U4 ~% T/ ?" n1 B
  3. void rx_isr(SPI_HandleTypeDef *hspi)
    / s/ s6 u3 J4 r2 ~5 A
  4. {0 Z6 S( P1 f& F8 F  b- D
  5.     if (__HAL_SPI_GET_FLAG(hspi, SPI_FLAG_TXE) == 1)( Z7 M& v9 N+ V' k% n/ ]+ ?
  6.     {
    6 _% \3 v8 Z& r- ~' u
  7.         u8 data = SPI3->DR;' v" Y  u3 ^; l% g$ n. g) c; F! ~
  8.                 printf("0x%X  ",data);; v/ c: H  V. N/ g7 u& t6 S
  9.     }$ W$ C( d+ O  l2 }- ?- E& P: k, @
  10. }' u4 y, n9 a/ C+ s8 c2 u9 J6 ^
  11. void tx_isr(SPI_HandleTypeDef *hspi)4 n" H! [% L( k% G
  12. {; o" f/ o) I) A" z3 b
  13.     if (__HAL_SPI_GET_FLAG(hspi, SPI_FLAG_TXE) == 1)
    " k. X4 n. ]  U8 ~, F# n7 Y! F
  14.     {
    / t2 P$ N6 E' T5 R) l; K
  15. % I1 I1 y8 a9 y) Q0 M9 n
  16.     }
    - ~- M7 s4 ^2 [- B+ v- D/ \
  17. }) s$ B. a; V( d% Z' H
  18. void SPI3_Init(void)9 z4 b  l4 ?9 r6 N; A% D
  19. {
      O) m7 h- W. G) b9 g
  20.     HAL_NVIC_SetPriority(SPI3_IRQn, 0, 0);
    : G7 h' B* p% Y) _4 z; O' @
  21.     HAL_NVIC_EnableIRQ(SPI3_IRQn);. X6 S7 ^* U9 q; j. w8 v5 e8 _+ W

  22. ! r" t7 [$ f6 V2 v# b+ _, U
  23.     SPI3_Handler.Instance = SPI3;
    / p8 a  S; M6 j( w% w6 I" ?5 w- N
  24.     SPI3_Handler.Init.Mode = SPI_MODE_MASTER;( U. W- \/ u  G, N$ i5 b/ N
  25.     SPI3_Handler.Init.Direction = SPI_DIRECTION_2LINES;. M6 F" B" M% O" F7 a9 n9 @
  26.     SPI3_Handler.Init.DataSize = SPI_DATASIZE_8BIT;* t& F9 c) Y" ~) S7 c/ g
  27.     SPI3_Handler.Init.CLKPolarity = SPI_POLARITY_LOW;
    : K0 |2 |+ T+ m0 r- y
  28.     SPI3_Handler.Init.CLKPhase = SPI_PHASE_1EDGE;
    + h# g% o1 {5 Z' ?3 u
  29.     SPI3_Handler.Init.NSS = SPI_NSS_SOFT;6 O6 r" Z: d, Q' r* y- i
  30.     SPI3_Handler.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_128;$ F2 j+ ^' _# S9 m" H
  31.     SPI3_Handler.Init.FirstBit = SPI_FIRSTBIT_MSB;
    , R* p) @0 B" U2 z( y" C% e
  32.     SPI3_Handler.Init.TIMode = SPI_TIMODE_DISABLE;
    ' S& W5 J: h3 x7 h
  33.     SPI3_Handler.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE;, t* K0 y: E& I/ h
  34.     SPI3_Handler.Init.CRCPolynomial = 7;
    ) \/ F' G# P- p1 }( y/ B8 l0 M
  35.     SPI3_Handler.Init.CRCLength = SPI_CRC_LENGTH_DATASIZE;* ^- M; E+ I0 U6 L
  36.     SPI3_Handler.Init.NSSPMode = SPI_NSS_PULSE_DISABLE;* Z! O, o/ b% {- g, G0 v
  37. ; `! Q6 M+ D' h6 D5 h) G
  38.     SPI3_Handler.RxISR = rx_isr;
    * [6 ^$ J2 F0 p  u1 W
  39.     SPI3_Handler.TxISR = tx_isr;
    7 j) R* {2 e+ r# L
  40.                
    , `# G5 z- z# P* m1 u- L! y( e
  41.     HAL_SPI_Init(&SPI3_Handler);6 |# W6 _4 X! |  N3 S% X9 v4 d& z

  42. + [6 _) Y' U; y" [! c
  43.     //__HAL_SPI_ENABLE_IT(&SPI3_Handler, SPI_IT_TXE);* R" C* m" f8 D+ q5 |' P0 W
  44.     __HAL_SPI_ENABLE_IT(&SPI3_Handler, SPI_IT_RXNE);/ k. C* K3 G& I1 k& G
  45. - q2 G" k) A5 k- A- q5 t. T) J
  46. }3 O9 j2 U* {- E! f9 ^
  47. void SPI3_IRQHandler(void)$ f2 ]8 V; N( A4 r
  48. {
    ! a; ~2 z4 K1 f) e6 E5 e0 U
  49.     HAL_SPI_IRQHandler(&SPI3_Handler);
    8 e1 u$ c' m: j
  50. }
复制代码
3 N# e- a4 b: x$ ^+ x
对应的读写操作如下:- r! ~5 b0 p( {( I4 R
) m; A, N  [/ c0 ^& ?
  1. u16 W25QXX_ReadID(void)6 u1 ?3 O8 i1 ]# F2 \
  2. {/ X& x$ \9 E4 Z% e1 P- Y
  3.     u16 Temp = 0;
    7 f' |  s& s( h1 ^! t6 p
  4. - c. a/ a4 U+ B5 r6 a- c
  5.     HAL_GPIO_WritePin(GPIOA, GPIO_PIN_4, GPIO_PIN_RESET);" V  o# L3 W; s! z2 \8 F1 f
  6.     SPI3_ReadWriteByte(0x90);//发送读取ID命令
    ) ]& N8 j8 z% d8 T& q
  7.     SPI3_ReadWriteByte(0x00);0 [1 N( {. U1 |; @7 Q6 s
  8.     SPI3_ReadWriteByte(0x00);( E2 J4 y3 y1 [' Y' K% p+ i
  9.     SPI3_ReadWriteByte(0x00);# P6 ?  n, C' O3 S5 r
  10.     Temp |= SPI3_ReadWriteByte(0xFF) << 8;
    " T* Z" O5 W) u& [4 ~
  11.     Temp |= SPI3_ReadWriteByte(0xFF);
    ' ]# ^  E- _3 M2 h, ~4 ^6 m
  12.     HAL_GPIO_WritePin(GPIOA, GPIO_PIN_4, GPIO_PIN_SET);4 }4 I4 {; C1 |; @
  13.     return Temp;; ?: k) X5 r) t* J5 X
  14. }
复制代码
, h- C  `$ H. c2 F
显示结果如下:, s( D+ R8 F+ j3 Q1 R% e# M) w; q
20200423172457741.png
) W, E, U$ G  w6 U% Z, L5 W/ N

2 U3 U! L3 W% V, J: |; M6 d其中前面4个0xFF是因为在写,写完4个byte同样会进入4次中断,但由于我们在接收中断就把数据接受了,所以SPI3_ReadWriteByte因为超时才退出的,可以明显看到几个数不是同时打印的,至于后面的ID没有显示也是同样的道理。
# l  J, I5 K4 @* F
4 }5 S5 x( b, c发送缓冲区空中断, A+ h0 c9 a; u3 V
同样在前面使能发送完成中断就可以了:
; p* ^, q' B+ m: `' W# G; r1 M5 y5 U9 T% h/ i
  1. __HAL_SPI_ENABLE_IT(&SPI3_Handler, SPI_IT_TXE);
复制代码
0 I& U" Z  m7 \5 e. \; z( ]
但是由于发送完成了之后,发送缓冲区一直为空,所以会一直进入中断,所以我们使用发送完成中断的话,发送完成后除非再次填值或者关闭中断,否则会一直不停进入中断。
: s3 n& {' O8 K* a! ^9 O3 k) f$ a  `. |5 f
而实际上HAL库是提供了一个HAL_SPI_TransmitReceive_IT用于中断使用的发送接收函数,其中很重要的一部分内容:
) Z' z* \5 C0 H! ~- T9 |9 K  _4 H: k4 A
  1.   hspi->ErrorCode   = HAL_SPI_ERROR_NONE;
    & y- x0 J, k$ Y( c( ]; H* O) J" Z
  2.   hspi->pTxBuffPtr  = pTxData;
    ( ~. g1 z; C7 l
  3.   hspi->TxXferSize  = Size;1 [2 l) p# _5 b7 v+ \
  4.   hspi->TxXferCount = Size;
    $ g" H! _) C) |4 W1 D5 ]
  5.   hspi->pRxBuffPtr  = pRxData;
    # @5 b, ^, |! U' |; |' p- `
  6.   hspi->RxXferSize  = Size;
    . h' t+ P. e/ U4 Y) Q
  7.   hspi->RxXferCount = Size;
    1 `2 h: u+ `- U6 @2 y* M! a8 z

  8. ; P% T3 }# Y9 N
  9.   /* Set the function for IT treatment */6 o/ s8 G, i; p# W
  10.   if(hspi->Init.DataSize > SPI_DATASIZE_8BIT )8 y2 X4 F+ {' F6 t: ]( v! J  n
  11.   {) A- q( l  T* V. R( o6 ?
  12.     hspi->RxISR = SPI_2linesRxISR_16BIT;0 F- h) \; Z' O- l& \1 ~
  13.     hspi->TxISR = SPI_2linesTxISR_16BIT;- [, S6 [5 C1 S: _: _3 w
  14.   }9 q  ^# g& O( A2 y: y" ~
  15.   else2 c/ e4 u6 b; h8 ]$ `/ j! V
  16.   {; Y. h- W  y  u* v0 V6 @8 q
  17.     hspi->RxISR = SPI_2linesRxISR_8BIT;. a% p" T3 [0 r9 z
  18.     hspi->TxISR = SPI_2linesTxISR_8BIT;" I$ ]$ e4 W5 j/ c5 k; U% Q
  19.   }2 Y* C: i/ `# Z; u! Q( _" F+ J
  20.   __HAL_SPI_ENABLE_IT(hspi, (SPI_IT_TXE | SPI_IT_RXNE | SPI_IT_ERR));
复制代码
  @/ b3 ^1 L; _2 ?: W/ Y
重新配置了中断函数,配置了发送和接收缓冲区为传入的数组,所以这里的数组要设置为全局变量,而前面设置的中断函数也失效了,而且使能了中断,所以我们前面所作的工作都是白费了。
6 X2 R( G" u! O/ q+ W- k1 o# h
% k6 |% T; I% X& n" V! o, a* T  K( O% _, I+ N& }

% j" p4 ^, ]" L) Y
收藏 评论0 发布时间:2021-12-17 12:04

举报

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