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

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

[复制链接]
STMCU小助手 发布时间:2021-12-17 12:04
虽然在平常的使用中,spi使用轮询等待发送完成或者接收完成就行了。2 y/ W3 e8 s8 V+ a& c
但是在对时间有严格要求的设计中,假设我们需要发送完成后立马做xx事情,此时如果有低优先级的信号需要处理,我们的轮询方式就得不到及时的响应;' P$ O: `/ X! B8 W7 J
或者说比如需要定时从spi设备中采集数据,定时器中断来了我们就要马上调用接收函数,接收完成马上进行其他计算,同样此时应该保证数据的优先级。
' s- @0 Y' U8 B& j9 x. k此时就需要用到发送完成和接收中断了。, |5 t! ~% G) a  p& W7 R- p7 u0 P# @
- L( Y7 b4 q  E  p1 W, `
前面我们已经实现了SPI轮询的发送和接收,在前面的基础上进行修改。
5 w0 j/ h1 m  C, I4 l* n* v* b" X6 k& t- q
接缓冲区满中断- Y* U3 Y! |0 n; k4 }
新增发送和接收的回调函数,并在初始化的时候配置,使能SPI接收中断:: E: E8 R0 ~" o5 ?2 x& R
5 a$ J0 a$ _# r" j
  1. SPI_HandleTypeDef SPI3_Handler;  //SPI2句柄* U( \7 @) T: }/ ~/ E- p" ?
  2. , v: y5 M9 @* r& Q$ W0 d
  3. void rx_isr(SPI_HandleTypeDef *hspi). F& O1 w+ ~1 g) ]
  4. {8 }1 ]# A8 K1 ^* [2 [% p
  5.     if (__HAL_SPI_GET_FLAG(hspi, SPI_FLAG_TXE) == 1)& H  T3 L, {2 S; j) G9 o) C  ~+ Z
  6.     {% \1 d& h3 V/ B  V
  7.         u8 data = SPI3->DR;2 ~! w- Y! U  E8 u/ N' ^. M
  8.                 printf("0x%X  ",data);( {, r, r+ v* p( p% `% \
  9.     }5 U/ B) D! A# s% N# o2 R
  10. }
    4 e0 {2 B. k, r! A1 _9 N8 [( a
  11. void tx_isr(SPI_HandleTypeDef *hspi)1 R. B) i) _/ v" q, c8 w( F0 V3 Z
  12. {+ A* ^: Z$ p3 f1 F! A. A: F' M
  13.     if (__HAL_SPI_GET_FLAG(hspi, SPI_FLAG_TXE) == 1). }* y# c: |" C' b% a$ a4 Q4 \
  14.     {
    " y! L* b1 V! l
  15. 3 O& D. g. |9 {- Y' J" O1 l- o
  16.     }+ S3 ?/ @* ~8 i& t6 v
  17. }
    & P( i) i9 `2 ]- j: ?. N
  18. void SPI3_Init(void); M! e7 t' y0 |# n
  19. {- D; w1 H$ B( d
  20.     HAL_NVIC_SetPriority(SPI3_IRQn, 0, 0);7 q2 m$ Z% K0 `
  21.     HAL_NVIC_EnableIRQ(SPI3_IRQn);# q8 _$ T3 a, m
  22. + \0 A- l6 {2 |! R, Y
  23.     SPI3_Handler.Instance = SPI3;+ N$ ~- F+ r9 v; G: s! w
  24.     SPI3_Handler.Init.Mode = SPI_MODE_MASTER;3 }; d  S# _: m
  25.     SPI3_Handler.Init.Direction = SPI_DIRECTION_2LINES;
    ; ~3 G; `1 k8 ]1 V
  26.     SPI3_Handler.Init.DataSize = SPI_DATASIZE_8BIT;
    , \# _$ V/ ^1 U1 ~; s1 T
  27.     SPI3_Handler.Init.CLKPolarity = SPI_POLARITY_LOW;! G* j4 Y# N8 {) ~6 ?% g* }
  28.     SPI3_Handler.Init.CLKPhase = SPI_PHASE_1EDGE;, W) c' @3 y& E3 w  [9 M
  29.     SPI3_Handler.Init.NSS = SPI_NSS_SOFT;5 P' V( m6 @6 m9 Z  x$ b$ F
  30.     SPI3_Handler.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_128;
    ( T  R* m; ]; ]
  31.     SPI3_Handler.Init.FirstBit = SPI_FIRSTBIT_MSB;
    + O9 {5 U" \: k. W
  32.     SPI3_Handler.Init.TIMode = SPI_TIMODE_DISABLE;
    $ [8 ~3 d& K! s- O1 L
  33.     SPI3_Handler.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE;
    1 t9 b" O1 M8 p) X2 i
  34.     SPI3_Handler.Init.CRCPolynomial = 7;
    , c5 |' U4 R1 ]9 [+ L8 m
  35.     SPI3_Handler.Init.CRCLength = SPI_CRC_LENGTH_DATASIZE;: l4 i( Y5 U' X: a
  36.     SPI3_Handler.Init.NSSPMode = SPI_NSS_PULSE_DISABLE;
    & G' g+ l- X7 Z) V& A$ }$ J% b
  37. " y' P8 n% E* s2 y$ T8 D
  38.     SPI3_Handler.RxISR = rx_isr;* J' f0 n6 u7 V8 n" W7 D
  39.     SPI3_Handler.TxISR = tx_isr;
    6 D, ~( h5 i1 H- N( T# q% @
  40.                 8 _& H0 R% R* ]2 `7 E* s
  41.     HAL_SPI_Init(&SPI3_Handler);
    " Q; }5 w7 y8 }
  42. 1 |% C2 ?" Y9 y- k
  43.     //__HAL_SPI_ENABLE_IT(&SPI3_Handler, SPI_IT_TXE);. S% o* ?) s6 N: G
  44.     __HAL_SPI_ENABLE_IT(&SPI3_Handler, SPI_IT_RXNE);
    , M0 Y1 ]7 j7 v5 V7 s* I

  45. 4 i) i' p# t! t' l+ l
  46. }4 i: q* v. @% B+ l
  47. void SPI3_IRQHandler(void)4 d6 s6 G2 d+ Q, X. Q
  48. {
    + g5 G% X( o6 N* ]: C; F
  49.     HAL_SPI_IRQHandler(&SPI3_Handler);1 V! ~" _5 s1 u: q
  50. }
