This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

TMS320F28335: 大佬们,为啥我这个始终进入不到ADC中断里?(功能为EPWM触发ADC采样)

Part Number: TMS320F28335


//main函数
#include "DSP2833x_Device.h"     // DSP2833x Headerfile Include File
#include "DSP2833x_Examples.h"   // DSP2833x Examples Include File
#include "epwm.h"
#include "adc.h"

void EPWM_init();
void EPWM_Configure(void);
void ADC_Configure();

__interrupt void adc_isr(void);
__interrupt void timer1_isr(void);

//Uint16 LoopCount;

void main()
{
    //步骤1。初始化系统控制:锁相锁、看门狗、使能外围时钟此功能在DSP2833x_SysCtrl.c文件中找到。
    InitSysCtrl();

//    EALLOW;
//    #if (CPU_FRQ_150MHZ)  //默认- 150MHz SYSCLKOUT
//        // HSPCLK = SYSCLKOUT/2*ADC_MODCLK2 = 150/(2*3)   = 25.0 MHz
//        #define ADC_MODCLK 0x3 //将ADC的工作频率设置为25MHz,等同于上一条语句
//    #endif
//    #if (CPU_FRQ_100MHZ)
//        // HSPCLK = SYSCLKOUT/2*ADC_MODCLK2 = 100/(2*2)   = 25.0 MHz
//        #define ADC_MODCLK 0x2
//    #endif
//    EDIS;

    // 定义ADCCLK时钟频率(小于或等于25MHz)
    // 假设InitSysCtrl()将SYSCLKOUT设置为150 MHz
//    EALLOW;
//    SysCtrlRegs.HISPCP.all = ADC_MODCLK;
//    EDIS;

    //步骤2。初始化GPIO:
    InitGpio();

    //步骤3。清除所有中断并初始化PIE向量表:禁用CPU中断
    DINT;

    //将PIE控制寄存器初始化为其默认状态。默认状态是禁用所有PIE中断并清除标志。
    InitPieCtrl();

    //禁用CPU中断并清除所有CPU中断标志:
    IER = 0x0000;
    IFR = 0x0000;

    //用指向shell中断服务例程(ISR)的指针初始化PIE向量表。
    InitPieVectTable();

    //本例中使用的中断被重新映射到该文件中的ISR函数。
    EALLOW;  // 写保护
    PieVectTable.ADCINT = &adc_isr;    //设置ADCINT中断服务程序的入口地址为adc_isr
    PieVectTable.EPWM1_INT = &timer1_isr;   //设置EPWM1_INT中断服务程序的入口地址为timer1_isr
    EDIS;    // 禁用写保护

    //步骤4。初始化所有设备外设:

    InitAdc();   //Adc初始化
    EPWM_init(); //EPWM初始化

    //第5步。自定义,启用中断:
    //在PIE中启用SEQ1INT
    PieCtrlRegs.PIEIER1.bit.INTx1 = 1;   //中断向量表第1列
    IER |= M_INT1;      // 开启CPU中断1,第一行
    //在PIE中启用EPWM1_INT
    IER|=M_INT3;                         //使能CPU中断3(中断向量表第三行)
    PieCtrlRegs.PIEIER3.bit.INTx1 = 1;   //EPWM1中断(中断向量表第1位,即第一列)
    EINT;               // 启用全局中断INTM
    ERTM;               // 启用全局实时中断DBGM

//    LoopCount = 0;

//    //ADC配置
//    AdcRegs.ADCMAXCONV.all = 0x0001;       // 在SEQ1上设置2个转换器
//    AdcRegs.ADCCHSELSEQ1.bit.CONV00 = 0x3; // 设置ADCINA3为第一个SEQ1转换。
//    AdcRegs.ADCCHSELSEQ1.bit.CONV01 = 0x2; // 设置ADCINA2为第二个SEQ1转换器。
//
//    //启用SOCA从ePWM启动SEQ1
//    AdcRegs.ADCTRL2.bit.EPWM_SOCA_SEQ1 = 1;
//    AdcRegs.ADCTRL2.bit.INT_ENA_SEQ1 = 1;  // 使能SEQ1中断(每个EOS)

    //假设在InitSysCtrl()中已经启用了ePWM1时钟。
//    EPwm1Regs.ETSEL.bit.SOCAEN = 1;     // 使能ADC启动脉冲EPWMxSOCA
//    EPwm1Regs.ETSEL.bit.SOCASEL = 4;    // TBCTR=CMPA且计数器处于递增状态时产生
//    EPwm1Regs.ETPS.bit.SOCAPRD = 1;     // 每发生一次事件,产生一次ADC信号
//    EPwm1Regs.CMPA.half.CMPA = 0x0080;  // 设置比较值A
//    EPwm1Regs.TBPRD = 0xFFFF;           // 设置ePWM1的周期
//    EPwm1Regs.TBCTL.bit.CTRMODE = 0;    // count up and start

    EPWM_Configure();
    ADC_Configure();
    // 等待ADC中断
    for(;;)
    {
    }
}



