PIC33F运行程序的时候出现Target halted是什么问题

2019-03-25 18:59发布

利用DMA0存储ADC采样结果,4路模拟输入,扫描采样,完成40次采样产生中断。然后再通过DMA1把数据用UART1发出去。程序运行后很快就出现Target halted,就运行结束了。但是发现串口有收到数据,但是不是每一次执行都会收到,而且是乱码。我实际4个模拟通道什么都没有接,原理上是不是采样都为0啊?附上程序,请大神帮忙看看!
//-------------------------------------------------------------------------------//
//                            LIXUE 电子工作室                                   //
//                       http://lixuediy.taobao.com                              //
//                                版权所有                                       //
//                       EMAIL:lixue51@126.com                                   //
//                       Mobile:13109884800                                      //
//                       MCU: dsPIC33FJ128MC706                                  //
//                       Compiler: MAPLAB IDE V8.53   C30 V3.20B                 //
//                       File: LX-64PIN-DMA.c                                    //
//                       DATE: 2010-11-13    Version:  1.0                       //
//-------------------------------------------------------------------------------//
//      外部晶振4MHZ   N 8 1  9600

#include "p33FJ128MC706.h"

_FOSCSEL(IESO_OFF&FNOSC_PRIPLL);        // 使用外部晶振XT
_FOSC(FCKSM_CSDCMD&OSCIOFNC_OFF&POSCMD_XT);        //禁止时钟切换,OSCO为时钟输出,XT晶振模式
_FWDT(FWDTEN_OFF);            // 关闭开门狗
_FICD(JTAGEN_OFF & ICS_PGD1)

void config_AD(void);
void config_TMR3(void);
void config_DMA0(void);
void config_DMA1(void);
void config_U1UART(void);
void config_INT(void);
void __attribute__((__interrupt__,no_auto_psv)) _DMA0Interrupt(void);
#define LL 10
unsigned int AN2[LL],AN3[LL],AN4[LL],AN5[LL];
volatile unsigned int *P;
unsigned int AA __attribute__((space(dma),address(0x4000))); //为了获取首地址



int main(void)
{    //外接4MHz晶振,通过PLL得到总振荡频率40MHz,Fcy=20MHz,Tcy=50ns
    CLKDIVbits.PLLPRE=0;            // N1=2,此输出为4MHz/2=2MHz,符合0.8~8.0MHz的要求
    PLLFBDbits.PLLDIV=78;            // M=80,此输出为2MHz*80=160MHz,符合100~200MHz的要求
    CLKDIVbits.PLLPOST=0b01;        // N2=4,此输出为160MHz/4=40MHz,符合12.5~80MHz的要求
    while(OSCCONbits.COSC!=0b011);    // 等待时钟稳定
    RCONbits.SWDTEN=0;                // 禁止WDT
    config_AD();
    config_TMR3();
    config_DMA0();
    config_DMA1();   
    config_U1UART();
    config_INT;
    while(1);
    {   
        Delay(10);
    }
}

//总中断设置
void config_INT(void)        
{    SRbits.IPL=4;        //CPU中断优先级=4
    CORCONbits.IPL3=0;    //CPU中断优先级<7
    INTCON1bits.NSTDIS=1;    //禁止嵌套中断
    INTCON2bits.ALTIVT=0;    //使用标准中断向量
}