复制代码

) b/ Y7 ]. ~) T( Q对应的读写操作如下:: w8 v$ {* B, W6 O2 ?9 d
& [; X$ r  u: S' `% H7 N1 h
  1. u16 W25QXX_ReadID(void)9 D' F4 Y6 n% J8 e& r' x
  2. {
    2 T. u4 v0 E( r7 E$ ]8 J
  3.     u16 Temp = 0;
    1 A7 M4 G8 K- w

  4. " v- h- s8 q8 B$ B; b1 |0 d% G
  5.     HAL_GPIO_WritePin(GPIOA, GPIO_PIN_4, GPIO_PIN_RESET);
    1 m4 ]3 e1 `& C! F
  6.     SPI3_ReadWriteByte(0x90);//发送读取ID命令0 W7 D# V7 {) [0 T+ ^5 s8 J- Y
  7.     SPI3_ReadWriteByte(0x00);
    , m5 N5 ~' ^; F* G( o0 u
  8.     SPI3_ReadWriteByte(0x00);% D, V: `8 ?( [2 z; u' n
  9.     SPI3_ReadWriteByte(0x00);
    0 W% ?& [! S- j/ j
  10.     Temp |= SPI3_ReadWriteByte(0xFF) << 8;+ ^' W+ I; t' D" H& l2 ~6 t5 y' m
  11.     Temp |= SPI3_ReadWriteByte(0xFF);9 {% Y1 N# ]( Q- T; Q
  12.     HAL_GPIO_WritePin(GPIOA, GPIO_PIN_4, GPIO_PIN_SET);. F; G4 P, l& F% R6 d0 f9 B
  13.     return Temp;- X, ]  L1 E4 Q% X  l* v
  14. }
复制代码

$ M* h3 i; \0 C) a4 }显示结果如下:
  K: B/ k3 E( X) s' e. }4 V
20200423172457741.png
1 M; @; ?) h( s
8 _: n8 v$ X  d" y! p! [8 F9 |" T# S
其中前面4个0xFF是因为在写,写完4个byte同样会进入4次中断,但由于我们在接收中断就把数据接受了,所以SPI3_ReadWriteByte因为超时才退出的,可以明显看到几个数不是同时打印的,至于后面的ID没有显示也是同样的道理。' f, U- p/ B' G

0 I) d+ N, z+ C' N1 m发送缓冲区空中断
! B: O+ K* u7 w1 L' E同样在前面使能发送完成中断就可以了:
& v  {# X9 D! K2 M! p
3 t; \. V) n3 M1 m" [6 ?9 o/ ]
  1. __HAL_SPI_ENABLE_IT(&SPI3_Handler, SPI_IT_TXE);
复制代码

$ X/ P! }7 B, ^- x/ a但是由于发送完成了之后,发送缓冲区一直为空,所以会一直进入中断,所以我们使用发送完成中断的话,发送完成后除非再次填值或者关闭中断,否则会一直不停进入中断。
. \4 x! N& p3 ]" v: k& c
) F2 `6 W6 [3 G! `而实际上HAL库是提供了一个HAL_SPI_TransmitReceive_IT用于中断使用的发送接收函数,其中很重要的一部分内容:& \8 ?. f* ~' w  T' w- D1 q- Y

