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

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

[复制链接]
STMCU小助手 发布时间:2021-12-17 12:04
虽然在平常的使用中,spi使用轮询等待发送完成或者接收完成就行了。( I; F* D/ A# l" M0 Y; B
但是在对时间有严格要求的设计中,假设我们需要发送完成后立马做xx事情,此时如果有低优先级的信号需要处理,我们的轮询方式就得不到及时的响应;
, I4 J/ t+ [5 d' K7 C  @或者说比如需要定时从spi设备中采集数据,定时器中断来了我们就要马上调用接收函数,接收完成马上进行其他计算,同样此时应该保证数据的优先级。: i& }% p! W; H; N2 x& Y+ z9 z
此时就需要用到发送完成和接收中断了。; [' c$ H0 C2 b: ]6 w
6 E$ ~4 T1 e4 s+ {: `
前面我们已经实现了SPI轮询的发送和接收,在前面的基础上进行修改。
; Z) [2 F. X+ Z1 \) a+ [% L4 F" w$ T
接缓冲区满中断
, L1 ?! l6 Y  \; Z新增发送和接收的回调函数,并在初始化的时候配置,使能SPI接收中断:( ~2 M0 V3 _; [$ j) ?- }  Z( _0 \

8 A3 Y7 ~9 y7 X% t; G3 ]$ F; U
  1. SPI_HandleTypeDef SPI3_Handler;  //SPI2句柄: v3 h, }0 C2 o$ r) k5 h

  2. + m0 z3 j/ x" O7 ?" @: N
  3. void rx_isr(SPI_HandleTypeDef *hspi)
    $ F2 B$ R1 o, H/ r+ Y4 @
  4. {
    6 a4 }0 l0 U: M- b; |5 u
  5.     if (__HAL_SPI_GET_FLAG(hspi, SPI_FLAG_TXE) == 1)
    1 Y5 M4 |. l: @% ]
  6.     {2 ~/ E- h7 r' h9 H" q
  7.         u8 data = SPI3->DR;  L6 }) `6 k& Y" U, B3 O
  8.                 printf("0x%X  ",data);* s6 {5 m) T; C  S2 V
  9.     }
    5 m/ w! T  \# M9 j
  10. }* I/ C8 T* E7 R# S
  11. void tx_isr(SPI_HandleTypeDef *hspi)) v. ~1 D  b# g, h4 [
  12. {# _* E9 d3 y+ _2 P
  13.     if (__HAL_SPI_GET_FLAG(hspi, SPI_FLAG_TXE) == 1)  k' u+ M1 b4 N; K
  14.     {
    $ Y* L% z* a, S) Z% W

  15. , G  U! @, X- `# n* z
  16.     }% A4 w8 C, P/ `$ m6 L4 e+ F9 I
  17. }
    " z4 B3 n- X$ n1 N( E4 F* D% \
  18. void SPI3_Init(void)6 T6 H6 k2 k5 r2 e6 f- e( _
  19. {5 W% n( N5 p5 }% Z* H$ m+ L+ w
  20.     HAL_NVIC_SetPriority(SPI3_IRQn, 0, 0);+ O6 |$ ^- M( ^; z$ f% o! r% f
  21.     HAL_NVIC_EnableIRQ(SPI3_IRQn);
    " V$ r* L0 @* ]. o( M

  22. + |: I7 J3 T, `, Y4 q4 T
  23.     SPI3_Handler.Instance = SPI3;- t- C9 v5 X! P- K* Y0 }
  24.     SPI3_Handler.Init.Mode = SPI_MODE_MASTER;
    7 x1 b1 g! ~- @2 Y+ Z+ u( ?! [) ^
  25.     SPI3_Handler.Init.Direction = SPI_DIRECTION_2LINES;) W7 L" \% m9 |3 t7 i( i" u
  26.     SPI3_Handler.Init.DataSize = SPI_DATASIZE_8BIT;
    3 x% P8 u- {6 h6 p7 t+ r: t
  27.     SPI3_Handler.Init.CLKPolarity = SPI_POLARITY_LOW;2 {% W0 Y  y1 g2 c" C$ \3 ~
  28.     SPI3_Handler.Init.CLKPhase = SPI_PHASE_1EDGE;
    3 k* @3 }  n( L
  29.     SPI3_Handler.Init.NSS = SPI_NSS_SOFT;
    + `. c) z. w$ q9 X
  30.     SPI3_Handler.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_128;# ~# r% s: S( a( ^9 X
  31.     SPI3_Handler.Init.FirstBit = SPI_FIRSTBIT_MSB;- b) z! z" l. ?
  32.     SPI3_Handler.Init.TIMode = SPI_TIMODE_DISABLE;
    ! S9 Z; b+ s+ w! c6 Z
  33.     SPI3_Handler.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE;
    0 E; r0 a& L0 u) o2 {' g3 ]
  34.     SPI3_Handler.Init.CRCPolynomial = 7;
    , \4 U% x! ~( |* O" k0 ]
  35.     SPI3_Handler.Init.CRCLength = SPI_CRC_LENGTH_DATASIZE;
    ; V% ?7 X$ A$ j$ l6 @
  36.     SPI3_Handler.Init.NSSPMode = SPI_NSS_PULSE_DISABLE;
    ! k8 {" E/ q; e% D

  37.   q0 b1 Z) {! a  W
  38.     SPI3_Handler.RxISR = rx_isr;! K& b3 u$ `4 S7 ~; S% h
  39.     SPI3_Handler.TxISR = tx_isr;
    , o9 p0 z/ {4 ^
  40.                 1 i# W& y" H# X( V
  41.     HAL_SPI_Init(&SPI3_Handler);
    + q0 ~1 i  U7 P8 y7 O/ H
  42. - `0 u. ]8 W# A1 I
  43.     //__HAL_SPI_ENABLE_IT(&SPI3_Handler, SPI_IT_TXE);
    - z  K7 T( J- c: L7 R
  44.     __HAL_SPI_ENABLE_IT(&SPI3_Handler, SPI_IT_RXNE);
    : I' G; d( a5 h* d
  45. ( b9 k; @; Q& T
  46. }
    - R' E; z7 j3 c3 g7 G* E* ^( h6 ^  S
  47. void SPI3_IRQHandler(void)
    . b, N9 Y/ r) F& z
  48. {; K" T2 k! p. J; A3 v
  49.     HAL_SPI_IRQHandler(&SPI3_Handler);
      q0 `: R: b5 Q: l. w* J5 ]
  50. }
复制代码

# L6 H7 L" _# n: \) i对应的读写操作如下:
  _7 n, S2 z# D/ r( M  m
; M1 s. a2 w. J& G
  1. u16 W25QXX_ReadID(void)
    . E4 @3 u3 B% |1 R9 X# _. S  H+ U
  2. {
    ' t: y: y7 X0 p5 c
  3.     u16 Temp = 0;
    8 a' K% @: L1 I& K) [, s+ @" ]

  4. , m- |5 o: N: t3 D& [- G
  5.     HAL_GPIO_WritePin(GPIOA, GPIO_PIN_4, GPIO_PIN_RESET);& L9 w& j% f$ b0 Z( R* |
  6.     SPI3_ReadWriteByte(0x90);//发送读取ID命令% t, W2 _4 l# l8 _/ u
  7.     SPI3_ReadWriteByte(0x00);
    1 {& E' s$ U4 P2 Q' ?% i
  8.     SPI3_ReadWriteByte(0x00);. k9 u- H2 z7 {
  9.     SPI3_ReadWriteByte(0x00);
    5 ~+ j+ B5 x, u8 G5 K; B/ P
  10.     Temp |= SPI3_ReadWriteByte(0xFF) << 8;* b, d. X5 t  B3 s/ j0 H* s
  11.     Temp |= SPI3_ReadWriteByte(0xFF);
    ) ]% j% Y) P1 B& }2 i
  12.     HAL_GPIO_WritePin(GPIOA, GPIO_PIN_4, GPIO_PIN_SET);, S( t, v' a) c# ^/ t: R% S+ W& b9 S
  13.     return Temp;! l3 ^4 \7 X$ M- h9 y) h/ I# |$ d1 S
  14. }
复制代码
7 @- B+ p+ \; Z, R
显示结果如下:
  g* n9 k3 s$ k. }
20200423172457741.png
4 m/ K0 \) Y, N- x& p' M
  `* ^6 F+ u# Q) p/ h! q0 ^
其中前面4个0xFF是因为在写,写完4个byte同样会进入4次中断,但由于我们在接收中断就把数据接受了,所以SPI3_ReadWriteByte因为超时才退出的,可以明显看到几个数不是同时打印的,至于后面的ID没有显示也是同样的道理。
# [8 v5 D) C2 A" }  h9 X
( i6 U& Z; \, s1 @) i发送缓冲区空中断* g) |6 I% S5 `3 \5 \
同样在前面使能发送完成中断就可以了:  A: p5 D8 z. f2 `

4 K) R* F- G2 k( G2 `$ N! I
  1. __HAL_SPI_ENABLE_IT(&SPI3_Handler, SPI_IT_TXE);
复制代码

7 Q1 x. Y5 Z" l- S# P) I- L但是由于发送完成了之后,发送缓冲区一直为空,所以会一直进入中断,所以我们使用发送完成中断的话,发送完成后除非再次填值或者关闭中断,否则会一直不停进入中断。
- E3 @- V' V& s
: Q; I! r8 U) Q( M, p' e而实际上HAL库是提供了一个HAL_SPI_TransmitReceive_IT用于中断使用的发送接收函数,其中很重要的一部分内容:* z4 ~3 a4 r0 t) ]3 {! X( n' s

  F! p( n$ P6 Z  @/ K; _& `
  1.   hspi->ErrorCode   = HAL_SPI_ERROR_NONE;9 P1 R) g+ P. `) B! _8 [4 C5 e
  2.   hspi->pTxBuffPtr  = pTxData;) w8 p) ?- |" p' U3 {' ^
  3.   hspi->TxXferSize  = Size;
    6 o8 q; }' m5 u# d
  4.   hspi->TxXferCount = Size;, z! Z1 s) v. i1 T0 ?
  5.   hspi->pRxBuffPtr  = pRxData;
    4 l* E: M; V  g7 ~3 l$ ?
  6.   hspi->RxXferSize  = Size;" l& ^0 _% n- g- \/ }  g! D5 N
  7.   hspi->RxXferCount = Size;5 U2 E: `% r2 L$ U+ D

  8. 1 O) q: b) d9 ]2 w! [
  9.   /* Set the function for IT treatment */
    8 I9 T7 f+ Q: m, N8 e/ r& V
  10.   if(hspi->Init.DataSize > SPI_DATASIZE_8BIT )
    + K8 G& w( J5 ^5 b; Q
  11.   {7 o: J9 \2 M3 k" Y
  12.     hspi->RxISR = SPI_2linesRxISR_16BIT;
    ' R# O0 A9 c, X! p# y
  13.     hspi->TxISR = SPI_2linesTxISR_16BIT;
    # _: t" `! h  F7 W; r# P1 c
  14.   }5 H  I/ h- }+ i) a
  15.   else
    3 ?' y+ \. \8 p! }
  16.   {& Y1 Q7 _- a1 A* G
  17.     hspi->RxISR = SPI_2linesRxISR_8BIT;' l/ U8 O" D7 k! _5 K8 X7 P) ]
  18.     hspi->TxISR = SPI_2linesTxISR_8BIT;
    ; c' ^+ r6 P' y' v2 k
  19.   }
    7 [; e* s# k7 V4 g- Y* s
  20.   __HAL_SPI_ENABLE_IT(hspi, (SPI_IT_TXE | SPI_IT_RXNE | SPI_IT_ERR));
复制代码
1 o4 i1 [' [  z0 V. }5 J
重新配置了中断函数,配置了发送和接收缓冲区为传入的数组,所以这里的数组要设置为全局变量,而前面设置的中断函数也失效了,而且使能了中断,所以我们前面所作的工作都是白费了。
0 |3 g( `+ w/ t& I7 r5 ]9 V
. P% c: B( `; u3 ~+ i4 `1 p8 ^+ C- M
% J) t( b( w- r3 f7 k9 n, v9 d2 I4 A1 J
收藏 评论0 发布时间:2021-12-17 12:04

举报

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