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

基于STM32F7发送或者接收中断-SPI

[复制链接]
STMCU小助手 发布时间:2023-3-11 19:00
虽然在平常的使用中,spi使用轮询等待发送完成或者接收完成就行了。8 l) a, H* `5 [6 g1 d. \+ [
但是在对时间有严格要求的设计中,假设我们需要发送完成后立马做xx事情,此时如果有低优先级的信号需要处理,我们的轮询方式就得不到及时的响应;
; p; m/ K; J: {$ }0 j1 f或者说比如需要定时从spi设备中采集数据,定时器中断来了我们就要马上调用接收函数,接收完成马上进行其他计算,同样此时应该保证数据的优先级。0 {+ H' u( X' P* ?! ^
此时就需要用到发送完成和接收中断了。4 Y$ i0 J! N5 J0 b

$ q* ?  ?1 c! F! x6 C1 a前面我们已经实现了SPI轮询的发送和接收,在前面的基础上进行修改。
- X  f% }  l( W3 m" I8 l; u" N+ S" M& b& c

6 z8 ?6 n& t  q2 t7 \9 q接缓冲区满中断
7 l5 Y% Y3 [2 R新增发送和接收的回调函数,并在初始化的时候配置,使能SPI接收中断:
+ ?2 ~( j2 f3 v$ S: b( g* A& S
  1. SPI_HandleTypeDef SPI3_Handler;  //SPI2句柄
    3 A0 I) p% t& b

  2. 2 ~. j& Y# e* C  q6 E2 I; U4 f
  3. void rx_isr(SPI_HandleTypeDef *hspi)
    ) u1 Z% A! ^0 A# F3 ~2 ~. _8 S
  4. {
    * k' L/ v( O3 C5 e$ s0 ^
  5.     if (__HAL_SPI_GET_FLAG(hspi, SPI_FLAG_TXE) == 1)
    - a, {1 V4 R* G' M, E" [
  6.     {
    9 R8 L5 l# g: l/ O& a# d' Q
  7.         u8 data = SPI3->DR;3 m5 @; Y, [+ y; v: C3 k' V; n
  8.                 printf("0x%X  ",data);
    6 O3 f. H' s$ \
  9.     }( w7 k$ v6 l* C5 c  y
  10. }
    2 }4 i6 w8 s; w/ ^$ d
  11. void tx_isr(SPI_HandleTypeDef *hspi)
    & @# n* c% Q: W0 R! y, l1 f8 P
  12. {& V* E% S, t) j1 I# @  L! p
  13.     if (__HAL_SPI_GET_FLAG(hspi, SPI_FLAG_TXE) == 1). _. p, g! \, e' L% ?* h
  14.     {
    % |* y. |' Y  O- B: W

  15. 3 L$ q* }7 w0 n4 ?; l
  16.     }
    - |- b* b* {: p. \" m3 t1 s
  17. }
    - ]' x/ }! B5 c, q- T! f
  18. void SPI3_Init(void)
    8 G/ R8 j. j; Q( Z# Q/ o/ s
  19. {
    6 x2 |+ T6 B2 U. ?: b# u4 T2 }; u
  20.     HAL_NVIC_SetPriority(SPI3_IRQn, 0, 0);
    3 B  O! N) z" _8 f( O
  21.     HAL_NVIC_EnableIRQ(SPI3_IRQn);
    $ i' V" _6 R1 J' L: S5 C% f+ B9 M

  22. 6 x. ?# r3 X9 P3 f) B' F
  23.     SPI3_Handler.Instance = SPI3;4 U6 ]& X0 y. v3 X6 a
  24.     SPI3_Handler.Init.Mode = SPI_MODE_MASTER;
    8 f; w8 L4 }  p9 I
  25.     SPI3_Handler.Init.Direction = SPI_DIRECTION_2LINES;" `  p8 Z1 |# o- G- R, }
  26.     SPI3_Handler.Init.DataSize = SPI_DATASIZE_8BIT;5 {$ t( a# a8 [0 d+ ~
  27.     SPI3_Handler.Init.CLKPolarity = SPI_POLARITY_LOW;
    * C2 K! Y6 v1 Q, ^" F
  28.     SPI3_Handler.Init.CLKPhase = SPI_PHASE_1EDGE;
    1 O6 ~+ i1 w! p" l5 y+ c  }. R8 n
  29.     SPI3_Handler.Init.NSS = SPI_NSS_SOFT;+ Z7 }) E3 X. A$ m
  30.     SPI3_Handler.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_128;7 }9 I& E# z+ h5 _1 F
  31.     SPI3_Handler.Init.FirstBit = SPI_FIRSTBIT_MSB;
    - S4 b7 s( A$ T( M( I0 }6 r
  32.     SPI3_Handler.Init.TIMode = SPI_TIMODE_DISABLE;
    - d* ]& H; G4 _
  33.     SPI3_Handler.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE;2 I& l$ `( Z1 O0 \& j( k- i
  34.     SPI3_Handler.Init.CRCPolynomial = 7;5 w: `4 G& P# P4 g1 \
  35.     SPI3_Handler.Init.CRCLength = SPI_CRC_LENGTH_DATASIZE;
    & D% D$ S) T4 S/ c
  36.     SPI3_Handler.Init.NSSPMode = SPI_NSS_PULSE_DISABLE;
    2 K/ F- T. A/ A* J$ J
  37. / q1 H& D$ `3 X  L  M& `" J
  38.     SPI3_Handler.RxISR = rx_isr;
    ! [- O" E) s8 G
  39.     SPI3_Handler.TxISR = tx_isr;  ]! h/ ~- q+ i9 _
  40.                
    7 X3 X' ~8 i' P) j
  41.     HAL_SPI_Init(&SPI3_Handler);/ j- l+ d: s& \( \

  42. , u# K" q- [* P4 c  S2 U1 Y' G
  43.     //__HAL_SPI_ENABLE_IT(&SPI3_Handler, SPI_IT_TXE);
    & @( ^8 G$ E" Y- y% v" E' T" e
  44.     __HAL_SPI_ENABLE_IT(&SPI3_Handler, SPI_IT_RXNE);8 S; o# g9 i; ]' r4 c. ?' b5 @

  45. # o2 b8 |0 S+ t  l/ K
  46. }# Y0 n' m! z" Z  ?
  47. void SPI3_IRQHandler(void)3 Y. Q! Q$ L4 r" w  j* k
  48. {5 i) @; X+ a: P! }
  49.     HAL_SPI_IRQHandler(&SPI3_Handler);
    / p' H9 |3 U* N  e* T  u
  50. }: E* Q, |( r9 m0 j

  51. 3 c" h8 h# d: S  ~
复制代码

- Y- s: c6 N3 n" [+ ~: `对应的读写操作如下:) R( e1 L7 E) D# C* y, l
  1. u16 W25QXX_ReadID(void)- x; g9 j7 {) a; S% }
  2. {
      T7 d, c$ J  @/ x
  3.     u16 Temp = 0;
    8 _& R& r5 R; f. l& a+ r0 O
  4. 7 {1 W2 `# d8 Q9 ]" `* ?( b
  5.     HAL_GPIO_WritePin(GPIOA, GPIO_PIN_4, GPIO_PIN_RESET);
    % y/ A. C" I  s8 [# z2 N; I5 z! L
  6.     SPI3_ReadWriteByte(0x90);//发送读取ID命令0 I: s8 i  E7 M; ]( x' Y
  7.     SPI3_ReadWriteByte(0x00);
    5 ^3 C+ ~( F. ?( y
  8.     SPI3_ReadWriteByte(0x00);& ~) z% `. ]: _
  9.     SPI3_ReadWriteByte(0x00);1 |  C( x* U( o% Q9 H: V8 ~
  10.     Temp |= SPI3_ReadWriteByte(0xFF) << 8;
    & L0 u- O( B$ n, u8 s
  11.     Temp |= SPI3_ReadWriteByte(0xFF);
      C+ r- n1 s  P
  12.     HAL_GPIO_WritePin(GPIOA, GPIO_PIN_4, GPIO_PIN_SET);
    8 W1 W. b' N$ w- u% M! B
  13.     return Temp;
    & p; f; o8 H# p+ p! p, w
  14. }
    2 d/ ?& T. v+ ?8 u5 u: z) B2 G
复制代码

  C( J8 v/ f* ^% F显示结果如下:, f& k1 r  n& c" G9 z* [

' u5 c$ E. J, {+ [+ ^5 W
20200423172457741.png
+ {: K7 J9 i. w2 A
* T+ ^& f$ K+ h! e- A
其中前面4个0xFF是因为在写,写完4个byte同样会进入4次中断,但由于我们在接收中断就把数据接受了,所以SPI3_ReadWriteByte因为超时才退出的,可以明显看到几个数不是同时打印的,至于后面的ID没有显示也是同样的道理。
" r' R0 G  w+ g9 ?
) n! c! t$ ?1 K* X6 q
发送缓冲区空中断
$ \9 _$ O& m' ?8 T同样在前面使能发送完成中断就可以了:
6 c6 l/ q9 L; ~8 u; a
  1. __HAL_SPI_ENABLE_IT(&SPI3_Handler, SPI_IT_TXE);
复制代码

2 y. B  g5 x: B8 {" B  v- j4 Z1 d. a/ B但是由于发送完成了之后,发送缓冲区一直为空,所以会一直进入中断,所以我们使用发送完成中断的话,发送完成后除非再次填值或者关闭中断,否则会一直不停进入中断。
# v: w. w( j% l. E# W
+ B+ U8 I. U. M
而实际上HAL库是提供了一个HAL_SPI_TransmitReceive_IT用于中断使用的发送接收函数,其中很重要的一部分内容:
1 |4 X" T" H- A% O( N
  1.   hspi->ErrorCode   = HAL_SPI_ERROR_NONE;
    ( [. g, m  L1 T6 @" ^9 b
  2.   hspi->pTxBuffPtr  = pTxData;2 \4 ?& Z& n& S- I) V* s% {+ w
  3.   hspi->TxXferSize  = Size;
    / ]4 H* U# t0 u2 ?& C
  4.   hspi->TxXferCount = Size;
    3 _* e. y1 m& G
  5.   hspi->pRxBuffPtr  = pRxData;' @8 Z9 l' P0 ?
  6.   hspi->RxXferSize  = Size;- _- C5 e/ b4 X1 f# S- F( t
  7.   hspi->RxXferCount = Size;
    , F" M# i" b& f6 q
  8. % n5 x8 b$ `$ n2 g# l
  9.   /* Set the function for IT treatment */
    5 C% z/ p' d0 @" O/ {9 _
  10.   if(hspi->Init.DataSize > SPI_DATASIZE_8BIT )
    . \7 w( N, t3 \- f9 v5 ]! ]
  11.   {
    % W: @, T1 t6 N) L8 M
  12.     hspi->RxISR = SPI_2linesRxISR_16BIT;
    . [# O8 d( h* C4 e# e, F4 c* Z
  13.     hspi->TxISR = SPI_2linesTxISR_16BIT;$ c+ {/ ~+ c8 \0 y* A. _9 X
  14.   }
    1 v* S# F0 `* n
  15.   else
    " E- m# w+ j4 Z$ T
  16.   {+ d( b- [7 V& H: m5 B
  17.     hspi->RxISR = SPI_2linesRxISR_8BIT;
    2 h. y! `0 J( j# T& t
  18.     hspi->TxISR = SPI_2linesTxISR_8BIT;
    3 q+ Z" t% {8 k, h$ n
  19.   }1 l/ f$ k4 x5 a: Q( f. R0 O
  20.   __HAL_SPI_ENABLE_IT(hspi, (SPI_IT_TXE | SPI_IT_RXNE | SPI_IT_ERR));
    0 C& ~' D; R' F7 L5 {9 d" |+ i
复制代码

8 b- A7 S2 P% K& @5 }重新配置了中断函数,配置了发送和接收缓冲区为传入的数组,所以这里的数组要设置为全局变量,而前面设置的中断函数也失效了,而且使能了中断,所以我们前面所作的工作都是白费了。
& C3 [& A- p( L9 ^, A; Z# n9 [( F5 X3 T. Z  F! X+ {. [
至于HAL_SPI_TransmitReceive_IT的具体过程,先埋个坑……(项目现在没这需求了)$ S) u; O' f( R; }+ M: E/ A/ a
————————————————
5 j8 C& @, [7 i1 S$ C  V版权声明:小盼你最萌哒
% F# a1 b( X( u& Z9 K- ?. @. n2 M9 r$ x4 h& m. d, E6 j: [! o
收藏 评论0 发布时间:2023-3-11 19:00

举报

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