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.

[参考译文] LAUNCHXL-F28379D:1 MHz ADC 采样频率验证

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

https://e2e.ti.com/support/microcontrollers/c2000-microcontrollers-group/c2000/f/c2000-microcontrollers-forum/1343887/launchxl-f28379d-1-mhz-adc-sampling-frequency-verification

器件型号:LAUNCHXL-F28379D

我的应用本质上是对同步降压转换器的 PWM 控制、其中的 PWM 频率为100kHz、我想在每个开关周期对电感器电流和输出电压进行多次采样。

我的执行情况如下:

  • 用于低侧和高侧 FET PWM 的 ePWM 4A 和4B
  • EPWM 3A 用作 ADC SOC 触发器
  • 使用 ADC A2作为中断

验证1MHz ADC 采样时遇到问题。 只是为了分析和验证 ADC 中断时序、我在每个中断例程期间使用了一个计数器来递增(跟踪经过的微秒数)、 当它达到等于1秒的值时、我会使标志递增、以表示已处理1秒的中断例程。 通过秒表、我可以比较"标志"更新和实时更新、以确保两者的速度相同。

这适用于高达200kHz 的 ePWM3频率、但超出该范围、"标志"更新会慢于1秒。 我不确定我的评估 ADC 中断时序的方法是否可靠/准确、或者是否有些东西实际上影响超过特定速率的 ADC 中断服务。 但我可以在外部示波器上看到、ePWM3脉冲的频率匹配 TBPRD 和预分频器所指的任何频率(在本例中为1 MHz)。 我甚至尝试禁用 ePWM4脉冲来排除任何优先级问题、但仍然无法正常工作。 请查看附件中的代码。

// ePWM 4A: 100 kHz, 27% duty, up-down counting
// ePWM 4B: 100 kHz, 27% duty, up-down counting, deadband + complementary

#include "F28x_Project.h"
#include "math.h"

void Gpio_select();
void Setup_ePWM4();
void Setup_ePWM3();
void ConfigureADC(void);
void SetupADCSoftware(void);
extern interrupt void adca2_isr(void);

float duty=0.27; //open-loop duty ratio of control FET
float timerprd; //EPWM3 period in micro seconds for ADC SOC trigger
long int counter=0; //counter to check CPU Timer0 timing
int flag=0; //checking 1 sec counter mark
float AdcaResult0;
float ADC_voltage=0.0;
long int adc_f=1000e3; // ADC sampling rate
int adc_x=1, adc_y=1; // ADC ePWM PRD prescalers
Uint16 PWM3_PRD; //TBPRD for ePWM3

void main(void)
{
    InitSysCtrl();
    DINT;
    InitPieCtrl();
    IER = 0x0000;
    IFR = 0x0000;
    InitPieVectTable();

    PWM3_PRD = (100e6/adc_f/adc_x/adc_y)-1;
    timerprd = 1e6/adc_f;

    EALLOW;
    PieVectTable.ADCA2_INT = &adca2_isr;
    EDIS;

    IER |= M_INT10;
    PieCtrlRegs.PIEIER10.bit.INTx2 = 1;

    Gpio_select();
    //Setup_ePWM4();
    Setup_ePWM3();
    ConfigureADC();
    SetupADCSoftware();
    EINT;
    ERTM;

    while(1);

}

void Gpio_select()
{
    EALLOW;
    GpioCtrlRegs.GPAMUX1.bit.GPIO4=1;
    GpioCtrlRegs.GPAMUX1.bit.GPIO5=1;
    GpioCtrlRegs.GPAMUX1.bit.GPIO6=1;
    GpioCtrlRegs.GPAMUX1.bit.GPIO7=1;
    EDIS;
}

void Setup_ePWM4()
{
    EPwm4Regs.TBCTL.bit.CLKDIV=0;
    EPwm4Regs.TBCTL.bit.HSPCLKDIV=0;
    EPwm4Regs.TBCTL.bit.CTRMODE=2;
    EPwm4Regs.TBPRD=500;
    EPwm4Regs.AQCTLA.all=0x0060;
    //EPwm3Regs.AQCTLB.all=0x0090;
    EPwm4Regs.CMPA.bit.CMPA=500*(1-duty);

    EPwm4Regs.DBCTL.bit.OUT_MODE=3;
    EPwm4Regs.DBCTL.bit.POLSEL=2;
    EPwm4Regs.DBRED.all=50;
    EPwm4Regs.DBFED.all=50;
}

