|
个人感觉,做嵌入式,底层就是datasheet,顶层就是数理逻辑。7 F4 r2 o( T G, \! i 不管什么芯片,当我们遇到问题时,通过查阅datasheet或上官网基本上都能找到解决方法。然而,这些基本都是英文。所以,英文好对做研发是有很大益处的。不过好在有翻译工具,如:有道( 我就是用有道划的)# E( T! K: d; o) R3 lC语言虽然没有class,但有struct。我们可以多用struct。ST库和ucos中就包含许多struct。 程序结构多用状态机或switch。个人感觉,状态机看起来很有条理,很清晰,后期修改维护也方便。% b8 G4 n) G- P* E; J 鄙人浅见,请大家不吝赐教。 进入正题:UART以DMA方式接收和发送的函数调用顺序:, U: U* a }5 Q- H- } 循环模式接收:HAL_UART_Receive_DMA(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size)==》DMA1_Channelx_IRQHandler(void)==》HAL_DMA_IRQHandler(&hdma_usartx_rx)==》UART_DMAReceiveCplt(DMA_HandleTypeDef *hdma)==》HAL_UART_RxCpltCallback(huart)/ K0 \+ U( b* H' ~$ L! c 当然这当中还会调用传输 Half 中断,这里就不讨论了。 0 Z" o- ?2 w, H Z9 ?5 k 正常模式发送:HAL_UART_Transmit_DMA(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size)==》DMA1_Channelx_IRQHandler(void)==》HAL_DMA_IRQHandler(&hdma_usartx_tx)==》UART_DMATransmitCplt(DMA_HandleTypeDef *hdma)==》USART3_IRQHandler(void)==》HAL_UART_IRQHandler(&huart3)==》UART_EndTransmit_IT(huart)==》HAL_UART_RxCpltCallback(huart). X! h6 D. h" }8 ? d% ] 这里只分析 HAL_UART_Receive_DMA 的源码,其它的大家自己分析: HAL_StatusTypeDef HAL_UART_Receive_DMA(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size) UART以DMA方式接收指定长度数据到指定缓冲区4 N: p* y& z8 Z* D* b* U1 n9 Z3 q { uint32_t *tmp; /* Check that a Rx process is not already ongoing */ if(huart->RxState == HAL_UART_STATE_READY) 检查huart->RxState是否处于 接收空闲 状态。当这一状态标志非READY时,会跳过DMA接收参数设置,直接返回HAL_BUSY。其它的UART接收函数也会检查这个状态,所以,哪个先调用就执行哪个。 { if((pData == NULL) || (Size == 0U)) {' p3 B3 t1 C8 o! @ return HAL_ERROR; }" F0 d( [- D4 Q% n Z+ l2 @( X, d; V8 o7 h /* Process Locked */- C3 G# w( l/ x; f% E) T __HAL_LOCK(huart);0 G- V5 Y" I& J7 u# m! C& p$ t: y- E 8 ?' K+ L ]2 Z+ \ huart->pRxBuffPtr = pData;; r9 ^/ W7 c/ p0 y3 p huart->RxXferSize = Size; huart->ErrorCode = HAL_UART_ERROR_NONE; huart->RxState = HAL_UART_STATE_BUSY_RX;" K5 V9 E! z* W' D4 I( U * }3 U- x- L$ R1 y1 Q$ S /* Set the UART DMA transfer complete callback */ huart->hdmarx->XferCpltCallback = UART_DMAReceiveCplt; 设置DMA传输完成的回调函数。当DMA以循环方式传输时会调用UART接收完成中断的回调函数;以Normal方式传输时会关闭UART的DMA通道,并使能UART传输完成中断,触发UART传输完成中断,设置huart->RxState为READY,并调用( L! p# ?2 O' T# ~9 f2 }5 f/ q4 ` UART接收完成中断的回调函数。所以,不管DMA按循环或正常模式传输,到最后都会调用UART接收完成中断的回调函数 /* Set the UART DMA Half transfer complete callback */3 y" I% `! [ y) T huart->hdmarx->XferHalfCpltCallback = UART_DMARxHalfCplt;+ S9 M8 y. [9 ~( P /* Set the DMA error callback */2 H$ R9 g7 Q, y huart->hdmarx->XferErrorCallback = UART_DMAError;2 Z9 a1 \; i7 V; s% t' p* i ! n+ Y# e7 C7 h4 Y {4 f. ? /* Set the DMA abort callback */ huart->hdmarx->XferAbortCallback = NULL;5 Q2 I/ d& ]2 ^) S/ @2 \. r4 U' V /* Enable the DMA channel */" T9 i) z0 e/ `7 \ tmp = (uint32_t*)&pData; HAL_DMA_Start_IT(huart->hdmarx, (uint32_t)&huart->Instance->DR, *(uint32_t*)tmp, Size);以中断方式打开DMA传输。所以CubeMx中DMA中断默认是打开的切不可更改 o- H8 y( m( a8 r: s /* Clear the Overrun flag just before enabling the DMA Rx request: can be mandatory for the second transfer */6 F* V- A7 k1 j# Z$ Y __HAL_UART_CLEAR_OREFLAG(huart);" d# a' \! T& [1 K; m1 [0 d9 a" d3 F( ? $ o2 ^1 f: x! s6 e /* Process Unlocked */$ W5 {0 X3 V8 Y* l6 h __HAL_UNLOCK(huart); /* Enable the UART Parity Error Interrupt */ SET_BIT(huart->Instance->CR1, USART_CR1_PEIE);8 Q2 z9 O h0 ~% K 6 a3 H5 m; }- ] /* Enable the UART Error Interrupt: (Frame error, noise error, overrun error) */ SET_BIT(huart->Instance->CR3, USART_CR3_EIE); /* Enable the DMA transfer for the receiver request by setting the DMAR bit in the UART CR3 register */ SET_BIT(huart->Instance->CR3, USART_CR3_DMAR);2 w; u: |' a' z7 o0 z2 I3 {7 t return HAL_OK;$ w' c4 `9 W2 |. i; d) _; \ }, m: q h% g7 x( \) | else$ } v4 |! ^. G! O {' b6 Q9 U, v$ M' E0 f- C return HAL_BUSY;. Y' `4 [6 n. E% [. T7 Z } }, }) A `+ J" S6 t 下面上我做的测试:一、Cube配置 1、DMA接收要用 循环模式,只需调用一次接收函数即可,重复调用也只有第一次调用有效。若是 正常模式,需要在每次接收完成后重复调用。 2、DMA发送要用 正常模式,需在每次发送时重复调用。还要打开UART中断,否则即使重复调用DMA发送函数也只有第一次发送有效,其余不会执行(UART发送状态一直处于 BUSY)。若是 循环模式,则会连续不断地发送,不会停止。 以上两点大家可以自己改改测试。/ \- y4 D4 w, a
二、Keil例程编写* v) h' D8 y( i1 v5 e* Q* g
三、测试4 B. \5 t9 x) G5 J7 R6 X+ a9 j0 L 可以看到,发送数 = 接收数。大家可以做更大数据的短间隔长时间测试,看看会不会出错。5 ~9 Y. t+ G! Z/ X1 [/ o
最后,奉上测试工程:
uart_dma_test.rar
(3.7 MB, 下载次数: 2111)
|
微信公众号
手机版
"no source": Error: #5: cannot open source input file "C:/Users/Administrator/STM32Cube/Repository/STM32Cube_FW_F1_V1.6.0/Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_rcc.c": No such file or directory
https://www.stmcu.org.cn/module/forum/thread-614550-1-1.html