打印
[其他产品]

DMA向UART发送数据误码,使用的是dsPIC33CK256MP508

[复制链接]
299|0
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
laocuo1142|  楼主 | 2021-4-13 14:26 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
用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接收中断允许
   
  
}

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;            
                }           
    }  


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

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

976

主题

3973

帖子

10

粉丝