////ADC
//ADC相关参数
#define ADC_MODCLK 0x3           //HSPCLK = SYSCLKOUT/2 * ADC_MODCLK2 = 150/(2 * 3) = 25MHz
#define ADC_CKPS 0x0             //ADC时钟 = HSPCLK/1 = 25.5MHz/(1) = 25.0MHz
#define ADC_SHCLK 0x1            //采样保持器宽度 = 2ADC时钟周期
#define BUF_SIZE 16              //缓存大小
#define OFFSET 0

float SampleTable[BUF_SIZE];     //保存采样结果

void ADC_Configure()
{
    Uint16 i;

    EALLOW;
    SysCtrlRegs.HISPCP.all = ADC_MODCLK;
    ADC_cal();//调用 ADC_cal 汇编程序,它是 TI 提供的 ADC 校准程序,直接使用即可
    EDIS;

    AdcRegs.ADCTRL1.bit.ACQ_PS = ADC_SHCLK;        //设置采集窗口大小;这个位场控制Soc脉冲的宽度,这反过来决定了采样开关关闭的持续时间。SOC脉冲的宽度为(ACQ_PS + 1)ADCLK周期。
    AdcRegs.ADCTRL3.bit.ADCCLKPS = ADC_CKPS;       //ADC时钟分频器;对F28x外设时钟 HSPCLK进行2×ADCLKPS[3:0]的分额,分频后的时钟再进行ADCTRL1[7]+1分频从而产生ADC的内核时钟ADCCLK
    AdcRegs.ADCTRL1.bit.SEQ_CASC = 1;              //级联方式
    AdcRegs.ADCTRL3.bit.SMODE_SEL = 0;             //顺序采样
    AdcRegs.ADCCHSELSEQ1.bit.CONV00 = 0x0;         //对ADC序列发生器进行赋值,就是设定ADC采样通道的采样顺序(例:第一次采样D0通道)
    AdcRegs.ADCCHSELSEQ1.bit.CONV01 = 0x1;         //例:第二次采样D1通道
    AdcRegs.ADCCHSELSEQ1.bit.CONV02 = 0x2;
    AdcRegs.ADCCHSELSEQ1.bit.CONV03 = 0x3;
    AdcRegs.ADCCHSELSEQ2.bit.CONV04 = 0x4;
    AdcRegs.ADCCHSELSEQ2.bit.CONV05 = 0x5;
    AdcRegs.ADCCHSELSEQ2.bit.CONV06 = 0x6;
    AdcRegs.ADCCHSELSEQ2.bit.CONV07 = 0x7;
    AdcRegs.ADCCHSELSEQ3.bit.CONV08 = 0x8;
    AdcRegs.ADCCHSELSEQ3.bit.CONV09 = 0x9;
    AdcRegs.ADCCHSELSEQ3.bit.CONV10 = 0xA;
    AdcRegs.ADCCHSELSEQ3.bit.CONV11 = 0xB;
    AdcRegs.ADCCHSELSEQ4.bit.CONV12 = 0xC;
    AdcRegs.ADCCHSELSEQ4.bit.CONV13 = 0XD;
    AdcRegs.ADCCHSELSEQ4.bit.CONV14 = 0xE;
    AdcRegs.ADCCHSELSEQ4.bit.CONV15 = 0xF;

    AdcRegs.ADCTRL1.bit.CONT_RUN = 1;              //连续转换模式
    AdcRegs.ADCTRL1.bit.SEQ_OVRD = 1;
    AdcRegs.ADCMAXCONV.bit.MAX_CONV1 = 0xF;        //设置最大采样通道数,上面是16个通道,所以设置为F(若是一个通道则赋值0,两个通道则赋值1)
    DINT;

    for(i=0;i<BUF_SIZE;i++)
    {
        SampleTable[i] = 0;
    }

    //启用SOCA从ePWM启动SEQ1
    AdcRegs.ADCTRL2.bit.EPWM_SOCA_SEQ1 = 1;
    AdcRegs.ADCTRL2.bit.INT_ENA_SEQ1 = 1;  // 使能SEQ1中断(每个EOS)
}

