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% _- HAL_StatusTypeDef HAL_UART_DMAStopRx(UART_HandleTypeDef *huart)$ ^) r1 ?7 B" l) X0 G/ _/ e) u
- {% r' t2 O2 T& I" ?
- /* Stop UART DMA Rx request if ongoing */
: d6 P5 j1 M+ y( [3 S+ } - if ((huart->RxState == HAL_UART_STATE_BUSY_RX) &&
0 d5 A, F8 h \ |; m1 ?! g1 k - (HAL_IS_BIT_SET(huart->Instance->CR3, USART_CR3_DMAR)))
! ^. ~( j* v6 {$ |! s - {
) q3 e% [( {9 M! P - CLEAR_BIT(huart->Instance->CR3, USART_CR3_DMAR);9 |/ ]0 E7 S! ]' v# S8 \, j9 t; Z
) T5 K/ j8 q2 m1 ^) _( M! w- /* Abort the UART DMA Rx channel */
" Z6 q) F6 @& ~+ w3 U - if(huart->hdmarx != NULL)0 F# F+ |2 i" C# ?( A* I: F
- {
7 m! f9 u6 t0 E( _( |0 x. D - HAL_DMA_Abort(huart->hdmarx);
, E2 t7 y0 ~& F) Q0 e - }8 G% w9 v2 A* I
! n* Y7 K: ?: W# h5 K: Y- //UART_EndRxTransfer(huart);. v, ~ n* n1 W$ b
- /* Disable RXNE, PE and ERR (Frame error, noise error, overrun error) interrupts */' y& V' R$ @. `5 }
- CLEAR_BIT(huart->Instance->CR1, (USART_CR1_RXNEIE | USART_CR1_PEIE));; Z C# I1 j. K/ y, h( G
- CLEAR_BIT(huart->Instance->CR3, USART_CR3_EIE);3 y" y6 v$ \6 P8 z$ V1 H& Y
- 8 v- a, @% `3 E" \# u# e" M6 C7 ^, b3 p
- /* At end of Rx process, restore huart->RxState to Ready */
$ \7 G* A" [0 \6 `5 t - huart->RxState = HAL_UART_STATE_READY;3 a) ]9 o, Y; b1 p! e( S
- }
) {7 y" b* u) `2 y+ H - # n8 d7 a5 y* Z' w$ R: k4 O: c
- return HAL_OK;) K! E) w9 s3 W& d. j
- }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- /**; t4 f- ?- {. V( t1 V! O& f$ k8 C" K
- * @brief This function handles UART4 global interrupt.
' N; r1 B8 g0 c' ~ - */
% R( @/ C& `3 T - void USART2_IRQHandler(void)/ c" R0 W+ n6 S s
- {
- E& k+ R3 Z; j - uint32_t _len_dmarev;$ t6 T1 o3 P; o0 g# _
- uint32_t isrflags;5 q. T$ K1 b' K- t
- uint32_t cr1its;
( t5 I. {& L+ R; O - BaseType_t xHigherPriorityTaskWoken;. P- M$ o2 O2 O' P% z
$ F9 ]/ }: f; k3 N) D5 ~- 7 c" M$ R5 r. L, U
- HAL_UART_IRQHandler(&UART2_Handler);
5 I5 D; f) J9 q0 d) k
3 R% o: {" H r7 ^- isrflags = READ_REG(UART2_Handler.Instance->ISR);
( v. T7 ~ }# t t- Q4 [ - cr1its = READ_REG(UART2_Handler.Instance->CR1);8 M* m6 C# F) m% _% N
& _: g% y, m+ w# R7 C) ?- a- if(((isrflags & USART_ISR_IDLE) != RESET) && ((cr1its & USART_CR1_IDLEIE) != RESET)). Z8 N) z# z3 R! f
- {- Q; Z# Q; b8 i
- __HAL_UART_CLEAR_IDLEFLAG(&UART2_Handler);! W! ?2 L# J: H; ^: K, m- Z& Z- G
- / s( C8 \9 Y9 \% h- _
- _len_dmarev = DMA_BUFFER_LENGTH - __HAL_DMA_GET_COUNTER(UART2_Handler.hdmarx);
+ o" ]* D' b1 S* t1 g3 h8 r
: d; u2 C. i# p2 d0 B7 O/ i+ l* I+ C- if(_len_dmarev) [: `2 S, {% \9 v
- {
% f7 Z) J ^% E% Q - //停止DMA& F6 {9 Q& b- N1 `+ U; ]; [6 n: o6 m
- HAL_UART_DMAStopRx(&UART2_Handler);. c, |( A/ Z4 {0 N [9 M
- //这个地方非常关键,DMA访问的ram,但是CPU访问的是cache,使用下面函数使ram和cache一致
/ r8 d- U3 H" p2 Z - SCB_InvalidateDCache_by_Addr((uint32_t *)dma_rx_buf, DMA_BUFFER_LENGTH);7 r' f) r. v8 b
- % \9 e+ E' ~" _* x
- xQueueSendToBackFromISR(Keyboard_Queue,(void*)&uart_to_keyboard_msg,&xHigherPriorityTaskWoken);! |6 D0 s1 q0 W1 X. T
- ( H/ Q, R3 X$ S: @1 ^
- portYIELD_FROM_ISR(xHigherPriorityTaskWoken);, u1 p/ F7 ]3 p
* a% R1 { L7 T% o( ] q9 t( q- HAL_UART_Receive_DMA(&UART2_Handler, dma_rx_buf, DMA_BUFFER_LENGTH);
0 Y! W+ M+ m5 j) b- U- e8 r4 l+ S - __HAL_UART_DISABLE_IT(&UART2_Handler, UART_IT_ERR);
2 [5 |8 S* \9 i; g - __HAL_UART_DISABLE_IT(&UART2_Handler, UART_IT_PE); A7 s, s2 c7 k6 O$ b( p3 \: a
- }6 f/ y) R! F$ M+ ^. O5 ?9 B
- else5 s/ h7 [# }$ A+ I8 N% |
- {/ X5 z7 o4 H+ Q
- READ_REG(UART2_Handler.Instance->RDR);
2 g! Y: C6 p7 n) j% W - __HAL_UART_CLEAR_OREFLAG(&UART2_Handler);% f& @' p: w7 \: k. Q; v& ^
- }! M5 U7 T5 w. n C( t; r& p
- " \8 s1 `% m! }$ \ I5 }
- }' k- _: H' }6 z) }$ _* d; m! F
- ; J9 a5 m8 o4 {
- }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 |- unsigned int KeyboardRs485TxFrame(uint8_t * buffer,uint32_t len)' L/ Y5 q1 x$ C J
- {( i* s0 C$ h( C6 g9 d {3 `
- UINT16 i;$ j' [& R4 b- \" ?4 `
. w1 t- w7 {) p0 @* p& o- //拷贝数据到DMA buffer
# J6 b7 Y! |" C - for(i = 0; i < len; i++)3 V; t6 }( Q. k) A' z6 C ?9 m& l
- {
% w4 e0 c4 s0 z; @: z% | - dma_tx_buf<i> =</i> buffer; ; A# v& r9 x% L+ K8 X. n, g
- }% b5 E7 m4 D, P
& l+ e9 ?# o% ]' ?0 |- M+ L1 b" `- //使发送RAM和cache一致4 i/ W' h8 s) c3 [* z( g
- SCB_InvalidateDCache_by_Addr((uint32_t *)dma_tx_buf, DMA_BUFFER_LENGTH);& S% K w9 X6 c- b3 A g
- HAL_UART_Transmit_DMA(&UART2_Handler, dma_tx_buf, len);
. u1 ?3 f- a% r; g1 v - 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
- ALIGN_32BYTES(attribute((section (".RAM_D2"))) uint8_t dma_rx_buf[DMA_BUFFER_LENGTH]) ;
9 |# m; W! Y4 a - 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
|