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.

[参考译文] TMS320F28377S:我对提供的'ti'代码及其与模数转换(ADC)的连接中的中断服务例程(ISR)有疑问。

Guru**** 2398695 points
Other Parts Discussed in Thread: C2000WARE

请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

https://e2e.ti.com/support/microcontrollers/c2000-microcontrollers-group/c2000/f/c2000-microcontrollers-forum/1314462/tms320f28377s-i-have-questions-regarding-the-interrupt-service-routine-isr-in-the-provided-ti-code-and-its-connection-to-analog-to-digital-conversion-adc

器件型号:TMS320F28377S
主题中讨论的其他器件:C2000WARE

"我参与了逆变器的电流控制、并创建了一个名为"maout"的代码来监控内部变量。 但是、我已经注意到、在中断服务例程(ISR)中将"详细信息"代码置于 ADC 寄存器相关代码的上方和下方时、电流控制特性有显著差异。 在我的理解中、我认为与 ADC 相关的代码应优先于 ISR 开始时。 但是、我听说有些代码有意在启动 ADC 之前包含虚拟代码。 您能否对此提供解释?

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    您好!

    Unknown 说:
    但是、当将"aout"代码放在 ADC 寄存器相关代码的上面和下面时、我注意到当前控制特性有很大差异

    您能否提供有关这些差异的更多详细信息?

    谢谢

    阿斯温

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    感谢您的答复。

    "我知道、要读取准确的 ADCResults、我需要保护采样保持时间(TSH)和锁存时间(tLAT)。 在我当前使用的规格中、TSH+tLAT 为425ns。 因此、在读取 ADCResult 值之前、我使用延迟代码进行了三次实验。

    1. 无任何延迟
    2. 延迟为550ns (有足够的时间)
    3. 具有800ns 的延迟(比情况2所得到的时间更多)

    我知道、如果不保护 TSH+tLAT、读取 ADCResults 会检索现有值。 实际上、案例1和案例2显示了一次采样的差异。 但奇怪的是第3种情况。 如果 TSH+tLAT 安全、则情况2和3下的 ADCResults 应相同、但值不同。 在第3种情况中、ADCResults 的采样延迟似乎小于第2种情况。 这种现象的原因是什么?"

    谢谢
    德公

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    Deokyong、您好!

    我很抱歉、我不清楚问题的确切情况。 您是否可以向我展示您的代码(如果需要、您可以排除任何专有信息)? 该延迟添加在何处?  根据其位置、有可能导致 ADC 发生中断溢出。 您是否使用了 TI 示例提供的示例 ADC ISR (如果是、我可以参考哪个示例)?

    在第3种情况下,ADCResults 的采样延迟似乎小于第2种情况。

    您能否澄清一下、您是说延迟不能正常工作、还是 ADC 结果本身低于预期?

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    感谢您的答复。 

    我将使用 ti 示例 ADC ISR。
    CC ISR 还用于控制逆变器电流、并且两个 ISR 都与 ePWM1的向上/向下计数同步。
    对于电流控制、CC ISR 必须读取 ADCResults 值。
    在这里、为了保护 ADC 的 SAMP 和保持时间以及锁存时间、在 CC ISR 的第一个启动点插入一个延迟。
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    我正在使用 ti 示例 ADC isr.

    该器件有14个 ADC 示例、您需要告诉我您指的是哪一个。 从该示例到您自己的项目、您做了哪些更改?

    CC ISR 也用于控制逆变器电流、并且两个 ISR 都与 ePWM1的上下计数同步。

    我通过这种方式解读、您只使用 ePWM 来触发 ISR、而不使用 ADC SOC、是正确的吗?

    此处、为了保护 ADC 的 SAMP 和保持时间和锁存时间、在 CC ISR 启动的第一个点插入延迟。

    您是否通过检查 ADCINTOVF 和 ADCSOCOVF1寄存器验证了没有溢出?

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    ISR 与 ePWM 同步、并​​在 ISR 启动时开始读取 ADCResults 值。 
    ADC SOC 是否与 ISR 分开? 我知道、当触发 ISR 时、ADC SOC 也会起作用。
    我知道的是什么错吗? 另外、您能否解释一下什么是溢出?
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    您好!

    请共享您的代码或 准确 示例您正在使用中、如果我看不到您在做什么、我就不能提供太多支持。 我需要查看您的外设是如何配置的、中断是如何设置的、ISR 的内容等。

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    这是 ADC 代码。

    //###########################################################################
    //
    // FILE:   F2837xS_Adc.c
    //
    // TITLE:  F2837xS Adc Support Functions.
    //
    //###########################################################################
    // $TI Release: F2837xS Support Library v210 $
    // $Release Date: Tue Nov  1 15:35:23 CDT 2016 $
    // $Copyright: Copyright (C) 2014-2016 Texas Instruments Incorporated -
    //             http://www.ti.com/ ALL RIGHTS RESERVED $
    //###########################################################################
    
    //
    // Included Files
    //
    #include "F2837xS_device.h"
    #include "F2837xS_Examples.h"
    
    
    void InitAdc(void)
    {
        Uint16 acqps = 19, tempsensor_acqps = 139; //temperature sensor needs at least 700ns
    
    
        EALLOW;
    
        AdcaRegs.ADCCTL2.bit.PRESCALE = 6; //set ADCCLK divider to /4
        AdcSetMode(ADC_ADCA, ADC_BITRESOLUTION_12BIT, ADC_SIGNALMODE_SINGLE);
        AdcaRegs.ADCCTL1.bit.INTPULSEPOS = 1;   // Set pulse positions to late
        AdcaRegs.ADCCTL1.bit.ADCPWDNZ = 1;      //power up the ADC
    
    
        AdcbRegs.ADCCTL2.bit.PRESCALE = 6; //set ADCCLK divider to /4
        AdcSetMode(ADC_ADCB, ADC_BITRESOLUTION_12BIT, ADC_SIGNALMODE_SINGLE);
        AdcbRegs.ADCCTL1.bit.INTPULSEPOS = 1;   // Set pulse positions to late
        AdcbRegs.ADCCTL1.bit.ADCPWDNZ = 1;    //power up the ADC
    
    
        AdccRegs.ADCCTL2.bit.PRESCALE = 6; //set ADCCLK divider to /4
        AdcSetMode(ADC_ADCC, ADC_BITRESOLUTION_12BIT, ADC_SIGNALMODE_SINGLE);
        AdccRegs.ADCCTL1.bit.INTPULSEPOS = 1;   // Set pulse positions to late
        AdccRegs.ADCCTL1.bit.ADCPWDNZ = 1;    //power up the ADC
    
    
        AdcdRegs.ADCCTL2.bit.PRESCALE = 6; //set ADCCLK divider to /4
        AdcSetMode(ADC_ADCD, ADC_BITRESOLUTION_12BIT, ADC_SIGNALMODE_SINGLE);
        AdcdRegs.ADCCTL1.bit.INTPULSEPOS = 1;   // Set pulse positions to late
        AdcdRegs.ADCCTL1.bit.ADCPWDNZ = 1;    //power up the ADC
    
    
        AdcaRegs.ADCSOCPRICTL.bit.SOCPRIORITY = 0x0f;
        acqps = 14 + AdcaRegs.ADCCTL2.bit.RESOLUTION * 49; // 75ns for 12bit mode, 320ns for 16bit mode
    
        //Select the channels to convert and end of conversion flag
        AdcaRegs.ADCSOC0CTL.bit.CHSEL = 0;      //SOC0 will convert pin A0
        AdcaRegs.ADCSOC0CTL.bit.ACQPS = acqps;  //sample window is 14 SYSCLK cycles
        AdcaRegs.ADCSOC0CTL.bit.TRIGSEL = 5;    //trigger on ePWM1 SOCA/C
    
        AdcaRegs.ADCSOC1CTL.bit.CHSEL = 1;      //SOC1 will convert pin A1
        AdcaRegs.ADCSOC1CTL.bit.ACQPS = acqps;  //sample window is 14 SYSCLK cycles
        AdcaRegs.ADCSOC1CTL.bit.TRIGSEL = 5;    //trigger on ePWM1 SOCA/C
    
        AdcaRegs.ADCSOC2CTL.bit.CHSEL = 2;      //SOC2 will convert pin A2
        AdcaRegs.ADCSOC2CTL.bit.ACQPS = acqps;  //sample window is 14 SYSCLK cycles
        AdcaRegs.ADCSOC2CTL.bit.TRIGSEL = 5;    //trigger on ePWM1 SOCA/C
    
        AdcaRegs.ADCSOC3CTL.bit.CHSEL = 3;      //SOC3 will convert pin A3
        AdcaRegs.ADCSOC3CTL.bit.ACQPS = acqps;  //sample window is 14 SYSCLK cycles
        AdcaRegs.ADCSOC3CTL.bit.TRIGSEL = 5;    //trigger on ePWM1 SOCA/C
    
        AdcaRegs.ADCSOC4CTL.bit.CHSEL = 4;      //SOC4 will convert pin A4
        AdcaRegs.ADCSOC4CTL.bit.ACQPS = acqps;  //sample window is 14 SYSCLK cycles
        AdcaRegs.ADCSOC4CTL.bit.TRIGSEL = 5;    //trigger on ePWM1 SOCA/C
    
        AdcaRegs.ADCSOC5CTL.bit.CHSEL = 5;      //SOC5 will convert pin A5
        AdcaRegs.ADCSOC5CTL.bit.ACQPS = acqps;  //sample window is 14 SYSCLK cycles
        AdcaRegs.ADCSOC5CTL.bit.TRIGSEL = 5;    //trigger on ePWM1 SOCA/C
    
        AdcaRegs.ADCSOC6CTL.bit.CHSEL = 13;      //SOC6 will convert pin TEMP SENSOR
        AdcaRegs.ADCSOC6CTL.bit.ACQPS = tempsensor_acqps;  //sample window is 100 SYSCLK cycles
        AdcaRegs.ADCSOC6CTL.bit.TRIGSEL = 5;    //trigger on ePWM1 SOCA/C
    
    
        //    AdcaRegs.ADCINTSEL1N2.bit.INT1SEL = 0; //end of SOC0 will set INT1 flag
        //    AdcaRegs.ADCINTSEL1N2.bit.INT1E = 1;   //enable INT1 flag
        //    AdcaRegs.ADCINTFLGCLR.bit.ADCINT1 = 1; //make sure INT1 flag is cleared
    
        // Adc B module :
        //Select the channels to convert and end of conversion flag
        AdcbRegs.ADCSOC0CTL.bit.CHSEL = 0;      //SOC0 will convert pin B0
        AdcbRegs.ADCSOC0CTL.bit.ACQPS = acqps;  //sample window is 14 SYSCLK cycles
        AdcbRegs.ADCSOC0CTL.bit.TRIGSEL = 5;    //trigger on ePWM1 SOCA/C
    
        AdcbRegs.ADCSOC1CTL.bit.CHSEL = 1;      //SOC1 will convert pin B1
        AdcbRegs.ADCSOC1CTL.bit.ACQPS = acqps;  //sample window is 14 SYSCLK cycles
        AdcbRegs.ADCSOC1CTL.bit.TRIGSEL = 5;    //trigger on ePWM1 SOCA/C
    
        AdcbRegs.ADCSOC2CTL.bit.CHSEL = 2;      //SOC2 will convert pin B2
        AdcbRegs.ADCSOC2CTL.bit.ACQPS = acqps;  //sample window is 14 SYSCLK cycles
        AdcbRegs.ADCSOC2CTL.bit.TRIGSEL = 5;    //trigger on ePWM1 SOCA/C
    
        AdcbRegs.ADCSOC3CTL.bit.CHSEL = 3;      //SOC3 will convert pin B3
        AdcbRegs.ADCSOC3CTL.bit.ACQPS = acqps;  //sample window is 14 SYSCLK cycles
        AdcbRegs.ADCSOC3CTL.bit.TRIGSEL = 5;    //trigger on ePWM1 SOCA/C
    
        AdcbRegs.ADCSOC4CTL.bit.CHSEL = 4;      //SOC4 will convert pin B4
        AdcbRegs.ADCSOC4CTL.bit.ACQPS = acqps;  //sample window is 14 SYSCLK cycles
        AdcbRegs.ADCSOC4CTL.bit.TRIGSEL = 5;    //trigger on ePWM1 SOCA/C
    
        AdcbRegs.ADCSOC5CTL.bit.CHSEL = 5;      //SOC5 will convert pin B5
        AdcbRegs.ADCSOC5CTL.bit.ACQPS = acqps;  //sample window is 14 SYSCLK cycles
        AdcbRegs.ADCSOC5CTL.bit.TRIGSEL = 5;    //trigger on ePWM1 SOCA/C
    
        // Adc C module :
        // Select the channels to convert and end of conversion flag
        AdccRegs.ADCSOC0CTL.bit.CHSEL = 14;      //SOC0 will convert pin 14
        AdccRegs.ADCSOC0CTL.bit.ACQPS = acqps;  //sample window is 14 SYSCLK cycles
        AdccRegs.ADCSOC0CTL.bit.TRIGSEL = 5;    //trigger on ePWM1 SOCA/C
    
        AdccRegs.ADCSOC1CTL.bit.CHSEL = 15;      //SOC1 will convert pin 15
        AdccRegs.ADCSOC1CTL.bit.ACQPS = acqps;  //sample window is 14 SYSCLK cycles
        AdccRegs.ADCSOC1CTL.bit.TRIGSEL = 5;    //trigger on ePWM1 SOCA/C
    
        AdccRegs.ADCSOC2CTL.bit.CHSEL = 2;      //SOC2 will convert pin C2
        AdccRegs.ADCSOC2CTL.bit.ACQPS = acqps;  //sample window is 14 SYSCLK cycles
        AdccRegs.ADCSOC2CTL.bit.TRIGSEL = 5;    //trigger on ePWM1 SOCA/C
    
        AdccRegs.ADCSOC3CTL.bit.CHSEL = 3;      //SOC3 will convert pin C3
        AdccRegs.ADCSOC3CTL.bit.ACQPS = acqps;  //sample window is 14 SYSCLK cycles
        AdccRegs.ADCSOC3CTL.bit.TRIGSEL = 5;    //trigger on ePWM1 SOCA/C
    
        AdccRegs.ADCSOC4CTL.bit.CHSEL = 4;      //SOC4 will convert pin C4
        AdccRegs.ADCSOC4CTL.bit.ACQPS = acqps;  //sample window is 14 SYSCLK cycles
        AdccRegs.ADCSOC4CTL.bit.TRIGSEL = 5;    //trigger on ePWM1 SOCA/C
    
        AdccRegs.ADCSOC5CTL.bit.CHSEL = 5;      //SOC5 will convert pin C5
        AdccRegs.ADCSOC5CTL.bit.ACQPS = acqps;  //sample window is 14 SYSCLK cycles
        AdccRegs.ADCSOC5CTL.bit.TRIGSEL = 5;    //trigger on ePWM1 SOCA/C
    
        // Adc D module :
        // Select the channels to convert and end of conversion flag
        AdcdRegs.ADCSOC0CTL.bit.CHSEL = 0;      //SOC0 wi   ll convert pin D0
        AdcdRegs.ADCSOC0CTL.bit.ACQPS = acqps*2;  //sample window is 14 SYSCLK cycles
        AdcdRegs.ADCSOC0CTL.bit.TRIGSEL = 5;    //trigger on ePWM1 SOCA/C
    
        AdcdRegs.ADCSOC1CTL.bit.CHSEL = 1;      //SOC1 will convert pin D1
        AdcdRegs.ADCSOC1CTL.bit.ACQPS = acqps;  //sample window is 14 SYSCLK cycles
        AdcdRegs.ADCSOC1CTL.bit.TRIGSEL = 5;    //trigger on ePWM1 SOCA/C
    
        AdcdRegs.ADCSOC2CTL.bit.CHSEL = 2;      //SOC2 will convert pin D2
        AdcdRegs.ADCSOC2CTL.bit.ACQPS = acqps;  //sample window is 14 SYSCLK cycles
        AdcdRegs.ADCSOC2CTL.bit.TRIGSEL = 5;    //trigger on ePWM1 SOCA/C
    
        AdcdRegs.ADCSOC3CTL.bit.CHSEL = 3;      //SOC3 will convert pin D3
        AdcdRegs.ADCSOC3CTL.bit.ACQPS = acqps;  //sample window is 14 SYSCLK cycles
        AdcdRegs.ADCSOC3CTL.bit.TRIGSEL = 5;    //trigger on ePWM1 SOCA/C
    
        AdcdRegs.ADCSOC4CTL.bit.CHSEL = 4;      //SOC4 will convert pin D4
        AdcdRegs.ADCSOC4CTL.bit.ACQPS = acqps;  //sample window is 14 SYSCLK cycles
        AdcdRegs.ADCSOC4CTL.bit.TRIGSEL = 5;    //trigger on ePWM1 SOCA/C
    
        AdcdRegs.ADCSOC5CTL.bit.CHSEL = 5;      //SOC5 will convert pin D5
        AdcdRegs.ADCSOC5CTL.bit.ACQPS = acqps;  //sample window is 14 SYSCLK cycles
        AdcdRegs.ADCSOC5CTL.bit.TRIGSEL = 5;    //trigger on ePWM1 SOCA/C
    
        EDIS;
    
        DELAY_US(1000);    //delay for 1ms to allow ADC time to power up
    
    }
    
    
    //
    // AdcSetMode - Set the resolution and signalmode for a given ADC. This will
    //              ensure that the correct trim is loaded.
    //
    void AdcSetMode(Uint16 adc, Uint16 resolution, Uint16 signalmode)
    {
        Uint16 adcOffsetTrimOTPIndex; //index into OTP table of ADC offset trims
        Uint16 adcOffsetTrim;         //temporary ADC offset trim
    
        //
        //re-populate INL trim
        //
        CalAdcINL(adc);
    
        if(0xFFFF != *((Uint16*)GetAdcOffsetTrimOTP))
        {
            //
            //offset trim function is programmed into OTP, so call it
            //
    
            //
            //calculate the index into OTP table of offset trims and call
            //function to return the correct offset trim
            //
            adcOffsetTrimOTPIndex = 4*adc + 2*resolution + 1*signalmode;
            adcOffsetTrim = (*GetAdcOffsetTrimOTP)(adcOffsetTrimOTPIndex);
        }
        else
        {
            //
            //offset trim function is not populated, so set offset trim to 0
            //
            adcOffsetTrim = 0;
        }
    
        //
        //Apply the resolution and signalmode to the specified ADC.
        //Also apply the offset trim and, if needed, linearity trim correction.
        //
        switch(adc)
        {
            case ADC_ADCA:
                AdcaRegs.ADCCTL2.bit.RESOLUTION = resolution;
                AdcaRegs.ADCCTL2.bit.SIGNALMODE = signalmode;
                AdcaRegs.ADCOFFTRIM.all = adcOffsetTrim;
                if(ADC_BITRESOLUTION_12BIT == resolution)
                {
                    //
                    //12-bit linearity trim workaround
                    //
                    AdcaRegs.ADCINLTRIM1 &= 0xFFFF0000;
                    AdcaRegs.ADCINLTRIM2 &= 0xFFFF0000;
                    AdcaRegs.ADCINLTRIM4 &= 0xFFFF0000;
                    AdcaRegs.ADCINLTRIM5 &= 0xFFFF0000;
                }
            break;
            case ADC_ADCB:
                AdcbRegs.ADCCTL2.bit.RESOLUTION = resolution;
                AdcbRegs.ADCCTL2.bit.SIGNALMODE = signalmode;
                AdcbRegs.ADCOFFTRIM.all = adcOffsetTrim;
                if(ADC_BITRESOLUTION_12BIT == resolution)
                {
                    //
                    //12-bit linearity trim workaround
                    //
                    AdcbRegs.ADCINLTRIM1 &= 0xFFFF0000;
                    AdcbRegs.ADCINLTRIM2 &= 0xFFFF0000;
                    AdcbRegs.ADCINLTRIM4 &= 0xFFFF0000;
                    AdcbRegs.ADCINLTRIM5 &= 0xFFFF0000;
                }
            break;
            case ADC_ADCC:
                AdccRegs.ADCCTL2.bit.RESOLUTION = resolution;
                AdccRegs.ADCCTL2.bit.SIGNALMODE = signalmode;
                AdccRegs.ADCOFFTRIM.all = adcOffsetTrim;
                if(ADC_BITRESOLUTION_12BIT == resolution)
                {
                    //
                    //12-bit linearity trim workaround
                    //
                    AdccRegs.ADCINLTRIM1 &= 0xFFFF0000;
                    AdccRegs.ADCINLTRIM2 &= 0xFFFF0000;
                    AdccRegs.ADCINLTRIM4 &= 0xFFFF0000;
                    AdccRegs.ADCINLTRIM5 &= 0xFFFF0000;
                }
            break;
            case ADC_ADCD:
                AdcdRegs.ADCCTL2.bit.RESOLUTION = resolution;
                AdcdRegs.ADCCTL2.bit.SIGNALMODE = signalmode;
                AdcdRegs.ADCOFFTRIM.all = adcOffsetTrim;
                if(ADC_BITRESOLUTION_12BIT == resolution)
                {
                    //
                    //12-bit linearity trim workaround
                    //
                    AdcdRegs.ADCINLTRIM1 &= 0xFFFF0000;
                    AdcdRegs.ADCINLTRIM2 &= 0xFFFF0000;
                    AdcdRegs.ADCINLTRIM4 &= 0xFFFF0000;
                    AdcdRegs.ADCINLTRIM5 &= 0xFFFF0000;
                }
            break;
        }
    }
    
    //
    // CalAdcINL - Loads INL trim values from OTP into the trim registers of the
    //             specified ADC. Use only as part of AdcSetMode function, since
    //             linearity trim correction is needed for some modes.
    //
    void CalAdcINL(Uint16 adc)
    {
        switch(adc)
        {
            case ADC_ADCA:
                if(0xFFFF != *((Uint16*)CalAdcaINL))
                {
                    //
                    //trim function is programmed into OTP, so call it
                    //
                    (*CalAdcaINL)();
                }
                else
                {
                    //
                    //do nothing, no INL trim function populated
                    //
                }
                break;
            case ADC_ADCB:
                if(0xFFFF != *((Uint16*)CalAdcbINL))
                {
                    //
                    //trim function is programmed into OTP, so call it
                    //
                    (*CalAdcbINL)();
                }
                else
                {
                    //
                    //do nothing, no INL trim function populated
                    //
                }
                break;
            case ADC_ADCC:
                if(0xFFFF != *((Uint16*)CalAdccINL))
                {
                    //
                    //trim function is programmed into OTP, so call it
                    //
                    (*CalAdccINL)();
                }
                else
                {
                    //
                    //do nothing, no INL trim function populated
                    //
                }
                break;
            case ADC_ADCD:
                if(0xFFFF != *((Uint16*)CalAdcdINL))
                {
                    //
                    //trim function is programmed into OTP, so call it
                    //
                    (*CalAdcdINL)();
                }
                else
                {
                    //
                    //do nothing, no INL trim function populated
                    //
                }
                break;
        }
    }
    
    //
    // End of file
    //
    

    这是 ISR 代码。

    interrupt void cc_isr(void)
    {
    
        //ccTimeInit = CPUTimer_getTimerCount(CPUTIMER0_BASE);
        //CPUTimer_startTimer(CPUTIMER0_BASE);
        //daOut();  // daOut() takes about 10[us].
        DELAY_US(0.55);
        /*------------------------------------------------------------------*/
        /*                         Start of ADC Sensing                     */
        /*------------------------------------------------------------------*/
        AdcResults[0] = AdcaResultRegs.ADCRESULT0;     // ADC01     : Ias_gs
        AdcResults[2] = AdcaResultRegs.ADCRESULT2;     // ADC03     : Ibs_gs
    
        AdcResults[4] = AdcaResultRegs.ADCRESULT4;     // ADC05     : Ias_c
        AdcResults[6] = AdccResultRegs.ADCRESULT0;     // ADC07     : Ibs_c
    
        AdcResults[1] = AdcaResultRegs.ADCRESULT1;     // ADC02     : Eab
        AdcResults[3] = AdcaResultRegs.ADCRESULT3;     // ADC04     : Ebc
        AdcResults[5] = AdcaResultRegs.ADCRESULT5;     // ADC06     : Vdc
        //AdcResults[7] = AdccResultRegs.ADCRESULT1;     // ADC08     : X
        AdcResults[8] = AdccResultRegs.ADCRESULT2;     // ADC09     : X
        //AdcResults[9] = AdccResultRegs.ADCRESULT3;     // ADC10     : X
    
        AdcValues[0] = ((((float)AdcResults[0] - (float)AdcOffset[0] * SetOffset[0])/ 4096. * 3.3 ) - (1.65 * (1-SetOffset[0])) ) * 6;  // ADC01
        AdcValues[1] = ((((float)AdcResults[1] - (float)AdcOffset[1] * SetOffset[1])/ 4096. * 3.3 ) - (1.65 * (1-SetOffset[1])) ) * 6;  // ADC02
        AdcValues[2] = ((((float)AdcResults[2] - (float)AdcOffset[2] * SetOffset[2])/ 4096. * 3.3 ) - (1.65 * (1-SetOffset[2])) ) * 6;  // ADC03
        AdcValues[3] = ((((float)AdcResults[3] - (float)AdcOffset[3] * SetOffset[3])/ 4096. * 3.3 ) - (1.65 * (1-SetOffset[3])) ) * 6;  // ADC04
        AdcValues[4] = ((((float)AdcResults[4] - (float)AdcOffset[4] * SetOffset[4])/ 4096. * 3.3 ) - (1.65 * (1-SetOffset[4])) ) * 6;  // ADC05
        AdcValues[5] = ((((float)AdcResults[5] - (float)AdcOffset[5] * SetOffset[5])/ 4096. * 3.3 ) - (1.65 * (1-SetOffset[5])) ) * 6;  // ADC06
        AdcValues[6] = ((((float)AdcResults[6] - (float)AdcOffset[6] * SetOffset[6])/ 4096. * 3.3 ) - (1.65 * (1-SetOffset[6])) ) * 6;  // ADC07
        //AdcValues[7] = ((((double)AdcResults[7] - (double)AdcOffset[7] * SetOffset[7])/ 4096. * 3.3 ) - (1.65 * (1-SetOffset[7])) ) * 6;  // ADC08
        AdcValues[8] = ((((float)AdcResults[8] - (float)AdcOffset[8] * SetOffset[8])/ 4096. * 3.3 ) - (1.65 * (1-SetOffset[8])) ) * 6;  // ADC09
        //AdcValues[9] = ((((double)AdcResults[9] - (double)AdcOffset[9] * SetOffset[9])/ 4096. * 3.3 ) - (1.65 * (1-SetOffset[9])) ) * 6;  // ADC10
    
        // <-- ADC variable calculation
        /*Ias_gs_test = AdcValues[0] * AdcScale[0];    // A-phase Grid-side Current
        Ibs_gs_test = AdcValues[2] * AdcScale[2];    // B-phase Grid-side Current
        Ics_gs_test = -(Ias_gs_test + Ibs_gs_test);  // C-phase Grid-side Current
        Ias_c_test = AdcValues[4] * AdcScale[4];     // A-phase Capacitor Current
        Ibs_c_test = AdcValues[6] * AdcScale[6];     // B-phase Capacitor Current
        Ics_c_test = -(Ias_c_test + Ibs_c_test);     // B-phase Capacitor Current
        Eab_test = AdcValues[1] * AdcScale[1];       // AB line to line Voltage
        Ebc_test = AdcValues[3] * AdcScale[3];       // BC line to line Voltage
        Eca_test = -(Eab_test + Ebc_test);           // CA line to line Voltage
        Vdc_test = AdcValues[5] * AdcScale[5];       // DC-link Voltage*/
    
        Controller.Ias_gs = AdcValues[0] * AdcScale[0];                // A-phase Grid-side Current
        Controller.Ibs_gs = AdcValues[2] * AdcScale[2];                // B-phase Grid-side Current
        Controller.Ics_gs = AdcValues[8] * AdcScale[8];//-(Controller.Ias_gs + Controller.Ibs_gs);  // C-phase Grid-side Current
        Controller.Ias_c = AdcValues[4] * AdcScale[4];                 // A-phase Capacitor Current
        Controller.Ibs_c = AdcValues[6] * AdcScale[6];                 // B-phase Capacitor Current
        Controller.Ics_c = -(Controller.Ias_c + Controller.Ibs_c);     // C-phase Capacitor Current
        GRID_AC.Eab = AdcValues[1] * AdcScale[1];                      // AB line to line Voltage
        GRID_AC.Ebc = AdcValues[3] * AdcScale[3];                      // BC line to line Voltage
        GRID_AC.Eca = -(GRID_AC.Eab + GRID_AC.Ebc);                    // CA line to line Voltage
        Controller.Vdc = AdcValues[5] * AdcScale[5];                   // DC-link Voltage
    
        /*------------------------------------------------------------------*/
        /*                         End of ADC Sensing                       */
        /*------------------------------------------------------------------*/
    
        /*------------------------------------------------------------------*/
        /*                         Start of Software Fault                  */
        /*------------------------------------------------------------------*/
    
        if(fabs(Controller.Ias_gs) > OC_Set_line)        Faults.SW_Prot.bit.OC_Ias = 1;
        if(fabs(Controller.Ibs_gs) > OC_Set_line)        Faults.SW_Prot.bit.OC_Ibs = 1;
        if(fabs(Controller.Ics_gs) > OC_Set_line)        Faults.SW_Prot.bit.OC_Ics = 1;
        if(fabs(GRID_AC.Eab) > OV_Set_line2line)         Faults.SW_Prot.bit.OV_Eab = 1;
        if(fabs(GRID_AC.Ebc) > OV_Set_line2line)         Faults.SW_Prot.bit.OV_Ebc = 1;
        if(fabs(Controller.Vdc) > OV_Set_DClink)         Faults.SW_Prot.bit.OV_Vdc = 1;
    
        if(Faults.SW_Prot.all){
        faultManage();
        checkHWFault();
        }
    
        /*------------------------------------------------------------------*/
        /*                         End of Software Fault                    */
        /*------------------------------------------------------------------*/
    
    //    // <-- Enable Signal
    
        if(Flags.EnableCnv == 1 && Flags.EnableCnv_Old == 0) {
    
            Flags.EnableGD2 = 1;
            //do something --> Flag_CCont = 1;
            Flags.EnableCnv_Old = 1;
        }
        if(Flags.EnableCnv == 0 && Flags.EnableCnv_Old == 1) {
           // Flags.EnableGD2 = 0;
            //do something --> Flag_VdcPCont = 0, Flag_BalCont = 0, Flag_CCont = 0;
            //do something --> Flag_StartDAB = 0, Flag_ControlDAB = 0;
            Flags.EnableCnv_Old = 0;
        }
    
        if(Flags.EnableInv == 1 && Flags.EnableInv_Old == 0) {
            Flags.EnableGD1 = 1;
            //do something --> Flag_CCont = 1;
            Flags.EnableInv_Old = 1;
        }
        if(Flags.EnableInv == 0 && Flags.EnableInv_Old == 1) {
         //   Flags.EnableGD1 = 0;
            //do something --> Flag_VdcPCont = 0, Flag_BalCont = 0, Flag_CCont = 0;
            //do something --> Flag_StartDAB = 0, Flag_ControlDAB = 0;
            Flags.EnableInv_Old = 0;
    
        }
    
        /*------------------------------------------------------------------*/
        /*                         User Code Start                          */
        /*------------------------------------------------------------------*/
    
        if(Flags.PLL_Start == 1){
    
            GRID_Update(&GRID_AC);
            Detector_Update(&Controller);
            tEqe_err = GRID_AC.Eqep / GRID_AC.Epeakp;
            PLL_Control(&GRID_AC_PLL, tEqe_err);
    
            GRID_AC.Thetae = GRID_AC_PLL.Thetae;
            GRID_AC.We = GRID_AC_PLL.We;
    
            }
    
        if(Flags.Detector_Start == 1){
    
            Detector_Update(&Controller);
            Controller.Thetae = GRID_AC_PLL.Thetae;
            Controller.We = GRID_AC_PLL.We;
            Controller.Ede = GRID_AC.Edep;
            Controller.Eqe = GRID_AC.Eqep;
            Controller.Eds = GRID_AC.Edsp;
            Controller.Eqs = GRID_AC.Eqsp;
            }
    
        if(Flags.Run_zero == 1 && (GRID_AC.Eab < 1 && GRID_AC.Eab > -1)){
    
            Flags.Run = 1;
            }
    
        if(Flags.Run == 1){
    
            Current_Controller(&Controller);
            Flags.StartInverter = 1;
            //Energy_Controller(&Controller);
    
            }
    
        if(Flags.Run == 1 && Flags.Stop == 1){
    
            GaCountA =0.; GaCountB =0.; GaCountC =0.;
            Flags.StartInverter = 0;
            Controller_Init(&Controller);
            Flags.Run_zero = 0;
            Flags.Run = 0;
            Flags.Stop = 0;
    
          }
    
        /*------------------------------------------------------------------*/
        /*                          User Code End                           */
        /*------------------------------------------------------------------*/
    
        // <-- Gating Counter Value Update
        // Inverter FLOAT to INT conversion
    
       GaCountA = (int)(SYS_CLK * Controller.TDuty_A);
       GaCountA = (GaCountA > PWMMaxCount) ? PWMMaxCount : ((GaCountA < 0) ? 0 : GaCountA);
       GaCountB = (int)(SYS_CLK * Controller.TDuty_B);
       GaCountB = (GaCountB > PWMMaxCount) ? PWMMaxCount : ((GaCountB < 0) ? 0 : GaCountB);
       GaCountC = (int)(SYS_CLK * Controller.TDuty_C);
       GaCountC = (GaCountC > PWMMaxCount) ? PWMMaxCount : ((GaCountC < 0) ? 0 : GaCountC);
    
        // ***** PWM1 ***** //
        EPwm1Regs.CMPA.bit.CMPA = GaCountA;
        EPwm2Regs.CMPA.bit.CMPA = GaCountB;
        EPwm3Regs.CMPA.bit.CMPA = GaCountC;
    
        // ***** PWM2 ***** //
        /*EPwm4Regs.CMPA.bit.CMPA= GaCountA2;
        EPwm5Regs.CMPA.bit.CMPA= GaCountB2;
        EPwm6Regs.CMPA.bit.CMPA= GaCountC2;*/
    
    
        // <-- PWM count reference mapping
        // EPwm1Regs.CMPA.bit.CMPA = PWM01_Count_Ref;
        // EPwm2Regs.CMPA.bit.CMPA = PWM02_Count_Ref;
        // EPwm3Regs.CMPA.bit.CMPA = PWM03_Count_Ref;
        // EPwm4Regs.CMPA.bit.CMPA = PWM04_Count_Ref;
        // EPwm5Regs.CMPA.bit.CMPA = PWM05_Count_Ref;
        // EPwm6Regs.CMPA.bit.CMPA = PWM06_Count_Ref;
        // EPwm7Regs.CMPA.bit.CMPA = PWM07_Count_Ref;
        // EPwm8Regs.CMPA.bit.CMPA = PWM08_Count_Ref;
        // EPwm9Regs.CMPA.bit.CMPA = PWM09_Count_Ref;
        // EPwm10Regs.CMPA.bit.CMPA = PWM10_Count_Ref;
        // EPwm11Regs.CMPA.bit.CMPA = PWM11_Count_Ref;
        // EPwm12Regs.CMPA.bit.CMPA = PWM12_Count_Ref;
        // PWM count reference mapping -->
    
    
    ///// <-- Gating Signal Enable
    /*
        if(Flags.Fault == 0 && Flags.Fault_Old == 0) {
            checkHWFault();
            if(Flags.EnableStart_Old == 0 && Flags.EnableStart == 1) {
                if(Flags.EnableGD1 == 1)    GpioDataRegs.GPCCLEAR.bit.GPIO69 = 1;               // GPIO69 = GD1_OEn
                else                GpioDataRegs.GPCSET.bit.GPIO69 = 1;
                if(Flags.EnableGD2 == 1)    GpioDataRegs.GPCCLEAR.bit.GPIO70 = 1;               // GPIO70 = GD2_OEn
                else                GpioDataRegs.GPCSET.bit.GPIO70 = 1;
                if(Flags.EnableGD3 == 1)    GpioDataRegs.GPCCLEAR.bit.GPIO74 = 1;               // GPIO74 = GD3_OEn
                else                GpioDataRegs.GPCSET.bit.GPIO74 = 1;
                if(Flags.EnableGD4 == 1)    GpioDataRegs.GPCCLEAR.bit.GPIO75 = 1;               // GPIO75 = GD4_OEn
                else                GpioDataRegs.GPCSET.bit.GPIO75 = 1;
    
                Flags.EnableStart_Old = 1;
            }
            if(Flags.EnableStart_Old == 1 && Flags.EnableStart == 0) {
                Flags.EnableGD1 = 0, GpioDataRegs.GPCSET.bit.GPIO69 = 1;
                Flags.EnableGD2 = 0, GpioDataRegs.GPCSET.bit.GPIO70 = 1;
                Flags.EnableGD3 = 0, GpioDataRegs.GPCSET.bit.GPIO74 = 1;
                Flags.EnableGD4 = 0, GpioDataRegs.GPCSET.bit.GPIO75 = 1;
                Flags.EnableStart_Old = 0;
            }
        } else {
            faultManage();
        }
        */
    
        if(Flags.Fault == 0 && Flags.Fault_Old == 0) {
               checkHWFault();
               if(Flags.StartInverter_old == 0 && Flags.StartInverter == 1) {Flags.EnableGD1 = 1;
                   if(Flags.EnableGD1 == 1)    GpioDataRegs.GPCCLEAR.bit.GPIO69 = 1;               // GPIO69 = GD1_OEn
                   else                GpioDataRegs.GPCSET.bit.GPIO69 = 1;
    
                   Flags.StartInverter_old = 1;
               }
               if(Flags.StartInverter_old == 1 && Flags.StartInverter == 0) {
                   Flags.EnableGD1 = 0, GpioDataRegs.GPCSET.bit.GPIO69 = 1;
                   Flags.StartInverter_old = 0;
               }
    
               if(Flags.StartCnverter_old == 0 && Flags.StartCnverter == 1) { Flags.EnableGD2 = 1;
                   if(Flags.EnableGD2 == 1)    GpioDataRegs.GPCCLEAR.bit.GPIO70 = 1;               // GPIO70 = GD2_OEn
                   else                GpioDataRegs.GPCSET.bit.GPIO70 = 1;
    
                   Flags.StartCnverter_old = 1;
               }
               if(Flags.StartCnverter_old == 1 && Flags.StartCnverter == 0) {
                   Flags.EnableGD2 = 0, GpioDataRegs.GPCSET.bit.GPIO70 = 1;
                   Flags.StartCnverter_old = 0;
                 }
           }
    
        else {
               faultManage();
           }
        ///// Gating Signal Enable -->
    
        // <-- Fault reset check
        if(Flags.Reset == 1) {
            checkHWFault();
            if(GpioDataRegs.GPBDAT.bit.GPIO53 == 0x1) {
                Flags.Fault = 0;
                Flags.Fault_Old = 0;
                Flags.Reset = 0;
                Fault_cnt=0;
            }
            else{
            Flags.Reset = 0;}
        }
    
        // Fault reset check -->
    
    
        // <-- LED code
        if(cc_cnt >= 5000U) {
            cc_cnt = 0;
            //GpioDataRegs.GPBTOGGLE.bit.GPIO48 = 1;       // LED0 - Red
            //GpioDataRegs.GPBTOGGLE.bit.GPIO49 = 1;       // LED1 -
            GpioDataRegs.GPBTOGGLE.bit.GPIO50 = 1;       // LED2 - Yellow
            //GpioDataRegs.GPBTOGGLE.bit.GPIO51 = 1;       // LED3 - Blue
        } else {
            cc_cnt++;
        }
    
        // LEC code -->
    
        // <-- Timer stop
        CPUTimer_stopTimer(CPUTIMER0_BASE);
        ccTimePresent = CPUTimer_getTimerCount(CPUTIMER0_BASE);
        ccTime_us = 1000000.*(float)SYS_CLK_PRD*(ccTimeInit - ccTimePresent);
        CPUTimer_reloadTimerCounter(CPUTIMER0_BASE);
        // Timer stop -->
    
     //   EPwm1Regs.ETCLR.bit.SOCA = 1; //clear SOCA flag
        EPwm1Regs.ETCLR.bit.INT = 1; //clear INT flag
        PieCtrlRegs.PIEACK.all = PIEACK_GROUP3;
    
    }
    /////////////////////////////////CC END/////////////////////////////////////////
    

    此处、我在 ISR 开始时插入了一个延迟、以确保采样保持时间和锁存时间。

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    您好!

    在没有将延迟考虑在内的情况下、你的 ISR 似乎是非常长的。 请阅读  参考手册 ADC 一章中的第10.7.1节中断溢出、了解有关检查该错误的更多信息。 您还可以参阅 C2000Ware_5_01_00_00\driverlib\f2837xs+ examples\cpu1\ADC 中提供的示例、这些示例更好地了解如何为某些用例配置 ADC 及其中断。 为了获得更准确的 ADC 读数、应该避免中断溢出。

    一般而言、ISR 应尽可能短、因为目的是将 ISR 用于实时程序、在实时程序中会快速发生中断并进行处理。

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    我采用100us 的采样周期进行控制、我的 ISR 的总执行时间大约为50us、从而提供了足够的裕度。 我的好奇心是在 ISR 开始时同时读取 ADCResults 值。 考虑到 SAMP 和保持时间以及锁存时间、我添加了大约550ns 的延迟、在这种情况下、ADC 似乎正常运行(我参考了第10.12节)。 但是、当我过度添加1us 延迟时、ADC 读取的值会有所不同。 如果未添加延迟、ADC 会按预期读取现有数据、因为 SAMP 和保持时间+锁存时间(我的规格是400ns)不受保护。

    总结)
    1. ADC 立即读取现有数据。

    2.在考虑 SAMP 和保持时间+锁存时间时,延迟约为550ns ,读取正确的值。

    3.添加1us 或以上的延迟会导致 ADC 读取的值与 ePWM 向上/向下计数点相比有所延迟。

    我认为2和3的结果应该是相同的。

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    我控制的采样周期为100 us

    我看到了、我没有看到您的 EPWM 配置代码、因此我认为您是尽快触发 ADC。

    2.在考虑 SAMP 和保持时间+锁存时间时,延迟约为550ns ,读取正确的值。

    3.添加1us 或以上的延迟会导致 ADC 读取的值与 ePWM 向上/向下计数点相比有所延迟。

    我认为2和3的结果应该相同、

    [/报价]

    您是在闪存还是 RAM 中运行这个程序?  您是否使用 CPU 定时器或 DELAY_US 创建延迟(您的屏幕截图与您提供的代码不一致)?

    在上下文中、从闪存运行总是比从 RAM 运行慢、所以一个诸如 DELAY_US 的 DELAY 函数将通过刻录周期来产生一个延迟、而这个周期在闪存中需要更长的时间(这会导致一个中断溢出)。 然而、使用 CPU 定时器会对来自 CPU 的一个独立定时器的周期进行计数、所以它应该在闪存上工作。 您 还应该通过切换 GPIO 或一些外部信号来验证每个 ISR 触发器之间的长度、从而验证所添加的延迟。 如果您通过这样做来看到一致的计时、请告诉我。