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

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

[复制链接]
STMCU小助手 发布时间:2023-3-11 19:00
虽然在平常的使用中,spi使用轮询等待发送完成或者接收完成就行了。- ]- K4 r$ U0 C# t
但是在对时间有严格要求的设计中,假设我们需要发送完成后立马做xx事情,此时如果有低优先级的信号需要处理,我们的轮询方式就得不到及时的响应;& |7 t1 d0 k0 [. y7 _
或者说比如需要定时从spi设备中采集数据,定时器中断来了我们就要马上调用接收函数,接收完成马上进行其他计算,同样此时应该保证数据的优先级。
# m9 U( A  _! r: G, E此时就需要用到发送完成和接收中断了。  f; O4 F: Y! V  t
9 P- u9 W$ t2 D
前面我们已经实现了SPI轮询的发送和接收,在前面的基础上进行修改。7 {4 a/ c8 y( Y

# L% [8 ~* ^  e4 N* s

( G: X* s5 D$ f; \( [接缓冲区满中断
6 N; _- y  i( j% o/ F新增发送和接收的回调函数,并在初始化的时候配置,使能SPI接收中断:5 H- u; Z, C; A# Q. j
  1. SPI_HandleTypeDef SPI3_Handler;  //SPI2句柄4 p  t! e& H) w9 O9 f1 O, G
  2. % ^5 J3 }$ p! k; Z9 `6 Q5 z1 J* l
  3. void rx_isr(SPI_HandleTypeDef *hspi)7 E; i5 d- m2 W" n
  4. {
    ! c# T* t  U' S& {1 n8 A
  5.     if (__HAL_SPI_GET_FLAG(hspi, SPI_FLAG_TXE) == 1)9 r2 t* R7 Y% K: ?" F7 {
  6.     {
    6 _7 Z: F* R0 }: k4 z1 P# u
  7.         u8 data = SPI3->DR;
    9 D2 Y5 h, H; }: ^- B
  8.                 printf("0x%X  ",data);
    3 |; I% v  o* [, O1 P$ y
  9.     }: U- z( U# K7 k3 o  Z# x2 r6 Z
  10. }
    7 o+ U* V; A4 c+ L. F- G) q
  11. void tx_isr(SPI_HandleTypeDef *hspi)
    9 w6 a- P1 g: e8 p6 I# Z
  12. {5 N: i6 A+ o' P; a+ f! @
  13.     if (__HAL_SPI_GET_FLAG(hspi, SPI_FLAG_TXE) == 1)
    2 I- \- v/ M3 n
  14.     {
    # o& v' i+ y- @

  15. & M, @+ ^. T" x2 r
  16.     }/ d3 h( z! g0 ?  A! P
  17. }$ c7 r- [$ V$ f% g2 B
  18. void SPI3_Init(void)
    5 C2 N5 i# h! h, y1 ?9 F, Z' q
  19. {  c7 B; k4 @0 W( o1 s6 b0 s( Y7 q
  20.     HAL_NVIC_SetPriority(SPI3_IRQn, 0, 0);
    3 e6 J  t6 r! Y4 z- k& Q
  21.     HAL_NVIC_EnableIRQ(SPI3_IRQn);' H4 G7 J5 e! Z" N6 C

  22. + Z# F+ y8 p) d3 H5 r: f# K
  23.     SPI3_Handler.Instance = SPI3;
    1 ]; q. O) ?2 ^0 z0 Q% Z
  24.     SPI3_Handler.Init.Mode = SPI_MODE_MASTER;
    , R+ N+ [/ U4 m7 }' U! {
  25.     SPI3_Handler.Init.Direction = SPI_DIRECTION_2LINES;
    " k. k. i* N: V$ ?# g+ M1 }* t
  26.     SPI3_Handler.Init.DataSize = SPI_DATASIZE_8BIT;
    + d* K' c8 V5 i$ I3 V
  27.     SPI3_Handler.Init.CLKPolarity = SPI_POLARITY_LOW;
    ' Q! A3 j  G- |) p* P6 Y
  28.     SPI3_Handler.Init.CLKPhase = SPI_PHASE_1EDGE;
    ; @+ t0 {  ^( R* V4 i1 m: z- C
  29.     SPI3_Handler.Init.NSS = SPI_NSS_SOFT;
    / j* M3 w* w/ C# {$ l
  30.     SPI3_Handler.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_128;
    ( Y& z- m3 b. L* `! Z
  31.     SPI3_Handler.Init.FirstBit = SPI_FIRSTBIT_MSB;
    9 i5 _4 j1 P# v. G
  32.     SPI3_Handler.Init.TIMode = SPI_TIMODE_DISABLE;
    4 @, K* c8 l5 ]3 C# K6 Z  f
  33.     SPI3_Handler.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE;! s; \) H  i0 o3 D1 ]
  34.     SPI3_Handler.Init.CRCPolynomial = 7;
      {" U$ a2 ]& c' a
  35.     SPI3_Handler.Init.CRCLength = SPI_CRC_LENGTH_DATASIZE;# d: Y" ^' @% x8 o2 e. R
  36.     SPI3_Handler.Init.NSSPMode = SPI_NSS_PULSE_DISABLE;
    : M- B1 |; O( M) u, L) Z& y7 ]& U
  37. 7 z$ [/ O9 ^+ f. s% y: U' J' }
  38.     SPI3_Handler.RxISR = rx_isr;- m! Q" J0 D) Q# c7 S
  39.     SPI3_Handler.TxISR = tx_isr;2 }5 ^3 r  M$ O, h5 g2 D- b/ V
  40.                 * u7 |9 {; E  |
  41.     HAL_SPI_Init(&SPI3_Handler);
    8 R! {5 n3 d1 y8 W8 T
  42. % B( d7 z" ^. [) t, D) X
  43.     //__HAL_SPI_ENABLE_IT(&SPI3_Handler, SPI_IT_TXE);
    - M1 R4 P4 P6 j' ^; S2 p
  44.     __HAL_SPI_ENABLE_IT(&SPI3_Handler, SPI_IT_RXNE);
    + E/ c! A+ o  ~+ k7 j: K
  45. # ^5 Z4 t+ c5 S+ R+ Q
  46. }
    * P+ G0 V3 y# p- `
  47. void SPI3_IRQHandler(void)* Y' [% s6 R3 }( r/ s# @! @
  48. {
    9 }4 q4 f4 B3 g  i/ m0 X' x
  49.     HAL_SPI_IRQHandler(&SPI3_Handler);! u  }- A4 D" j9 _& b; @& v
  50. }7 W+ W. ?& k& s8 m% \) B

  51. 5 G. \% D8 T7 t
