华芯微特开发论坛

 找回密码
 立即注册
搜索
热搜: SWM341 资料
查看: 79|回复: 1

UART DMA通讯问题

[复制链接]

2

主题

5

帖子

30

积分

新手上路

Rank: 1

积分
30
发表于 2026-3-17 13:19:18 | 显示全部楼层 |阅读模式
使用SWM34S串口DMA通讯时遇到一个奇怪问题,SWM34S循环发送modbus命令向从机获取数据,正常情况下一切正常,不正常的情况就在于如果在通讯过程中突然拔掉串口数据线,然后再插上就会导致通讯失败(SWM34S端串口无法再获取到从机数据),通过逻辑分析仪捕捉数据发现SWM34S还在正常发送数据,并且从机也正常回应数据,但通过仿真调试发现SWM34S在数据线拔掉再接上之后,DMA接收数据存入的数据缓冲区数据错乱,我的DMA每次发送数据前都是会重新配置的,代码如下
#include "sys.h"
u8 rx_buff[33];
u8 tx_buff[13];
/*---------------------------------------------------
配置uart_rx_dma
des_addr 内存地址
bcnt 数据传输长度
----------------------------------------------------*/
void uart_rx_dma_config(u32 rx_addr, u16 bcnt)
{
  DMA_InitStructure DMA_initStruct;
        DMA_initStruct.Mode = DMA_MODE_SINGLE;
        DMA_initStruct.Unit = DMA_UNIT_BYTE;
        DMA_initStruct.Count = bcnt;
        DMA_initStruct.SrcAddr = (uint32_t)&UART3->DATA;
        DMA_initStruct.SrcAddrInc = 0;
        DMA_initStruct.DstAddr = (uint32_t)rx_addr;
        DMA_initStruct.DstAddrInc = 1;
        DMA_initStruct.Handshake = DMA_CH1_UART3RX;
        DMA_initStruct.Priority = DMA_PRI_LOW;
        DMA_initStruct.INTEn = 0;
        DMA_CH_Init(DMA_CH1, &DMA_initStruct);
        DMA_CH_Open(DMA_CH1);
}
/*---------------------------------------------------
配置uart_rx_dma
des_addr 内存地址
bcnt 数据传输长度
----------------------------------------------------*/
void uart_tx_dma_config(u32 tx_addr, u16 bcnt)
{
        DMA_InitStructure DMA_initStruct;
  DMA_initStruct.Mode = DMA_MODE_SINGLE;
        DMA_initStruct.Unit = DMA_UNIT_BYTE;
        DMA_initStruct.Count = bcnt;
        DMA_initStruct.SrcAddr = (uint32_t)tx_addr;
        DMA_initStruct.SrcAddrInc = 1;
        DMA_initStruct.DstAddr = (uint32_t)&UART3->DATA;
        DMA_initStruct.DstAddrInc = 0;
        DMA_initStruct.Handshake = DMA_CH0_UART3TX;
        DMA_initStruct.Priority = DMA_PRI_LOW;
        DMA_initStruct.INTEn = 0;
        DMA_CH_Init(DMA_CH0, &DMA_initStruct);
        DMA_CH_Open(DMA_CH0);
}

void uart_process()
{
        volatile static u16 tx_len, rx_len;
        volatile u32 crc, dat, adr=1318;
       
        /*- 发命令 -*/
        tx_buff[0] = 1;                  //站号
        tx_buff[1] = 0x03;               //功能码
        tx_buff[2] = adr >> 8;           //地址
        tx_buff[3] = adr;
       
        tx_buff[4] = 0;                  //寄存器数量
        tx_buff[5] = 2;

        crc=GetCRC16(tx_buff,6);         //CRC16
        tx_buff[7] = crc >> 8;
        tx_buff[6] = crc;
        tx_len = 8;  //发送长度
        rx_len = 9;  //接收长度       
        uart_rx_dma_config((u32)rx_buff, rx_len);
        uart_tx_dma_config((u32)tx_buff, tx_len);                                       
       
       
        /*- 接收数据 -*/
        volatile u32 timeout=10000000;
        while((DMA_CH_INTStat(DMA_CH1, DMA_IT_DONE)==0) && (timeout--));
        DMA_CH_INTClr(DMA_CH1, DMA_IT_DONE);
       
        if(timeout > 0)
        {
                crc =GetCRC16(rx_buff, rx_len-2);
                u16 ret =rx_buff[rx_len-2];
                ret|=rx_buff[rx_len-1]<<8;
                if(crc==ret) //CRC16
                {
                        dat =rx_buff[3]<<24;
                        dat|=rx_buff[4]<<16;
                        dat|=rx_buff[5]<<8;
                        dat|=rx_buff[6]<<0;
                        reg[0].dat =dat;  //实际数据
                }
        }
}



这个程序已经是简化过的,为了方便排查问题,在主线程循环调用uart_process()函数,只要在上电通讯前数据线是插着的那么就一切正常,一旦中途拔掉通讯线就会出现DMA接收数据错乱,我猜测是uart_rx_dma_config((u32)rx_buff, rx_len) 这个设置函数没能完全清除上一切DMA接收的数据计数导致的,也就是拔掉数据线时可能DMA已经接收了一定长度的数据,再次插上数据线后DMA接收到的数据还是从上一次位置存入数据
回复

使用道具 举报

2

主题

5

帖子

30

积分

新手上路

Rank: 1

积分
30
 楼主| 发表于 2026-3-17 15:21:07 | 显示全部楼层
我在重新配置DMA前关闭UART,DMA配置好后再次开启UART,问题在一定程度上得到了解决,比如这样设置后手动插拔数据线几十次,偶尔才会出现一次通讯错误,一旦出现通讯错误后再怎么插拔数据线都无法在恢复
回复

使用道具 举报

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

本版积分规则

Archiver|手机版|小黑屋|华芯微特开发论坛

GMT+8, 2026-9-17 19:24 , Processed in 0.030661 second(s), 19 queries .

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

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