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

【经验分享】STM32H7串口DMA+空闲中断实现接收和发送不定长度数据

[复制链接]
STMCU小助手 发布时间:2021-12-27 21:00
stm32f103芯片的串口一直使用DMA+空闲中断,现在使用stm32h7芯片,打算也使用相同的方法
4 l/ l, [& M) C: A2 X! l芯片型号:stm32h743
# e; c/ k8 S+ M; {5 l' N8 t+ N串口:USART2% D0 Z5 X9 P. z" X  w9 W
代码生成:stm32CubeMX
# E4 p4 n4 K: r% U' M8 C第一步:使用stm32CubeMX生成代码! v- r: B+ @6 I. ^. X1 I. U
8 z4 S+ \0 v! \1 n
第二步:添加自己代码
" w6 l( S4 i! l, A' D* n, h8 _, T3 R8 J$ r3 |
1.发生空闲中断需要reset DMA重新开始接收数据7 E: V; S5 v! z9 `

0 [5 c! Y" [+ X% _
  1. HAL_StatusTypeDef HAL_UART_DMAStopRx(UART_HandleTypeDef *huart)$ ^) r1 ?7 B" l) X0 G/ _/ e) u
  2. {% r' t2 O2 T& I" ?
  3.   /* Stop UART DMA Rx request if ongoing */
    : d6 P5 j1 M+ y( [3 S+ }
  4.   if ((huart->RxState == HAL_UART_STATE_BUSY_RX) &&
    0 d5 A, F8 h  \  |; m1 ?! g1 k
  5.       (HAL_IS_BIT_SET(huart->Instance->CR3, USART_CR3_DMAR)))
    ! ^. ~( j* v6 {$ |! s
  6.   {
    ) q3 e% [( {9 M! P
  7.     CLEAR_BIT(huart->Instance->CR3, USART_CR3_DMAR);9 |/ ]0 E7 S! ]' v# S8 \, j9 t; Z

  8. ) T5 K/ j8 q2 m1 ^) _( M! w
  9.     /* Abort the UART DMA Rx channel */
    " Z6 q) F6 @& ~+ w3 U
  10.     if(huart->hdmarx != NULL)0 F# F+ |2 i" C# ?( A* I: F
  11.     {
    7 m! f9 u6 t0 E( _( |0 x. D
  12.       HAL_DMA_Abort(huart->hdmarx);
    , E2 t7 y0 ~& F) Q0 e
  13.     }8 G% w9 v2 A* I

  14. ! n* Y7 K: ?: W# h5 K: Y
  15.     //UART_EndRxTransfer(huart);. v, ~  n* n1 W$ b
  16.     /* Disable RXNE, PE and ERR (Frame error, noise error, overrun error) interrupts */' y& V' R$ @. `5 }
  17.         CLEAR_BIT(huart->Instance->CR1, (USART_CR1_RXNEIE | USART_CR1_PEIE));; Z  C# I1 j. K/ y, h( G
  18.         CLEAR_BIT(huart->Instance->CR3, USART_CR3_EIE);3 y" y6 v$ \6 P8 z$ V1 H& Y
  19. 8 v- a, @% `3 E" \# u# e" M6 C7 ^, b3 p
  20.         /* At end of Rx process, restore huart->RxState to Ready */
    $ \7 G* A" [0 \6 `5 t
  21.         huart->RxState = HAL_UART_STATE_READY;3 a) ]9 o, Y; b1 p! e( S
  22.   }
    ) {7 y" b* u) `2 y+ H
  23. # n8 d7 a5 y* Z' w$ R: k4 O: c
  24.   return HAL_OK;) K! E) w9 s3 W& d. j
  25. }2 {- Y5 G8 |: w$ H/ e( g* y
复制代码

$ j8 C9 x- S  P+ W! }7 a( y串口空闲中断  ~  S7 M$ D2 q$ b  ^4 e# p

- I* `2 R" ]. `0 C9 Q; f
  1. /**; t4 f- ?- {. V( t1 V! O& f$ k8 C" K
  2.   * @brief This function handles UART4 global interrupt.
    ' N; r1 B8 g0 c' ~
  3.   */
    % R( @/ C& `3 T
  4. void USART2_IRQHandler(void)/ c" R0 W+ n6 S  s
  5. {
    - E& k+ R3 Z; j
  6.         uint32_t _len_dmarev;$ t6 T1 o3 P; o0 g# _
  7.         uint32_t isrflags;5 q. T$ K1 b' K- t
  8.         uint32_t cr1its;
    ( t5 I. {& L+ R; O
  9.         BaseType_t xHigherPriorityTaskWoken;. P- M$ o2 O2 O' P% z

  10. $ F9 ]/ }: f; k3 N) D5 ~
  11.         7 c" M$ R5 r. L, U
  12.         HAL_UART_IRQHandler(&UART2_Handler);
    5 I5 D; f) J9 q0 d) k

  13. 3 R% o: {" H  r7 ^
  14.         isrflags   = READ_REG(UART2_Handler.Instance->ISR);
    ( v. T7 ~  }# t  t- Q4 [
  15.         cr1its     = READ_REG(UART2_Handler.Instance->CR1);8 M* m6 C# F) m% _% N

  16. & _: g% y, m+ w# R7 C) ?- a
  17.         if(((isrflags & USART_ISR_IDLE) != RESET) && ((cr1its & USART_CR1_IDLEIE) != RESET)). Z8 N) z# z3 R! f
  18.         {- Q; Z# Q; b8 i
  19.                 __HAL_UART_CLEAR_IDLEFLAG(&UART2_Handler);! W! ?2 L# J: H; ^: K, m- Z& Z- G
  20. / s( C8 \9 Y9 \% h- _
  21.                 _len_dmarev = DMA_BUFFER_LENGTH -                                         __HAL_DMA_GET_COUNTER(UART2_Handler.hdmarx);
    + o" ]* D' b1 S* t1 g3 h8 r

  22. : d; u2 C. i# p2 d0 B7 O/ i+ l* I+ C
  23.                 if(_len_dmarev)  [: `2 S, {% \9 v
  24.                 {
    % f7 Z) J  ^% E% Q
  25.                   //停止DMA& F6 {9 Q& b- N1 `+ U; ]; [6 n: o6 m
  26.                   HAL_UART_DMAStopRx(&UART2_Handler);. c, |( A/ Z4 {0 N  [9 M
  27.                 //这个地方非常关键,DMA访问的ram,但是CPU访问的是cache,使用下面函数使ram和cache一致
    / r8 d- U3 H" p2 Z
  28.                  SCB_InvalidateDCache_by_Addr((uint32_t *)dma_rx_buf, DMA_BUFFER_LENGTH);7 r' f) r. v8 b
  29.                  % \9 e+ E' ~" _* x
  30.                  xQueueSendToBackFromISR(Keyboard_Queue,(void*)&uart_to_keyboard_msg,&xHigherPriorityTaskWoken);! |6 D0 s1 q0 W1 X. T
  31.                  ( H/ Q, R3 X$ S: @1 ^
  32.                  portYIELD_FROM_ISR(xHigherPriorityTaskWoken);, u1 p/ F7 ]3 p

  33. * a% R1 {  L7 T% o( ]  q9 t( q
  34.                   HAL_UART_Receive_DMA(&UART2_Handler, dma_rx_buf, DMA_BUFFER_LENGTH);
    0 Y! W+ M+ m5 j) b- U- e8 r4 l+ S
  35.                   __HAL_UART_DISABLE_IT(&UART2_Handler, UART_IT_ERR);
    2 [5 |8 S* \9 i; g
  36.                   __HAL_UART_DISABLE_IT(&UART2_Handler, UART_IT_PE);  A7 s, s2 c7 k6 O$ b( p3 \: a
  37.                 }6 f/ y) R! F$ M+ ^. O5 ?9 B
  38.           else5 s/ h7 [# }$ A+ I8 N% |
  39.           {/ X5 z7 o4 H+ Q
  40.                   READ_REG(UART2_Handler.Instance->RDR);
    2 g! Y: C6 p7 n) j% W
  41.                   __HAL_UART_CLEAR_OREFLAG(&UART2_Handler);% f& @' p: w7 \: k. Q; v& ^
  42.           }! M5 U7 T5 w. n  C( t; r& p
  43. " \8 s1 `% m! }$ \  I5 }
  44.   }' k- _: H' }6 z) }$ _* d; m! F
  45. ; J9 a5 m8 o4 {
  46. }8 l" r% ^6 `; X" \% i
复制代码

  K5 H& b: K' T! U0 i发送函数- B$ k/ K3 G& }6 u" U

5 a5 @2 \3 b+ D4 m6 |
  1. unsigned int KeyboardRs485TxFrame(uint8_t * buffer,uint32_t len)' L/ Y5 q1 x$ C  J
  2. {( i* s0 C$ h( C6 g9 d  {3 `
  3. UINT16 i;$ j' [& R4 b- \" ?4 `

  4. . w1 t- w7 {) p0 @* p& o
  5. //拷贝数据到DMA buffer
    # J6 b7 Y! |" C
  6. for(i = 0; i < len; i++)3 V; t6 }( Q. k) A' z6 C  ?9 m& l
  7. {
    % w4 e0 c4 s0 z; @: z% |
  8.         dma_tx_buf<i> =</i> buffer; ; A# v& r9 x% L+ K8 X. n, g
  9. }% b5 E7 m4 D, P

  10. & l+ e9 ?# o% ]' ?0 |- M+ L1 b" `
  11. //使发送RAM和cache一致4 i/ W' h8 s) c3 [* z( g
  12. SCB_InvalidateDCache_by_Addr((uint32_t *)dma_tx_buf, DMA_BUFFER_LENGTH);& S% K  w9 X6 c- b3 A  g
  13. HAL_UART_Transmit_DMA(&UART2_Handler, dma_tx_buf, len);
    . u1 ?3 f- a% r; g1 v
  14. return 0;
复制代码

$ d5 @% A; B9 \% G) F$ |还有一点需要特别注意:DMA访问的是0x24000000以后区域,定义的发送和接收DMA buffer 一定要在这个区域
' d6 `0 n* e' f! _: Y可使用下面的编译指令:. [6 N- G4 C- r/ G" A/ k
  1. ALIGN_32BYTES(attribute((section (".RAM_D2"))) uint8_t dma_rx_buf[DMA_BUFFER_LENGTH]) ;
    9 |# m; W! Y4 a
  2. ALIGN_32BYTES(attribute((section (".RAM_D2"))) uint8_t dma_tx_buf[DMA_BUFFER_LENGTH]);
    & Q8 B. P; g* z! W6 i2 R
复制代码
7 R5 o+ {/ c; \% r
赞 收藏 评论0 发布时间:2021-12-27 21:00

举报

0个回答

所属标签

相似技术帖

官网相关资源

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