AI8051 8位模式 UART1 DMA配置发送地址发数据错误 | 已解决
//========================================================================// 函数: void DMA_Config(void)
// 描述: UART DMA 功能配置.
// 参数: none.
// 返回: none.
// 版本: V1.0, 2024-5-6
//========================================================================
void DMA_Uart1Config(u8 *Uart1TxBuff,u8 *Uart1RxBuff)
{
DMA_UR1T_CFG = 0x00; //bit7 0:Disable Interrupt
DMA_UR1T_STA = 0x00;
DMA_UR1T_AMT = 0xff; //设置传输总字节数(低8位):n+1
DMA_UR1T_AMTH = 0x01; //设置传输总字节数(高8位):n+1
DMA_UR1T_TXAH = (u8)((u16)&DmaUart1TXBuffer >> 8);
DMA_UR1T_TXAL = (u8)((u16)&DmaUart1TXBuffer);
DMA_UR1T_CR = 0x80; //bit7 1:使能 UART1_DMA, bit6 1:开始 UART1_DMA 自动发送
DMA_UR1R_CFG = 0x00; //bit7 0:Disable Interrupt
DMA_UR1R_STA = 0x00;
DMA_UR1R_AMT = 0xff; //设置传输总字节数(低8位):n+1
DMA_UR1R_AMTH = 0x03; //设置传输总字节数(高8位):n+1
DMA_UR1R_RXAH = (u8)((u16)&Uart1RxBuff >> 8);
DMA_UR1R_RXAL = (u8)((u16)&Uart1RxBuff);
DMA_UR1R_CR = 0xa1; //bit7 1:使能 UART1_DMA, bit5 1:开始 UART1_DMA 自动接收, bit0 1:清除 FIFO
}
根据例程改的,写了一个发送代码。上面的是配置函数,只要把内部的地址改成函数上传递参数的地址就出错。
//========================================================
// 函数: uart1_dma_send(u8 brt)
// 描述: 串口1发送数据
// 参数: *flag输入标志位 *pbuff
// 返回: 0 发送正常 1发送异常
// 版本: VER1.0
// 日期:
// 备注:
u8uart1_dma_send(u8 *flag,u16 len)
{
u16 i ;
i = len ;
if(*flag == 1 )
{
//printf("flag == 1\n");
*flag = 0;
TI = 0; //清除发送标志(DMA发送完不会自动清除标志位)
i--; //传输字节设置为(i-1)个数据 ;
DMA_UR1T_CFG = 0x80; //bit7 0:Disable Interrupt
DMA_UR1T_STA = 0x00;
//DMA_UR1T_TXAH = (u8)((u16)&senddata >> 8);
//DMA_UR1T_TXAL = (u8)((u16)&senddata);
DMA_UR1T_AMT = (u8)i; //设置传输总字节数(低8位):n+1
DMA_UR1T_AMTH = (u8)(i>>8); //设置传输总字节数(高8位):n+1
DMA_UR1T_CR = 0xc0; //bit7 1:使能 UART1_DMA, bit6 1:开始 UART1_DMA 自动发送
//DMA_UR1R_CR = 0xa1; //bit7 1:使能 UART1_DMA, bit5 1:开始 UART1_DMA 自动接收, bit0 1:清除 FIFO
return 0 ;
}
else
{
//printf("flag == 0\n");
return 1 ;
}
}
上面是DMA发送函数。
输出表现为把发送缓存的地址用参数传递就出错,void DMA_Uart1Config(u8 *Uart1TxBuff,u8 *Uart1RxBuff),用全局定义在内部直接配置就能正常发送。求助!
您好,关于您在使用国芯AI8051 8位MCU进行UART1 DMA配置时遇到的“发送地址发数据错误”问题,以下从硬件配置、代码逻辑、常见错误点及建议调试方法几个方面进行专业分析,供您参考。
一、问题定位分析
您提供的代码片段中,函数名为DMAUart1Config,参数为两个u8类型变量Uart1TxBuff和Uart1RxBuff,但这两个参数并未在函数体内使用,这可能是潜在的问题来源之一。
此外,发送地址配置部分采用了如下代码:
c
DMAUR1TTXAH = (u8)((u16)&DmaUart1TXBuffer >> 8);
DMAUR1TTXAL = (u8)((u16)&DmaUart1TXBuffer);
该段代码的目的是将发送缓冲区DmaUart1TXBuffer的地址拆分为高8位和低8位,分别写入DMA的发送地址寄存器高位和低位。但存在以下几个可能的问题:
1. 地址取值方式是否正确?
若DmaUart1TXBuffer为局部变量或未正确声明为全局数组/指针,其地址可能未被正确解析。
需确认DmaUart1TXBuffer是否为数组类型,且具有固定内存地址。
2. DMA地址寄存器是否支持16位地址?
若芯片DMA模块仅支持8位地址宽度(如低端MCU),则无法支持大于256字节的缓冲区。
您配置了DMAUR1TAMT = 0xff; DMAUR1TAMTH = 0x01;,表示传输长度为0x01FF(511字节),需确保地址寄存器也支持16位寻址。
3. 编译器优化导致地址未被正确计算?
某些编译器在优化时可能对地址计算进行简化或重排,建议使用volatile关键字或查看反汇编确认地址是否正确。
二、建议修改方案
1. 使用正确的地址计算方式
c
extern u8 DmaUart1TXBuffer[]; // 确保缓冲区已在别处定义
DMAUR1TTXAH = (u8)((u16)DmaUart1TXBuffer >> 8);// 注意去掉取址符&,数组名即为地址
DMAUR1TTXAL = (u8)((u16)DmaUart1TXBuffer & 0xFF);
说明:若DmaUart1TXBuffer为数组,使用其数组名即可代表其起始地址;若为指针,应使用DmaUart1TXBuffer或DmaUart1TXBuffer本身(根据上下文判断)。
2. 参数未使用问题
函数定义中参数u8 Uart1TxBuff, u8 Uart1RxBuff未使用,建议删除或用于动态配置缓冲区地址:
c
void DMAUart1Config(u8 txBuff, u16 txLen)
{
u16 addr = (u16)txBuff;
DMAUR1TTXAH = (u8)(addr >> 8);
DMAUR1TTXAL = (u8)(addr & 0xFF);
DMAUR1TAMT = (u8)(txLen - 1); // 假设传输长度为n+1
DMAUR1TAMTH = (u8)((txLen - 1) >> 8);
DMAUR1TCFG = 0x00;
DMAUR1TSTA = 0x00;
DMAUR1TCR = 0x80;
}
3. 检查DMA和UART1的时钟使能
确保在调用DMA配置函数前,UART1和DMA模块的时钟已正确开启:
c
CLKCON |= 0x04;// 使能DMA时钟
PCON |= 0x10; // 使能UART1
三、常见错误点总结
| 错误类型 | 描述 | 解决方法 |
|----------|------|----------|
| 地址错误 | 缓冲区地址未正确传入或未对齐 | 使用全局数组或显式指针,确认地址正确 |
| 传输长度溢出 | 设置长度超过DMA支持范围 | 查阅手册确认最大传输长度 |
| 未初始化UART | UART未正确配置波特率、模式等 | 检查UART初始化函数 |
| 中断未使能 | 发送完成中断未处理 | 若需中断,设置DMAUR1TCFG |= 0x80; |
| 编译器优化问题 | 地址被优化或未正确计算 | 使用volatile或查看反汇编 |
四、调试建议
1. 使用调试器查看寄存器值
检查DMAUR1TTXAH与DMAUR1TTXAL是否写入了正确的地址。
观察DMAUR1TSTA是否反映DMA传输状态(如是否完成)。
2. 使用示波器或逻辑分析仪监测UART输出
确认是否有数据发出,数据内容是否与预期一致。
3. 打印调试信息
若系统支持串口打印,可在DMA传输前后打印调试信息,确认执行流程。
4. 最小系统测试
使用最小缓冲区(如2字节)测试DMA是否能正常发送。
五、结语
DMA配置在嵌入式系统中是提升效率的重要手段,但也因其与硬件强相关而容易出错。建议在开发过程中严格遵循芯片手册规范,结合调试工具进行逐项验证。若您能提供更多上下文(如缓冲区定义、DMA手册片段等),可进一步帮助定位问题。
如需完整DMA+UART1配置示例代码或芯片手册分析,欢迎继续提问。
祝开发顺利!
—— 国芯AI助手
[本文内容由国芯人工智能辅助生成,仅供参考] 对指针取地址操作,错误。直接对指针转u16。
ercircle 发表于 2025-10-3 19:19
对指针取地址操作,错误。直接对指针转u16。
感谢指出我的问题,已解决
页:
[1]