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.

TMS320F28069 PWM中断问题

问题如下:

使用PWM1和PWM5各产生19.2KHz(52us)的中断(计数过零触发, 其他寄存器配置如下),并在中断中执行相关的算法。

当我在这两个中断中各对一个GPIO翻转来测试中断周期是否正确时,发现这两个中断的周期为一个随机变化的值(大约在50us~53us之间跳动),测试它们输出的PWM波是稳定的,duty改变符合要求。

我的程式中运行uCOS操作系统,当我把操作系统屏蔽,只跑中断程序时(main函数执行while),PWM中断周期又是稳定的52us。

我修改程式,只跑一个任务,任务不做任何事情,情况没有得到改善。

通过JTAG仿真,查看有OS和无OS时程序执行情况,观察PWM各个寄存器没有差异。

我又测试了两个中断中算法最长路径执行的时间:PWM1为11us左右,PWM5为12us左右, OS任务调度时间为5us左右,总共11+12+5=28us<52us, 中断时间有较大余量。

 以上是我遇到的问题描述和处理过程,目前还没有头绪,请问大家之前是否遇到类似情况?非常感谢!

PWM配置如下(PWM1和PWM5中断使能,其他组PWM配置一致,但不使能中断):

//    EPwm1Regs.TBPRD = 2083;                //Set timer period: 80MHz*20.83us@19.2K

//    EPwm1Regs.TBPHS.half.TBPHS = 0x00;               //相位偏移0us

//    EPwm1Regs.TBCTR = 0x00;                          //PWM计数器清零

//    EPwm1Regs.TBCTL.bit.CTRMODE = TB_COUNT_UPDOWN;   //计数模式:上升+下降

//    EPwm1Regs.TBCTL.bit.PHSEN = TB_DISABLE;          //禁止相位偏移加载控制

//    EPwm1Regs.TBCTL.bit.PHSDIR = TB_UP;              //同步后向上计数

//    EPwm1Regs.TBCTL.bit.PRDLD = TB_SHADOW;           //周期值在过零时从缓冲区加载

//    EPwm1Regs.TBCTL.bit.SYNCOSEL = TB_SYNC_DISABLE;       //不输出同步信号

//    EPwm1Regs.TBCTL.bit.HSPCLKDIV = TB_DIV1;         //计数时钟=系统时钟

//    EPwm1Regs.TBCTL.bit.CLKDIV = TB_DIV1;            //计数时钟=系统时钟

//    EPwm1Regs.CMPCTL.bit.SHDWAMODE = CC_SHADOW;      //双缓冲模式

//    EPwm1Regs.CMPCTL.bit.SHDWBMODE = CC_SHADOW;      //双缓冲模式

//    EPwm1Regs.CMPCTL.bit.LOADAMODE = CC_CTR_PRD;     //周期值时加载比较值

//    EPwm1Regs.CMPCTL.bit.LOADBMODE = CC_CTR_PRD;     //周期值时加载比较值

//    EPwm1Regs.CMPA.half.CMPA = 1;                    //duty setting

//    EPwm1Regs.CMPB = 1;                              //比较值B清零

//    EPwm1Regs.AQCTLA.bit.CAU = AQ_CLEAR;             //向上计数比较匹配清零

//    EPwm1Regs.AQCTLA.bit.CAD = AQ_SET;               //向下计数比较配置置位

//    EPwm1Regs.AQCTLB.bit.CBU = AQ_CLEAR;             //向上计数比较匹配清零

//    EPwm1Regs.AQCTLB.bit.CBD = AQ_SET;               //向下计数比较配置置位

//    EPwm1Regs.AQCSFRC.all |= 0x0005;                 //禁止PWM输出

//    EPwm1Regs.DBCTL.bit.OUT_MODE = DB_DISABLE;       //PWM输出模式0:两路独立输出,disable deadtime

//    EPwm1Regs.ETSEL.bit.INTSEL = ET_CTR_ZERO;        //Enable event TBCTR = 0

//    EPwm1Regs.ETSEL.bit.INTEN = 1;                       //Enable EPWM1 INT generation

