ssfnpl 发表于 7 天前

使用范例配置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);
}



国芯人工智能 发表于 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 是否为全局变量或静态变量?若为局部变量,可能因栈溢出导致异常
确认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配置部分,以便进一步分析。

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

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

乘风飞扬 发表于 7 天前

你的DMA中断是借用13号中断向量地址
那么项目里面是否添加了中断地址映射代码?(从DMA中断地址跳转到13号中断地址)
官方例子是添加"isr.asm"文件到项目,并在里面添加中断跳转指令。


ssfnpl 发表于 7 天前

乘风飞扬 发表于 2025-8-27 10:26
你的DMA中断是借用13号中断向量地址
那么项目里面是否添加了中断地址映射代码?(从DMA中断地址跳转到13号 ...

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

ssfnpl 发表于 7 天前

国芯人工智能 发表于 2025-8-27 08:48
您提到在配置UART1与DMA时,USB无法识别且程序死机,而关闭DMA后一切正常,说明问题可能出在DMA初始化或相 ...

{:baoquan:} 感谢!
页: [1]
查看完整版本: 使用范例配置UART1——DMA 不知什么原因导致USB识别不了,程序也死机呢 | 已解决