STM32
直播中

李浯

8年用户 1119经验值
私信 关注
[问答]

使用F334的USART+DMA进行发送数据遇到的疑问求解

最近在使用F334的USART+DMA进行发送数据的时候,遇到了一个很奇怪的问题。

在调用HAL_UART_Transmit_DMA(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size)发送数据时,实际发送的数据长度总比我设置的Size少两个。

比如配置成HAL_UART_Transmit_DMA( huart3, pucData, 19), 然后在DMA的发送完成中断里观察寄存器,发现串口的发送长度和发送计数器两个值,都是19,应该是对的。DMA配置的是normal模式,通讯的参数是9600bps, 8个数据位, 无校验位 , 1个停止位。

但是,从串口实际发送出来的数据,其实只有17个数。


如果我需要发送19个Byte,我在调用DMA发送的时候,需要将发送数据长度配置为21,即HAL_UART_Transmit_DMA( huart3, pucData, 21)
这个时候,串口发送出来的就是完整的19个Byte了。

我实际是用在485通讯上,所以有一个GPIO用于控制数据流。 这个GPIO,在DMA发送完成中断程序的最开始我打断点看过IO口的电平,依然是在发送状态,随后,我才将IO后电平反转至接收状态。

除此之外,发现DMA的中断函数里,normal模式下会使能串口的发送完成中断TCIE,我如果在串口的发送完成中断里反转485的流控制IO,就可以完整的发送我需要发送的数据长度,不用再加2个byte的长度。

感觉好奇怪啊,难道是DMA的传输完成中断时,数据只是从DMA移到了串口的发送的寄存器,但是实际还没发出去吗? 如果是这个逻辑,在DMA的传输完成中断里,将流控制的IO反转,确实会打断数据的发送。

各位兄弟姐妹,大佬大神,走过路过帮忙支支招,看大家有没有遇到类似的问题呢。

回帖(2)

吴萍

2024-4-10 10:06:22
应该在串口发送完成中断里再反转流控制的IO
DMA中断时,只表示需要传送的所有数据字节全部传送到串口的发送数据寄存器中了。
此时串口实际上还有2个字节并未发送完成,数据寄存器和移位寄存器中的2个字节还需要发送,并不能关闭串口发送。
同理,如果是485切换方向,必须要等到发送完成,也就是移位寄存器发送完成-TC标志置位。
举报

时见栖鸦

2024-4-10 10:49:09
有可能是由于USART发送数据时,发送完最后一个字节后,需要一定的时间才能将该字节完全发送出去,导致你观察到的实际发送的数据长度比设置的Size少两个字节。

解决这个问题的方法是,在调用HAL_UART_Transmit_DMA函数前,先等待一段时间,确保USART已经完全发送了所有数据,然后再执行其它操作。

具体的实现可以使用HAL_Delay函数来等待一段时间,例如可以延时10ms,确保USART发送完所有数据:

```cpp
HAL_UART_Transmit_DMA(&huart3, pucData, 19);
HAL_Delay(10);
```

或者可以使用HAL_UART_GetState函数来查询USART的状态,当USART处于空闲状态时,说明数据已经发送完毕,可以继续执行其它操作:

```cpp
HAL_UART_Transmit_DMA(&huart3, pucData, 19);
while(HAL_UART_GetState(&huart3) != HAL_UART_STATE_READY);
```

通过以上方法,可以确保USART已经完全发送了所有数据,避免了观察到的实际发送的数据长度比设置的Size少两个字节的问题。
举报

更多回帖

发帖
×
20
完善资料,
赚取积分