用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都没有问题,有没有大侠能够指点一下
|