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.

TMS320F28027: 为什么ADC_ISR里面几乎不能写代码?它是由每个PWM触发的,稍微写一点代码,它就不是一对一的触发了。

Part Number: TMS320F28027
Other Parts Discussed in Thread: C2000WARE

adc_isr1中,正常PWM和ADC一比一触发时,这个变量应该维持住0或1。但只要放开注释的那几行,PWM1_Cnt就会一直往上涨。ADC中断的触发次数会变的很少。

int32 PWM1_Cnt=0;
__interrupt void epwm1_isr(void)
{
++PWM1_Cnt;
EPwm1Regs.ETCLR.bit.INT = 1; // Clear INT flag for this timer
PieCtrlRegs.PIEACK.all = PIEACK_GROUP3; // Acknowledge this interrupt to receive more interrupts from group 3
}


__interrupt void adc_isr1(void)
{
Uint32 power;
Uint32 r1,r2,r3;

--PWM1_Cnt;

/*

for (r1=0; r1<10; ++r1)
asm(" nop");

r1 = AdcResult.ADCRESULT1;

u  = r1*1048576; //

r1 = r1<<20;

*/

AdcRegs.ADCINTFLGCLR.bit.ADCINT1 = 1; //Clear ADCINT1 flag reinitialize for next SOC
PieCtrlRegs.PIEACK.all = PIEACK_GROUP1; // Acknowledge interrupt to PIE
return;
}

  • //PWM频率设置的100K, 60MHZ CPU

    void EnableEpwm1()
    {
    EPwm1Regs.TBPHS.half.TBPHS = 0x0000; // Phase is 0

    //初始化计数模式
    EPwm1Regs.TBCTL.bit.CTRMODE = TB_COUNT_UP; // Count up
    EPwm1Regs.TBCTL.bit.PHSEN = TB_DISABLE; // Disable phase loading
    EPwm1Regs.TBCTL.bit.HSPCLKDIV = TB_DIV1; // Clock ratio to SYSCLKOUT
    EPwm1Regs.TBCTL.bit.CLKDIV = TB_DIV1;

    // Setup shadowing
    EPwm1Regs.CMPCTL.bit.SHDWAMODE = CC_SHADOW;
    EPwm1Regs.CMPCTL.bit.SHDWBMODE = CC_SHADOW;
    EPwm1Regs.CMPCTL.bit.LOADAMODE = CC_CTR_ZERO; // Load on Zero
    EPwm1Regs.CMPCTL.bit.LOADBMODE = CC_CTR_ZERO;

    EPwm1Regs.AQCTLA.all = 0;
    EPwm1Regs.AQCTLB.all = 0;

    EPwm1Regs.AQCTLA.bit.ZRO = AQ_CLEAR;
    EPwm1Regs.AQCTLA.bit.PRD = AQ_CLEAR;
    EPwm1Regs.AQCTLA.bit.CAU = AQ_SET;
    EPwm1Regs.AQCTLA.bit.CBU = AQ_CLEAR;

    EPwm1Regs.AQCTLB.bit.ZRO = AQ_SET;
    EPwm1Regs.AQCTLB.bit.PRD = AQ_SET;
    EPwm1Regs.AQCTLB.bit.CAU = AQ_CLEAR;
    EPwm1Regs.AQCTLB.bit.CBU = AQ_SET;

    //Dead band---------------------------------------------------------------------------------//计600次为10us
    EPwm1Regs.DBCTL.bit.IN_MODE = DBA_ALL;//00:ePWMxA是双边沿延时输入源;01:B是上升输入源,A是下降源;10:A是上源,B是下源;11:B是双边源
    EPwm1Regs.DBCTL.bit.OUT_MODE = DBA_ENABLE;//00:A,B不经过死区模块;01:禁止上升沿延迟,使能下降沿延迟;10:禁止下降延迟,使能上升;11:使能双边延迟
    EPwm1Regs.DBCTL.bit.POLSEL = DB_ACTV_HIC;
    EPwm1Regs.DBCTL.bit.HALFCYCLE = 0; //0:Full cycle clocking enabled. 1:Half cycle clocking enabled

    EPwm1Regs.DBRED = 60; //Dead band Rising Edge Delay(DBRED) 600为10us一周期
    EPwm1Regs.DBFED = 0;//Dead band Fall edge delay
    //------------------------------------------------------------------------------------------------

    //占空比
    EPwm1Regs.TBPRD = 600;
    EPwm1Regs.CMPA.half.CMPA = 0;
    EPwm1Regs.CMPB = 0;
    EPwm1Regs.TBCTR = 0x0000; // Clear counter
    //------------------------------------------------------------------------------------------------

    //与pwm关联的ADC设置 BSP,要跟随硬件改动--------------------------------------------------------------------
    //触发ADC设置
    EALLOW;
    AdcRegs.ADCCTL1.bit.INTPULSEPOS = 1; //INT发生的位置:1:结果锁存好后再触发 0:更早的时间,查看时序图
    AdcRegs.INTSEL1N2.bit.INT1CONT = 0; //Disable ADCINT1 Continuous mode
    AdcRegs.INTSEL1N2.bit.INT1E = 1; //Enabled ADCINT1,有ADCINTxNy 从1N2一直到9N10,10个中断资源
    AdcRegs.INTSEL1N2.bit.INT1SEL = 2; //2结束时触发中断,05h:设置EOC5作为触发器触发ADCINTx,x由bit.INTxSEL决定
    //AdcRegs.INTSEL1N2.bit.INT1SEL = 3; //3结束时触发中断

    // 中断资源号x
    AdcRegs.ADCSOC1CTL.bit.CHSEL = 0; //A0 0~7h:A0~A7, 8h~Fh B0~B7
    AdcRegs.ADCSOC2CTL.bit.CHSEL = 1; //选择ADCINA1
    AdcRegs.ADCSOC3CTL.bit.CHSEL = 2; //选择ADCINA2

    AdcRegs.ADCSOC1CTL.bit.TRIGSEL = 5; //00 software触发,01~03O为定时器触发,04:XINT2触发,05~12h(5~18)为EPWM1 SOCA(5),SOCBB(6)~EPWM7 SOCA(11h),SOCB(12h)触发。
    AdcRegs.ADCSOC2CTL.bit.TRIGSEL = 5; //由PWM触发ADC A,B转换
    AdcRegs.ADCSOC3CTL.bit.TRIGSEL = 5; //EPWM1 SOCA

    AdcRegs.ADCSOC1CTL.bit.ACQPS = 6;
    AdcRegs.ADCSOC2CTL.bit.ACQPS = 6;
    AdcRegs.ADCSOC3CTL.bit.ACQPS = 6;
    EDIS;

    //ETSEL寄存器中与ADC有关的Bit位
    EPwm1Regs.ETSEL.bit.SOCAEN = 1; // 1:Enable EPWMxSOCA pulse; 0:Disable;
    EPwm1Regs.ETSEL.bit.SOCASEL = 2; // Select SOC from TBCTR=TBPRD,即一个PWM周期结束时开始ADC转换
    EPwm1Regs.ETPS.bit.SOCAPRD = 1; // Generate pulse on 1st event
    //SOCB CLOSE ADCB1 暂时关闭温度采集
    EPwm1Regs.ETSEL.bit.SOCBEN = 1; // 1:Enable EPWMxSOCA pulse; 0:Disable;
    EPwm1Regs.ETSEL.bit.SOCBSEL = 2; // Select SOC from TBCTR=TBPRD,即一个PWM周期结束时开始ADC转换
    EPwm1Regs.ETPS.bit.SOCBPRD = 1; // Generate pulse on 1st event

    //----------------------------------------------------------------------------------------------

    EPwm1Regs.ETSEL.bit.INTSEL = ET_CTR_PRD; // Select INT on Zero event
    EPwm1Regs.ETSEL.bit.INTEN = 1; // Enable INT
    EPwm1Regs.ETPS.bit.INTPRD = ET_1ST;
    }

  • PWM中断里,几乎也不能写什么代码,一写几行,PWM_Cnt就朝着负方向跑了。明显的进入次数不够。

    int32 PWM1_Cnt=0;
    Uint32 r1,r2,r3;
    __interrupt void epwm1_isr(void)
    {
    ++PWM1_Cnt;

    r1 = _IQ21mpy(_IQ21(r1), _IQ21(3300));
    r1 = _IQ21div(r1, _IQ21(4095));
    r1 = _IQ21div(r1, _IQ21(0.06976744));
    r1 = r1>>21;

    EPwm1Regs.ETCLR.bit.INT = 1; // Clear INT flag for this timer
    PieCtrlRegs.PIEACK.all = PIEACK_GROUP3; // Acknowledge this interrupt to receive more interrupts from group 3
    }

  • 我发现它和CMD有关系,用RAM那个就可以,用FLASH就不行,这该怎么办呢

  • 还好你最后一个回复说明了一下这个情况,那问题就很明确了,是因为程序在ram中运行和在flash中运行的速率不同导致的。

    一般PWM中断,delay_us函数等都要求下载到flash之后,在运行的时候将这部分代码搬移到ram中运行,否则就会出现问题。memcpy函数就是用于程序搬移的,你可以看一下这个路径的例程,选择flash编译之后就会启用这部分代码:

    #ifdef _FLASH
        memcpy(&RamfuncsRunStart, &RamfuncsLoadStart, (size_t)&RamfuncsLoadSize);
    #endif

    C:\ti\c2000\C2000Ware_3_04_00_00\device_support\f2802x\examples\drivers\epwm_up_aq

  • 现在跑普通的代码算是差不多可以了,但函数里如果有下面这样的代码,执行次数还是不一致,比如:

    if (PWM1_Cnt2++ % 100000 == 0)

    x=(float)r1 / 4095 * 3.3 /0.073156;

    这种代码运行还是有点慢,不知道还有没有办法加快一点?运行时这些代码转成了大量的汇编,也不知道这些汇编是跑在RAM还是FLASH上面了?

  • 这部分代码是在中断中的?如果是的话,你把整个中断都搬移到ram了,那这部分也是跑在ram的。或者你可以对比一下ram运行和flash运行的时间差多少。

    另外我看你的程序中用了很多除法计算,C2000芯片的话计算加减乘的速度很快,但是除法会慢很多。可以考虑把除法做成乘法来处理。

  • 有除法的地方的确慢很多。我已经感受到了。通过变量的++或--。28027这版,对于常数型 的除数,我先算好除数的倒数,再相乘。

    前些时间为了浮点计算,用IQ函数把代码改的有点乱,这几天准备更换CPU为280021,这个有FPU,运行除法应该要快不少吧?

    但我IQ遇到一些问题:e2echina.ti.com/.../tms320f28027-iqmath

  • FPU的话对浮点运算是有加速,但除法的话整体上还是会比加减乘慢很多。

    那接下来我们在新帖子中讨论