使用范例配置UART1——DMA 不知什么原因导致USB识别不了,程序也死机呢 | 已解决
烦请各位大佬帮忙看下什么原因呢?配置的DMA 初始化程序就死了, 不初始化DMA就正常 ,串口1也调通了能正常打印字符串现在初始化就不行了,所以主程注释了DMA部分
#include "AI8051U.H"
#include "ai_usb.h"
#include "uart_3.h"
#define T22M_ADDR CHIPID11
#define VRT27M_ADDR CHIPID23
#define MAIN_Fosc 22118400L
#define Baudratel 115200L
#define Timer0_Reload (65536UL-(MAIN_Fosc/1000))
#define DMA_AMT_LEN 255
bit B_1ms;
bit DMATxFlag;
bit DMARxFlag;
bit BusyFlag;
u8 Rx_cnt;
u8 RX1_TimeOut;
u8 xdata DMABuffer;
unsigned int ci = 0;
void UART1_config(u8 brt);
void DMA_Config(void);
void SetTimer2Baudraye(u16 dat);
void UartPutc(unsigned char dat)
{
BusyFlag = 1;
SBUF = dat;
while(BusyFlag);
}
void PrintString1(u8 *puts) //发送一个字符串
{
for (; *puts != 0;puts++) //遇到停止符0结束
{
SBUF = *puts;
BusyFlag = 1;
while(BusyFlag);
}
}
char putchar(char c)
{
UartPutc(c);
return c;
}
void delay_ms(uint16_t ms);
void main(void)
{
u16 i;
EAXFR = 1; //允许访问扩展的特殊寄存器,XFR
WTST = 0; //设置取程序代码等待时间,
//赋值为0表示不等待,程序以最快速度运行
CKCON = 0; //设置访问片内的xdata速度,
//赋值为 0表示用最快速度访问,
//不增加额外的等待时间
P0M1 = 0x00; P0M0 = 0x00;
P1M1 = 0x00; P1M0 = 0x00;
P2M1 = 0x00; P2M0 = 0x00;
P3M1 = 0x00; P3M0 = 0x00;
P4M1 = 0x00; P4M0 = 0x00;
P5M1 = 0x00; P5M0 = 0x00;
/*22.1184MHz*/
CLKDIV = 0x04; //时钟分频寄存器
IRTRIM = T22M_ADDR;
VRTRIM = VRT27M_ADDR;
IRCBAND &=~0x03;
IRCBAND |= 0X02;
CLKDIV = 0x00;
for(i=0;i<256;i++)
{
DMABuffer = i;
}
/************************************************/
//1毫秒@22.1184MHz
//AUXR |= 0x80; //定时器时钟1T模式
T0x12 = 1;
//TMOD &= 0xF0; //设置定时器模式
TL0 = 0x9A; //设置定时初始值
TH0 = 0xA9; //设置定时初始值
TF0 = 0; //清除TF0标志
TR0 = 1; //定时器0开始计时
ET0 = 1;
usb_init();
// AUXR = 0x80;
// TH0 = (u8)(Timer0_Reload/256);
// TL0 = (u8)(Timer0_Reload%256);
// ET0 = 1;
// TR0 = 1;
UART1_config(2);
DMA_Config();
EA = 1;
// printf_usb("UART1 DMA Timeout programme!\r\n");
DMATxFlag = 0;
DMARxFlag = 0;
P2 = 0xff;
while (1)
{
if (bUsbOutReady)
{ //发送数据缓冲区,长度(接收数据原样返回, 用于测试)
USB_SendData(UsbOutBuffer,OutNumber);
usb_OUT_done();
}
if (UsbOutBuffer == 6)
{
printf_usb("Hielo");
usb_OUT_done(); //当前包的数据处理完成
delay_ms(300);
P2=~P2;
}
if(ci>=500){ci=0; P2=~P2;
//PrintString1("8051u");
}
// if((DMATxFlag)&&(DMARxFlag))
// {
// Rx_cnt = 0;
// RX1_TimeOut = 0;
// printf_usb("\r\nUART1 DMA FULL!\r'n");
// DMATxFlag = 0;
// DMA_UR1T_CR = 0xc0; //B7 1: 使能DMA
// //B6 1:开始UART1_DMA 自动发送
// DMARxFlag = 0;
// DMA_UR1R_CR = 0xa1; //B7 1:使能DMA
// //B5 1:开始DMA自动接收
// } //B0 1:清除FIFO
//
// if(B_1ms)
// {
// B_1ms = 0;
// if(RX1_TimeOut > 0)
// {
// if(RX1_TimeOut ==0) //超时计数
// {
// DMA_UR1R_CR = 0x00; //关闭DMA
// printf_usb("\r\nUART1 Timeout!\r\n");
//
// for(i=0;i<Rx_cnt;i++)
// {
// UartPutc(DMABuffer);
// }
// printf_usb("\r\n");
//
// Rx_cnt = 0;
// DMA_UR1R_CR = 0xa1;//B7 1:使能UART1_DMA B5 1:开始DMA自动接收 B0 1:清除FIFO
//
// }
// }
// }
//
}
}
void DMA_Config(void)
{
// EAXFR = 1;
// WTST = 0;
// CKCON = 0;
//UR1TI1 = 1; 使能DMA中断
DMA_UR1T_CFG = 0x80;
DMA_UR1T_STA = 0x00;
DMA_UR1T_AMTH = (u8)(DMA_AMT_LEN>>8);
DMA_UR1T_AMT= (u8)(DMA_AMT_LEN); //设置总字节数:n+1
DMA_UR1T_TXAH = (u8)(((u16)DMABuffer)>>8);
DMA_UR1T_TXAL = (u8)((u16)DMABuffer);
DMA_UR1T_CR = 0xC0; //B7 1:使能DMAB6 1:开始DMA自动发送 ???
DMA_UR1R_CFG = 0x80; //B7 1:Enable interrupt
DMA_UR1R_STA = 0x00;
DMA_UR1R_AMTH = (u8)(DMA_AMT_LEN>>8);
DMA_UR1R_AMT= (u8)(DMA_AMT_LEN); //设置传输总字节数: n+1
DMA_UR1R_RXAH = (u8)(((u16)DMABuffer)>>8);
DMA_UR1R_RXAL = (u8)((u16)DMABuffer);
DMA_UR1R_CR = 0xA1; //B7 1:使能DMA B5 1:开始自动接收 B0 1:清除FIFO
}
void SetTimer2Baudraye(u16 dat)
{
AUXR &=~(1<<4);
AUXR &=~(1<<3);
AUXR |=(1<<2);
T2H= dat/256;
T2L = dat%256;
IE2 &= ~(1<<2); //禁止中断
AUXR |=(1<<4);
}
void UART1_config(u8 brt)
{
if(brt ==2)
{
AUXR|= 0x01;
SetTimer2Baudraye((u16)65536UL-(MAIN_Fosc/4)/Baudratel);
} else
{
TR1 = 0;
AUXR &= ~0x01;
AUXR |= (1<<6);
TMOD &= ~(1<<6);
TMOD &= ~0x30;
TH1 = (u8)((65536UL-(MAIN_Fosc/4)/Baudratel)/256);
TL1 = (u8)((65536UL-(MAIN_Fosc/4)/Baudratel)%256);
ET1 = 0;
INTCLKO &= ~0x02;
TR1 = 1;
}
// UART1模式:0x00同步移位输出, 0x40:8位数据可变波特率
// 0x80: 9位数据固定波特率, 0xc0:9位数据可变波特率
SCON = (SCON & 0x3f) | 0x40;
//PS = 1; //优先级中
ES = 1; //允许中断
REN= 1; //允许接收
P_SW1 &= 0x3f;
//P_SW1串口引脚选择0X00: P3.0 3.1,0X40:3.6,3.7 0X80:1.6 1.7 0XC0:4.3 4.4
P_SW1 |= 0x40;
RX1_TimeOut = 0;
}
void RART1_int(void) interrupt 4
{
if(RI)
{
RI = 0;
Rx_cnt++;
if(Rx_cnt>=DMA_AMT_LEN) Rx_cnt = 0;
RX1_TimeOut = 5; //5ms无数据 判定一串数据接收完成
}
if(TI)
{
TI = 0;
BusyFlag = 0;
}
}
void timer0 (void) interrupt 1
{
B_1ms = 1;
if(ci<1000) {ci++;}
}
void UAART1_DMA_Interrupt(void) interrupt 13
{
if(DMA_UR1T_STA &= ~0x01) //发送完成
{
DMA_UR1T_STA &= ~0x01;
DMATxFlag= 1;
}
if(DMA_UR1T_STA &= 0x04) //数据复盖
{
DMA_UR1T_STA &= ~0x04;
}
if(DMA_UR1T_STA &= 0x01) //接收完成
{
DMA_UR1T_STA &= ~0x01;
}
if(DMA_UR1T_STA &= 0x02) //数据丢弃
{
DMA_UR1T_STA &= ~0x20;
}
}
////////////////////////////////////////
// 毫秒延时函数
// 入口参数: ms (设置延时的毫秒值)
// 函数返回: 无
////////////////////////////////////////
void delay_ms(uint16_t ms)
{
uint16_t i;
if(ms<=0) {return;}
do
{
i = 22118400UL / 6000;
while (--i);
} while (--ms);
}
您提到在配置UART1与DMA时,USB无法识别且程序死机,而关闭DMA后一切正常,说明问题可能出在DMA初始化或相关资源冲突上。以下是对该问题的分析和建议:
一、问题初步分析
1. DMA初始化导致系统异常
您提到“不初始化DMA就正常”,而一旦启用DMA,程序死机或USB无法识别,这表明DMA配置过程中可能存在以下问题:
DMA通道未正确分配或冲突
DMA传输参数设置错误(如地址、长度等)
DMA中断未正确处理,导致死锁或异常
与USB控制器共用某些硬件资源,导致资源冲突
2. UART1与DMA配合使用需注意
UART1与DMA配合使用时,需确保:
UART1的TX/RX引脚与DMA通道绑定正确
DMA传输方向、缓冲区地址、数据长度等参数设置准确
中断优先级合理配置,避免DMA中断干扰其他关键任务
3. USB识别失败可能原因
USB识别失败可能是由于:
系统资源被DMA占用,导致USB控制器无法正常工作
DMA配置过程中修改了USB相关的寄存器或时钟配置
系统复位或异常中断导致USB模块未正确初始化
二、建议检查点
1. 确认DMA通道配置是否正确
检查DMA通道号是否与UART1使用的通道匹配(例如:UART1 TX使用DMA0,RX使用DMA1)
确保DMA通道未与其他外设(如USB、ADC等)冲突
验证DMA源/目标地址是否正确指向UART1的发送/接收寄存器
2. 检查DMA传输参数
DMAAMTLEN 设置为255是否符合实际需求?若超出缓冲区长度可能导致越界访问
DMABuffer 是否为全局变量或静态变量?若为局部变量,可能因栈溢出导致异常
确认DMA传输方向(发送/接收)与UART配置一致
3. 验证DMA中断配置
检查DMA中断使能位是否正确设置
确保DMA中断服务函数(ISR)中没有长时间阻塞操作
确认DMA中断优先级是否合理,避免与USB中断冲突
4. 检查UART1与DMA的同步机制
在DMA传输完成前,UART1应处于空闲状态,避免数据覆盖或冲突
若使用DMA发送,需确保发送缓冲区为空后再启动DMA传输
5. 检查USB相关配置
确认USB初始化代码是否在DMA初始化之前执行
检查USB时钟配置是否受DMA初始化影响
确保USB设备枚举过程未被DMA中断打断
三、示例修正建议
以下是一个简化版DMA配置参考(请根据具体芯片手册调整):
c
void DMAConfig(void)
{
// 选择DMA通道(假设为DMA0用于UART1 TX)
DMACON = 0x00; // 关闭DMA
DMACON |= 0x01; // 启用DMA0
DMAP0 = (u16)DMABuffer; // 设置源地址
DMAP1 = (u16)&SBUF;// 设置目标地址(UART1发送寄存器)
DMAL0 = DMAAMTLEN; // 设置传输长度
DMAL1 = 0;
DMACON |= 0x80; // 启动DMA传输
}
注意:以上代码仅为示意,具体寄存器名及位定义请参考芯片数据手册。
四、调试建议
1. 逐步调试法
分段注释DMA相关代码,逐步定位问题点
使用调试器观察寄存器状态,确认DMA是否正常启动
2. 添加日志输出
在DMA初始化前后添加打印语句,判断程序是否卡死在某处
检查USB初始化流程是否被中断或跳过
3. 检查系统时钟配置
确保主频(MAINFosc)与DMA、UART、USB等模块的时钟配置匹配
五、总结
您的问题可能由以下原因引起:
DMA通道配置错误或资源冲突
DMA传输参数设置不当
DMA中断处理不当或优先级冲突
USB模块与DMA共享资源导致异常
建议按照上述检查点逐一排查,并结合调试工具进行验证。如仍无法解决,可提供完整的DMA配置代码及UART配置部分,以便进一步分析。
如需帮助,请提供完整的代码片段及硬件平台信息,我们将继续协助您定位问题。
[本文内容由国芯人工智能辅助生成,仅供参考] 你的DMA中断是借用13号中断向量地址
那么项目里面是否添加了中断地址映射代码?(从DMA中断地址跳转到13号中断地址)
官方例子是添加"isr.asm"文件到项目,并在里面添加中断跳转指令。
乘风飞扬 发表于 2025-8-27 10:26
你的DMA中断是借用13号中断向量地址
那么项目里面是否添加了中断地址映射代码?(从DMA中断地址跳转到13号 ...
谢谢!这个确实漏了{:cahan:}好低级的错误。对了好几遍芯片手册的寄存器找不出原因,示例程序后面也有向量程序没跟着加入。 国芯人工智能 发表于 2025-8-27 08:48
您提到在配置UART1与DMA时,USB无法识别且程序死机,而关闭DMA后一切正常,说明问题可能出在DMA初始化或相 ...
{:baoquan:} 感谢!
页:
[1]