完善资料让更多小伙伴认识你,还能领取20积分哦, 立即完善>
一直使用F4系列,没有出现此类现象,也可能出现了没有发现。最近在做和研华工控机通讯时出现串口接收问题。总结如下:
1. 使用DMA+空闲中断未出现串口同时收发死锁现象,但是由于研华某款工控机在与板子通信时,出现丢包现象
最终几天过后,另外的同事找到研华工控机技术,查阅工控机的串口芯片手册,发现了重大问题,是因为该芯片缓存的FIFO大小是16,而我们出现问题的帧长度是40,硬件将其分3次发送(16+16+8),但是板子的空闲中断又认为是3次空闲中断,所以包不完整导致校验不通过。但是项目已经临近,没有再做修改,只计划在新一版上修改。 2. 这里又到了新的一版,由于上面的串口缓存FIFO问题,这样我就考虑不能再使用高效方便的DMA+串口中断方式了。直接使用串口普通中断进行接收工控机数据。问题又来了,出现现象如下:
这下GG,尝试了多种方式依然还是无法解决此类现象(换中断与发送方式,重新制作新的测试工程,尝试了更换更新的库,参照网上使能串口错误回调函数在里面进行清除各种错误标志等等),只是有长有短,没办法根治。发现问题是在 HAL_UART_Receive_IT(&huart2, (uint8_t *)aRxBuffer, 1) 出现问题的时候,上面函数一致返回 HAL_BUSY,该函数如下: HAL_StatusTypeDef HAL_UART_Receive_IT(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size) { /* Check that a Rx process is not already ongoing */ if (huart->RxState == HAL_UART_STATE_READY) { if ((pData == NULL) || (Size == 0U)) { return HAL_ERROR; } /* Process Locked */ __HAL_LOCK(huart); huart->pRxBuffPtr = pData; huart->RxXferSize = Size; huart->RxXferCount = Size; huart->ErrorCode = HAL_UART_ERROR_NONE; huart->RxState = HAL_UART_STATE_BUSY_RX; /* Process Unlocked */ __HAL_UNLOCK(huart); /* Enable the UART Parity Error Interrupt */ __HAL_UART_ENABLE_IT(huart, UART_IT_PE); /* Enable the UART Error Interrupt: (Frame error, noise error, overrun error) */ __HAL_UART_ENABLE_IT(huart, UART_IT_ERR); /* Enable the UART Data Register not empty Interrupt */ __HAL_UART_ENABLE_IT(huart, UART_IT_RXNE); return HAL_OK; } else { return HAL_BUSY; } } 以为是 if (huart->RxState == HAL_UART_STATE_READY)此语句判断不过导致,在串口接收完成回调函数里增加强制改变该串口状态为HAL_UART_STATE_READY,依旧无法解决问题。然后看到网上有人在串口错误回调函数里进行清除错误操作,照例使用,该函数改为 void HAL_UART_ErrorCallback(UART_HandleTypeDef *huart) { /* Prevent unused argument(s) compilation warning */ UNUSED(huart); /* NOTE: This function Should not be modified, when the callback is needed, the HAL_UART_ErrorCallback could be implemented in the user file */ uint32_t isrflags = READ_REG(huart->Instance->SR);//手册上有讲,清错误都要先读SR if((__HAL_UART_GET_FLAG(huart, UART_FLAG_PE))!=RESET) { READ_REG(huart->Instance->DR);//PE清标志,第二步读DR __HAL_UART_CLEAR_FLAG(huart, UART_FLAG_PE);//清标志 } if((__HAL_UART_GET_FLAG(huart, UART_FLAG_FE))!=RESET) { READ_REG(huart->Instance->DR);//FE清标志,第二步读DR __HAL_UART_CLEAR_FLAG(huart, UART_FLAG_FE); } if((__HAL_UART_GET_FLAG(huart, UART_FLAG_NE))!=RESET) { READ_REG(huart->Instance->DR);//NE清标志,第二步读DR __HAL_UART_CLEAR_FLAG(huart, UART_FLAG_NE); } if((__HAL_UART_GET_FLAG(huart, UART_FLAG_ORE))!=RESET) { READ_REG(huart->Instance->CR1);//ORE清标志,第二步读CR __HAL_UART_CLEAR_FLAG(huart, UART_FLAG_ORE); } if (HAL_UART_GetError(huart) & HAL_UART_ERROR_ORE) __HAL_UART_FLUSH_DRREGISTER(huart); if(huart->ErrorCode&HAL_UART_ERROR_ORE) { __HAL_UART_CLEAR_OREFLAG(huart); } if(__HAL_UART_GET_FLAG(huart, UART_FLAG_ORE) != RESET) { __HAL_UART_CLEAR_FLAG(huart, UART_FLAG_ORE); //清除溢出中断 HAL_UART_Receive_IT(&huart2, (uint8_t *)aRxBuffer, 1); } if(__HAL_UART_GET_FLAG(huart, UART_FLAG_RXNE) != RESET) { __HAL_UART_CLEAR_FLAG(huart, UART_FLAG_RXNE); //rebuf[num++] = USART_ReceiveData(USART2); 读取串口数据 } } 看到这么多错误该清除的都清除了,心想应该没问题了,但是烧写后问题依旧存在。 最后的最后,有幸看到资料,解决此类问题。 main函数主要部分如下: /* USER CODE BEGIN PV */ extern uint32_t cnt; /* USER CODE END PV */ /* Private function prototypes -----------------------------------------------*/ void SystemClock_Config(void); /* USER CODE BEGIN PFP */ /* USER CODE END PFP */ /* Private user code ---------------------------------------------------------*/ /* USER CODE BEGIN 0 */ /* USER CODE END 0 */ /** * @brief The application entry point. * @retval int */ int main(void) { /* USER CODE BEGIN 1 */ /* USER CODE END 1 */ /* MCU Configuration--------------------------------------------------------*/ /* Reset of all peripherals, Initializes the Flash interface and the Systick. */ HAL_Init(); /* USER CODE BEGIN Init */ /* USER CODE END Init */ /* Configure the system clock */ SystemClock_Config(); /* USER CODE BEGIN SysInit */ /* USER CODE END SysInit */ /* Initialize all configured peripherals */ MX_GPIO_Init(); MX_USART2_UART_Init(); /* USER CODE BEGIN 2 */ HAL_UART_Receive_IT(&huart2, (uint8_t *)aRxBuffer, 1); /* USER CODE END 2 */ /* Infinite loop */ /* USER CODE BEGIN WHILE */ while (1) { /* USER CODE END WHILE */ /* USER CODE BEGIN 3 */ sprintf((char*)sendbuff,(const char*)"recv data cnt %drn",cnt); HAL_UART_Transmit(&huart2,sendbuff,strlen((char*)sendbuff),100); HAL_Delay(20); } /* USER CODE END 3 */ 在usart.c文件中,最重要的两部, 在usart.h文件中 原因分析:问题出现在串口接收中断函数中,锁住了串口,但是后面那句已经解锁了啊,但是为什么还是锁住了呢 按照上面进行解锁操作后,没有出现互锁现象了。 |
|
|
|
只有小组成员才能发言,加入小组>>
3278 浏览 9 评论
2955 浏览 16 评论
3455 浏览 1 评论
8987 浏览 16 评论
4050 浏览 18 评论
1102浏览 3评论
570浏览 2评论
const uint16_t Tab[10]={0}; const uint16_t *p; p = Tab;//报错是怎么回事?
568浏览 2评论
用NUC131单片机UART3作为打印口,但printf没有输出东西是什么原因?
2301浏览 2评论
NUC980DK61YC启动随机性出现Err-DDR是为什么?
1857浏览 2评论
小黑屋| 手机版| Archiver| 电子发烧友 ( 湘ICP备2023018690号 )
GMT+8, 2024-11-22 07:54 , Processed in 1.062480 second(s), Total 79, Slave 59 queries .
Powered by 电子发烧友网
© 2015 bbs.elecfans.com
关注我们的微信
下载发烧友APP
电子发烧友观察
版权所有 © 湖南华秋数字科技有限公司
电子发烧友 (电路图) 湘公网安备 43011202000918 号 电信与信息服务业务经营许可证:合字B2-20210191 工商网监 湘ICP备2023018690号