//    EPwm1Regs.ETPS.bit.INTPRD = ET_1ST;                //1 event

  • Jacky

           你有没有在PWM配置前加入时钟同步代码,然后在PWM配置后打开时钟使能。

    //---------------------------------------------------------------------
    //--- Must disable the clock to the ePWM modules if you      
    //--- want all ePMW modules synchronized.
    //---------------------------------------------------------------------
     asm(" EALLOW");      // Enable EALLOW protected register access
     SysCtrlRegs.PCLKCR0.bit.TBCLKSYNC = 0;
     asm(" EDIS");      // Disable EALLOW protected register access

    ……

    //---------------------------------------------------------------------
    //--- Enable the clocks to the ePWM module.                  
    //--- Note: this should be done after all ePWM modules are configured
    //--- to ensure synchronization between the ePWM modules.
    //---------------------------------------------------------------------
     asm(" EALLOW");       // Enable EALLOW protected register access
     SysCtrlRegs.PCLKCR0.bit.TBCLKSYNC = 1; // TBCLK to ePWM modules enabled
     asm(" EDIS");       // Disable EALLOW protected register access

             首先注意一下,由于PWM1和PWM5代码几乎相同,但是PWM1和PWM5的中断优先级是不一样的,PWM1优先级高于PWM5,如果两个中断同时到来,那么CPU会先响应PWM1。

           其次,你的操作代码是否有影响中断的相关代码,比如如果CPU要响应中断,需要保存一些数据。因为你描述把操作系统删除掉后,就不会影响中断周期,所以初步可以认为是操作系统影响了每次进入中断服务程序的时间。我建议你仔细检查这一点,或是上网查一下uCOS中断处理的资料。

    Eric

  • 1、  关于第1点,PWM配置的时钟同步,我是按照“0—>PWM配置代码—>1”的方式写的,和您说的一致。

    2、  关于第2点,PWM1和PWM5的中断同时发生在我的程序中是允许的,因为两个中断服务程序执行的时间加起来小于52us(中断周期为52us),不会影响第2次中断的正常触发。 之前之前也怀疑是这个原因,然后尝试只使用PWM5一个PWM中断也还是有这样的问题。

    3、  关于操作系统部分,使用的是timer2作为OS节拍,下面是任务堆栈保存的寄存器值,不知道有没有少了什么?  这部分似乎跟2809差异不大, 这个程序在2809上面跑没有这样的问题。

    4、  在同样的程序,使用timer0和timer1定时的周期很准。

     

    之前怀疑是PWM之间的同步引起的。如使能PWM1计数为0时发出同步信号,其他的PWM计数可以强制归0。后来我把同步的机制禁止了,没有改善。

     

     

    OS_STK *OSTaskStkInit(void (*task)(void), OS_STK *ptos)

    {

        OS_STK *stk;

        stk = ptos;                //Load stack pointer

        *stk++= (INTOS)0x0000;     //ST0=0

        *stk++= (INTOS)0x0000;     //T=0

        *stk++= (INTOS)0x0000;     //AL=0

        *stk++= (INTOS)0x0000;     //AH=0

        *stk++= (INTOS)0x0000;     //PL=0

        *stk++= (INTOS)0x0000;     //PH=0

        *stk++= (INTOS)0x0000;     //AR0=0

        *stk++= (INTOS)0x0000;     //AR1=0

        *stk++= (INTOS)0x0A0B;     //ST1=0 Interrupts are enabled

        *stk++= (INTOS)0x0000;     //DP=0

        *stk++= (INTOS)0x21AD;     //IER

        *stk++= (INTOS)0x0000;     //DBGSTAT=0

        *stk++= (INTOS)((uint32_t)task & 0x0000FFFF); //PC:L H

        *stk++= (INTOS)((uint32_t)task >> 16);

        *stk++= (INTOS)0x0A0B;     //ST1=0 Interrupts are enabled

        *stk++= (INTOS)0x0000;     //DP=0

        *stk++= (INTOS)0x0000;     //RPC

        *stk++= (INTOS)0x0000;

        *stk++= (INTOS)0x0000;     //XT

        *stk++= (INTOS)0x0000;

        *stk++= (INTOS)0x0000;     //XAR7

        *stk++= (INTOS)0x0000;

        *stk++= (INTOS)0x0000;     //XAR6

        *stk++= (INTOS)0x0000;

        *stk++= (INTOS)0x0000;     //XAR5

        *stk++= (INTOS)0x0000;

        *stk++= (INTOS)0x0000;     //XAR4

        *stk++= (INTOS)0x0000;

        *stk++= (INTOS)0x0000;     //XAR3

        *stk++= (INTOS)0x0000;

        *stk++= (INTOS)0x0000;     //XAR2

        *stk++= (INTOS)0x0000;

        *stk++= (INTOS)0x0000;     //AR1H:AR0H

        *stk++= (INTOS)0x0000;

        stk++;

        return(stk);

    }

  • Jacky,

            在OS的timer2你是使用什么方式来作为节拍呢,OS底层是否有中断影响PWM进入中断的时间?

    Eric

  • 使用TIMER2定时1ms作为OS时钟节拍。

    OS底层使用了一个软件中断(USER11_ISR),实现任务切换。 在OS系统中我只使用了TIMER事件,而TIMER的时间周期为OS时钟节拍(1ms),相对PWM的52us中断影响应该可以忽略的了。

  • Jacky,

               我认为底层的这个中断对ePWM中断是有影响的, 你说TIMER的是时钟周期是1ms,多个ePWM后才有一次os节拍,那如果刚好PWM中断来的时候,os在执行软件中断,这个时候就会导致ePWM中断响应延迟。你可以将软件中断屏蔽一下测试。然后将os节拍设得更长,观察一个节拍内的ePWM中断周期。

    Eric

  • 谢谢~

    这个测试过了,没有改善。

    如问题所述,ePWM周期时间差异是发生在每个周期(相差1~2us),而不是1ms才来一次哦。