完善资料让更多小伙伴认识你,还能领取20积分哦, 立即完善>
最近用HAL库做个单工的无线串口,因为无线通信是阻塞的,就用串口的DMA接收函数HAL_UART_Receive_DMA。
实际用的时候发现很多问题: 1.串口接收一旦溢出就会丢数据。 例如串口接收满了,稍等几秒再启动新的DMA接收函数HAL_UART_Receive_DMA时,就丢失数据了,而且是再也收不到串口数据。如果接满后马上启动就没这个问题。 看官方示例代码,停止DMA接收后似乎要DeInit后重新初始化Init和启动DMA接收 2.串口DMA接收不能单独停止。 例如串口同时在DMA发送和DMA接收,DMA接收到一半我要终止DMA的话,只能调用HAL_UART_DMAStop把接收DMA和串口DMA都停止。 换言之,不能单独停止DMA接收。 我理解的接收DMA和发送DMA是两个独立的操作,为什么不能单独停止? 大家有没有类似的经验,应当怎样规避这些坑? 还是说我的做法和理解其实是有问题的?有错误的请大家批评指正,一起学习提高 |
|
相关推荐
20个回答
|
|
本帖最后由 龙吟风独恋云 于 2018-5-11 17:05 编辑
针对第2点,串口DMA接收不能单独停止。 HAL_UART_DMAStop()函数的确是uart接收和发送同时关闭,找了好久终于找到只关闭接收的函数了。 只关闭接收的函数。HAL_UART_AbortReceive() 下面看一下函数具体实现: HAL_StatusTypeDef HAL_UART_DMAStop(UART_HandleTypeDef *huart) { uint32_t dmarequest = 0x00U; /* The Lock is not implemented on this API to allow the user application to call the HAL UART API under callbacks HAL_UART_TxCpltCallback() / HAL_UART_RxCpltCallback(): when calling HAL_DMA_Abort() API the DMA TX/RX Transfer complete interrupt is generated and the correspond call back is executed HAL_UART_TxCpltCallback() / HAL_UART_RxCpltCallback() */ /* Stop UART DMA Tx request if ongoing */ dmarequest = HAL_IS_BIT_SET(huart->Instance->CR3, USART_CR3_DMAT); if((huart->gState == HAL_UART_STATE_BUSY_TX) && dmarequest) { CLEAR_BIT(huart->Instance->CR3, USART_CR3_DMAT); /* Abort the UART DMA Tx channel */ if(huart->hdmatx != NULL) { HAL_DMA_Abort(huart->hdmatx); } UART_EndTxTransfer(huart); } /* Stop UART DMA Rx request if ongoing */ dmarequest = HAL_IS_BIT_SET(huart->Instance->CR3, USART_CR3_DMAR); if((huart->RxState == HAL_UART_STATE_BUSY_RX) && dmarequest) { CLEAR_BIT(huart->Instance->CR3, USART_CR3_DMAR); /* Abort the UART DMA Rx channel */ if(huart->hdmarx != NULL) { HAL_DMA_Abort(huart->hdmarx); } UART_EndRxTransfer(huart); } return HAL_OK; } 主要分为2大部分,处理标志,关闭发送和接收DMA。 HAL_StatusTypeDef HAL_UART_AbortReceive(UART_HandleTypeDef *huart) { /* Disable RXNE, PE and ERR (Frame error, noise error, overrun error) interrupts */ CLEAR_BIT(huart->Instance->CR1, (USART_CR1_RXNEIE | USART_CR1_PEIE)); CLEAR_BIT(huart->Instance->CR3, USART_CR3_EIE); /* Disable the UART DMA Rx request if enabled */ if(HAL_IS_BIT_SET(huart->Instance->CR3, USART_CR3_DMAR)) { CLEAR_BIT(huart->Instance->CR3, USART_CR3_DMAR); /* Abort the UART DMA Rx channel : use blocking DMA Abort API (no callback) */ if(huart->hdmarx != NULL) { /* Set the UART DMA Abort callback to Null. No call back execution at end of DMA abort procedure */ huart->hdmarx->XferAbortCallback = NULL; HAL_DMA_Abort(huart->hdmarx); } } /* Reset Rx transfer counter */ huart->RxXferCount = 0x00U; /* Restore huart->RxState to Ready */ huart->RxState = HAL_UART_STATE_READY; return HAL_OK; } 也是分为2部分,处理标志和关闭接收DMA。 最简单的实现: 1. 先关闭接收DMA,HAL_DMA_Abort(huart->hdmarx); 2. 置位RX ready状态,huart->RxState = HAL_UART_STATE_READY; 忽略了错误标志和IT标志处理,最保险的方式还是使用HAL_UART_AbortReceive()函数。 |
|
|
|
你正在撰写答案
如果你是对答案或其他答案精选点评或询问,请使用“评论”功能。
1129 浏览 0 评论
AD7686芯片不传输数据给STM32,但是手按住就会有数据。
1075 浏览 2 评论
2175 浏览 0 评论
如何解决MPU-9250与STM32通讯时,出现HAL_ERROR = 0x01U
1269 浏览 1 评论
hal库中i2c卡死在HAL_I2C_Master_Transmit
1693 浏览 1 评论
小黑屋| 手机版| Archiver| 电子发烧友 ( 湘ICP备2023018690号 )
GMT+8, 2024-11-25 22:09 , Processed in 0.504022 second(s), Total 43, Slave 36 queries .
Powered by 电子发烧友网
© 2015 bbs.elecfans.com
关注我们的微信
下载发烧友APP
电子发烧友观察
版权所有 © 湖南华秋数字科技有限公司
电子发烧友 (电路图) 湘公网安备 43011202000918 号 电信与信息服务业务经营许可证:合字B2-20210191 工商网监 湘ICP备2023018690号