//配置AD
void config_AD(void)
{    //引脚设置
    AD1CON1bits.ADON = 0;        
    AD1PCFGL=0xFFC3;                // AN2、AN3、AN4、AN5为模拟口
   
    //AD1CON1
    AD1CON1bits.ADSIDL=1;            // A/D模块休眠不工作
    AD1CON1bits.ADDMABM = 1;         // DMA按照ADC转换顺序来存放
    AD1CON1bits.AD12B = 1;             // 12-bitA/D
    AD1CON1bits.FORM = 0b00;         // 转换结果:整数
    AD1CON1bits.SSRC = 2;             // Timer3触发A/D
    AD1CON1bits.ASAM = 1;             // 转换结束后立即开始采样
    AD1CON1bits.SIMSAM = 0;         // 按顺序依次采样多个通道
   
    //AD1CON2
    AD1CON2bits.VCFG = 0b000;        // 参考电压为电源电压
    AD1CON2bits.CSCNA = 1;             // 扫描采样多路开关A的CH0+输入
    AD1CON2bits.CHPS = 0;             // 选择转换CH0
    AD1CON2bits.BUFM = 0;            // 总是从起始地址开始填充缓冲区
    AD1CON2bits.SMPI=0b0011;        // 完成4次采样
    AD1CON2bits.ALTS=0;                // 只用A开关
   
    //AD1CON3
    AD1CON3bits.ADRC = 0;             // ADC时钟由系统时钟产生
    AD1CON3bits.ADCS = 3;             // Tad=4Tcy=4*50=200ns

    //AD1CHS0:A/D 输入通道0选择寄存器
    AD1CHS0bits.CH0SA = 0;             // 通道0的同向输入为AN0
    AD1CHS0bits.CH0NA = 0;             // 通道0的反向输入为Vref-
   
    //AD1CHS123:A/D 输入通道1、2、3选择寄存器
    AD1CHS123bits.CH123SA = 0;         // CH1的同向输入为AN0,CH2的同向输入为AN1,CH3的同向输入为AN2,
    AD1CHS123bits.CH123NA = 0;         // CH1、CH2、CH3的反向输入为Vref-,

    //AD1CSSH/AD1CSSL:A/D 输入扫描选择寄存器
    AD1CSSL = 0x003C;                 // 扫描AN2, AN3, AN4, AN5
   
   
    AD1CON4bits.DMABL = 3;             // Each buffer contains 8 words
    IFS0bits.AD1IF = 0;                 // 清除A/D中断标志位
    IEC0bits.AD1IE = 0;                 // 不使能A/D中断
    AD1CON1bits.ADON = 1;             // 使能A/D模块
}

//配置TMR3
void config_TMR3(void)
{
    TMR3 = 0x0000;
    PR3 = 2499;                     // Trigger ADC1 every 125usec
    IFS0bits.T3IF = 0;                 // Clear Timer 3 interrupt
    IEC0bits.T3IE = 0;                 // Disable Timer 3 interrupt
    T3CONbits.TON = 1;                 // Start Timer 3
}   

//配置DMA0:把ADC结果自动放入DMA RAM
void config_DMA0(void)   
{
    DMA0REQbits.IRQSEL=13;                // ADC1触发DMA
    DMA0CONbits.SIZE=0;                //字模式
    DMA0CONbits.DIR=0;                //DMA方向为外设到RAM
    DMA0CONbits.HALF=0;                //整块传输,即结束后产生中断
    DMA0CONbits.AMODE = 0;            // 带后递增间接寻址模式
    DMA0CONbits.MODE  = 1;            // 禁止单数据块乒乓模式   
    DMA0STA=__builtin_dmaoffset(&AA);    //获得DMA0的寄存器起始地址
    DMA0PAD=(volatile unsigned int)&ADC1BUF0;//将ADC结果地址告诉DMA RAM的数组
    DMA0CNT=LL*4-1;                    // 每完成40次采样/转换操作产生中断
    IFS0bits.DMA0IF  = 0;            // 清除中断标志
    IEC0bits.DMA0IE  = 1;            // 允许DMA 中断
    IPC1bits.DMA0IP  = 6;            // DMA中断优先级为6
    DMA0CONbits.CHEN = 1;            // 使能 DMA0 通道
}   