// Adc中断
__interrupt void adc_isr(void)
{
    Uint16 array_index = 0;
    Uint16 j;
    for(j=0;j<(BUF_SIZE/16);j++)
    {
        while(AdcRegs.ADCST.bit.INT_SEQ1 == 0){}         //等待,直到转换完成,然后读取结果

        LED1_ON;

        SampleTable[array_index++] = ((AdcRegs.ADCRESULT0)>>4)*3.0/4095.0 - OFFSET;   //OFFSET为偏置,通常为0
        SampleTable[array_index++] = ((AdcRegs.ADCRESULT1)>>4)*3.0/4095.0 - OFFSET;
        SampleTable[array_index++] = ((AdcRegs.ADCRESULT2)>>4)*3.0/4095.0 - OFFSET;
        SampleTable[array_index++] = ((AdcRegs.ADCRESULT3)>>4)*3.0/4095.0 - OFFSET;
        SampleTable[array_index++] = ((AdcRegs.ADCRESULT4)>>4)*3.0/4095.0 - OFFSET;
        SampleTable[array_index++] = ((AdcRegs.ADCRESULT5)>>4)*3.0/4095.0 - OFFSET;
        SampleTable[array_index++] = ((AdcRegs.ADCRESULT6)>>4)*3.0/4095.0 - OFFSET;
        SampleTable[array_index++] = ((AdcRegs.ADCRESULT7)>>4)*3.0/4095.0 - OFFSET;
        SampleTable[array_index++] = ((AdcRegs.ADCRESULT8)>>4)*3.0/4095.0 - OFFSET;
        SampleTable[array_index++] = ((AdcRegs.ADCRESULT9)>>4)*3.0/4095.0 - OFFSET;
        SampleTable[array_index++] = ((AdcRegs.ADCRESULT10)>>4)*3.0/4095.0 - OFFSET;
        SampleTable[array_index++] = ((AdcRegs.ADCRESULT11)>>4)*3.0/4095.0 - OFFSET;
        SampleTable[array_index++] = ((AdcRegs.ADCRESULT12)>>4)*3.0/4095.0 - OFFSET;
        SampleTable[array_index++] = ((AdcRegs.ADCRESULT13)>>4)*3.0/4095.0 - OFFSET;
        SampleTable[array_index++] = ((AdcRegs.ADCRESULT14)>>4)*3.0/4095.0 - OFFSET;
        SampleTable[array_index++] = ((AdcRegs.ADCRESULT15)>>4)*3.0/4095.0 - OFFSET;

        LED1_OFF;

        // 为下一个ADC序列重新初始化
        AdcRegs.ADCTRL2.bit.RST_SEQ1 = 1;         // 重置SEQ1
        AdcRegs.ADCST.bit.INT_SEQ1_CLR = 1;       //清除标志位
        PieCtrlRegs.PIEACK.all = PIEACK_GROUP1;   // 向PIE确认中断

        return;
    }
}



////EPWM
unsigned int i;

