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

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

[复制链接]
STMCU小助手 发布时间:2023-3-11 19:00
虽然在平常的使用中,spi使用轮询等待发送完成或者接收完成就行了。
4 s" u9 n3 k2 u# h8 a* v/ N/ z/ `* @但是在对时间有严格要求的设计中,假设我们需要发送完成后立马做xx事情,此时如果有低优先级的信号需要处理,我们的轮询方式就得不到及时的响应;
/ [* I5 h" t7 l5 Q# w* ]  i或者说比如需要定时从spi设备中采集数据,定时器中断来了我们就要马上调用接收函数,接收完成马上进行其他计算,同样此时应该保证数据的优先级。" `" _! y4 t  v" k; ^" V1 ^" ~
此时就需要用到发送完成和接收中断了。
3 G9 Q2 Z2 q  L
3 I# ^! B$ j$ S: N- O前面我们已经实现了SPI轮询的发送和接收,在前面的基础上进行修改。) `* Z" b+ c( ]

. }) r" y3 X$ z4 Z5 b" d) C
8 A) ]; _4 `7 M1 ?& p
接缓冲区满中断
- ]  E" O' \  i1 p& t3 S. O新增发送和接收的回调函数,并在初始化的时候配置,使能SPI接收中断:8 \- l6 r$ e& D1 g& z
  1. SPI_HandleTypeDef SPI3_Handler;  //SPI2句柄, c- E1 S, o3 k' n2 f/ B) O

  2. 9 G- t" R$ t! Z) r* ?2 E+ B7 Q$ Q
  3. void rx_isr(SPI_HandleTypeDef *hspi)
    % n! [0 H/ |7 O( V7 w7 q
  4. {
      m! \+ n$ u/ i8 x: T0 l* J
  5.     if (__HAL_SPI_GET_FLAG(hspi, SPI_FLAG_TXE) == 1)
    * i  d! `+ j1 e# Y& J6 i+ a+ [
  6.     {' X9 _9 ]& l* K/ [) ^% O
  7.         u8 data = SPI3->DR;; m& q( g9 w8 r, C
  8.                 printf("0x%X  ",data);' G: {8 K5 I/ T* [1 w' g
  9.     }
    ; Y' b, Q+ f3 [5 l3 r: b) l
  10. }% F4 ?, S- r9 H
  11. void tx_isr(SPI_HandleTypeDef *hspi)
    0 _. x9 j) s1 x0 j5 K+ [
  12. {
    5 ]7 i; M6 Z9 A/ i
  13.     if (__HAL_SPI_GET_FLAG(hspi, SPI_FLAG_TXE) == 1)
    5 T) s& E$ K7 S; Z: ~  B  I
  14.     {6 T! @6 {) a  f7 o- v

  15. ' z4 m3 q, n1 t
  16.     }
    $ K; ]3 |* R( m1 d# }& ^0 T6 d% o
  17. }; w5 |  i7 }, D9 H# s
  18. void SPI3_Init(void)4 \; N9 t4 q8 Y/ @5 @# ?" q
  19. {) Z6 Q7 N9 |8 w$ K7 ]9 ]8 G
  20.     HAL_NVIC_SetPriority(SPI3_IRQn, 0, 0);' c# O  o+ x1 m# I
  21.     HAL_NVIC_EnableIRQ(SPI3_IRQn);/ @9 U1 v0 T, _) \8 s/ M6 S" l% M; o# S

  22. 3 x/ X) D4 d: o- F; c& K/ _- n; F7 Z
  23.     SPI3_Handler.Instance = SPI3;
    ; q4 i' V# w* {0 W
  24.     SPI3_Handler.Init.Mode = SPI_MODE_MASTER;
    0 k/ R+ K& n3 m" ?1 v
  25.     SPI3_Handler.Init.Direction = SPI_DIRECTION_2LINES;
    " a8 I( M* T0 o* N2 s
  26.     SPI3_Handler.Init.DataSize = SPI_DATASIZE_8BIT;( h9 l" t, U. _$ ^7 y  [
  27.     SPI3_Handler.Init.CLKPolarity = SPI_POLARITY_LOW;
    2 K* K) o! F6 P( ]9 }0 N. `
  28.     SPI3_Handler.Init.CLKPhase = SPI_PHASE_1EDGE;5 D: i# Y. ?  {7 Y" c; s  h
  29.     SPI3_Handler.Init.NSS = SPI_NSS_SOFT;
    - [" {( Q$ f7 a# _- d1 F
  30.     SPI3_Handler.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_128;* n& h9 Q2 `0 `' \
  31.     SPI3_Handler.Init.FirstBit = SPI_FIRSTBIT_MSB;
    - }! U/ |+ w5 O7 E6 S) [+ u
  32.     SPI3_Handler.Init.TIMode = SPI_TIMODE_DISABLE;; b  r2 a0 o: v% r. |- @" E
  33.     SPI3_Handler.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE;
    " A4 D$ Y! J" b5 q3 d
  34.     SPI3_Handler.Init.CRCPolynomial = 7;
    - T6 W8 m9 _: |) [2 b1 F
  35.     SPI3_Handler.Init.CRCLength = SPI_CRC_LENGTH_DATASIZE;% R* W2 @  Y& F( z
  36.     SPI3_Handler.Init.NSSPMode = SPI_NSS_PULSE_DISABLE;. P6 G9 C* P; z

  37. & U, m$ U: a# g& u" D1 j( o
  38.     SPI3_Handler.RxISR = rx_isr;
    ; ~3 I, \& u7 M' m) e8 H7 [
  39.     SPI3_Handler.TxISR = tx_isr;
    & v# s9 g& ~5 H: U& W8 J
  40.                
    ) u! e) h# h: t( a* q
  41.     HAL_SPI_Init(&SPI3_Handler);
    - _" [7 e) {' O' U( I  C; ?( ?
  42. 7 K. g1 B/ Y. j, P" ]) {
  43.     //__HAL_SPI_ENABLE_IT(&SPI3_Handler, SPI_IT_TXE);, G' \" q2 B/ E( T- b, Q( y
  44.     __HAL_SPI_ENABLE_IT(&SPI3_Handler, SPI_IT_RXNE);
    ' K; M/ K) C4 I" {5 _! E
  45. ' i% i/ W  q( O0 @6 ]
  46. }6 D; C  i: x- L& q+ I
  47. void SPI3_IRQHandler(void)$ S/ Y* T  F/ @( i/ J8 d6 h  O! U
  48. {% J# P* t2 k* o+ ~: y
  49.     HAL_SPI_IRQHandler(&SPI3_Handler);0 J2 b/ h/ Y; Q, s, s2 C
  50. }: w7 ~; S) b6 G: n$ Z0 ?

  51. - v/ @) S8 D* ^) g
复制代码
$ f9 _. @% P. y0 C, c0 x4 v
对应的读写操作如下:
' p+ }  w: Y) X+ c* F
  1. u16 W25QXX_ReadID(void)
    6 ^/ M+ E; L' K$ X4 _4 Z& v* k
  2. {) F+ I) L2 r' D/ ~% }: J! A% j
  3.     u16 Temp = 0;9 Q/ ^! L: ^, D  m& J5 Z

  4. 9 k+ q2 b8 |9 N  m; H3 p1 p
  5.     HAL_GPIO_WritePin(GPIOA, GPIO_PIN_4, GPIO_PIN_RESET);
    $ A* i/ t* a5 d7 q$ y9 r$ ]
  6.     SPI3_ReadWriteByte(0x90);//发送读取ID命令
    * M3 `3 @  r+ J2 j  U
  7.     SPI3_ReadWriteByte(0x00);
    , I4 {, D' D3 J7 h  c, A
  8.     SPI3_ReadWriteByte(0x00);
    9 e* n$ b, v$ }" c
  9.     SPI3_ReadWriteByte(0x00);
    2 f, W, z3 r& x* K0 T8 _
  10.     Temp |= SPI3_ReadWriteByte(0xFF) << 8;
      s3 A" Q1 B5 H
  11.     Temp |= SPI3_ReadWriteByte(0xFF);
    . R* k) h+ w, i( T4 X$ [7 P( p! j
  12.     HAL_GPIO_WritePin(GPIOA, GPIO_PIN_4, GPIO_PIN_SET);
    - F/ N( i* i% f" L8 ^! |( I* ~
  13.     return Temp;
    2 R/ @" d# ~7 R- a4 l$ {
  14. }
    + E: I$ [6 q2 ~4 G4 w
复制代码
$ `: b2 M' k8 t. X" K3 b5 {
显示结果如下:3 ~' e/ O  S) f' v" x+ B3 F( Q& i
. B& M" g9 A8 O' `! l+ ^
20200423172457741.png 2 F9 f$ U7 c  s5 @: k( U: }
% u# O& v7 n2 C  G* ^9 @% `
其中前面4个0xFF是因为在写,写完4个byte同样会进入4次中断,但由于我们在接收中断就把数据接受了,所以SPI3_ReadWriteByte因为超时才退出的,可以明显看到几个数不是同时打印的,至于后面的ID没有显示也是同样的道理。# c  ^, u9 @7 O  {+ H& }% T
" ?: ~) l6 m% _2 H
发送缓冲区空中断  _' p. Y# v0 M+ H
同样在前面使能发送完成中断就可以了:7 O% C  C( t' c- A2 E
  1. __HAL_SPI_ENABLE_IT(&SPI3_Handler, SPI_IT_TXE);
复制代码
4 V7 ]  k; m! j( q& E
但是由于发送完成了之后,发送缓冲区一直为空,所以会一直进入中断,所以我们使用发送完成中断的话,发送完成后除非再次填值或者关闭中断,否则会一直不停进入中断。- F- L7 R8 |3 W7 C$ k* I

- o: ]0 W. L' D而实际上HAL库是提供了一个HAL_SPI_TransmitReceive_IT用于中断使用的发送接收函数,其中很重要的一部分内容:
7 m8 W9 ]! V4 }, p
  1.   hspi->ErrorCode   = HAL_SPI_ERROR_NONE;
    - d( G* V; I9 I& W7 z; ]9 t
  2.   hspi->pTxBuffPtr  = pTxData;" w. k3 b: Q& R$ U" H2 z
  3.   hspi->TxXferSize  = Size;1 O, M7 O% J) V" `& A; D% n
  4.   hspi->TxXferCount = Size;9 F: ~- O" A4 [' b9 F3 d
  5.   hspi->pRxBuffPtr  = pRxData;+ H/ \) i: p! j; ]7 A. |, {8 u
  6.   hspi->RxXferSize  = Size;
    7 J/ y* E! E! v  x' I
  7.   hspi->RxXferCount = Size;
    + A1 e- E/ l, J$ t* t8 x
  8. 3 ~. ^6 k7 W3 [( S5 S" K
  9.   /* Set the function for IT treatment */
    ) |0 p7 e; x" E
  10.   if(hspi->Init.DataSize > SPI_DATASIZE_8BIT )
    0 E% F" z5 s- j- j
  11.   {, O6 r* n4 ?/ O& i4 A7 v9 V
  12.     hspi->RxISR = SPI_2linesRxISR_16BIT;, V/ Z- v6 A; d7 d& V5 f
  13.     hspi->TxISR = SPI_2linesTxISR_16BIT;( [% q! D; s/ }' r6 p# P
  14.   }! X0 w9 g" R& a/ q
  15.   else7 R: B4 d6 r0 F
  16.   {
    5 p+ s+ |0 d8 D0 ]. E9 Q9 ~
  17.     hspi->RxISR = SPI_2linesRxISR_8BIT;
    / _: a: s8 {5 @) d: J
  18.     hspi->TxISR = SPI_2linesTxISR_8BIT;7 P, D; d5 ^9 a0 n  p
  19.   }
    8 L- b3 b. }9 H5 h5 ?4 K* R
  20.   __HAL_SPI_ENABLE_IT(hspi, (SPI_IT_TXE | SPI_IT_RXNE | SPI_IT_ERR));$ Z) A! @: \; S/ j
复制代码
& P' u5 B8 _0 P+ W# l8 P5 Y" T
重新配置了中断函数,配置了发送和接收缓冲区为传入的数组,所以这里的数组要设置为全局变量,而前面设置的中断函数也失效了,而且使能了中断,所以我们前面所作的工作都是白费了。4 h" r. j$ o/ P+ V3 B4 w* [  r

+ ]$ e) y* h6 c0 j9 u! u+ Y至于HAL_SPI_TransmitReceive_IT的具体过程,先埋个坑……(项目现在没这需求了); c& ]5 v0 V/ s( ?
————————————————  r6 f# n9 U$ v. c+ a1 t
版权声明:小盼你最萌哒
) A; o; z8 p1 P3 _7 x2 N' U: r8 p. R/ f% q( s5 B
收藏 评论0 发布时间:2023-3-11 19:00

举报

0个回答
关于意法半导体
我们是谁
投资者关系
意法半导体可持续发展举措
创新和工艺
招聘信息
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
关注我们
st-img 微信公众号
st-img 手机版