找回密码
 立即注册
查看: 76|回复: 4

使用范例配置UART1——DMA 不知什么原因导致USB识别不了,程序也死机呢 | 已解决

[复制链接]
  • 打卡等级:偶尔看看III
  • 打卡总天数:38
  • 最近打卡:2025-08-27 08:34:42
已绑定手机

2

主题

8

回帖

192

积分

注册会员

积分
192
发表于 7 天前 | 显示全部楼层 |阅读模式
烦请各位大佬帮忙看下什么原因呢?  配置的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[256];

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[0] == 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:使能DMA  B6 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);
}



回复

使用道具 举报 送花

3

主题

2001

回帖

850

积分

等待验证会员

积分
850
发表于 7 天前 | 显示全部楼层
您提到在配置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[256] 是否为全局变量或静态变量?若为局部变量,可能因栈溢出导致异常
确认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配置参考(请根据具体芯片手册调整):
  1. c
  2. void DMAConfig(void)
  3. {
  4.     // 选择DMA通道(假设为DMA0用于UART1 TX)
  5.     DMACON = 0x00;       // 关闭DMA
  6.     DMACON |= 0x01;      // 启用DMA0
  7.     DMAP0 = (u16)DMABuffer; // 设置源地址
  8.     DMAP1 = (u16)&SBUF;  // 设置目标地址(UART1发送寄存器)
  9.     DMAL0 = DMAAMTLEN; // 设置传输长度
  10.     DMAL1 = 0;
  11.     DMACON |= 0x80;      // 启动DMA传输
  12. }
复制代码
注意:以上代码仅为示意,具体寄存器名及位定义请参考芯片数据手册。

四、调试建议

1. 逐步调试法  
分段注释DMA相关代码,逐步定位问题点
使用调试器观察寄存器状态,确认DMA是否正常启动

2. 添加日志输出  
在DMA初始化前后添加打印语句,判断程序是否卡死在某处
检查USB初始化流程是否被中断或跳过

3. 检查系统时钟配置  
确保主频(MAINFosc)与DMA、UART、USB等模块的时钟配置匹配

五、总结

您的问题可能由以下原因引起:
DMA通道配置错误或资源冲突
DMA传输参数设置不当
DMA中断处理不当或优先级冲突
USB模块与DMA共享资源导致异常

建议按照上述检查点逐一排查,并结合调试工具进行验证。如仍无法解决,可提供完整的DMA配置代码及UART配置部分,以便进一步分析。

如需帮助,请提供完整的代码片段及硬件平台信息,我们将继续协助您定位问题。

[本文内容由国芯人工智能辅助生成,仅供参考]
回复

使用道具 举报 送花

  • 打卡等级:以坛为家II
  • 打卡总天数:505
  • 最近打卡:2025-09-02 16:59:35
已绑定手机

45

主题

2194

回帖

7662

积分

论坛元老

积分
7662
发表于 7 天前 | 显示全部楼层
你的DMA中断是借用13号中断向量地址
那么项目里面是否添加了中断地址映射代码?(从DMA中断地址跳转到13号中断地址)
官方例子是添加"isr.asm"文件到项目,并在里面添加中断跳转指令。

截图202508271034071389.jpg
回复

使用道具 举报 送花

  • 打卡等级:偶尔看看III
  • 打卡总天数:38
  • 最近打卡:2025-08-27 08:34:42
已绑定手机

2

主题

8

回帖

192

积分

注册会员

积分
192
发表于 7 天前 | 显示全部楼层
乘风*** 发表于 2025-8-27 10:26
你的DMA中断是借用13号中断向量地址
那么项目里面是否添加了中断地址映射代码?(从DMA中断地址跳转到13号 ...

谢谢!这个确实漏了好低级的错误。对了好几遍芯片手册的寄存器找不出原因,示例程序后面也有向量程序没跟着加入。
回复

使用道具 举报 送花

  • 打卡等级:偶尔看看III
  • 打卡总天数:38
  • 最近打卡:2025-08-27 08:34:42
已绑定手机

2

主题

8

回帖

192

积分

注册会员

积分
192
发表于 7 天前 | 显示全部楼层
国芯人*** 发表于 2025-8-27 08:48
您提到在配置UART1与DMA时,USB无法识别且程序死机,而关闭DMA后一切正常,说明问题可能出在DMA初始化或相 ...

感谢!
回复

使用道具 举报 送花

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|手机版|深圳国芯人工智能有限公司 ( 粤ICP备2022108929号-2 )

GMT+8, 2025-9-3 05:22 , Processed in 0.123101 second(s), 75 queries .

Powered by Discuz! X3.5

© 2001-2025 Discuz! Team.

快速回复 返回顶部 返回列表