复制代码

) ]! I& r% @7 V! H" b对应的读写操作如下:3 D0 X6 k( ]4 M( ?2 W+ K
  1. u16 W25QXX_ReadID(void)/ ]% y% T9 }4 \, ]8 ^
  2. {
    , {, h1 x& f% @6 f$ k. f
  3.     u16 Temp = 0;" P" U* S. ~" l( ^* P

  4. 1 t' v/ L* G) W$ c4 e- K
  5.     HAL_GPIO_WritePin(GPIOA, GPIO_PIN_4, GPIO_PIN_RESET);
    9 u* l) \- v1 T
  6.     SPI3_ReadWriteByte(0x90);//发送读取ID命令% q0 M6 m. q* R$ `
  7.     SPI3_ReadWriteByte(0x00);% ]1 p& O9 W" M/ M. j6 ?
  8.     SPI3_ReadWriteByte(0x00);% x: l0 V; e0 Y6 `( p$ o- ^
  9.     SPI3_ReadWriteByte(0x00);3 H+ _3 ^  u, M' D# a
  10.     Temp |= SPI3_ReadWriteByte(0xFF) << 8;& @/ P- A7 _" k* S9 W
  11.     Temp |= SPI3_ReadWriteByte(0xFF);
    9 I% l8 V3 d4 G/ @
  12.     HAL_GPIO_WritePin(GPIOA, GPIO_PIN_4, GPIO_PIN_SET);/ m+ }. J3 i1 [# K
  13.     return Temp;" A0 I+ r6 O$ i1 Y; Q) K% p
  14. }0 O: F; o! u6 G4 S
复制代码
& t6 n2 w' m3 q) y/ P% a
显示结果如下:9 N) |+ O( \  Z2 w
' l1 V) V5 J" M1 Y- o8 B) u# _
20200423172457741.png
# |2 T% L! O6 K5 _: h) n' e

& \4 N! n9 p/ m/ y其中前面4个0xFF是因为在写,写完4个byte同样会进入4次中断,但由于我们在接收中断就把数据接受了,所以SPI3_ReadWriteByte因为超时才退出的,可以明显看到几个数不是同时打印的,至于后面的ID没有显示也是同样的道理。* w# V4 J% O9 p; o4 D+ S) q
  \: w% B2 B+ b5 c, k/ l
发送缓冲区空中断
6 {% H6 x) [3 V同样在前面使能发送完成中断就可以了:
  g5 D( z! D. ]. h9 D5 E6 _7 Q
  1. __HAL_SPI_ENABLE_IT(&SPI3_Handler, SPI_IT_TXE);
复制代码

' `. @$ R4 X# J但是由于发送完成了之后,发送缓冲区一直为空,所以会一直进入中断,所以我们使用发送完成中断的话,发送完成后除非再次填值或者关闭中断,否则会一直不停进入中断。
* Z7 p7 c* I' @2 X/ I5 }
+ ~( u' R4 E% H
而实际上HAL库是提供了一个HAL_SPI_TransmitReceive_IT用于中断使用的发送接收函数,其中很重要的一部分内容:
2 E0 H7 D4 m/ g( b' K+ @
  1.   hspi->ErrorCode   = HAL_SPI_ERROR_NONE;, ]: [9 `. t% X  U% R' Z& P" J- z
  2.   hspi->pTxBuffPtr  = pTxData;3 h2 f- ^8 B: D( b- I
  3.   hspi->TxXferSize  = Size;
    2 }* |! l4 q! @1 B0 h, p/ u
  4.   hspi->TxXferCount = Size;
    $ Z- f, T! I2 R: w; L9 k% Q
  5.   hspi->pRxBuffPtr  = pRxData;' s* Q8 E! c+ r8 @5 B/ N. t3 n$ M
  6.   hspi->RxXferSize  = Size;
    4 K3 h$ L' h+ t/ o% [) r5 q, T0 w
  7.   hspi->RxXferCount = Size;! V5 ]- Z, ]- n) s+ T

  8. # f4 A4 U& e: l" U% c/ n
  9.   /* Set the function for IT treatment */
    1 }1 |2 ]% |3 p( Z) V
  10.   if(hspi->Init.DataSize > SPI_DATASIZE_8BIT )
    4 ~$ q( i& H4 w. W. P( j5 b+ T, O
  11.   {) D, Y( F$ m3 X9 B. i
  12.     hspi->RxISR = SPI_2linesRxISR_16BIT;
    % S) F5 T- [" ~% G
  13.     hspi->TxISR = SPI_2linesTxISR_16BIT;# {8 a, ^' M; K) a5 f6 E
  14.   }4 ^8 [$ p8 O% U/ ]
  15.   else
    9 \( W$ i& B/ G5 c1 l) ^* M/ E
  16.   {% `, Z- G8 X' |) G& x  g$ r3 f) _
  17.     hspi->RxISR = SPI_2linesRxISR_8BIT;5 `$ P% U6 L8 J$ c& a8 C
  18.     hspi->TxISR = SPI_2linesTxISR_8BIT;! Q8 A  e6 ~" P9 E9 u' d
  19.   }
    : t3 d* s! K' [
  20.   __HAL_SPI_ENABLE_IT(hspi, (SPI_IT_TXE | SPI_IT_RXNE | SPI_IT_ERR));8 V' P7 c5 i7 D$ a# C1 y
复制代码
) v( s" L+ Z; r( B$ V
重新配置了中断函数,配置了发送和接收缓冲区为传入的数组,所以这里的数组要设置为全局变量,而前面设置的中断函数也失效了,而且使能了中断,所以我们前面所作的工作都是白费了。# o0 R$ P! Z  c3 g1 m' Z8 H4 v
; N* Z  Y. b$ h# K' ]: P
至于HAL_SPI_TransmitReceive_IT的具体过程,先埋个坑……(项目现在没这需求了), @+ N, G! g: ?3 {
————————————————
% C& c- i" @% g( b1 a8 c版权声明:小盼你最萌哒* j8 l7 J$ l/ z% B, M2 S

. V7 {+ H. T3 t3 ], t
赞 收藏 评论0 发布时间:2023-3-11 19:00

举报

0个回答

所属标签

相似技术帖

官网相关资源

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