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

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

[复制链接]
STMCU小助手 发布时间:2021-12-27 21:00
stm32f103芯片的串口一直使用DMA+空闲中断,现在使用stm32h7芯片,打算也使用相同的方法
, k$ t" a) x5 U4 O; }芯片型号:stm32h7432 _. P8 Z9 S: O- Z
串口:USART29 |( K" R' m  Y
代码生成:stm32CubeMX
1 V: V7 I9 J8 @' |: `第一步:使用stm32CubeMX生成代码4 ^3 @: k7 o# Z! ?2 `- k0 i+ i

: F9 v% b' M3 M) ^第二步:添加自己代码6 W8 }' e& s; L2 Z* U

) k  y  Y9 x+ p  \& ]4 S1.发生空闲中断需要reset DMA重新开始接收数据
3 d1 B( \0 j: S( x4 B5 r
) J; }" P0 r6 k$ @0 Y( j
  1. HAL_StatusTypeDef HAL_UART_DMAStopRx(UART_HandleTypeDef *huart)
    " G: h$ i+ d% L" d% ^6 k0 A+ i5 i
  2. {
    4 H: Q2 f/ a0 m( u. t8 |
  3.   /* Stop UART DMA Rx request if ongoing */4 K7 z9 |# \6 g5 D5 Y( j  f
  4.   if ((huart->RxState == HAL_UART_STATE_BUSY_RX) &&5 m" I5 \( @& a7 b7 ]6 C: F" n
  5.       (HAL_IS_BIT_SET(huart->Instance->CR3, USART_CR3_DMAR)))3 T$ o. I# c2 z; d. l* _6 z# c9 B
  6.   {
    ) n7 R; b% C' f5 x" n* T" a
  7.     CLEAR_BIT(huart->Instance->CR3, USART_CR3_DMAR);
    ( B, Y; Z! n! W- J' m# n

  8. ( P. n2 X4 H7 J) ~4 ^4 y# P" @7 B- |
  9.     /* Abort the UART DMA Rx channel */
    ( J4 X1 ?4 {' ]; _* q" r4 ?
  10.     if(huart->hdmarx != NULL)
    ; z0 Q9 r, M. x  d2 p) ]
  11.     {% u! F) w0 v) U% M1 K& }; B: C% ?
  12.       HAL_DMA_Abort(huart->hdmarx);
    # U, `. B/ P* ~, i1 ^. m, G
  13.     }
    * D. w" Y% l7 M& y3 H: }) K
  14. - _7 @/ }  K% r8 o; i
  15.     //UART_EndRxTransfer(huart);( E& x1 g  ~2 h
  16.     /* Disable RXNE, PE and ERR (Frame error, noise error, overrun error) interrupts */
    3 V" s9 P4 A& q' O$ a
  17.         CLEAR_BIT(huart->Instance->CR1, (USART_CR1_RXNEIE | USART_CR1_PEIE));
    / Z6 {7 @& R0 g8 O; ~, U, h8 y
  18.         CLEAR_BIT(huart->Instance->CR3, USART_CR3_EIE);
    ; |. {1 Q. {  r4 \8 ^3 O

  19. 6 E, K3 P' ]9 J* c4 N/ T
  20.         /* At end of Rx process, restore huart->RxState to Ready */
    * L  L" _1 S, W! Z& k
  21.         huart->RxState = HAL_UART_STATE_READY;3 m' t9 {  W* a$ h1 ^( i
  22.   }
    . \7 s, W7 U9 W8 f- w
  23. ( N2 K. H+ a$ R& d1 M
  24.   return HAL_OK;. y7 [/ P9 X, M0 q
  25. }
    ; `3 ~5 D8 S( t8 P* K* l
复制代码

, ^0 D, G; L$ @: q8 F: G) Q串口空闲中断  `3 ^5 B$ N* a9 H& B+ X& B2 Y
9 @/ b5 H$ E- ?, \2 X
  1. /**2 `/ ?8 b9 K+ r: C# ~; T( D0 \- |/ D
  2.   * @brief This function handles UART4 global interrupt.
    6 r% d& o( w; J! ^& r, p
  3.   */
    % f5 V: _- w# S
  4. void USART2_IRQHandler(void)
    & w, s) N# t& f0 D7 a
  5. {8 i: K, d4 J- o) _% f6 m3 d* v% P
  6.         uint32_t _len_dmarev;
    % E2 z: ]) i( f2 ], T0 @
  7.         uint32_t isrflags;
    : G2 q& [! x( f! y' F; v/ M  l
  8.         uint32_t cr1its;
    / {+ @7 d2 h' O- r- E" }
  9.         BaseType_t xHigherPriorityTaskWoken;0 g9 |/ m# O- ^' O

  10. 7 W; ^2 I" X$ Z+ k" M! r
  11.         
    * w" D& D0 d+ T
  12.         HAL_UART_IRQHandler(&UART2_Handler);, n3 _4 a8 o4 ^" Z

  13. 7 `8 f& M: c9 C4 j
  14.         isrflags   = READ_REG(UART2_Handler.Instance->ISR);
    , b1 k& |  D1 @3 b$ n
  15.         cr1its     = READ_REG(UART2_Handler.Instance->CR1);
    2 |! R) o! `5 c6 I9 h

  16. ; G1 B" K5 r! C0 N0 }5 Q
  17.         if(((isrflags & USART_ISR_IDLE) != RESET) && ((cr1its & USART_CR1_IDLEIE) != RESET))
    0 }1 J, Z: l2 ~7 B2 o
  18.         {
    : l' T6 x8 X/ ]) j7 ]9 a7 y
  19.                 __HAL_UART_CLEAR_IDLEFLAG(&UART2_Handler);
    + h6 i2 H4 S  E, x) O
  20. 6 t5 v& V6 i+ K* |
  21.                 _len_dmarev = DMA_BUFFER_LENGTH -                                         __HAL_DMA_GET_COUNTER(UART2_Handler.hdmarx);
    ; D  Z4 w1 @* l" J5 y/ k, z

  22. & j: b3 m: M( V5 S) V7 f, c
  23.                 if(_len_dmarev)
    - R# A# Z" X& }; i$ E
  24.                 {
      |5 b, }+ Z0 Z
  25.                   //停止DMA. U0 |- @+ v4 I4 q9 x
  26.                   HAL_UART_DMAStopRx(&UART2_Handler);
    6 N' L, r2 O  [4 \, G; o! Q
  27.                 //这个地方非常关键,DMA访问的ram,但是CPU访问的是cache,使用下面函数使ram和cache一致" ~6 H8 Z; `: m: q0 I
  28.                  SCB_InvalidateDCache_by_Addr((uint32_t *)dma_rx_buf, DMA_BUFFER_LENGTH);7 N9 v% q& G! }4 Q4 |% t) Z, D
  29.                  
    " `; M) F/ E" z/ T6 N7 n5 u
  30.                  xQueueSendToBackFromISR(Keyboard_Queue,(void*)&uart_to_keyboard_msg,&xHigherPriorityTaskWoken);) H7 l3 L8 @# M% T, l% U( j
  31.                  
    / k3 F. p- R* H* r# x
  32.                  portYIELD_FROM_ISR(xHigherPriorityTaskWoken);8 _5 g. H: e  D: ]7 g& }

  33. - |3 Y5 B+ a) m. w$ F6 W! ?, A
  34.                   HAL_UART_Receive_DMA(&UART2_Handler, dma_rx_buf, DMA_BUFFER_LENGTH);
    . Q. @6 P2 \1 f$ C% p: O
  35.                   __HAL_UART_DISABLE_IT(&UART2_Handler, UART_IT_ERR);
    " o; p7 d% \: h2 R& U6 ?
  36.                   __HAL_UART_DISABLE_IT(&UART2_Handler, UART_IT_PE);
    " b9 b! D9 r' y! [
  37.                 }
    $ y: Q3 d1 k1 @: J/ d8 ^/ X9 @, z
  38.           else# l1 d: ]& c; F0 {! z# }
  39.           {6 e2 G5 J8 d& \6 ]: c
  40.                   READ_REG(UART2_Handler.Instance->RDR);
    ' U- J8 P% n. s! g
  41.                   __HAL_UART_CLEAR_OREFLAG(&UART2_Handler);  K- `4 f4 ]" [9 S% f! _' [5 w( h
  42.           }3 _( Q" v( T6 j; c+ L  \
  43. + I; v% N7 O1 Y9 |* ^2 z. d
  44.   }9 g4 `8 _( P4 V, H& ^* }) w
  45. # q4 A# Q5 `& j
  46. }; N7 S- N, z4 v( Y  h& f* ?
复制代码

$ J* Z) Z& U8 [% U& W' M0 k4 E- k3 [+ Z发送函数; K& x% ]! @0 d3 @* q

2 [8 l3 y" V0 i: z; B0 L+ f
  1. unsigned int KeyboardRs485TxFrame(uint8_t * buffer,uint32_t len)
    6 Y; [+ n: S4 E2 L4 A' I6 a
  2. {
    1 O7 u3 n8 h, y& W% q8 X! \
  3. UINT16 i;, d+ r+ x% s# L
  4. ) q& G5 E9 s+ z& j1 w6 m
  5. //拷贝数据到DMA buffer  \6 d8 @) _6 W) b
  6. for(i = 0; i < len; i++). _) d$ s7 b/ s0 ?+ v
  7. {
    ; c) h. K+ T+ l8 i
  8.         dma_tx_buf<i> =</i> buffer;
    , C  S% K0 N! X# V8 R( [7 N5 L
  9. }! E. j/ f6 y2 G4 V7 T" W6 \
  10. ( E( c2 e& o6 a1 Z! ~7 n4 k7 _
  11. //使发送RAM和cache一致
    3 Q! R( k9 |& \* u) \- l( k, f
  12. SCB_InvalidateDCache_by_Addr((uint32_t *)dma_tx_buf, DMA_BUFFER_LENGTH);( a# u( V8 ?( l4 k7 g3 A
  13. HAL_UART_Transmit_DMA(&UART2_Handler, dma_tx_buf, len);
    8 x/ U, x1 H/ A3 G! s1 \
  14. return 0;
复制代码
7 T# _2 J, k9 W* @5 \$ K
还有一点需要特别注意:DMA访问的是0x24000000以后区域,定义的发送和接收DMA buffer 一定要在这个区域
4 Y# V1 Q4 \+ `可使用下面的编译指令:% o; w* p* ]- z. ?9 H
  1. ALIGN_32BYTES(attribute((section (".RAM_D2"))) uint8_t dma_rx_buf[DMA_BUFFER_LENGTH]) ;
    / T! z. C2 L1 A4 X
  2. ALIGN_32BYTES(attribute((section (".RAM_D2"))) uint8_t dma_tx_buf[DMA_BUFFER_LENGTH]);
    / Q7 P" D+ C, f/ v. i' c7 V
复制代码

% `6 M7 H/ j1 O; Y+ M6 a: g! H6 C
收藏 评论0 发布时间:2021-12-27 21:00

举报

0个回答

所属标签

相似分享

官网相关资源

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