我一定是因为一些愚蠢的错误而失明了。我没有保留该代码,所以我不得不重做它,然后似乎没有遇到任何问题。我一定有点老了。
尽管如此,无论如何,启用 uart 中断似乎是最佳实践,如果它只是清除错误标志,例如在连接和断开线路时很容易发生的帧错误。
我想我会分享一些直接的示例供其他(合作)开发人员使用。
在阻塞 HAL_Delay 期间,使用 UART RX 上的 DMA 获取字符。
我们可以使用 UART RTO 中断(以位数表示的接收超时)来检测数据接收的结束(可能在接收 Modbus 时,35 位是 3.5 个字符的超时),或者对接收到的数据进行 pol,或者识别一些特定的接收数据。
请注意,我认为应始终避免阻止呼叫。这只是一个简单的演示示例。
还应该尽可能多地使用硬件来完成,因此尽可能多地使用 DMA 通常是一件好事。MCU 然后可以同时执行其他任务。
第一:Mode = DMA_CIRCULAR,启动一次(我认为最好的解决方案,因为不会遗漏任何字符)
第二:DMA_NORMAL 或 DMA_CIRCULAR,启动/停止
- /* Mode = DMA_CIRCULAR, start once */
-
- /* Interrupt Enable */
- HAL_NVIC_EnableIRQ(USART1_IRQn);
-
- uint8_t DataRX[256];
- if (HAL_UART_Receive_DMA(&huart1, DataRX, sizeof(DataRX)) != HAL_OK)
- {
- /* Error */
- char Error[] = "Error HAL_UART_Receive_DMAn";
- HAL_UART_Transmit(&huart2, (uint8_t*)Error, strlen(Error), 100); /* To USB serial port */
- }
-
- uint16_t First_Byte_Index = 0;
- uint16_t Last_Byte_Index_Previous = 0;
- while (1)
- {
- /* Show what's in the DataRX */
- uint16_t Last_Byte_Index = (uint16_t)(sizeof(DataRX) - __HAL_DMA_GET_COUNTER(huart1.hdmarx));
- uint16_t DataRX_Length = Last_Byte_Index - Last_Byte_Index_Previous;
- First_Byte_Index = Last_Byte_Index - DataRX_Length;
- /* If the new Index is greater than Index_old, we received something */
- if (DataRX_Length)
- {
- char Received[] = "Received: ";
- HAL_UART_Transmit(&huart2, (uint8_t*)Received, strlen(Received), 100); /* To USB serial port */
- for (uint16_t i = 0; i < DataRX_Length; i++)
- {
- uint16_t DataRX_Index = i + First_Byte_Index;
- /* Roll over DataRX_index if necessary */
- if (DataRX_Index > sizeof(DataRX))
- {
- DataRX_Index -= sizeof(DataRX);
- }
- HAL_UART_Transmit(&huart2, &DataRX[DataRX_Index], 1, 100); /* To USB serial port */
- }
- char CR[] = "n";
- HAL_UART_Transmit(&huart2, (uint8_t*)CR, strlen(CR), 100); /* To USB serial port */
-
- /* Reset Index_old to latest Index */
- Last_Byte_Index_Previous = Last_Byte_Index;
- }
-
- HAL_UART_Transmit(&huart2, (uint8_t*)Test, strlen(Test), 100); /* To USB serial port */
-
- HAL_Delay(1000);
- HAL_IWDG_Refresh(&hiwdg); /* Don't forget to take good care of your watch-dog, feed it! */
- }
- /* Mode = DMA_NORMAL or DMA_CIRCULAR, start/stop */
-
- /* Interrupt Enable */
- HAL_NVIC_EnableIRQ(USART1_IRQn);
-
- uint8_t DataRX[256];
- while (1)
- {
- if (HAL_UART_Receive_DMA(&huart1, DataRX, sizeof(DataRX)) != HAL_OK)
- {
- /* Error */
- char Error[] = "Error HAL_UART_Receive_DMAn";
- HAL_UART_Transmit(&huart2, (uint8_t*)Error, strlen(Error), 100); /* To USB serial port */
- }
-
- HAL_Delay(1000);
-
- /*Checking length and print buffer (on a different UART) */
- uint16_t Last_Byte_Index = (uint16_t)(sizeof(DataRX) - __HAL_DMA_GET_COUNTER(huart1.hdmarx));
-
- /* printing the buffer on another UART */
- if (Last_Byte_Index)
- {
- char Received[] = "Received: ";
- HAL_UART_Transmit(&huart2, (uint8_t*)Received, strlen(Received), 100); /* To USB serial port */
- for (uint16_t i = 0; i < Last_Byte_Index; i++)
- {
- HAL_UART_Transmit(&huart2, &DataRX, 1, 100); /* To USB serial port */
- }
- char CR[] = "n";
- HAL_UART_Transmit(&huart2, (uint8_t*)CR, strlen(CR), 100); /* To USB serial port */
- }
-
- if (HAL_UART_DMAStop(&huart1) != HAL_OK)
- {
- /* Error */
- char Error[] = "Error HAL_UART_DMAStopn";
- HAL_UART_Transmit(&huart2, (uint8_t*)Error, strlen(Error), 100); /* To USB serial port */
- }
-
- HAL_IWDG_Refresh(&hiwdg); /* Don't forget to take good care of your watch-dog, feed it! */
- }
在 stm32g4xx_it.c 中我们清除了一些错误标志,它们会不会发生。我们可以不检查就清除它们,但也许有人会维护帧和奇偶校验错误计数器。
- /**
- * @brief This function handles USART1 global interrupt / USART1 wake-up interrupt through EXTI line 25.
- */
- void USART1_IRQHandler(void)
- {
- /* USER CODE BEGIN USART1_IRQn 0 */
-
- /* Noise immunity feature enabled for RS (Modbus-RTU) interfaces */
- /* Clear the errors if they occurred */
-
- /* UART parity error detected */
- if (__HAL_UART_GET_FLAG(&huart1, UART_FLAG_PE) == SET)
- {
- __HAL_UART_CLEAR_PEFLAG(&huart1);
- }
- /* UART frame error detected or break character is detected */
- if (__HAL_UART_GET_FLAG(&huart1, UART_FLAG_FE) == SET)
- {
- __HAL_UART_CLEAR_FEFLAG(&huart1);
- }
- /* UART noise error detected */
- if (__HAL_UART_GET_FLAG(&huart1, UART_FLAG_NE) == SET)
- {
- __HAL_UART_CLEAR_NEFLAG(&huart1);
- }
- /* UART overrun error detected */
- if (__HAL_UART_GET_FLAG(&huart1, UART_FLAG_ORE) == SET)
- {
- __HAL_UART_CLEAR_OREFLAG(&huart1);
- }
- /* UART idle flag */
- if((__HAL_UART_GET_FLAG(&huart1, UART_FLAG_IDLE) != RESET))
- {
- __HAL_UART_CLEAR_IDLEFLAG(&huart1);
- }
-
- /* USER CODE END USART1_IRQn 0 */
- HAL_UART_IRQHandler(&huart1);
- /* USER CODE BEGIN USART1_IRQn 1 */
-
- /* USER CODE END USART1_IRQn 1 */
- }
|
|
2023-2-1 14:27:20
评论
举报
|
|
|