[英]HAL_UART_Receive_DMA works only once. How can I fix it?
I am working with STM32F103RB board and I want to simply echo everything I receive from my computer via serial port back to that port.我正在使用 STM32F103RB 板,我想简单地将我通过串行端口从计算机收到的所有内容回显到该端口。 I must do it using UART and DMA.我必须使用 UART 和 DMA 来完成。 I've set up DMA on USART2_RX with CubeMX in normal mode.我已经在正常模式下使用 CubeMX 在 USART2_RX 上设置了 DMA。 My problem is that HAL_UART_RxCpltCallback
gets called only once.我的问题是HAL_UART_RxCpltCallback
只被调用一次。 Interestingly I get the response on PC end but with additional 0xFC
byte.有趣的是,我在 PC 端得到了响应,但有额外0xFC
字节。 After that the controller stops reacting to new data sent through the serial port and won't do so until I unplug and plug controller back in with usb. Here is the code for call back and main function:之后 controller 停止对通过串行端口发送的新数据做出反应,直到我将 controller 拔出并重新插入 usb 时才会这样做。这是回调和主要 function 的代码:
#define BUF_SIZE 16
uint8_t RX_BUF[BUF_SIZE] = {0};
uint8_t TX_BUF[BUF_SIZE] = {0};
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
HAL_UART_Transmit(&huart2, RX_BUF, BUF_SIZE, 1000);
HAL_UART_Receive_DMA(&huart2, RX_BUF, BUF_SIZE);
}
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_DMA_Init();
MX_USART2_UART_Init();
/* USER CODE BEGIN 2 */
HAL_UART_Receive_DMA(&huart2, RX_BUF, sizeof (RX_BUF));
/* USER CODE END 2 */
/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1)
{
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
}
/* USER CODE END 3 */
}
Edit: I am trying to do this on a Mac through USB-C dongle.编辑:我正在尝试通过 USB-C 加密狗在 Mac 上执行此操作。 Can this be the problem?这可能是问题所在吗?
Calling complex functions in an ISR is a bad idea.在 ISR 中调用复杂函数不是一个好主意。 Many of the HAL functions use the system tick to measure timeouts, and depending on your interrupt priorities, the tick may be blocked while your ISR runs.许多 HAL 函数使用系统节拍来测量超时,并且根据您的中断优先级,节拍可能会在您的 ISR 运行时被阻止。
It would be better to move any complex processing out of your ISR, into the main function. Just set a flag in the ISR to indicate when reception is complete.最好将任何复杂的处理从您的 ISR 移到主 function 中。只需在 ISR 中设置一个标志以指示接收何时完成。 Something like:就像是:
static volatile bool uart_rx_done = false;
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
uart_rx_done = true;
}
int main()
{
// Initialisation stuff
for (;;)
{
uart_rx_done = false;
HAL_UART_Receive_DMA(&huart2, RX_BUF, BUF_SIZE);
while (!uart_rx_done)
;
HAL_UART_Transmit(&huart2, RX_BUF, BUF_SIZE, 1000);
}
}
First of all, check if you configured uart
and dma
interrupts correctly.首先,检查您是否正确配置了uart
和dma
中断。 in the stm21f1xx_it.c
file you should see these functions在stm21f1xx_it.c
文件中,您应该会看到这些函数
void DMA1_Channel6_IRQHandler(void)
{
/* USER CODE BEGIN DMA1_Channel6_IRQn 0 */
/* USER CODE END DMA1_Channel6_IRQn 0 */
HAL_DMA_IRQHandler(&hdma_usart2_rx);
/* USER CODE BEGIN DMA1_Channel6_IRQn 1 */
/* USER CODE END DMA1_Channel6_IRQn 1 */
}
void USART2_IRQHandler(void)
{
/* USER CODE BEGIN USART2_IRQn 0 */
/* USER CODE END USART2_IRQn 0 */
HAL_UART_IRQHandler(&huart2);
/* USER CODE BEGIN USART2_IRQn 1 */
/* USER CODE END USART2_IRQn 1 */
}
and also a uart2
configuration in the MX_NVIC_Init()
function in your main.c
file.以及main.c
文件中的MX_NVIC_Init()
function 中的uart2
配置。
But your main mistake is that you're not activating uart
receive interrupt at all.但是你的主要错误是你根本没有激活uart
接收中断。 I suggest not using dma
for now, and try this to see if the uart
interrupt gets activated:我建议暂时不要使用dma
,试试这个看看uart
中断是否被激活:
#define BUF_SIZE 16
bool uart_received = false;
uint8_t RX_BUF[BUF_SIZE] = {0};
uint8_t TX_BUF[BUF_SIZE] = {0};
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
// HAL_UART_Transmit(&huart2, RX_BUF, BUF_SIZE, 1000);
uart_received = true;
HAL_UART_Receive_IT(&huart2, RX_BUF, BUF_SIZE);
}
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_DMA_Init();
MX_USART2_UART_Init();
/* USER CODE BEGIN 2 */
//HAL_UART_Receive_DMA(&huart2, RX_BUF, sizeof (RX_BUF));
HAL_UART_Receive_IT(&huart2, RX_BUF, BUF_SIZE);
/* USER CODE END 2 */
/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1)
{
if (uart_received) {
HAL_UART_Transmit(&huart2, RX_BUF, BUF_SIZE, 1000);
uart_received = false;
}
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
}
/* USER CODE END 3 */
}
If this works, then you can use HAL_UARTEx_ReceiveToIdle_DMA
for activating uart-dma
interrupt and HAL_UARTEx_RxEventCallback
for callback function (assuming the dam
interrupt is configured).如果这可行,那么您可以使用HAL_UARTEx_ReceiveToIdle_DMA
激活uart-dma
中断,并使用HAL_UARTEx_RxEventCallback
回调 function(假设已配置dam
中断)。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.