//配置DMA1:把DMA0放在DMA RAM中的数据用UART1发送出去
void config_DMA1(void)   
{
    DMA1REQbits.IRQSEL=12;            //UART1发送,首次需手动发送一个数
    DMA1CONbits.SIZE=1;                //字节模式
    DMA1CONbits.DIR=1;                //DMA方向为RAM到外设
    DMA1CONbits.HALF=0;                //整块传输,即结束后产生中断
    DMA1CONbits.AMODE = 0b00;        // 带后递增间接寻址模式
    DMA1CONbits.MODE  = 0b01;        // 禁止乒乓模式    ,单次模式
    DMA1STA=DMA0STA;                //获得DMA0的寄存器起始地址
    DMA1PAD=(volatile unsigned int)&U1TXREG;
    DMA1CNT=LL*4-1;                    // 40次发送后中断
    DMA1CONbits.CHEN = 0;            // 先不使能 DMA0 通道
    _DMA1IE=1;
    _DMA1IP=6;
}

//配置UART
void config_U1UART(void)  //串口初始化
{    //U1MODE
    U1MODEbits.USIDL = 1;            //休眠关闭串口
    U1MODEbits.IREN = 0;            //IrDA编码器关闭
    U1MODEbits.RTSMD = 1;           // 引脚处于单工模式
    U1MODEbits.UEN = 0;                //使能U1TX,U1RX
    U1MODEbits.WAKE = 0;            //禁止启动位唤醒
    U1MODEbits.LPBACK = 0;            //禁止环回模式
    U1MODEbits.ABAUD = 0;            // 自动波特率禁止
    U1MODEbits.URXINV = 0;            //U1RX空闲状态是0
    U1MODEbits.BRGH = 0;            //标准模式
    U1MODEbits.PDSEL = 0;            // N , 8, 1
    U1MODEbits.STSEL = 0;           // 1个停止位

    //U1STA
    U1STAbits.UTXISEL1 = 0;         
    U1STAbits.UTXISEL0 = 0;        // 发送一个数据中断
    U1STAbits.UTXINV = 0;        //IrDA编码的UxTX空闲状态为0
    U1STAbits.UTXBRK = 0;        //禁止或已完成同步间隔字符的发送
    U1STAbits.URXISEL = 0b00;    //收到一个数即中断
    U1STAbits.ADDEN = 0;        //禁止地址检测模式                          
   
    U1BRG =129;                     // Fcy=20MHZ  N 8 1 波特率9600 = 129;

    IPC3bits.U1TXIP=6;             //TX中断优先级=6
    IEC0bits.U1TXIE = 1;        // 允许发送中断
   
    U1MODEbits.UARTEN = 1;        // 串口使能
    U1STAbits.UTXEN   = 1;        // 发送使能
}

//两次中断时间间隔为5ms(0.125*40=5ms),每个AD通道的数据个数为10个
void __attribute__((__interrupt__,no_auto_psv)) _DMA0Interrupt(void)
{
    IFS0bits.DMA0IF = 0;            // 清除中断标志
/*    unsigned char i;
    for(i=0;i<LL;i++)                //共40个数据
    {
        AN2=*P++;
        AN3=*P++;
        AN4=*P++;
        AN5=*P++;
    }*/
    U1TXREG=0;            //异步串行发送触发DMA第一次需手动发送一个数
    DMA1STA=DMA0STA;        //DMA1的DMA RAM首地址与DMA0的相同
    DMA1CONbits.CHEN=1;        //打开DMA1模块,传送次数完成后自动关闭模块
    DMA1REQbits.FORCE=1;        //手动触发DMA1模块
}

void Delay(unsigned int i)                  //延时程序
{
    unsigned int j;
    for(;i>0;i--)
    {
        Nop();
        for(j=0;j<255;j++)
        {
            Nop();
            ClrWdt();
        }
    }   
}


此帖出自小平头技术问答
友情提示: 此问题已得到解决,问题已经关闭,关闭后问题禁止继续编辑,回答。
该问题目前已经被作者或者管理员关闭, 无法添加新回复
1条回答
lene
1楼-- · 2019-03-25 21:14
有没有熟悉这系列单片机的啊,能帮帮忙吗

一周热门 更多>