单片机/MCU论坛
直播中

没人知道我是谁

3年用户 26经验值
擅长:MEMS/传感技术 测量仪表 处理器/DSP 接口/总线/驱动 控制/MCU RF/无线
私信 关注
[问答]

dsPIC33CK,DMA向UART发送数据出现间断性的有字节提前覆盖前面的字节

用DMA0向UART1-TX发数据,出现奇怪现象,要发送的字节提前了,而且总数还是对的?
要发送的数据为
chr(04) & 197331" & chr(0x1B) & "2021Echo00202111
接收到的是:
chr(04) & 197332"& chr(0x1B) & "202EEch2**202**


经过试验发现197332最后一个2,是2021第一个2多发一遍,并且覆盖了前面的1


DMA设置:
static void SendCC(uint8_t ComName)
{
    uint8_t i ;

        //- ********本段为DMA为初始化部分***********/

    DMACONbits.DMAEN = 0; //禁止DMA模块
    DMACONbits.PRSSEL = 1;  //优先级循环方案
    DMAL = 0;                                                //RAM寻址下限
        DMAH = 0x8000;                        //RAM寻址上限
        IPC3bits.U1TXIP = 7;  //DMA0优先级为7
       
        IEC0bits.DMA0IE = 0;   //关闭DMA0中断
        IEC0bits.DMA1IE = 0;   //关闭DMA1中断
        IEC1bits.DMA2IE = 0;   //关闭DMA2中断
        IEC1bits.DMA3IE = 0;   //关闭DMA3中断
//禁用计时器中断矢量
            T1CONbits.TON = 0;      
            _T1IE = 0;
                IEC0bits.INT0IE = 0;

        //- ********************************************

  //-------初始化DMA0-------------------
    // ******设置DMA0通道从COMM_BUF向UART1-FIFO发送数据*****************
        DMACH0 = 0x42;                        //禁止DMA0,并开始对DMA进行配置       
        DMASRC0 = (unsigned short int) & Send_Comm_Buf + 4 ;//设置DMA0的源数据地址
        //                DMASRC0 = *Send_Comm_Buf;//设置DMA0的原数据地址
        DMADST0 = (unsigned short int) & U1TXREG;//设置DMA0目标地址为UART1-FIFO;
    DMAINT0bits.CHSEL = 0x05;//设置DMA0通道触发源为UART1
    DMAINT0bits.HALFEN = 1;        //设置DMA0半满中断


  //-------------------------------------

//写入前7个字节,即指令号+器件ID,
//由于器件ID为6字节,由于某些通讯部件FIFO不支持7个字节的存入,须将器件字节分段
//现分为两段,即直接写入FIFO的,包含指令一共4个字节

        Send_Comm_Buf_P = Send_Comm_Buf;
    U1TXREG =  ComName ;//写入指令
        *Send_Comm_Buf_P++ = ComName;//指令写入Buf,Buf指针加一
        for (i=0;i<6;i++)
    {
        *Send_Comm_Buf_P++ = SYSID;//写入数据到Buf
        if (i<=2)
        {
                  U1TXREG = SYSID ;//写入数据到FIFO
        }
    }



        // 以下针对各不同指令进行处理,不再直接写入TXBUF,而由DMA进行处理
        //  发送本机基本参数,
        if (ComName == C_SysInf)
        {
                        Send_Comm_Buf_Len = 0x1B;

                        *Send_Comm_Buf_P++ = Send_Comm_Buf_Len;//07:指令长度
                        *Send_Comm_Buf_P++ = SYSMData[0];//08:出厂日期Y
                        *Send_Comm_Buf_P++ = SYSMData[1];//09:        Y
                        *Send_Comm_Buf_P++ = SYSMData[2];//0A        M
                        *Send_Comm_Buf_P++ = SYSMData[3];//0B        D
                        *Send_Comm_Buf_P++ = SYSModel[0];//0C型号
                        *Send_Comm_Buf_P++ = SYSModel[1];//0D型号
                        *Send_Comm_Buf_P++ = SYSModel[2];//0F型号
                        *Send_Comm_Buf_P++ = SYSModel[3];//10型号
                        *Send_Comm_Buf_P++ = SYSMEdition[0];//11出厂版本号
                        *Send_Comm_Buf_P++ = SYSMEdition[1];//12
                        *Send_Comm_Buf_P++ = SYSCData[0];//13系统更新日期Y
                        *Send_Comm_Buf_P++ = SYSCData[1];//14            Y
                        *Send_Comm_Buf_P++ = SYSCData[2];//15            M
                        *Send_Comm_Buf_P++ = SYSCData[3];//16            D
                        *Send_Comm_Buf_P++ = SYSCEdition[0];//17更新的版本号
                        *Send_Comm_Buf_P++ = SYSCEdition[1];//18
        }
       
        //启动通讯-DMA

        DMACNT0 = Send_Comm_Buf_Len - 7;  //设置传输数据数量
        U1STAHbits.UTXISEL = 0;//TX接收缓冲区有8个空位触发中断
        // *********************************************************************
       
        // **************启动DMA0***************************************
        //IFS0bits.DMA0IF = 0;   //清除DMA0中断标志
        DMACONbits.DMAEN = 1 ;  //启动DMA模块
        DMACH0bits.CHEN = 1;        //使能DMA0
         
        // ************************************************************
       
        IEC0bits.U1TXIE = 1;//开启U1中断
        IEC0bits.DMA0IE = 1;   //开启DMA中断
       
       

}

