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

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

[复制链接]
STMCU小助手 发布时间:2021-12-17 12:04
虽然在平常的使用中,spi使用轮询等待发送完成或者接收完成就行了。5 \6 w1 ]" Q  Y8 \3 M
但是在对时间有严格要求的设计中,假设我们需要发送完成后立马做xx事情,此时如果有低优先级的信号需要处理,我们的轮询方式就得不到及时的响应;
7 O; Q- T8 H* d9 d' B2 v或者说比如需要定时从spi设备中采集数据,定时器中断来了我们就要马上调用接收函数,接收完成马上进行其他计算,同样此时应该保证数据的优先级。* L0 Y- W% r1 u3 i6 z, j! b" z, `2 L/ c
此时就需要用到发送完成和接收中断了。+ E7 d6 V+ s0 D0 b+ Q) e
* `1 Y4 O, _% u
前面我们已经实现了SPI轮询的发送和接收,在前面的基础上进行修改。
; t# F* C0 l% ?- J
: R9 L, |2 T9 B6 E# n' t接缓冲区满中断, L, s2 [" D2 A$ K: `, p
新增发送和接收的回调函数,并在初始化的时候配置,使能SPI接收中断:( g7 ^  U, ^8 ]' n3 m% s% u9 j
5 \9 p. @# Y) L& q) v
  1. SPI_HandleTypeDef SPI3_Handler;  //SPI2句柄
    7 Q/ t& w$ }4 M  x# Z8 A# K, I
  2. $ z1 `! p6 X! o; p3 N
  3. void rx_isr(SPI_HandleTypeDef *hspi)
    % E% v  D4 s& m
  4. {
      ~, x( R8 L  U2 I% H
  5.     if (__HAL_SPI_GET_FLAG(hspi, SPI_FLAG_TXE) == 1)
    : v( m2 i9 V0 Q! u9 A
  6.     {. i6 ^# f/ Z% ~' v6 `0 g4 H
  7.         u8 data = SPI3->DR;! \+ J' c. J! K6 P% h2 w
  8.                 printf("0x%X  ",data);( e; R& z1 u, n
  9.     }/ S  T9 a. J! W& v# o- a, F" i
  10. }- Q: p, F2 N# Y. R0 h3 _% a' R
  11. void tx_isr(SPI_HandleTypeDef *hspi)
    ( {; e7 S+ \0 U/ l2 p7 |+ ?4 c
  12. {
    8 y5 Z5 [5 }5 I
  13.     if (__HAL_SPI_GET_FLAG(hspi, SPI_FLAG_TXE) == 1)7 S2 @; F. Y" v% ^; H  X
  14.     {
    / {# A2 ]$ J  a& X5 `( h; e

  15. " n" f9 Q7 d) M" o
  16.     }# Y, D; Z* ?! d0 r
  17. }$ ^, X& q" N( F  G& E/ }" |
  18. void SPI3_Init(void)% [2 P6 k, f4 L" y# A1 i
  19. {
    . o' ^$ ]6 M3 h5 b% _, y5 E; |
  20.     HAL_NVIC_SetPriority(SPI3_IRQn, 0, 0);+ R& [2 \" \3 b3 X8 q4 K
  21.     HAL_NVIC_EnableIRQ(SPI3_IRQn);  R* P! h3 V: I. i: y! n$ y
  22. 4 X7 t- E, U6 N. j# p/ r* q; V
  23.     SPI3_Handler.Instance = SPI3;( w! {$ [8 b# E4 I
  24.     SPI3_Handler.Init.Mode = SPI_MODE_MASTER;
    - Z8 D% K7 [, h: u
  25.     SPI3_Handler.Init.Direction = SPI_DIRECTION_2LINES;
    3 W5 v# `1 p' K, i9 _' T- S
  26.     SPI3_Handler.Init.DataSize = SPI_DATASIZE_8BIT;
    / k' @4 \! b! c* Q) _
  27.     SPI3_Handler.Init.CLKPolarity = SPI_POLARITY_LOW;. i# ~6 l# q/ y
  28.     SPI3_Handler.Init.CLKPhase = SPI_PHASE_1EDGE;
    4 j% M8 r1 S2 h, L& B1 w3 K
  29.     SPI3_Handler.Init.NSS = SPI_NSS_SOFT;
    . `9 s, f' z6 o8 d2 X/ S3 C
  30.     SPI3_Handler.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_128;+ @4 n6 P( ?# ?# \
  31.     SPI3_Handler.Init.FirstBit = SPI_FIRSTBIT_MSB;
    5 B; L) m( x9 K/ }
  32.     SPI3_Handler.Init.TIMode = SPI_TIMODE_DISABLE;; Z$ ]& z/ S; V3 h4 d  k& w
  33.     SPI3_Handler.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE;
    % m4 J& M2 Q3 s
  34.     SPI3_Handler.Init.CRCPolynomial = 7;) M2 l# U  T! S9 B8 k1 P2 |# e8 M
  35.     SPI3_Handler.Init.CRCLength = SPI_CRC_LENGTH_DATASIZE;
    * }! |9 V& U2 F' f2 E6 l1 {
  36.     SPI3_Handler.Init.NSSPMode = SPI_NSS_PULSE_DISABLE;
    ! o- {) \! R7 L

  37. & b9 N/ Y4 m! m
  38.     SPI3_Handler.RxISR = rx_isr;
    + G  Y- e: f# c4 V- `: g: l8 _
  39.     SPI3_Handler.TxISR = tx_isr;( `6 d( @0 _- y' j% i; L
  40.                 ; Z: l/ ?8 d+ m! T; m  |
  41.     HAL_SPI_Init(&SPI3_Handler);
      ?1 I9 H& H' K# ]# ~( _  v
  42. ( W+ j) o0 q+ [, L1 L; V
  43.     //__HAL_SPI_ENABLE_IT(&SPI3_Handler, SPI_IT_TXE);
    / K# W4 z7 b9 z3 T2 V  Y9 d: K
  44.     __HAL_SPI_ENABLE_IT(&SPI3_Handler, SPI_IT_RXNE);
    5 e4 c- B) K. a

  45. ! _# p  |: D& f: k
  46. }9 {6 }1 D9 w$ J' ^% ~
  47. void SPI3_IRQHandler(void)' U2 G& ^4 h2 s* \# j' T7 _( @
  48. {
    ; H9 t7 K9 U" n5 h" Q, n
  49.     HAL_SPI_IRQHandler(&SPI3_Handler);
    : [: F: E! A; B1 F
  50. }
复制代码

6 a8 f3 D0 |7 i  z( S  W+ u对应的读写操作如下:
/ ^! p% K9 W9 k/ x4 R2 x* E# o
# {  L: M; e, s
  1. u16 W25QXX_ReadID(void)9 P. H# e5 f. X0 N9 q/ v' W
  2. {
    & J  `; B  ^1 [8 j0 l. g9 c* N
  3.     u16 Temp = 0;1 u  J. W" q1 c3 u& y. }4 }
  4. ! r$ y8 P# ~  y, h: Y; ^) c" E
  5.     HAL_GPIO_WritePin(GPIOA, GPIO_PIN_4, GPIO_PIN_RESET);! n! z# I# X% p2 i( w  N
  6.     SPI3_ReadWriteByte(0x90);//发送读取ID命令( A  e; B6 |" r, P6 t  m/ u3 D. n
  7.     SPI3_ReadWriteByte(0x00);. C) Z8 e4 a, d5 `& D! z
  8.     SPI3_ReadWriteByte(0x00);% t. A; p6 P3 W8 q2 i0 j
  9.     SPI3_ReadWriteByte(0x00);
    + i6 O3 A& y5 n  p* T: M/ W
  10.     Temp |= SPI3_ReadWriteByte(0xFF) << 8;0 H! A# X( m5 M- t
  11.     Temp |= SPI3_ReadWriteByte(0xFF);( x7 n, F" U/ T- a& K: F" A- i6 ]
  12.     HAL_GPIO_WritePin(GPIOA, GPIO_PIN_4, GPIO_PIN_SET);; }9 J2 {2 R: D, C3 M
  13.     return Temp;
    # X" K/ B3 y' c/ v& g" e
  14. }
复制代码
( A( H4 M. E5 Z3 U6 [
显示结果如下:
9 t. Q; C. E! r$ H
20200423172457741.png
8 y) J% x8 P) G

0 w8 H& ?1 [& n& I其中前面4个0xFF是因为在写,写完4个byte同样会进入4次中断,但由于我们在接收中断就把数据接受了,所以SPI3_ReadWriteByte因为超时才退出的,可以明显看到几个数不是同时打印的,至于后面的ID没有显示也是同样的道理。" R/ X2 X  [; C

7 Y0 [7 _0 Q" k4 F发送缓冲区空中断* `8 A5 \, B; v
同样在前面使能发送完成中断就可以了:$ Q/ z$ L4 o5 |: N; m2 l- K
6 c4 ?) `& Z9 X
  1. __HAL_SPI_ENABLE_IT(&SPI3_Handler, SPI_IT_TXE);
复制代码

- x$ t- ~% A6 _6 Y但是由于发送完成了之后,发送缓冲区一直为空,所以会一直进入中断,所以我们使用发送完成中断的话,发送完成后除非再次填值或者关闭中断,否则会一直不停进入中断。' ^$ U8 w3 ]" K6 N

) O6 u/ @& X6 b9 [- {, k而实际上HAL库是提供了一个HAL_SPI_TransmitReceive_IT用于中断使用的发送接收函数,其中很重要的一部分内容:
/ ^5 R/ v: T+ q5 V7 Q
' T- b, E+ K1 K
  1.   hspi->ErrorCode   = HAL_SPI_ERROR_NONE;9 y* g. q, t1 ?& r7 ^
  2.   hspi->pTxBuffPtr  = pTxData;. J$ }8 i1 e6 ]' M# R
  3.   hspi->TxXferSize  = Size;7 _4 J7 z# j/ a+ V3 D
  4.   hspi->TxXferCount = Size;
      [" {/ q( }* {6 n8 ?4 F$ a: s/ Y
  5.   hspi->pRxBuffPtr  = pRxData;
    : ]- S6 G; V, K5 X9 r, t5 d) x
  6.   hspi->RxXferSize  = Size;. Y' i2 w1 p  l/ k# g$ r
  7.   hspi->RxXferCount = Size;* c0 ]0 h2 {! x# m

  8. ' t+ X; m( G/ J; K- A
  9.   /* Set the function for IT treatment */
    5 i$ M3 r# `6 j
  10.   if(hspi->Init.DataSize > SPI_DATASIZE_8BIT )
    . M0 A5 n9 Y/ t; g9 o5 @
  11.   {
    5 F' P* h5 U9 O1 s
  12.     hspi->RxISR = SPI_2linesRxISR_16BIT;
    $ E2 r8 b+ a2 }
  13.     hspi->TxISR = SPI_2linesTxISR_16BIT;/ e: C& }6 V% I) B5 N3 |
  14.   }" L+ H' @8 t# I' G  r9 _
  15.   else
    6 y. d# x! J4 c* {6 a( A
  16.   {
    0 h2 U3 J$ ]$ _4 l$ H1 ~
  17.     hspi->RxISR = SPI_2linesRxISR_8BIT;, X8 O6 X; E* B- ]* |
  18.     hspi->TxISR = SPI_2linesTxISR_8BIT;
    ; `4 V: j( L* j2 n$ f1 k
  19.   }' a7 k8 F2 A8 }: }1 O8 \
  20.   __HAL_SPI_ENABLE_IT(hspi, (SPI_IT_TXE | SPI_IT_RXNE | SPI_IT_ERR));
复制代码

' |  n/ W$ b: M! ^5 J" \重新配置了中断函数,配置了发送和接收缓冲区为传入的数组,所以这里的数组要设置为全局变量,而前面设置的中断函数也失效了,而且使能了中断,所以我们前面所作的工作都是白费了。
: H" U4 Y4 x6 {* S% R" P+ S5 N/ X8 X' W8 u- R
" |. R, ^9 `3 H' p2 K# n

( J7 w6 p$ i7 H# i+ f
赞 收藏 评论0 发布时间:2021-12-17 12:04

举报

0个回答

所属标签

相似技术帖

官网相关资源

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