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

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

[复制链接]
STMCU小助手 发布时间:2021-12-17 12:04
虽然在平常的使用中,spi使用轮询等待发送完成或者接收完成就行了。
3 w) {$ W4 y; K) L. F1 |但是在对时间有严格要求的设计中,假设我们需要发送完成后立马做xx事情,此时如果有低优先级的信号需要处理,我们的轮询方式就得不到及时的响应;( \! h4 W% J  [2 J
或者说比如需要定时从spi设备中采集数据,定时器中断来了我们就要马上调用接收函数,接收完成马上进行其他计算,同样此时应该保证数据的优先级。* U5 F. c& ^( L( ?) K. L- [. M
此时就需要用到发送完成和接收中断了。
6 S' K  `/ {9 S- A% [. W3 W! C
9 @, v& F2 i2 d7 t前面我们已经实现了SPI轮询的发送和接收,在前面的基础上进行修改。
, C% W4 |+ [% @  q/ m/ I, \& A
9 w' h& e6 j7 y- t7 s6 J+ ]接缓冲区满中断
* ^* t: S5 o* {2 @& |新增发送和接收的回调函数,并在初始化的时候配置,使能SPI接收中断:  g  \; ?; B) r

5 }3 O; d% W" m% b
  1. SPI_HandleTypeDef SPI3_Handler;  //SPI2句柄5 r' s0 {% j7 q4 v7 D
  2. ( p  h0 m) |: {7 Y4 k7 p- X
  3. void rx_isr(SPI_HandleTypeDef *hspi)
    + ~0 L: j7 a  f2 u% `% R7 c, C6 O
  4. {, x. y+ E. c3 s: b+ A5 @! E
  5.     if (__HAL_SPI_GET_FLAG(hspi, SPI_FLAG_TXE) == 1)* r! a1 j+ l" g0 N
  6.     {; u2 R$ f8 C+ q* g
  7.         u8 data = SPI3->DR;
    % P2 C1 J5 L6 K4 k7 z
  8.                 printf("0x%X  ",data);1 V$ U3 ]) @$ D& r* e  @
  9.     }& [: j, {2 q+ w. U7 X, V
  10. }) x" W' w4 [) h/ E$ a) u
  11. void tx_isr(SPI_HandleTypeDef *hspi)2 Y% w9 l: S# k/ F
  12. {# D2 `- h$ T) m6 {7 n; Q- T8 c( B
  13.     if (__HAL_SPI_GET_FLAG(hspi, SPI_FLAG_TXE) == 1)1 T5 p8 K4 R6 G7 t8 S
  14.     {
    - S( E2 r. J; Q" w8 H6 K0 E) x

  15. 4 O1 C) d) h, n! g9 F2 ]7 S
  16.     }1 K3 B* o: t; y: N6 L6 n
  17. }
    ! y! Y3 P3 G' |% I9 L" [
  18. void SPI3_Init(void)
    9 [1 R% U& d% t# Q+ _
  19. {
    # A3 H1 ]" q/ A7 l1 ^
  20.     HAL_NVIC_SetPriority(SPI3_IRQn, 0, 0);
    $ n$ `3 u4 e8 X' e5 o1 x6 k
  21.     HAL_NVIC_EnableIRQ(SPI3_IRQn);
    ! J  s3 j% m2 Q! g7 F
  22. 7 q0 E+ m+ E% J; U8 E8 T% m
  23.     SPI3_Handler.Instance = SPI3;+ T! V1 T! E) [: C
  24.     SPI3_Handler.Init.Mode = SPI_MODE_MASTER;2 _+ L  I% X5 u- W- f+ k
  25.     SPI3_Handler.Init.Direction = SPI_DIRECTION_2LINES;
    & V2 }+ u/ @4 c
  26.     SPI3_Handler.Init.DataSize = SPI_DATASIZE_8BIT;4 O8 f- ^7 M& S( Z( T
  27.     SPI3_Handler.Init.CLKPolarity = SPI_POLARITY_LOW;
    - r/ l8 u3 z) W( j/ B  R/ }
  28.     SPI3_Handler.Init.CLKPhase = SPI_PHASE_1EDGE;
    & K$ r0 i6 a2 s- T1 ?
  29.     SPI3_Handler.Init.NSS = SPI_NSS_SOFT;# \# T2 z8 D9 w0 ~& ~
  30.     SPI3_Handler.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_128;
    - s' `. M/ l$ N; G7 [
  31.     SPI3_Handler.Init.FirstBit = SPI_FIRSTBIT_MSB;5 U7 {  D, d3 `* P/ x
  32.     SPI3_Handler.Init.TIMode = SPI_TIMODE_DISABLE;: O# L. \- V. ^, b: I8 R
  33.     SPI3_Handler.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE;9 |6 o4 }7 w4 h7 N7 v) c
  34.     SPI3_Handler.Init.CRCPolynomial = 7;
    + ?+ l+ @  {# g3 p( t6 ^
  35.     SPI3_Handler.Init.CRCLength = SPI_CRC_LENGTH_DATASIZE;
    + S0 ^8 b' A3 D* }
  36.     SPI3_Handler.Init.NSSPMode = SPI_NSS_PULSE_DISABLE;
    4 w5 O8 }) }- L* }
  37. 8 n7 r/ k5 Z# b6 h4 o; h
  38.     SPI3_Handler.RxISR = rx_isr;0 U) X% f0 A/ x! \
  39.     SPI3_Handler.TxISR = tx_isr;
    9 B. E& M  |, V( R. P
  40.                
    7 i# `6 h( q" Z$ |4 ^/ x! _
  41.     HAL_SPI_Init(&SPI3_Handler);! o4 O  q% C) _2 A7 V- X: V

  42. - c0 j: m3 Z, i- ~
  43.     //__HAL_SPI_ENABLE_IT(&SPI3_Handler, SPI_IT_TXE);
    ' K4 r2 @6 O  e) Z- C' _% f- k, `1 S
  44.     __HAL_SPI_ENABLE_IT(&SPI3_Handler, SPI_IT_RXNE);# y' W$ j/ e% \9 a$ [

  45. 4 F5 L( n3 G, Y+ B: x# A- t
  46. }
    + \& F! D# m/ B. W1 m) H: \$ a5 ?
  47. void SPI3_IRQHandler(void)& V: s: J8 A, ~* @" I
  48. {- V1 \, W$ T# q3 F% i
  49.     HAL_SPI_IRQHandler(&SPI3_Handler);
    " G( A; e1 I0 q; [
  50. }
复制代码

( i" P& H1 r0 e+ J5 c. w. t8 G$ h对应的读写操作如下:
/ J6 q1 }" u5 f. k; u- F4 ^$ h4 L
; \3 g. j3 g9 U3 P9 |
  1. u16 W25QXX_ReadID(void)
    " l/ G! }& i( Q1 B6 }  v% ?# f
  2. {" `5 i6 z0 o" _
  3.     u16 Temp = 0;6 c1 ~8 u4 {# x; a" k0 T1 v

  4. ! l+ c* d7 D8 v: J- {# K+ I$ `
  5.     HAL_GPIO_WritePin(GPIOA, GPIO_PIN_4, GPIO_PIN_RESET);
    * Z9 g! b0 D* N
  6.     SPI3_ReadWriteByte(0x90);//发送读取ID命令+ C: S7 b/ @! _
  7.     SPI3_ReadWriteByte(0x00);1 ^! U, c* z; i
  8.     SPI3_ReadWriteByte(0x00);
    1 a. B% o1 x7 Q, R" U
  9.     SPI3_ReadWriteByte(0x00);9 |) q( A) _+ H9 T0 |) a, H
  10.     Temp |= SPI3_ReadWriteByte(0xFF) << 8;* e$ Q0 r6 Z4 y" G4 a9 R1 z
  11.     Temp |= SPI3_ReadWriteByte(0xFF);0 m& r, E) r  z
  12.     HAL_GPIO_WritePin(GPIOA, GPIO_PIN_4, GPIO_PIN_SET);
    . @6 D  y* \' W
  13.     return Temp;
      r/ W' [4 `! r: ^/ z1 K
  14. }
复制代码

7 A1 E# K, U( I5 h7 t显示结果如下:
0 t$ ?) P: b/ P8 q, p
20200423172457741.png

/ u- {+ q5 W" g9 Z1 w
6 b+ v0 X; N  r+ J- h- F其中前面4个0xFF是因为在写,写完4个byte同样会进入4次中断,但由于我们在接收中断就把数据接受了,所以SPI3_ReadWriteByte因为超时才退出的,可以明显看到几个数不是同时打印的,至于后面的ID没有显示也是同样的道理。
6 E' r9 ^* [4 y) b! T' Y- m
! w1 p) t) L1 S( p  ^发送缓冲区空中断6 @4 w3 B$ \/ Q9 t
同样在前面使能发送完成中断就可以了:, ~. S. m$ f; H: D. O: f* E: Z% F4 Q" j
* X! d9 t# j: t2 B* s7 I& [' K) K. ]
  1. __HAL_SPI_ENABLE_IT(&SPI3_Handler, SPI_IT_TXE);
复制代码
  V; U9 E' L/ r/ ?
但是由于发送完成了之后,发送缓冲区一直为空,所以会一直进入中断,所以我们使用发送完成中断的话,发送完成后除非再次填值或者关闭中断,否则会一直不停进入中断。
% \' l2 V+ c4 Q6 H$ [# l
" z" U- ]# h" m4 s+ ?+ u4 }0 B而实际上HAL库是提供了一个HAL_SPI_TransmitReceive_IT用于中断使用的发送接收函数,其中很重要的一部分内容:
1 b. B- j8 ], T. Z0 m# e4 k
$ A7 \+ s3 [) L6 @8 x2 u3 ~6 H) K; j
  1.   hspi->ErrorCode   = HAL_SPI_ERROR_NONE;
    + B1 K0 m8 {' f2 F9 i
  2.   hspi->pTxBuffPtr  = pTxData;
    6 l6 {" M: [: r6 b9 v1 k+ g5 Y: D4 H
  3.   hspi->TxXferSize  = Size;
      [5 p( T- S7 N5 U; ~/ z8 R+ r2 B
  4.   hspi->TxXferCount = Size;+ p/ f: b9 s( P; ^5 h  D
  5.   hspi->pRxBuffPtr  = pRxData;4 F3 R0 o) s  D9 R* M: }8 s
  6.   hspi->RxXferSize  = Size;* B+ K4 x+ y9 o% C0 v2 D4 g9 r$ \
  7.   hspi->RxXferCount = Size;, i! V$ {2 u, o. r. u
  8. ( w+ V! s7 d8 R5 `+ I  s/ r
  9.   /* Set the function for IT treatment */
    ; g: w6 T9 P+ a+ V+ _) Z8 @1 s+ W. m, r
  10.   if(hspi->Init.DataSize > SPI_DATASIZE_8BIT )# J8 o' J1 ?: z' A+ @$ _
  11.   {  Y- c* X  k* E( @! L/ x5 m0 ~; [
  12.     hspi->RxISR = SPI_2linesRxISR_16BIT;
    ! C: n' }6 Z0 c+ E  ]
  13.     hspi->TxISR = SPI_2linesTxISR_16BIT;, F+ Y& d; H6 J1 k* ~( E" m( ^
  14.   }
    , q/ }6 s: f( Y1 w( T4 a
  15.   else
    % ?: T( B# H" b3 e3 P1 Z5 v( w2 |
  16.   {: S- P: j: ^6 P2 x+ G
  17.     hspi->RxISR = SPI_2linesRxISR_8BIT;! u; A  R) B" r" Y
  18.     hspi->TxISR = SPI_2linesTxISR_8BIT;
    " x. e9 N/ H! S4 ~+ ]" R% p
  19.   }6 X0 V# `6 v' y  E) w
  20.   __HAL_SPI_ENABLE_IT(hspi, (SPI_IT_TXE | SPI_IT_RXNE | SPI_IT_ERR));
复制代码
4 Z* v1 V" E! V; N& B( K0 P& V1 b, u+ U. q
重新配置了中断函数,配置了发送和接收缓冲区为传入的数组,所以这里的数组要设置为全局变量,而前面设置的中断函数也失效了,而且使能了中断,所以我们前面所作的工作都是白费了。
  K2 w7 |; w# Y9 `& }. j0 G. N1 @/ P; M, _, O9 _7 H. b3 x

6 Z" C9 b0 m4 N5 \% M
0 D/ C4 P# q8 A7 r& Z8 |' P
收藏 评论0 发布时间:2021-12-17 12:04

举报

0个回答
关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
STM32N6 AI生态系统
STM32MCU,MPU高性能GUI
ST ACEPACK电源模块
意法半导体生物传感器
STM32Cube扩展软件包
关注我们
st-img 微信公众号
st-img 手机版