UART设置:




void UART1_Initialize(void)
{
    // URXEN disabled; URXEN禁用;
    // RXBIMD RXBKIF flag when Break makes low-to-high transition after being low for at least 23/11 bit periods;
    // RXBIMD RXBKIF 标志当中断在低到高过渡至少23/11位期间后进行低到高转换;
    // UARTEN enabled;使能Uart1;
    // MOD Asynchronous 8-bit UART; 异步8位UART;
    // UTXBRK disabled; 禁止同步暂停符号发送
    // BRKOVR TX line driven by shifter;  TX线由移位器驱动;
    // UTXEN disabled; 禁止发送;
    // USIDL disabled; 在空闲模式下工作;
    // WAKE disabled; 关闭唤醒使能
    // ABAUD disabled; 禁止自动波特率检测
    // BRGH enabled; 高速波特率(baudclk/4)
      U1MODE = (0x8080 & ~(1<<15));  // disabling UARTEN bit
  
    // STSEL 1 Stop bit sent; 一个停止位
    // 1 checked at RX;
    // BCLKMOD disabled; 使用传统技术器生成波特率具体取决于BRGH位;
    // SLPEN disabled; 休眠模式下关闭
    // FLO Off;流控制关闭
    // BCLKSEL FOSC/2; 时钟源为Fosc/2(指令周期时钟)
    // C0EN disabled; 校验和模式0
    // RUNOVF disabled;检测到溢出错误时RX停止接受新数据
    // UTXINV disabled; 输出数据不翻转,空闲状态TX高电平
    // URXINV disabled; 输入数据不翻转,空闲状态为高电平
    // HALFDPLX disabled; 全双工模式
    U1MODEH = 0x00;
   
    // OERIE disabled; 接收缓冲区溢出中断禁止
    // RXBKIF disabled; 接收暂停字符中断禁止
    // RXBKIE disabled; 接收暂停字符中断标志位清除
    // ABDOVF disabled; BRG尚未在自动波特率采集序列期间计满返回
    // OERR disabled; 接收缓冲区溢出标志清除
    // TXCIE disabled; 发送冲突中断禁止
    // TXCIF disabled; 发送冲突中断标志清除
    // FERIE disabled; 帧错误中断禁止
    // TXMTIE disabled; 发送移位寄存器空中断禁止
    // ABDOVE disabled; 自动波特率采集中断禁止
    // CERIE disabled; 校验和错误中断禁止
    // CERIF disabled;检验和错误中断标志清除
    // PERIE disabled;  奇偶校验错误中断标志清除
    U1STA = 0x00;
   
    // URXISEL RX_ONE_WORD; 在缓冲区有1个以上字节时触发接收中断
    // UTXBE enabled; 发送缓冲区设为空,在UTXEN=0时写入1将复位TX FIFO指针和计数器
   
    // UTXISEL TX_BUF_EMPTY; 发送缓冲区全空时触发中断
   
    // URXBE enabled; 接收缓冲区为空,在URXEN=1时写入1将复位RX FIFO指针和计数器
    // STPMD disabled; 在第一个或第二个停止位(取决于STSEL)的中间位置触发RXIF
    // TXWRE disabled; 清除写发送错误标志
    U1STAH = 0x22;
   
        // BaudRate = 38400; Frequency = 4,000,000 Hz; BRG 25;

    U1BRG =0x19;
    U1BRGH = 0x00;
   
    U1P1 = 0x00;
    U1P2 = 0x00;
    U1P3 = 0x00;
    U1P3H = 0x00;
    U1TXCHK = 0x00;
    U1RXCHK = 0x00;
   
    U1SCCON = 0x00;//
   
    U1SCINT = 0x00;
   
    // UART1中断寄存器
    // ABDIF disabled; ABAUD 未使能,或已使能但未完成自动波特率
    // WUIF disabled; WAKE 未使能,或已使能但未发生唤醒事件
    // ABDIE disabled; 不设置事件中断
    U1INT = 0x00;


    IEC0bits.U1RXIE = 1;// UART1接收中断允许
   
  
}