void Setup_ePWM3()
{
    EPwm3Regs.TBCTL.bit.CLKDIV=0;
    EPwm3Regs.TBCTL.bit.HSPCLKDIV=0;
    EPwm3Regs.TBCTL.bit.CTRMODE=0;
    EPwm3Regs.TBPRD=PWM3_PRD;
    EPwm3Regs.AQCTLA.all=0x0012;
    EPwm3Regs.CMPA.bit.CMPA=PWM3_PRD/2;

    EPwm3Regs.ETSEL.bit.SOCAEN=1;
    EPwm3Regs.ETSEL.bit.SOCASEL=1;
    EPwm3Regs.ETPS.bit.SOCAPRD=1;
    EPwm3Regs.ETCLR.bit.SOCA=1;

    EPwm3Regs.ETSEL.bit.INTEN=1;
    EPwm3Regs.ETSEL.bit.INTSEL=1;
    EPwm3Regs.ETPS.bit.INTPRD=1;
    EPwm3Regs.ETCLR.bit.INT=1;
}

void ConfigureADC(void)
{
    EALLOW;
    AdcaRegs.ADCCTL2.bit.PRESCALE = 6; // Set ADCCLK divider to SYSCLK/4
    AdcSetMode(ADC_ADCA, ADC_RESOLUTION_12BIT, ADC_SIGNALMODE_SINGLE);
    AdcaRegs.ADCCTL1.bit.INTPULSEPOS = 1;
    AdcaRegs.ADCCTL1.bit.ADCPWDNZ = 1; // Set value to power up the ADCs
    EDIS;
    DELAY_US(1000); // Set value for delay of 1 ms to allow ADC time to power up
}

void SetupADCSoftware(void)
{
    Uint16 acqps;
    if(ADC_RESOLUTION_12BIT == AdcaRegs.ADCCTL2.bit.RESOLUTION)
    {
       acqps = 14; // Determine minimum acquisition window (in SYSCLKS)
    }
    else
    {
       acqps = 63; // Determine minimum acquisition window (in SYSCLKS)
    }
    EALLOW;
    AdcaRegs.ADCSOC0CTL.bit.CHSEL = 4; // Set value for channel selection
    AdcaRegs.ADCSOC0CTL.bit.ACQPS = acqps;
    AdcaRegs.ADCSOC0CTL.bit.TRIGSEL = 9; // Sets ePWM3 as SOC0 trigger source
    AdcaRegs.ADCINTSEL1N2.bit.INT2SEL = 0; // Event for which INT2 flag is set
    AdcaRegs.ADCINTSEL1N2.bit.INT2E = 1; // Enable INT2 flag
    AdcaRegs.ADCINTFLGCLR.bit.ADCINT2 = 1; // Make sure INT2 flag is cleared
    EDIS;
}

extern interrupt void adca2_isr(void)
{
    AdcaRegs.ADCINTFLGCLR.bit.ADCINT2 = 1;
    if(1 == AdcaRegs.ADCINTOVF.bit.ADCINT2)
    {
        AdcaRegs.ADCINTFLGCLR.bit.ADCINT2 = 1;
        AdcaRegs.ADCINTOVFCLR.bit.ADCINT2 = 1;
    }
    AdcaResult0 = AdcaResultRegs.ADCRESULT0; // Write code to store results to this variable
    ADC_voltage = AdcaResult0/4095*3; // Convert ADC result to voltage
    counter++;
    if(counter>=1000000/timerprd)
    {
        flag++;
        counter=0;
    }
    PieCtrlRegs.PIEACK.all = PIEACK_GROUP10;
}

我对 DSP 编程相对比较陌生、因此、如果我遗漏了一些额外的信息或在这里犯了一个简单的错误、请用我有限的知识忍受我的知识。 请就此事请求支持。 请告诉我、我是否可以提供任何其他支持信息来更好地帮助我提出问题。

提前感谢、
SV

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

    您好!

    我想您的问题与 ISR 的延迟有关。 您是否需要 AdcaResult0为浮点数? 对浮点值执行除法和乘法会花费大量的周期。

    有关如何使用 CCS 测量时钟周期的信息、请参阅此文章: https://software-dl.ti.com/ccs/esd/documents/ccs_counting_cycles.html

    此致、

    本·科利尔

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

    如果您不需要这种精度、请考虑使用位移来近似乘法和除法、以节省时间。