; b- r) Y- [, ]9 a! r3 a) H
  1.   hspi->ErrorCode   = HAL_SPI_ERROR_NONE;: V- a2 {1 a- i9 g  P% l
  2.   hspi->pTxBuffPtr  = pTxData;
    ( z/ l  n. m# I. J1 @/ _4 M. n! M
  3.   hspi->TxXferSize  = Size;2 d' F8 Q- k/ t" q8 l) a, Z* \
  4.   hspi->TxXferCount = Size;* Q! Z0 H5 f3 m1 `  d
  5.   hspi->pRxBuffPtr  = pRxData;
    ) ^$ U0 O2 G* T  w4 W
  6.   hspi->RxXferSize  = Size;; S- n- L( g+ j( F7 P; K1 S3 H0 a# t
  7.   hspi->RxXferCount = Size;$ B2 R# W- U% {+ H

  8. 4 J, {; p; V1 G+ {) [8 j8 r
  9.   /* Set the function for IT treatment */6 r. K& C# Y* d* R' p* c! t* l
  10.   if(hspi->Init.DataSize > SPI_DATASIZE_8BIT )
      c# }5 X0 ~  S  H. p1 M
  11.   {6 E9 }5 W4 B& [* o1 k
  12.     hspi->RxISR = SPI_2linesRxISR_16BIT;* l: @. d3 E& M9 Q$ c
  13.     hspi->TxISR = SPI_2linesTxISR_16BIT;
    / r9 j1 x8 D3 D$ g5 I+ I
  14.   }! S/ g6 @/ N0 f  l7 E2 Z
  15.   else
      Q9 V: J0 B  v" ^
  16.   {9 o; v* W4 ?3 T8 r  W% D
  17.     hspi->RxISR = SPI_2linesRxISR_8BIT;5 g  `( K8 D0 _- Z0 y
  18.     hspi->TxISR = SPI_2linesTxISR_8BIT;) J" |6 F% o- ~+ M- ~6 q
  19.   }
    7 ?2 d3 r/ a2 X
  20.   __HAL_SPI_ENABLE_IT(hspi, (SPI_IT_TXE | SPI_IT_RXNE | SPI_IT_ERR));
复制代码
1 x' T8 _. Z  K6 I+ y
重新配置了中断函数,配置了发送和接收缓冲区为传入的数组,所以这里的数组要设置为全局变量,而前面设置的中断函数也失效了,而且使能了中断,所以我们前面所作的工作都是白费了。! ?9 N* O' {5 z7 S- O9 I
6 E: e; j/ V4 n! |1 y
) K: g7 e( H0 l, E

+ Z' _& B, l3 q
收藏 评论0 发布时间:2021-12-17 12:04

举报

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