各种办法都试过了,包括降低波特率,提高优先级,关闭了所有其他中断,把TX发送中断改为7个空位,等等,都试过了。甚至只发送chr(04) &“197331”,结果收到的还是chr(4) &“197332”。改为不用DMA都没有问题,有没有大侠能够指点一下


回帖(8)

没人知道我是谁

2021-3-31 14:02:42
补充一下DMA中断:
void __attribute__ ( ( interrupt, no_auto_psv ) ) _DMA0Interrupt ( void )
{
    static uint8_t i=0;
    i++;
   IFS0bits.DMA0IF = 0;
        if (DMAINT0bits.HALFEN == 1) //半满中断
                {
                        DMAINT0bits.HALFEN = 0;//下次全满中断
            //U1TXREG = i;
           // U1TXREG = 0x48;
                        //U1TXREG = 0x41;
            //U1TXREG = 0x4C;
                        //U1TXREG = 0x46;
            IEC0bits.U1TXIE = 1;//开启U1中断
                }
        else
                {
                        DMAINT0bits.HALFEN = 1;//下次全满中断
                        //U1TXREG = 0x45;
                        //U1TXREG = 0x6E;
                        //U1TXREG = 0x64;            
                }           
    }
举报

没人知道我是谁

2021-3-31 14:18:13
补充一下BUF定义
//定义用于串口发送指令的buf;
//该buf为直接通过TX发送的数据,包含全部格式;
uint8_t Send_Comm_Buf[34];// __attribute__((space(dma)))
uint8_t *Send_Comm_Buf_P;//指针
uint8_t Send_Comm_Buf_Len;//定义指令段需要发送的字节数;
举报

阿信509

2021-3-31 15:33:15
从来没用过dma,问题 应该出在这里,多在网上找找这方面的资料看看
9 举报
  • 没人知道我是谁: 老大,您这话说得没错,不过资料找了n多了,各种PIC的系列都研究过了,看似没有问题,但问题就在那里!
  • 阿信509 回复 没人知道我是谁: 有没有相关的例程呢?试试他们的有没有这样的问题,然后再对照自己的程序看看
  • 没人知道我是谁 回复 阿信509: 没找到我要的那个芯片的例程,找了
    接近的型号,但是我逐条对应,看不出有什么本质上的差别,
  • 没人知道我是谁 回复 阿信509: 问题是数据发出来了,大部分对的,但是你看会有几个字节出问题
    我猜可能是由什么冲突,所以把其他中断都关了,没用。再怀疑是有别的DMA,俄没有关掉,有竞争,都关了,没用。最后都怀疑是不是变量或者BUF定义有问题,其实也没有。现在我差不多打算放弃,改用发送中断直接处理了,
  • 没人知道我是谁 回复 阿信509: 甚至改成在DMA中只发7个,结果还是那个位置有问题,后续接着往TXFIFO里写,一点问题没有
  • 阿信509 回复 没人知道我是谁: 如果每次都是固定的位置有问题,会不会是被其他变量侵入了呢,还有,你的程序太复杂了,能不能简化一下,就是简单的发送,发送的数据固定,那样在试试
  • 阿信509 回复 没人知道我是谁: 有相近的也行,我的意思是不要用自己写的程序
  • 阿信509 回复 没人知道我是谁: 先发5个试试,就发12345固定的试试
  • 没人知道我是谁 回复 阿信509: 你说得方法试过了,没用

没人知道我是谁

2021-4-1 13:07:30
今天好像找到问题了。
原来要发送的数据定义是这样的
//Æ÷¼þID,µ÷ÊÔ³ÌÐò¼Ù¶¨Îª197331
uint8_t SYSID[5] = {
    0x31,0x39,0x37,0x33,0x33,0x31
};

//³ö³§ÈÕÆÚ£¬4×Ö½ÚYYMD£¬µ÷ÊÔ³ÌÐò¼Ù¶¨Îª2021
uint8_t SYSMData[3] = {0x38,0x37,0x36,0x31};

//Ðͺţ¬4×Ö½Ú£¬ËùÓÐÐͺžù²ÉÓñàºÅ£¬µ÷ÊÔ³ÌÐò¼Ù¶¨ÎªEcho,
uint8_t SYSModel[3] = {0x45,0x63,0x68,0x6f};

