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

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

[复制链接]
STMCU小助手 发布时间:2021-12-17 12:04
虽然在平常的使用中,spi使用轮询等待发送完成或者接收完成就行了。, E0 u, Z, C' x/ \; e& |
但是在对时间有严格要求的设计中,假设我们需要发送完成后立马做xx事情,此时如果有低优先级的信号需要处理,我们的轮询方式就得不到及时的响应;
$ f+ Z9 O$ D/ O0 |6 u或者说比如需要定时从spi设备中采集数据,定时器中断来了我们就要马上调用接收函数,接收完成马上进行其他计算,同样此时应该保证数据的优先级。3 m8 b. o0 j6 X* u# G+ O! ~2 ^
此时就需要用到发送完成和接收中断了。
; U" J9 t9 h& X* R5 J6 f8 n
" G2 D; T) Z4 d9 I前面我们已经实现了SPI轮询的发送和接收,在前面的基础上进行修改。1 [/ M+ n/ g9 H8 z' S7 M$ y! d6 k

" D; T/ q$ U6 b3 L, e  v接缓冲区满中断
' p) c3 b+ N- j0 i( i% F; q5 h新增发送和接收的回调函数,并在初始化的时候配置,使能SPI接收中断:. ]# h" ~* f) ?& j6 b" ?: }
: r, |  B6 ]; w5 t7 F
  1. SPI_HandleTypeDef SPI3_Handler;  //SPI2句柄
    + S% _7 o$ Z* x  H5 C

  2.   c. H* o! P' e% v2 ^0 p% I# U
  3. void rx_isr(SPI_HandleTypeDef *hspi)
    , O% R0 y- {0 B' g8 _( N) f! c
  4. {
    - Y# T- ?+ e: J( z+ K& g3 C/ Q
  5.     if (__HAL_SPI_GET_FLAG(hspi, SPI_FLAG_TXE) == 1)
    : r" K9 k1 j. n6 `2 z
  6.     {
    % i# t/ t5 E1 A7 t- |
  7.         u8 data = SPI3->DR;6 I6 f2 a" d" }! d
  8.                 printf("0x%X  ",data);
    3 }6 b6 K8 y: C! G$ U0 R! U6 N
  9.     }) I6 g- v6 a1 U) a& n8 M
  10. }" T2 r1 z. j' J3 W
  11. void tx_isr(SPI_HandleTypeDef *hspi)
    ; u4 v8 C9 @; C
  12. {5 i" o: S$ N- V+ D7 W; w; F; K
  13.     if (__HAL_SPI_GET_FLAG(hspi, SPI_FLAG_TXE) == 1)# @6 s7 ?  F$ M* r
  14.     {4 D1 V5 f  ]/ W/ j8 T

  15. ' `4 f$ J$ ?7 @7 M5 Z. `
  16.     }
    2 h3 m- u  F; P1 x1 w5 _* r
  17. }
    1 b: L9 j/ Q; s7 `( N
  18. void SPI3_Init(void)
    ) T# V* w5 \; F4 x/ ^
  19. {
    0 K! n5 }( b7 |5 ?+ D
  20.     HAL_NVIC_SetPriority(SPI3_IRQn, 0, 0);
    ( X) e; f! T/ I$ w
  21.     HAL_NVIC_EnableIRQ(SPI3_IRQn);
    ' i6 k# L* O# O6 O# {) t1 U
  22. # b) M3 U7 z8 z9 \4 C
  23.     SPI3_Handler.Instance = SPI3;
    2 \+ [  J) |  d; V5 {6 U- A
  24.     SPI3_Handler.Init.Mode = SPI_MODE_MASTER;
    3 G1 B1 A1 D- Y* q1 f$ e
  25.     SPI3_Handler.Init.Direction = SPI_DIRECTION_2LINES;
    3 @6 O! M# S! o) N5 I3 ?  P* m& p% M
  26.     SPI3_Handler.Init.DataSize = SPI_DATASIZE_8BIT;$ n6 x0 Z5 s% ~4 S2 x9 V
  27.     SPI3_Handler.Init.CLKPolarity = SPI_POLARITY_LOW;! i; I  p7 d. |9 Z2 G) N
  28.     SPI3_Handler.Init.CLKPhase = SPI_PHASE_1EDGE;9 z' W6 w. y: {* q
  29.     SPI3_Handler.Init.NSS = SPI_NSS_SOFT;8 l, H; B) D; e1 A" v' S* v7 s6 x
  30.     SPI3_Handler.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_128;
    % Q! @& j, B. z2 S- N9 q/ v
  31.     SPI3_Handler.Init.FirstBit = SPI_FIRSTBIT_MSB;) I' b: m  V. _$ j( c, w
  32.     SPI3_Handler.Init.TIMode = SPI_TIMODE_DISABLE;+ {' a3 a9 i: W6 ^& A: q+ Z! Q+ }
  33.     SPI3_Handler.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE;
    # |0 v& s4 J+ z9 J
  34.     SPI3_Handler.Init.CRCPolynomial = 7;, O+ W" B& r; W3 P9 H3 [
  35.     SPI3_Handler.Init.CRCLength = SPI_CRC_LENGTH_DATASIZE;
    - n/ w! j1 P3 X# }' _% U& |
  36.     SPI3_Handler.Init.NSSPMode = SPI_NSS_PULSE_DISABLE;5 m  M! q6 e: C# G5 V" B' j1 h

  37. 5 e( P  }" Q) L0 Y) C
  38.     SPI3_Handler.RxISR = rx_isr;& X! h. K, l' g6 z
  39.     SPI3_Handler.TxISR = tx_isr;
    ! l- c0 F4 o! j) A4 R# W* E# J
  40.                
    3 h+ Y" \9 T; n. k' I9 O
  41.     HAL_SPI_Init(&SPI3_Handler);" b+ O" {/ L( u7 G
  42. $ N/ Y0 B+ a2 u+ M$ X
  43.     //__HAL_SPI_ENABLE_IT(&SPI3_Handler, SPI_IT_TXE);5 j7 s, L: U4 W9 h9 V$ ?' d
  44.     __HAL_SPI_ENABLE_IT(&SPI3_Handler, SPI_IT_RXNE);
    " v8 d* y# G, ?- _# q8 v, K5 J
  45. 9 D/ g9 U: ~9 _7 `
  46. }2 ^% Z6 ?2 u$ g' c' M- s5 _
  47. void SPI3_IRQHandler(void)
    + f3 @9 C& \+ T- {, W- j
  48. {
    ! `9 M0 s, l. ]
  49.     HAL_SPI_IRQHandler(&SPI3_Handler);0 X$ j# c! j. d% N2 U. {  U1 c- b9 H
  50. }
复制代码
9 H, s7 F1 Q& z& W
对应的读写操作如下:, }" y  ~- S! ^
% s: d! b) _! C* n8 X' ~* U
  1. u16 W25QXX_ReadID(void)/ s+ p8 v' ]+ t" _! H
  2. {  _. w" J6 R* V- Q. D6 M
  3.     u16 Temp = 0;
    & p) T: |# l5 H/ x

  4.   E. U5 V$ `! T
  5.     HAL_GPIO_WritePin(GPIOA, GPIO_PIN_4, GPIO_PIN_RESET);
      `, s: ~4 D; R: g" L, s
  6.     SPI3_ReadWriteByte(0x90);//发送读取ID命令
    ! R$ i( t& V4 H4 `
  7.     SPI3_ReadWriteByte(0x00);1 h* k5 Y) s. Y: R+ @
  8.     SPI3_ReadWriteByte(0x00);
    - U5 X8 K, ]; L8 W
  9.     SPI3_ReadWriteByte(0x00);
    + p$ [( i6 X+ @5 ]
  10.     Temp |= SPI3_ReadWriteByte(0xFF) << 8;+ i/ I$ Q( U* X
  11.     Temp |= SPI3_ReadWriteByte(0xFF);+ ~/ O; n6 Q! y/ j  D1 V, @4 q  x
  12.     HAL_GPIO_WritePin(GPIOA, GPIO_PIN_4, GPIO_PIN_SET);
    4 u; {$ `0 ?3 v6 m, B( q
  13.     return Temp;8 t! l* d% z1 B/ z8 ]1 n8 z
  14. }
复制代码
: A, g: _- Z3 G: Q2 Y# e
显示结果如下:
7 s5 V- t- A1 c2 n
20200423172457741.png

' C5 }1 a# ^) B
3 K# S8 S- B, Y8 }其中前面4个0xFF是因为在写,写完4个byte同样会进入4次中断,但由于我们在接收中断就把数据接受了,所以SPI3_ReadWriteByte因为超时才退出的,可以明显看到几个数不是同时打印的,至于后面的ID没有显示也是同样的道理。" \" w& s2 q+ `2 _

% P8 d3 e6 Z3 L  i发送缓冲区空中断
2 R9 T" |8 e+ d' I( l同样在前面使能发送完成中断就可以了:
; c& m" Y0 r  E! E6 C% Q
" K: J' X6 u! f5 t& n* q* l2 t& S
  1. __HAL_SPI_ENABLE_IT(&SPI3_Handler, SPI_IT_TXE);
复制代码
; R0 @4 B: S+ U8 Q9 x! U; D
但是由于发送完成了之后,发送缓冲区一直为空,所以会一直进入中断,所以我们使用发送完成中断的话,发送完成后除非再次填值或者关闭中断,否则会一直不停进入中断。
% _5 ]0 X  _: N9 c
6 S+ c! [& t' |+ ~1 ?而实际上HAL库是提供了一个HAL_SPI_TransmitReceive_IT用于中断使用的发送接收函数,其中很重要的一部分内容:
  p1 a" T* _3 b" s3 ^/ n0 y9 T8 @) J4 F4 J% }/ Q1 O
  1.   hspi->ErrorCode   = HAL_SPI_ERROR_NONE;
    * M+ }! d8 z+ q% F5 j) |; K* ]& r
  2.   hspi->pTxBuffPtr  = pTxData;
    % Q* p/ O8 {5 h9 h9 \/ b
  3.   hspi->TxXferSize  = Size;1 H4 e* L" i2 n  w4 W  L; o
  4.   hspi->TxXferCount = Size;
    9 W. x. s' I" g7 j( H1 f; q. v5 J
  5.   hspi->pRxBuffPtr  = pRxData;
    . u. `9 m9 }% Z3 V
  6.   hspi->RxXferSize  = Size;
    . j% ~4 _2 I! L: O7 O$ K
  7.   hspi->RxXferCount = Size;
    & O4 Q' \, L' b6 m  p0 ?7 ]2 C
  8. 2 ^8 S- K6 _0 y4 x% a
  9.   /* Set the function for IT treatment */, H3 T- m% l- {9 K, O3 W
  10.   if(hspi->Init.DataSize > SPI_DATASIZE_8BIT )# I0 G2 ]: a  Z6 O
  11.   {! V& s2 U/ @- r5 Y; q- C- V# g9 ~
  12.     hspi->RxISR = SPI_2linesRxISR_16BIT;
    2 A- l# ?  M% [2 \1 D
  13.     hspi->TxISR = SPI_2linesTxISR_16BIT;
    ( ~* L+ Q; d' J  _' h
  14.   }7 X8 Q9 h* b0 U( o
  15.   else! d3 W' p  R) j) T, ~
  16.   {/ ?& U% P- Q' X2 `) U; I0 [
  17.     hspi->RxISR = SPI_2linesRxISR_8BIT;
    7 Q7 v+ @- W8 w
  18.     hspi->TxISR = SPI_2linesTxISR_8BIT;
    ( w2 P" L3 @1 q% k) n, ?
  19.   }8 `) e2 k5 L9 X9 S/ o, y
  20.   __HAL_SPI_ENABLE_IT(hspi, (SPI_IT_TXE | SPI_IT_RXNE | SPI_IT_ERR));
复制代码

: {, L) ]+ H6 v: a7 x! k重新配置了中断函数,配置了发送和接收缓冲区为传入的数组,所以这里的数组要设置为全局变量,而前面设置的中断函数也失效了,而且使能了中断,所以我们前面所作的工作都是白费了。
. Q, t- a* ^1 D0 N! r, h- o6 p2 {" ]1 A6 K9 ]4 P0 t

8 s6 m" V7 ]8 T  {, Y  F+ N& \; Y2 @; f0 W! B
收藏 评论0 发布时间:2021-12-17 12:04

举报

0个回答
关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
STM32Cube扩展软件包
意法半导体边缘AI套件
ST - 理想汽车豪华SUV案例
ST意法半导体智能家居案例
STM32 ARM Cortex 32位微控制器
关注我们
st-img 微信公众号
st-img 手机版