UART如何使用DMA接收不定长字符串。。
SWM341 等芯片中,DMA接收数据时,只有当接收到一个字(4个字节)的数据时,才会将接收到的数据写入 RAM。。因此如果将 DMA_initStruct.Unit 设定为 BYTE,,就会导致当接收到数据个数不是 4 的整数倍时,,最后几个字节被暂存在 DMA 内部,,无法取出。。
解决这个问题的方法是将 DMA_initStruct.Unit 设定为 WORD,UART 每接收到一个字节数据时,,DMA 从 UARTx->DATA 读取一个字写入 RAM,,这样每次 UART 接收到数据后都会立即被 DMA 搬运到 RAM 中,,不会产生接收数据被暂存在 DMA 内部的问题。。
具体使用代码见 gitee 上最新的例程代码: https://gitee.com/synwit-co-ltd/SWM341_Lib/tree/main/UART/SimplUART_DMA
:lol没有使用过DMA,用串口都是把数据收到队列,然后超时接收就处理数据。你的dma方式感觉不错,有空再玩玩。 我现在测试DMA也是遇到非4字节整数倍有数据被DMA内部FIFO缓存情况,楼主发的这个方法会导致接收缓冲区变4倍大小了,而且数据不是字节连续的,也不是很方便,我目前使用256000波特率接收数据,如果单纯中断接收,中断压力太大了,一直都是使用DMA,奈何这个芯片的DMA数量少,而且还这么不好用。重新设置DMA也无法生效。 给大家分享一下我的曲线救国方案,现在实测数据如果非4字节整数倍,会被缓存1-3个字节在DMA内部的FIFO,且用户不可见,确定原因后测试了很多办法都没法解决,那就将错就错,目前可以通过 SRCSR 计算出实际数量,哪怕非4自己的都可以,这个寄存器会实时更新;SRCSR是实际被传输到内存的数据剩余数量,通过总数减去这个寄存器就是已经传输的,永远是4的倍数,通过这2个寄存器做减法,就能知道FIFO中还有几个字节,假设还有n个字节没有取出,此时用4-n就是还要有几个字节收到了,后面数据就会一起发过来,那么将串口切换到环回模式,发送4-n个字节岂不就把剩余的n个字节逼出来了:lol,实测可行!
if (DMA->CH.DSTSR > DMA->CH.SRCSR) //有数据缓存在FIFO里面了,逼出来
{
cnt2 = DMA->CH.DSTSR - DMA->CH.SRCSR; //获取没有被传出来的数据数量
cnt2 = 4 - cnt2; //计算还差几个字节凑成4字节
UART0->CTRL |= BIT10; //进入环回模式
for (i = 0; i < cnt2; i++) //环回模式把剩余数据逼出来
{
UARTx_SendByte(UART_PRINTF_CH, 0);
}
//本来准备检查一下等待数据发送完成再退出换回模式,实测不需要等待
//UARTx_WaitSendComplete(UART_PRINTF_CH, 3); //等待数据发送完成,检查 UARTx->CTRL & BIT0
UART0->CTRL &=~BIT10; //退出环回模式
} 本帖最后由 cp1300 于 2024-8-25 17:48 编辑
cp1300 发表于 2024-8-25 17:09
给大家分享一下我的曲线救国方案,现在实测数据如果非4字节整数倍,会被缓存1-3个字节在DMA内部的FIFO,且 ...
补充一下,由于去掉了调试信息后出问题了,最终原因是环回模式,也必须等待数据发送完了,发送完了,才能接收完,接收完了才能将FIFO中的数据逼出来,判断串口的 UARTx->CTRL & BIT0,为1了就是发送完了
页:
[1]