//³ö³§°æ±¾ºÅ£¬2×Ö½Ú£¬µ÷ÊÔ³ÌÐò¼Ù¶¨Îª0£»
uint8_t SYSMEdition[1] = {0x30,0x30};


//¸üÐÂÈÕÆÚ£¬4×Ö½ÚYYMD£¬µ÷ÊÔ³ÌÐò¼Ù¶¨Îª2021
uint8_t SYSCData[3] = {0x32,0x30,0x32,0x31};

//¸üа汾ºÅ£¬2×Ö½Ú£¬µ÷ÊÔ³ÌÐò¼Ù¶¨Îª1£»
uint8_t SYSCEdition[1] ={ 0x31,0x31};

今天突然感觉好像是错位了,就改了一下变成这样
//Æ÷¼þID,µ÷ÊÔ³ÌÐò¼Ù¶¨Îª197331
uint8_t SYSID[6] = {
    0x31,0x39,0x37,0x33,0x33,0x31
};

//³ö³§ÈÕÆÚ£¬4×Ö½ÚYYMD£¬µ÷ÊÔ³ÌÐò¼Ù¶¨Îª2021
uint8_t SYSMData[4] = {0x38,0x37,0x36,0x31};

//Ðͺţ¬4×Ö½Ú£¬ËùÓÐÐͺžù²ÉÓñàºÅ£¬µ÷ÊÔ³ÌÐò¼Ù¶¨ÎªEcho,
uint8_t SYSModel[4] = {0x45,0x63,0x68,0x6f};

//³ö³§°æ±¾ºÅ£¬2×Ö½Ú£¬µ÷ÊÔ³ÌÐò¼Ù¶¨Îª0£»
uint8_t SYSMEdition[2] = {0x30,0x30};


//¸üÐÂÈÕÆÚ£¬4×Ö½ÚYYMD£¬µ÷ÊÔ³ÌÐò¼Ù¶¨Îª2021
uint8_t SYSCData[4] = {0x32,0x30,0x32,0x31};

//¸üа汾ºÅ£¬2×Ö½Ú£¬µ÷ÊÔ³ÌÐò¼Ù¶¨Îª1£»
uint8_t SYSCEdition[2] ={ 0x31,0x31};

现在输出正常了

上面一行是原来定义的输出结果,下面一行是改过定义之后的
f197338876EEch201202*1??àúf
------------------------------------------------------------------
f1973318761Echo00202111??àúf
------------------------------------------------------------------


但这是不是X-IDE有毛病吧,就算没有对齐,也不能写在别的变量里吧
举报

没人知道我是谁

2021-4-1 13:09:18
今天好像找到问题了。
原来要发送的数据定义是这样的
uint8_t SYSID[5] = {
    0x31,0x39,0x37,0x33,0x33,0x31
};

uint8_t SYSMData[3] = {0x38,0x37,0x36,0x31};

uint8_t SYSModel[3] = {0x45,0x63,0x68,0x6f};

uint8_t SYSMEdition[1] = {0x30,0x30};

uint8_t SYSCData[3] = {0x32,0x30,0x32,0x31};

uint8_t SYSCEdition[1] ={ 0x31,0x31};

今天突然感觉好像是错位了,就改了一下变成这样
uint8_t SYSID[6] = {
    0x31,0x39,0x37,0x33,0x33,0x31
};

uint8_t SYSMData[4] = {0x38,0x37,0x36,0x31};

uint8_t SYSModel[4] = {0x45,0x63,0x68,0x6f};

uint8_t SYSMEdition[2] = {0x30,0x30};

uint8_t SYSCData[4] = {0x32,0x30,0x32,0x31};

uint8_t SYSCEdition[2] ={ 0x31,0x31};

现在输出正常了

上面一行是原来定义的输出结果,下面一行是所有定义的数组增加了一个改过定义之后的
f 197338 876EEch201202*1 ??àúf
------------------------------------------------------------------
f 197331 8761Echo00202111??àúf
------------------------------------------------------------------


但这是不是X-IDE有毛病吧,就算没有对齐,也不能写在别的变量里吧
1 举报

没人知道我是谁

2021-4-1 13:10:24
请教一下,不应该这样搞吧,感觉很没谱啊
举报

没人知道我是谁

2021-4-1 13:20:06
只要前面一个数组少定义一个,后面数组的第一个字节就覆盖到前面的数组的最后一个???
举报

没人知道我是谁

2021-4-2 10:50:10
虽然还存有疑问,但问题总是解决了,就让疑问暂时留着吧!
最终输出结果:
1973312021EHALFcho00202111 End
中间的HALF是在DMA半满时插入的,END是全满时加上的。
一切OK了
举报

更多回帖

×
20
完善资料,
赚取积分