硬汉嵌入式论坛

 找回密码
 立即注册
查看: 3327|回复: 6
收起左侧

[UART] HAL_UARTEx_ReceiveToIdle_DMA 接收数据两次进入中断,一次接收到一半的问题

[复制链接]

10

主题

56

回帖

86

积分

初级会员

积分
86
发表于 2024-8-7 16:36:40 | 显示全部楼层 |阅读模式
芯片是STM32H750,一次接收1028个字节,
HAL_UARTEx_ReceiveToIdle_DMA 传入的数组长为1028,

这是代码:
[C] 纯文本查看 复制代码
RX_Data_num = 0;
RX_complete_flag = 0;
HAL_UARTEx_ReceiveToIdle_DMA(&huart2, RX_Data, 1028);


DMA中断优先级:0
使用usart2,中断优先级:2
现象是,第一次进回调函数接收到一半,第二次进回调函数全部接收完成。
这是回调函数:
[C] 纯文本查看 复制代码
void HAL_UARTEx_RxEventCallback(UART_HandleTypeDef *huart, uint16_t Size)
{
	if(huart == &huart2){
		RX_complete_flag = 1;
		RX_Data_num=Size;
		if(RX_Data_num < 64){
			RX_Data[RX_Data_num] = '\0';
		}
		U_OR_U = uart;
	}
}

如果RX_complete_flag==1之后,延时50ms,可以看到完整的数据。


有人知道怎么回事吗?
回复

使用道具 举报

0

主题

20

回帖

20

积分

新手上路

积分
20
发表于 2024-8-7 16:54:12 | 显示全部楼层
这个问题很简单,你分析一下HAL_UARTEx_ReceiveToIdle_DMA()这个函数功能就清洗了,HAL_UARTEx_ReceiveToIdle_DMA()函数功能大致如下:
    函数调用调用
        HAL_UARTEx_ReceiveToIdle_DMA() > UART_Start_Receive_DMA() > HAL_DMA_Start_IT()
    中断配置
        HAL_UARTEx_ReceiveToIdle_DMA()函数内开启了空闲中断
        UART_Start_Receive_DMA()函数内开启了错误中断
        HAL_DMA_Start_IT()内开启了DMA传输一半、传输完成中断

所以是因为HAL_UARTEx_ReceiveToIdle_DMA()这个函数最终配置了DMA传输一半、传输完成中断

回复

使用道具 举报

1万

主题

7万

回帖

11万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
117546
QQ
发表于 2024-8-7 16:56:33 | 显示全部楼层
使用函数HAL_UARTEx_ReceiveToIdle_DMA做超时接收整理:
1、半DMA传输完成中断UART_DMARxHalfCplt     调用  HAL_UARTEx_RxEventCallback,标识继续为HAL_UART_RECEPTION_TOIDLE
2、DMA传输完成中断UART_DMAReceiveCplt       调用   HAL_UARTEx_RxEventCallback,标识继续为HAL_UART_RECEPTION_TOIDLE
3、如果传输期间触发了空闲,DMA又没有传输完成,调用串口中断HAL_UART_IRQHandler,空闲标识处理的HAL_UARTEx_RxEventCallback,并设置HAL_UART_RECEPTION_STANDARD
回复

使用道具 举报

10

主题

56

回帖

86

积分

初级会员

积分
86
 楼主| 发表于 2024-8-8 09:30:48 | 显示全部楼层
serendipity 发表于 2024-8-7 16:54
这个问题很简单,你分析一下HAL_UARTEx_ReceiveToIdle_DMA()这个函数功能就清洗了,HAL_UARTEx_ReceiveToId ...

OK,明白了,在这里。
[C] 纯文本查看 复制代码
HAL_StatusTypeDef UART_Start_Receive_DMA(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size)
{
  huart->pRxBuffPtr = pData;
  huart->RxXferSize = Size;

  huart->ErrorCode = HAL_UART_ERROR_NONE;
  huart->RxState = HAL_UART_STATE_BUSY_RX;

  if (huart->hdmarx != NULL)
  {
    /* Set the UART DMA transfer complete callback */
    huart->hdmarx->XferCpltCallback = UART_DMAReceiveCplt;

    /* Set the UART DMA Half transfer complete callback */
    huart->hdmarx->XferHalfCpltCallback = UART_DMARxHalfCplt;
回复

使用道具 举报

10

主题

56

回帖

86

积分

初级会员

积分
86
 楼主| 发表于 2024-8-8 09:33:17 | 显示全部楼层
eric2013 发表于 2024-8-7 16:56
使用函数HAL_UARTEx_ReceiveToIdle_DMA做超时接收整理:
1、半DMA传输完成中断UART_DMARxHalfCplt     调 ...

第3条没看懂,另外问一下,以前接收十几个字节的时候,并没有这种情况,只进一次中断,这是为啥
回复

使用道具 举报

1万

主题

7万

回帖

11万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
117546
QQ
发表于 2024-8-9 09:58:44 | 显示全部楼层
quanshimutou 发表于 2024-8-8 09:33
第3条没看懂,另外问一下,以前接收十几个字节的时候,并没有这种情况,只进一次中断,这是为啥

现在带DMA都是开了半传输完成和传输完成中断。

第3条需要你看下源码来理解。这个空闲DMA函数必须要看下源码来理解。
回复

使用道具 举报

0

主题

1

回帖

1

积分

新手上路

积分
1
发表于 2024-11-28 16:17:56 | 显示全部楼层
void HAL_UARTEx_RxEventCallback(UART_HandleTypeDef *huart, uint16_t Size) {
        if (huart->Instance == USART3) {
                if (huart->RxEventType == HAL_UART_RXEVENT_TC) {

                }
                else if (huart->RxEventType == HAL_UART_RXEVENT_HT) {

                }
                else if (huart->RxEventType == HAL_UART_RXEVENT_IDLE) {

                }
        }
}
huart->RxEventType有这个字段可以判断
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|小黑屋|Archiver|手机版|硬汉嵌入式论坛

GMT+8, 2025-8-14 03:04 , Processed in 0.060447 second(s), 24 queries .

Powered by Discuz! X3.4 Licensed

Copyright © 2001-2023, Tencent Cloud.

快速回复 返回顶部 返回列表