void EPWM_init()
{
    EALLOW;

    GpioCtrlRegs.GPAMUX1.bit.GPIO0 = 1;    //GPIO0 = PWM1A
    GpioCtrlRegs.GPAMUX1.bit.GPIO1 = 1;    //GPIO1 = PWM1B
    EDIS;

    //PWM1A.PWM1B
    EPwm1Regs.TBPRD = 0xFFFF;              //设置EPWM1周期寄存器
    EPwm1Regs.TBPHS.half.TBPHS = 0x0000;   //相位为0
    EPwm1Regs.TBCTR = 0x0000;              //清除计数器

    //设置比较寄存器
    EPwm1Regs.CMPA.half.CMPA = 0xFFFF;     //设置比较寄存器A
    EPwm1Regs.CMPB = 0xFFFF;               //设置比较寄存器B

    //设置计数模式
    EPwm1Regs.TBCTL.bit.CTRMODE = 2;       //增减计数模式
    EPwm1Regs.TBCTL.bit.PHSEN = 0;         //禁止相位功能
    EPwm1Regs.TBCTL.bit.PRDLD = 0;         //使用映射功能
    EPwm1Regs.TBCTL.bit.SYNCOSEL = 1;      //选择同步信号为CTR=0;
    EPwm1Regs.TBCTL.bit.HSPCLKDIV = 1;     //TBCLK = SYSCLKOUT/2 = 75MHz
    EPwm1Regs.TBCTL.bit.HSPCLKDIV = 0;

    //设置映射模式
    EPwm1Regs.CMPCTL.bit.SHDWAMODE = 0;    //CMPA采用映射模式
    EPwm1Regs.CMPCTL.bit.SHDWBMODE = 0;    //CMPB采用映射模式
    EPwm1Regs.CMPCTL.bit.LOADAMODE = 0;    //CTR=0时加载CMPA
    EPwm1Regs.CMPCTL.bit.LOADBMODE = 0;    //CTR=0时加载CMPB

    //设置死区模式
    EPwm1Regs.DBCTL.bit.OUT_MODE = 0x3;    //使能上升沿和下降沿延时
    EPwm1Regs.DBCTL.bit.POLSEL = 0x2;      //ePWMxA不翻转,ePWMxB翻转
    EPwm1Regs.DBCTL.bit.IN_MODE = 0x2;     //ePWMxA是上升沿延时输入源,ePWMxB是下降沿延时输入源

    //设置EPWM中断
//    EPwm1Regs.ETSEL.bit.INTSEL = 1;        //中断事件 TBCTR=0x0000
//    EPwm1Regs.ETSEL.bit.INTEN = 1;         //使能EPWM1中断
//    EPwm1Regs.ETPS.bit.INTPRD = 1;         //开关频率10KHz,对应中断频率10KHz
//    EPwm1Regs.ETCLR.bit.INT = 1;           //清除中断标志
    EPwm1Regs.ETSEL.bit.SOCAEN = 1;     // 使能ADC启动脉冲EPWMxSOCA
    EPwm1Regs.ETSEL.bit.SOCASEL = 4;    // TBCTR=CMPA且计数器处于递增状态时产生
    EPwm1Regs.ETPS.bit.SOCAPRD = 1;     // 每发生一次事件,产生一次ADC信号

    //设置引脚动作
    //当CTR=CMPA并减计数时,EPWMA输出低电平;当CTR=CMPA且增计数时,EPWMA输出高电平
    EPwm1Regs.AQCTLA.all = 0x0060;
    //当CTR=CMPB并减计数时,EPWMB输出低电平;当CTR=CMPA且增计数时,EPWMB输出高电平
    EPwm1Regs.AQCTLB.all = 0x0060;
}

void EPWM_Configure(void)                  //EPWM配置
{
    EALLOW;

    EPwm1Regs.TBPRD = 37500;                //频率为10KHz
    EPwm1Regs.TBPHS.half.TBPHS = 0x0000;
    EPwm1Regs.DBRED = 75 * 0.6;              //上升沿死区为300ns  每增加0.1,死区增加50ns
    EPwm1Regs.DBFED = 75 * 0.6;              //下降沿死区为300ns
    EPwm1Regs.CMPA.half.CMPA = EPwm1Regs.TBPRD * 0.5;    //占空比为50%
    EDIS;
}

__interrupt void timer1_isr(void)            //周期为0.1ms
{
    i++;
    if(i > 10000)i = 0;                    //1s
    EPwm1Regs.ETCLR.bit.INT = 1;           //清除中断标志位
    PieCtrlRegs.PIEACK.all = PIEACK_GROUP3;//相应同组中断
}