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.

电机控制例程F280XILEG_VDC.C中的疑问?麻烦解答,谢谢!



您好,F280XILEG_VDC.C中有几处不明白的,望您解答!下面是TI例程:

void F280X_ileg2_dcbus_drv_init(ILEG2DCBUSMEAS *p)
{
    DELAY_US(ADC_usDELAY); 
 
    AdcRegs.ADCTRL1.all = ADC_RESET_FLAG;   // Reset the ADC Module
 asm(" NOP ");
 asm(" NOP ");   

    AdcRegs.ADCTRL3.bit.ADCBGRFDN = 0x3;  // Power up bandgap/reference circuitry
 DELAY_US(ADC_usDELAY);         // Delay before powering up rest of ADC
   
    AdcRegs.ADCTRL3.bit.ADCPWDN = 1;      // Power up rest of ADC
 DELAY_US(ADC_usDELAY); 

    AdcRegs.ADCTRL3.bit.ADCCLKPS = 16;       // Set up ADCTRL3 register
    AdcRegs.ADCTRL1.all = ADCTRL1_INIT_STATE; // Set up ADCTRL1 register
    AdcRegs.ADCTRL2.all = ADCTRL2_INIT_STATE;  // Set up ADCTRL2 register
 AdcRegs.ADCMAXCONV.bit.MAX_CONV1 = 2;       // Specify three conversions
    AdcRegs.ADCCHSELSEQ1.all = p->ChSelect;     // Configure channel selection

    AdcRegs.ADCREFSEL.all = 39;                 // Set up the ADC reference select register
    AdcRegs.ADCOFFTRIM.all = 65534;             // Set up the ADC offset trim register

    // Set up Event Trigger with CNT_zero enable for Time-base of EPWM1
    EPwm1Regs.ETSEL.bit.SOCAEN = 1;     // Enable SOCA
    EPwm1Regs.ETSEL.bit.SOCASEL = 1;    // Enable CNT_zero event for SOCA
    EPwm1Regs.ETPS.bit.SOCAPRD = 1;     // Generate SOCA on the 1st event
 EPwm1Regs.ETCLR.bit.SOCA = 1;       // Clear SOCA flag

void F280X_ileg2_dcbus_drv_read(ILEG2DCBUSMEAS *p)
{
       int16 DatQ15;
       int32 Tmp;

        // Wait until ADC conversion is completed
        while (AdcRegs.ADCST.bit.SEQ1_BSY == 1)
        {};

        DatQ15 = AdcRegs.ADCRESULT0^0x8000;       // Convert raw result to Q15 (bipolar signal)
        Tmp = (int32)p->ImeasAGain*(int32)DatQ15; // Tmp = gain*dat => Q28 = Q13*Q15
        p->ImeasA = (int16)(Tmp>>13);             // Convert Q28 to Q15
        p->ImeasA += p->ImeasAOffset;             // Add offset
        p->ImeasA *= -1;                         // Positive direction, current flows to motor

        DatQ15 = AdcRegs.ADCRESULT1^0x8000;      // Convert raw result to Q15 (bipolar signal)
        Tmp = (int32)p->ImeasBGain*(int32)DatQ15; // Tmp = gain*dat => Q28 = Q13*Q15
        p->ImeasB = (int16)(Tmp>>13);             // Convert Q28 to Q15
        p->ImeasB += p->ImeasBOffset;             // Add offset
        p->ImeasB *= -1;                       // Positive direction, current flows to motor
 
        DatQ15 = (AdcRegs.ADCRESULT2>>1)&0x7FFF;   // Convert raw result to Q15 (unipolar signal)
        Tmp = (int32)p->VdcMeasGain*(int32)DatQ15; // Tmp = gain*dat => Q28 = Q13*Q15
        if (Tmp > 0x0FFFFFFF)                      // Limit Tmp to 1.0 in Q28
           Tmp = 0x0FFFFFFF;
        p->VdcMeas = (int16)(Tmp>>13);             // Convert Q28 to Q15
        p->VdcMeas += p->VdcMeasOffset;            // Add offset

        p->ImeasC = -(p->ImeasA + p->ImeasB);      // Compute phase-c current

        AdcRegs.ADCTRL2.all |= 0x4040;             // Reset the sequence

}           

我的问题如下:

1,寄存器:(1)AdcRegs.ADCTRL1.all = ADCTRL1_INIT_STATE; // Set up ADCTRL1 register
    AdcRegs.ADCTRL2.all = ADCTRL2_INIT_STATE;  // Set up ADCTRL2 register

请问这两个控制寄存器ADCTRL1_INIT_STATE,ADCTRL2_INIT_STATE,具体代表的怎样设置呢,没找到相关的说明。

(2)AdcRegs.ADCREFSEL.all = 39;                 // Set up the ADC reference select register
    AdcRegs.ADCOFFTRIM.all = 65534;             // Set up the ADC offset trim register

这两个ADC寄存器麻烦您解释下,设置的39和65534分别怎么样得来的呢?代表什么意思呢 ?谢谢,我看了下寄存器资料,但还是有疑问,谢谢!

2.,第二个read函数中ImeasBGain怎么样得到的?为什么设置成Q格式为Q13呢?

3,   p->ImeasA *= -1;                         // Positive direction, current flows to motor这条指令的意思?

4,关于将ADC结果异或的,双极性电流与0x8000异或,单极性电压与0x7FFF异或,虽然!知道这样处理简单有效,呵呵,大概能懂意思,但还是希望您解释下,呵呵,再次感谢

  • e,麻烦 ti的技术员大哥和各位大神看下噢,谢谢!

  • 你好。

    1. 请参考,该头文件里有对这两个寄存器值的定义。另外,关于ADC的参考值与偏移是需要根据你的系统来定的。

    2. ImeasBGain也在前面那个头文件里有定义,定义时的格式就是Q13.

    3. 这一句是把电流方向作了一个反向,这也是需要根据你实际的系统,可以更改。如果采样得到的电流与直接就是正向的,就没必要乘-1了。

    4. 关于电压采样与变换的说明文档,请参考

  • Jay, 您好,感谢回答!

    但是还有疑问,望解疑,呵呵。

    1.AdcRegs.ADCCHSELSEQ1.all = p->ChSelect;     // Configure channel selection

    这句指令中ChSelect没看懂,而在PMSM3_4中应该是采样两相电流和一个直流电压,三个通道,那么程序中这句:

     ilg2_vdc1.ChSelect = 0x0610;

    其中0x0610;怎么得来的呢?麻烦解释下!

    2.电机控制中PWM同步的问题,以前问过Jones Chen,我后来自己验证了 例程大概如下(TI的EPWM Reference Guide(这里看的是28335的epwm reference,跟2808差不多吧应该)中第三章Controlling Dual 3-Phase Inverters for Motors(ACI and PMSM)介绍的例程也跟下面一样的,):

    EALLOW;

      SysCtrlRegs.PCLKCR0.bit.TBCLKSYNC = 0;

      EDIS;

      // Configure ePWM4 for ADC SOC

      EPwm1Regs.ETSEL.bit.SOCAEN = 0;                 // Disable SOC on EPwm1A group for now - enable when ADC needed

      EPwm1Regs.ETSEL.bit.SOCBEN = 0;                 // Disable SOC on EPwm1B group for now - enable when ADC needed

      EPwm2Regs.ETSEL.bit.SOCAEN = 0;                 // Disable SOC on EPwm1A group for now - enable when ADC needed

      EPwm2Regs.ETSEL.bit.SOCBEN = 0;                 // Disable SOC on EPwm1B group for now - enable when ADC needed

      EPwm1Regs.ETSEL.bit.SOCASEL= 1;                 // EPwm1 SOCA--Zero

      EPwm1Regs.ETSEL.bit.SOCBSEL= 2;                 // EPwm1 SOCB--Prd

      EPwm2Regs.ETSEL.bit.SOCASEL= 2;                 // EPwm2SOCA--Zero

      EPwm2Regs.ETSEL.bit.SOCBSEL= 1;                 // EPwm2 SOCB--Prd

      EPwm1Regs.ETPS.bit.SOCAPRD = 1;                 // Generate pulse on 1st event

      EPwm1Regs.ETPS.bit.SOCBPRD = 1;                 // Generate pulse on 1st event

      EPwm2Regs.ETPS.bit.SOCAPRD = 1;                 // Generate pulse on 1st event

      EPwm2Regs.ETPS.bit.SOCBPRD = 1;                 // Generate pulse on 1st event

      EPwm1Regs.TBPRD = XXXX;    

     EPwm2Regs.TBPRD = XXXX;

      EPwm1Regs.TBCTL.bit.CTRMODE = TB_COUNT_UPDOWN;  // count up and down to trigger SOC

      EPwm2Regs.TBCTL.bit.CTRMODE = TB_COUNT_UPDOWN;  // count up and down to trigger SOC

      // Setup TBCLK

      EPwm1Regs.TBPHS.half.TBPHS = 0x0000;           // Phase is 0

      EPwm1Regs.TBCTR = 0x0000;                      // Clear counter

      EPwm1Regs.TBCTL.bit.PHSEN = TB_DISABLE;        // Disable phase loading

      EPwm1Regs.TBCTL.bit.SYNCOSEL = TB_CTR_ZERO;    // Sync out @ counter=zero

      EPwm1Regs.TBCTL.bit.HSPCLKDIV = TB_DIV1;       // Clock ratio to SYSCLKOUT

      EPwm1Regs.TBCTL.bit.CLKDIV = TB_DIV1;          // Clock ratio to SYSCLKOUT

      EPwm2Regs.TBPHS.half.TBPHS = 240;              // Phase is 90

      EPwm2Regs.TBCTR = 0x0000;                      // Clear counter

      EPwm2Regs.TBCTL.bit.PHSEN = TB_ENABLE;         // enable phase loading//Jones added

      EPwm2Regs.TBCTL.bit.PHSDIR= 1;                 // count up when sync//Jones added

      EPwm2Regs.TBCTL.bit.SYNCOSEL = TB_SYNC_IN;    // 

      EPwm2Regs.TBCTL.bit.HSPCLKDIV = TB_DIV1;       // Clock ratio to SYSCLKOUT

      EPwm2Regs.TBCTL.bit.CLKDIV = TB_DIV1;          // Clock ratio to SYSCLKOUT

      EALLOW;

      SysCtrlRegs.PCLKCR0.bit.TBCLKSYNC = 1;

      EDIS;

    }

    我的问题:

    (1)而在安装的文件tidcs-dmc文件夹中的280x_xpwm.c中,跟上面的例程有点不同,pmsm3_4是在主程序里开始直接写

     EALLOW;

      SysCtrlRegs.PCLKCR0.bit.TBCLKSYNC = 1;

      EDIS;

    然后接着配置EPWM模块,前面没有设置 SysCtrlRegs.PCLKCR0.bit.TBCLKSYNC = 0;;而上面给出的例程是先写SysCtrlRegs.PCLKCR0.bit.TBCLKSYNC = 0;

    再配置EPWM模块;再写SysCtrlRegs.PCLKCR0.bit.TBCLKSYNC = 1;不知道这两种模式的区别?

    (2)问题2,上例程中配置的EPwm1Regs.TBCTL.bit.PHSEN = TB_DISABLE;        // Disable phase loading

    与EPwm1Regs.TBCTL.bit.SYNCOSEL = TB_CTR_ZERO;    // Sync out @ counter=zero

    这两个寄存器配置与xpwm.c中也不同,体现的是主模块epwm1的配置,xpwm.c中配置的是EPwm1Regs.TBCTL.bit.PHSEN = 1;  与

    EPwm1Regs.TBCTL.bit.SYNCOSEL = 0;(照理来说epwm1是主模块,EPWM2,EPWM3是从模块,应该配置不同吧,而xpwm.c中配置是一样的EPWM1,

    EPWM2,EPWM3)原配置如下xpwm.c 中:

    void F280X_PWM_Init(PWMGEN *p)
    {      

             // Setup Sync
             EPwm1Regs.TBCTL.bit.SYNCOSEL = 0;          // Pass through
             EPwm2Regs.TBCTL.bit.SYNCOSEL = 0;          // Pass through
             EPwm3Regs.TBCTL.bit.SYNCOSEL = 0;          // Pass through
             EPwm4Regs.TBCTL.bit.SYNCOSEL = 0;          // Pass through
             EPwm5Regs.TBCTL.bit.SYNCOSEL = 0;          // Pass through
             EPwm6Regs.TBCTL.bit.SYNCOSEL = 0;          // Pass through

             // Allow each timer to be sync'ed
             EPwm1Regs.TBCTL.bit.PHSEN = 1;
             EPwm2Regs.TBCTL.bit.PHSEN = 1;
             EPwm3Regs.TBCTL.bit.PHSEN = 1;
             EPwm4Regs.TBCTL.bit.PHSEN = 1;
             EPwm5Regs.TBCTL.bit.PHSEN = 1;
             EPwm6Regs.TBCTL.bit.PHSEN = 1;

    也麻烦说一下为什么不同呢?两种对应的方式,问题1和问题2中对应的设置都能够达到时基同步(都能达到EPWM1主模块,EPWM2,EPWM3从模块)?两种设置的区别(是否同步的方式不同)?

  • 你好。

    1. 根据TRM上对ADCCHSELSEQ1寄存器的说明,0x0610表示选择了ADCINA0,ADCINA1和ADCINA6作为转换通道。根据转换序列和f280xileg_vdc.c中void F280X_ileg2_dcbus_drv_read(ILEG2DCBUSMEAS *p)的定义,ADCINA0是A相电流,ADCINA1是B相电流,ADCINA6是母线电压。通道的选择和序列可以根据你的实际系统进行调整理,只需要修改这里的0x0610即可。

    2. ePWM时钟同步问题。

    (1)对于SysCtrlRegs.PCLKCR0.bit.TBCLKSYNC全局时基同步使能寄存器的使用,请参考下面TRM上对该寄存器的说明。红框标记为建议的设置顺序。

    (2)各个PWM模块之间的同步关系。你的理解没错,ePWM2和ePWM3是由ePWM1来提供同步信号的,对于ePWM1自身是否需要同步关键在于TBPHS相位寄存器的设置。一般地,我们设置ePWM1的相位寄存器为0,那么ePWM1是否同步就无所谓了。如果ePWM1也需要调整相位,那么就需要使能它的同步。

  • dat_q15 = AdcRegs.ADCRESULT0^0x8000; 
    
    dat_q15 = AdcRegs.ADCRESULT1^0x8000; 
    
    dat_q15 = (AdcRegs.ADCRESULT2>>1)&0x7FFF; 
    您好!请问用这种方法来处理AD转换结果有没有办法进行AD校准,另外 为什么直流和交流的处理方法不一样?非常的困惑 多谢解答
  • 老师您好:

        关于这段程序我还有一个不懂的地方,恳请您不吝赐教,就是为什么DatQ15 = (AdcRegs.ADCRESULT0>>1)&0x7FFF要右移一位后才相与呢??下面附录部分程序,感谢您的回复!!

      DatQ15 = (AdcRegs.ADCRESULT0>>1)&0x7FFF;    // Convert raw result to Q15 (unipolar signal)
            Tmp = (int32)p->Ch1Gain*(int32)DatQ15;      // Tmp = gain*dat => Q28 = Q13*Q15
            p->Ch1Out = (int16)(Tmp>>13);               // Convert Q28 to Q15

            DatQ15 = (AdcRegs.ADCRESULT1>>1)&0x7FFF;    // Convert raw result to Q15 (unipolar signal)
            Tmp = (int32)p->Ch2Gain*(int32)DatQ15;      // Tmp = gain*dat => Q28 = Q13*Q15
            p->Ch2Out = (int16)(Tmp>>13);               // Convert Q28 to Q15

            DatQ15 = (AdcRegs.ADCRESULT2>>1)&0x7FFF;    // Convert raw result to Q15 (unipolar signal)
            Tmp = (int32)p->Ch3Gain*(int32)DatQ15;      // Tmp = gain*dat => Q28 = Q13*Q15
            p->Ch3Out = (int16)(Tmp>>13);               // Convert Q28 to Q15

            DatQ15 = (AdcRegs.ADCRESULT3>>1)&0x7FFF;    // Convert raw result to Q15 (unipolar signal)
            Tmp = (int32)p->Ch4Gain*(int32)DatQ15;      // Tmp = gain*dat => Q28 = Q13*Q15
            p->Ch4Out = (int16)(Tmp>>13);               // Convert Q28 to Q15

            AdcRegs.ADCTRL2.all |= 0x4040;            // Reset the sequence

  • zeyuan du 说:

    老师您好:

        关于这段程序我还有一个不懂的地方,恳请您不吝赐教,就是为什么DatQ15 = (AdcRegs.ADCRESULT0>>1)&0x7FFF要右移一位后才相与呢??下面附录部分程序,感谢您的回复!!

      DatQ15 = (AdcRegs.ADCRESULT0>>1)&0x7FFF;    // Convert raw result to Q15 (unipolar signal)
            Tmp = (int32)p->Ch1Gain*(int32)DatQ15;      // Tmp = gain*dat => Q28 = Q13*Q15
            p->Ch1Out = (int16)(Tmp>>13);               // Convert Q28 to Q15

            DatQ15 = (AdcRegs.ADCRESULT1>>1)&0x7FFF;    // Convert raw result to Q15 (unipolar signal)
            Tmp = (int32)p->Ch2Gain*(int32)DatQ15;      // Tmp = gain*dat => Q28 = Q13*Q15
            p->Ch2Out = (int16)(Tmp>>13);               // Convert Q28 to Q15

            DatQ15 = (AdcRegs.ADCRESULT2>>1)&0x7FFF;    // Convert raw result to Q15 (unipolar signal)
            Tmp = (int32)p->Ch3Gain*(int32)DatQ15;      // Tmp = gain*dat => Q28 = Q13*Q15
            p->Ch3Out = (int16)(Tmp>>13);               // Convert Q28 to Q15

            DatQ15 = (AdcRegs.ADCRESULT3>>1)&0x7FFF;    // Convert raw result to Q15 (unipolar signal)
            Tmp = (int32)p->Ch4Gain*(int32)DatQ15;      // Tmp = gain*dat => Q28 = Q13*Q15
            p->Ch4Out = (int16)(Tmp>>13);               // Convert Q28 to Q15

            AdcRegs.ADCTRL2.all |= 0x4040;            // Reset the sequence

    请另起一贴提问。