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-F28027: ADC sampling rate

Part Number: LAUNCHXL-F28027
Other Parts Discussed in Thread: CONTROLSUITE

Hi.

I've been trying to configure the sample rate of f28027 adc. 

I set the TPBRD to 500 in order to obtain 100kHz, but i don't know how to verify this configuration. then i tried toggle a led before i read the ADC result, but it gives me 9.61 kHz so I don't know if i'm measuring wrong.

I see the XCLKOUT register on a GPIO and it gives me the frequency expected.

Regards

thank you

  • Hi David,

    The best way to check this is to output the ePWM pulse that triggers ADC soc. To do the same, you can refer any ePWM example from controlSuite.

    Regards,
    Gautam
  • Hi Gautam, thank's  for answer.

    i did what you told me, and i can see in the scope the ADC Frequency that i configure in the following code. (10 MHz)

    But i have a problem: I don''t know if i'm measuring right and in the right part of the code.

    its supposed the ADC takes 7 cycles of the ADC clock (in this case 10 MHz) and take 13 cycles to convert the value it measures. so when i toogle the led everytime the ADC does the conversion, it should give me 500 kHz but it didn't, it gives me a frequency of 24 kHz so it means 48 kHz of conversion rate  (No matter the ADC frequency i configure)

    This code takes an ADC value and convert it to an equivalent duty cycle and then do a PWM.

    #include "DSP28x_Project.h"     // Device Headerfile and Examples Include File
    #include "f2802x_common/include/adc.h"
    #include "f2802x_common/include/clk.h"
    #include "f2802x_common/include/flash.h"
    #include "f2802x_common/include/gpio.h"
    #include "f2802x_common/include/pie.h"
    #include "f2802x_common/include/pll.h"
    #include "f2802x_common/include/timer.h"
    #include "f2802x_common/include/wdog.h"
    #include "f2802x_common/include/pwr.h"
    #include "f2802x_common/include/pwm.h"
    void pwm_Init_();
    unsigned int TBPRD = 600;
    unsigned int CMPA=0; //32500;
    ADC_Handle   myAdc;
    CLK_Handle   myClk;
    FLASH_Handle myFlash;
    GPIO_Handle  myGpio;
    PIE_Handle   myPie;
    TIMER_Handle myTimer;
    CPU_Handle   myCpu;
    PLL_Handle   myPll;
    WDOG_Handle  myWDog;
    PWM_Handle myPwm1;
    PWM_Handle myPwm2;
    PWR_Handle myPwr;
    uint16_t Digital_Result =0;
    void globaldisable();
    void globalenable();
    void ADC_INIT_Fn();
    void ADC_SETUP_Fn();
    void set_duty(int a);
    int adcresult=5;
    int flag1=0;
    interrupt void adc_isr(void)
    {
        //discard ADCRESULT0 as part of the workaround to the 1st sample errata for rev0
        Digital_Result = ADC_readResult(myAdc, ADC_ResultNumber_0);
        adcresult =Digital_Result;
        set_duty(adcresult);
        GPIO_toggle(myGpio, GPIO_Number_3);
        ADC_clearIntFlag(myAdc, ADC_IntNumber_1);   // Clear ADCINT1 flag reinitialize for next SOC
        PIE_clearInt(myPie, PIE_GroupNumber_10);// Acknowledge interrupt to PIE
        return;
    }
    void main(void)
    {
    myAdc = ADC_init((void *)ADC_BASE_ADDR, sizeof(ADC_Obj));
       myClk = CLK_init((void *)CLK_BASE_ADDR, sizeof(CLK_Obj));
       myCpu = CPU_init((void *)NULL, sizeof(CPU_Obj));
       myFlash = FLASH_init((void *)FLASH_BASE_ADDR, sizeof(FLASH_Obj));
       myGpio = GPIO_init((void *)GPIO_BASE_ADDR, sizeof(GPIO_Obj));
       myPie = PIE_init((void *)PIE_BASE_ADDR, sizeof(PIE_Obj));
       myPll = PLL_init((void *)PLL_BASE_ADDR, sizeof(PLL_Obj));
       myTimer = TIMER_init((void *)TIMER0_BASE_ADDR, sizeof(TIMER_Obj));
       myWDog = WDOG_init((void *)WDOG_BASE_ADDR, sizeof(WDOG_Obj));
       myPwm1 = PWM_init((void *)PWM_ePWM1_BASE_ADDR, sizeof(PWM_Obj));
       myPwm2 = PWM_init((void *)PWM_ePWM2_BASE_ADDR, sizeof(PWM_Obj));
       myPwr = PWR_init((void *)PWR_BASE_ADDR, sizeof(PWR_Obj));
        // Perform basic system initialization
        WDOG_disable(myWDog);
        CLK_enableAdcClock(myClk);
        (*Device_cal)();
        CLK_setOscSrc(myClk, CLK_OscSrc_Internal);  //Select the internal oscillator 1 as the clock source
        PLL_setup(myPll, PLL_Multiplier_12, PLL_DivideSelect_ClkIn_by_1);  // Setup the PLL for x10 /2 which will yield 50Mhz = 10Mhz * 10 / 2
        PIE_disable(myPie);
        PIE_disableAllInts(myPie);
        CPU_disableGlobalInts(myCpu);
        CPU_clearIntFlags(myCpu);
        GPIO_setMode(myGpio, GPIO_Number_18, GPIO_18_Mode_XCLKOUT);
        GPIO_setMode(myGpio, GPIO_Number_0, GPIO_0_Mode_EPWM1A);
        GPIO_setMode(myGpio, GPIO_Number_3, GPIO_0_Mode_GeneralPurpose);
        GPIO_setDirection(myGpio, GPIO_Number_3, GPIO_Direction_Output);
        GPIO_setMode(myGpio, GPIO_Number_2, GPIO_2_Mode_EPWM2A);
        CLK_setClkOutPreScaler(myClk, CLK_ClkOutPreScaler_SysClkOut_by_2);
        PIE_setDebugIntVectorTable(myPie);
        PIE_enable(myPie);
        globalenable();
        ADC_INIT_Fn();
        ADC_SETUP_Fn();
          CLK_disableTbClockSync(myClk);
          CLK_enablePwmClock(myClk, PWM_Number_2);
          PWM_enableSocAPulse(myPwm2);                                         // Enable SOC on A group
              PWM_setSocAPulseSrc(myPwm2, PWM_SocPulseSrc_CounterEqualCmpAIncr);   // Select SOC from from CPMA on upcount
              PWM_setSocAPeriod(myPwm2, PWM_SocPeriod_FirstEvent);                 // Generate pulse on 1st event
              PWM_setCmpA(myPwm2, 3);                                         // Set compare A value
              PWM_setPeriod(myPwm2, 6);                                       // Set period for ePWM1
              PWM_setCounterMode(myPwm2, PWM_CounterMode_UpDown);                      // count up and start
              PWM_disableCounterLoad(myPwm2);                     // Disable phase loading
              PWM_setHighSpeedClkDiv(myPwm2, PWM_HspClkDiv_by_1); // Clock ratio to SYSCLKOUT
              PWM_setClkDiv(myPwm2, PWM_ClkDiv_by_1);
                 // Setup shadowing
              PWM_setShadowMode_CmpA(myPwm2, PWM_ShadowMode_Shadow);
              PWM_setLoadMode_CmpA(myPwm2, PWM_LoadMode_Zero);
                 // Set actions
              PWM_setActionQual_CntUp_CmpA_PwmA(myPwm2, PWM_ActionQual_Clear);      // Set PWM1A on event A, up count
              PWM_setActionQual_CntDown_CmpA_PwmA(myPwm2, PWM_ActionQual_Set);  // Clear PWM1A on event A, down count
              pwm_Init_();
      //
          CLK_enableTbClockSync(myClk);
        while(1)
        {
         ADC_forceConversion(myAdc, ADC_SocNumber_0);// Wait for ADC interrupt
         }
    }
    void globalenable()
    {
      PIE_enable(myPie);
      // Register interrupt handlers in the PIE vector table
      CPU_enableInt(myCpu, CPU_IntNumber_10);  // Enable CPU Interrupt 1
      CPU_enableGlobalInts(myCpu);        // Enable Global interrupt INTM
      CPU_enableDebugInt(myCpu);     // Enable Global realtime interrupt DBGM
          // Enable XINT1 in the PIE: Group 1 interrupt 4 & 5
          // Enable INT1 which is connected to WAKEINT
          PIE_enableInt(myPie, PIE_GroupNumber_1, PIE_InterruptSource_XINT_1);
          CPU_enableInt(myCpu, CPU_IntNumber_1);
         // GPIO0 is XINT1, GPIO1 is XINT2
         GPIO_setExtInt(myGpio, GPIO_Number_12, CPU_ExtIntNumber_1);
         // Configure XINT1
         PIE_setExtIntPolarity(myPie, CPU_ExtIntNumber_1, PIE_ExtIntPolarity_RisingEdge);
         // Enable XINT1 and XINT2
         PIE_enableExtInt(myPie, CPU_ExtIntNumber_1);
    }
    void ADC_INIT_Fn()
    {
      ADC_enableBandGap(myAdc);
      ADC_enableRefBuffers(myAdc);
      ADC_powerUp(myAdc);
      ADC_enable(myAdc);
      ADC_setVoltRefSrc(myAdc, ADC_VoltageRefSrc_Int);
    }
    void ADC_SETUP_Fn()
    {
     PIE_registerPieIntHandler(myPie, PIE_GroupNumber_10, PIE_SubGroupNumber_1, (intVec_t)&adc_isr);
      PIE_enableAdcInt(myPie, ADC_IntNumber_1);  // Enable ADCINT1 in PIE
      //Note: Channel ADCINA1  will be double sampled to workaround the ADC 1st sample issue for rev0 silicon errata
      //ADC_setIntPulseGenMode(myAdc, ADC_IntPulseGenMode_Prior);               //ADCINT1 trips after AdcResults latch
      ADC_setIntPulseGenMode(myAdc, ADC_IntPulseGenMode_During);               //ADCINT1 trips after AdcResults latch
      ADC_enableInt(myAdc, ADC_IntNumber_1);                                  //Enabled ADCINT1
      //ADC_setIntMode(myAdc, ADC_IntNumber_1, ADC_IntMode_ClearFlag);          //Disable ADCINT1 Continuous mode
      //ADC_setIntMode(myAdc, ADC_IntNumber_1, ADC_IntMode_EOC);          //Disable ADCINT1 Continuous mode
      ADC_setIntSrc(myAdc, ADC_IntNumber_1, ADC_IntSrc_EOC0);                 //setup EOC0 to trigger ADCINT1 to fire
      ADC_setSocChanNumber (myAdc, ADC_SocNumber_0, ADC_SocChanNumber_A4);    //set SOC0 channel select to ADCINA4
     ADC_setSocTrigSrc(myAdc, ADC_SocNumber_0, ADC_SocTrigSrc_EPWM2_ADCSOCA);      //set SOC0 start trigger on EPWM1A, due to round-robin SOC0 converts first then SOC1
     ADC_setSocSampleWindow(myAdc, ADC_SocNumber_0, ADC_SocSampleWindow_7_cycles);   //set SOC0 S/H Window to 7 ADC Clock Cycles, (6 ACQPS plus 1)
    }
    void pwm_Init_()
    {
        CLK_enablePwmClock(myClk, PWM_Number_1);
        // Setup TBCLK
        PWM_setPeriod(myPwm1, TBPRD);   // Set timer period 801 TBCLKs
        PWM_setPhase(myPwm1, 0x0000);   // Phase is 0
        PWM_setCount(myPwm1, 0x0000);   // Clear counter
        // Set Compare values
        // Setup counter mode
        PWM_setCounterMode(myPwm1, PWM_CounterMode_UpDown); // Count up and down
        PWM_disableCounterLoad(myPwm1);                     // Disable phase loading
        PWM_setHighSpeedClkDiv(myPwm1, PWM_HspClkDiv_by_1); // Clock ratio to SYSCLKOUT
        PWM_setClkDiv(myPwm1, PWM_ClkDiv_by_1);
        // Setup shadowing
        PWM_setShadowMode_CmpA(myPwm1, PWM_ShadowMode_Shadow);
        PWM_setLoadMode_CmpA(myPwm1, PWM_LoadMode_Zero);
        // Set actions
        PWM_setActionQual_CntUp_CmpA_PwmA(myPwm1, PWM_ActionQual_Clear);      // Set PWM1A on event A, up count
        PWM_setActionQual_CntDown_CmpA_PwmA(myPwm1, PWM_ActionQual_Set);  // Clear PWM1A on event A, down count
    }
    void set_duty( int a)
    {
     CMPA =a*0.14652;
     PWM_setCmpA(myPwm1, CMPA);      // Set compare A value
    }
    Thank you so much
    Regards
  • Hi David,

    Continually software forcing conversions is going to cause strange things to happen if ePWM triggering is also occuring:

    while(1)
    {
    ADC_forceConversion(myAdc, ADC_SocNumber_0);// Wait for ADC interrupt
    }

    This doesn't wait for the ADC interrupt, but instead causes the ADC to start converting right away instead of waiting for an ePWM trigger.