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.

EK-TM4C123GXL: TM4C123GH6PM ADC TRIGGER BY PWM (ONLY RISING EDGE)

Part Number: EK-TM4C123GXL
Other Parts Discussed in Thread: TM4C123GH6PM

I want to do ADC calculation on EK-TM4C132GXL development board. But I want to do this calculation using PWM signal. In short, every time the PWM signal is at the rising edge, I want the ADC to trigger and take a sample at that time and continue this process, but I could not do this, can you help me?

#include <stdint.h>
#include <stdbool.h>
#include "inc/hw_memmap.h"
#include "inc/hw_types.h"
#include "driverlib/debug.h"
#include "driverlib/sysctl.h"
#include "driverlib/adc.h"
#define TARGET_IS_BLIZZARD_RB1
#include "driverlib/rom.h"
#include "driverlib/sysctl.h"
#include "driverlib/pin_map.h"
#include "driverlib/gpio.h"
#include "driverlib/pwm.h"


uint32_t ui32ADCAvg=0;
uint32_t ui32ADC0Value[8] = {0};
uint32_t ui32Load=0;
int cnt=0;
void handler_ADC(void);

void ADC_init(void);
void PWM_init(void);

int main(void)
{

// Set the System clock to 80MHz and enable the clock for peripherals ADC0 and GPIO PortB
SysCtlClockSet(SYSCTL_SYSDIV_2_5|SYSCTL_USE_PLL|SYSCTL_OSC_MAIN|SYSCTL_XTAL_16MHZ);

//handler_ADC();
PWM_init();
ADC_init();
while(1)
{
// Clear the ADC Interrupt (if any generated) for Sequencer 0
//ADCSequenceDataGet(ADC0_BASE, 1, &ui32ADC0Value[0]);
/*ADCSequenceDataGet(ADC0_BASE, 1, &ui32ADC0Value[1]);
ADCSequenceDataGet(ADC0_BASE, 1, &ui32ADC0Value[2]);
ADCSequenceDataGet(ADC0_BASE, 1, &ui32ADC0Value[3]);
ADCSequenceDataGet(ADC0_BASE, 1, &ui32ADC0Value[4]);
ADCSequenceDataGet(ADC0_BASE, 1, &ui32ADC0Value[5]);
ADCSequenceDataGet(ADC0_BASE, 1, &ui32ADC0Value[6]);
ADCSequenceDataGet(ADC0_BASE, 1, &ui32ADC0Value[7]);*/
// Trigger the ADC Sampling for Sequencer 0
//ADCProcessorTrigger(ADC0_BASE, 1);
// Wait the program till the conversion isn't complete
// while(ADCIntStatus(ADC0_BASE, 1, false));
// Store the values in sequencer 0 of ADC0 to an Array
// Calculate the Average of the Readings

}


}

void ADC_init(void)
{
SysCtlPeripheralEnable(SYSCTL_PERIPH_ADC0);
SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOE);
//SysCtlADCSpeedSet(SYSCTL_ADCSPEED_250KSPS);

// Enable hardware averaging on ADC0
ADCHardwareOversampleConfigure(ADC0_BASE, 64);//

// Configure to use ADC0, sample sequencer 0, processor to trigger sequence and use highest priority
ADCSequenceConfigure(ADC0_BASE, 0, ADC_TRIGGER_PWM0, 1);
// Configure PB4 as Analog Input Pin
//GPIOPinTypeADC(GPIO_PORTE_BASE, GPIO_PIN_3);
// Configure all 8 steps on sequencer 0 to sample temperature sensor

ADCSequenceStepConfigure(ADC0_BASE, 1, 0, ADC_CTL_CH0 );
ADCSequenceStepConfigure(ADC0_BASE, 1, 1, ADC_CTL_CH0 );
ADCSequenceStepConfigure(ADC0_BASE, 1, 2, ADC_CTL_CH0 );
//ADCSequenceStepConfigure(ADC0_BASE, 1, 3, ADC_CTL_CH0 );
/*ADCSequenceStepConfigure(ADC0_BASE, 1, 4, ADC_CTL_CH0 );
ADCSequenceStepConfigure(ADC0_BASE, 1, 5, ADC_CTL_CH0 );
ADCSequenceStepConfigure(ADC0_BASE, 1, 6, ADC_CTL_CH0 );*/

// Mark as last conversion on sequencer 0 and enable interrupt flag generation on sampling completion
ADCSequenceStepConfigure(ADC0_BASE, 1, 3, ADC_CTL_CH0|ADC_CTL_IE|ADC_CTL_END);
ADCIntEnable(ADC0_BASE, 1);
ADCIntRegister(ADC0_BASE, 1, handler_ADC);

// Enable Sequencer 0
ADCSequenceEnable(ADC0_BASE, 1);
//ADCIntClear(ADC0_BASE, 0);
//ADCIntEnable(ADC0_BASE, 0);
//IntEnable(ADC_INT_SS0);
ADCProcessorTrigger(ADC0_BASE, 1);

}

void PWM_init(void)
{
// Initialise PB7 M0PWM1
SysCtlPWMClockSet(SYSCTL_PWMDIV_1); // clock defined in sysctl.c
SysCtlPeripheralEnable(SYSCTL_PERIPH_PWM0); // TM4C123GH6PM has two modules (0 and 1)
//SysCtlPeripheralEnable(SYSCTL_PERIPH_PWM1); // TM4C123GH6PM has two modules (0 and 1)
SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOB);
//GPIOPinTypePWM(GPIO_PORTB_BASE, GPIO_PIN_7);
GPIOPinTypePWM(GPIO_PORTB_BASE, GPIO_PIN_6);
GPIOPinConfigure(GPIO_PB6_M0PWM0);
//GPIOPinConfigure(GPIO_PB7_M0PWM1);
//IntEnable(INT_PWM0_0_TM4C123);


PWMGenConfigure(PWM0_BASE, PWM_GEN_0, PWM_GEN_MODE_UP_DOWN | PWM_GEN_MODE_NO_SYNC);
ui32Load = (SysCtlClockGet() / 25000) ;
/*PWMGenPeriodSet(PWM0_BASE, PWM_GEN_0, ui32Load);
PWMPulseWidthSet(PWM0_BASE, PWM_OUT_1, 900);
PWMOutputState(PWM0_BASE, PWM_OUT_1_BIT, true);
PWMGenEnable(PWM0_BASE, PWM_GEN_0);*/

PWMGenConfigure(PWM0_BASE, PWM_GEN_0, PWM_GEN_MODE_UP_DOWN | PWM_GEN_MODE_NO_SYNC);
PWMGenPeriodSet(PWM0_BASE, PWM_GEN_0, ui32Load);
PWMGenIntTrigEnable(PWM0_BASE, PWM_GEN_0, PWM_TR_CNT_LOAD | PWM_TR_CNT_ZERO |PWM_INT_CNT_ZERO | PWM_INT_CNT_LOAD |
PWM_INT_CNT_AU | PWM_INT_CNT_AD | PWM_INT_CNT_BU |
PWM_INT_CNT_BD | PWM_TR_CNT_ZERO |
PWM_TR_CNT_LOAD | PWM_TR_CNT_AU | PWM_TR_CNT_AD |
PWM_TR_CNT_BU | PWM_TR_CNT_BD );

PWMGenEnable(PWM0_BASE, PWM_GEN_0);
PWMPulseWidthSet(PWM0_BASE, PWM_OUT_0, 2700);
PWMOutputState(PWM0_BASE, PWM_OUT_0_BIT, true);
}

void handler_ADC(void)
{
ADCIntClear(ADC0_BASE, 1);
ADCSequenceDataGet(ADC0_BASE, 1, &ui32ADC0Value[0]);
ADCSequenceDataGet(ADC0_BASE, 1, &ui32ADC0Value[1]);
ADCSequenceDataGet(ADC0_BASE, 1, &ui32ADC0Value[2]);
ADCSequenceDataGet(ADC0_BASE, 1, &ui32ADC0Value[3]);
ADCSequenceDataGet(ADC0_BASE, 1, &ui32ADC0Value[4]);
ADCSequenceDataGet(ADC0_BASE, 1, &ui32ADC0Value[5]);
ADCSequenceDataGet(ADC0_BASE, 1, &ui32ADC0Value[6]);
ADCSequenceDataGet(ADC0_BASE, 1, &ui32ADC0Value[7]);
cnt++;
ui32ADCAvg = (ui32ADC0Value[0]+ui32ADC0Value[1]+ui32ADC0Value[2]+ui32ADC0Value[3]+ui32ADC0Value[4]+ui32ADC0Value[5]+ui32ADC0Value[6]+ui32ADC0Value[7])/8;

}

  • Hi,

      Below is the code you wrote. In ADCSequenceConfigure you specify sequencer 0 while in ADCSequenceStepConfigure you specify sequencer 1. You need to use sequencer 0 for ADCSequenceStepConfigure.

    // Configure to use ADC0, sample sequencer 0, processor to trigger sequence and use highest priority
    ADCSequenceConfigure(ADC0_BASE, 0, ADC_TRIGGER_PWM0, 1);
    // Configure PB4 as Analog Input Pin
    //GPIOPinTypeADC(GPIO_PORTE_BASE, GPIO_PIN_3);
    // Configure all 8 steps on sequencer 0 to sample temperature sensor

    ADCSequenceStepConfigure(ADC0_BASE, 1, 0, ADC_CTL_CH0 );
    ADCSequenceStepConfigure(ADC0_BASE, 1, 1, ADC_CTL_CH0 );
    ADCSequenceStepConfigure(ADC0_BASE, 1, 2, ADC_CTL_CH0 );

    Please also be aware that response will be delayed starting today until next year as our forum support team is on vacation. 

  • I also changed this part of the code, but it still does not work exactly as I want. Here I am measuring the value of a pot from adc, but I want to measure this measurement every time the PWM signal is at the rising edge. I'm missing some things here, can you help with this? The value I'm actively measuring right now is around 3400 when it is maximum. Normally I need to measure this between 0-4096. What should I add to the code for this?

    #include <stdint.h>
    #include <stdbool.h>
    #include "inc/hw_memmap.h"
    #include "inc/hw_types.h"
    #include "driverlib/debug.h"
    #include "driverlib/sysctl.h"
    #include "driverlib/adc.h"
    #define TARGET_IS_BLIZZARD_RB1
    #include "driverlib/rom.h"
    #include "driverlib/sysctl.h"
    #include "driverlib/pin_map.h"
    #include "driverlib/gpio.h"
    #include "driverlib/pwm.h"


    uint32_t ui32ADCAvg=0;
    uint32_t ui32ADC0Value[8] = {0};
    uint32_t ui32Load=0;
    int cnt=0;
    void handler_ADC(void);

    void ADC_init(void);
    void PWM_init(void);

    int main(void)
    {

    // Set the System clock to 80MHz and enable the clock for peripherals ADC0 and GPIO PortB
    SysCtlClockSet(SYSCTL_SYSDIV_2_5|SYSCTL_USE_PLL|SYSCTL_OSC_MAIN|SYSCTL_XTAL_16MHZ);

    //handler_ADC();
    PWM_init();
    ADC_init();
    while(1)
    {
    // Clear the ADC Interrupt (if any generated) for Sequencer 0
    //ADCSequenceDataGet(ADC0_BASE, 1, &ui32ADC0Value[0]);
    /*ADCSequenceDataGet(ADC0_BASE, 1, &ui32ADC0Value[1]);
    ADCSequenceDataGet(ADC0_BASE, 1, &ui32ADC0Value[2]);
    ADCSequenceDataGet(ADC0_BASE, 1, &ui32ADC0Value[3]);
    ADCSequenceDataGet(ADC0_BASE, 1, &ui32ADC0Value[4]);
    ADCSequenceDataGet(ADC0_BASE, 1, &ui32ADC0Value[5]);
    ADCSequenceDataGet(ADC0_BASE, 1, &ui32ADC0Value[6]);
    ADCSequenceDataGet(ADC0_BASE, 1, &ui32ADC0Value[7]);*/
    // Trigger the ADC Sampling for Sequencer 0
    //ADCProcessorTrigger(ADC0_BASE, 1);
    // Wait the program till the conversion isn't complete
    // while(ADCIntStatus(ADC0_BASE, 1, false));
    // Store the values in sequencer 0 of ADC0 to an Array
    // Calculate the Average of the Readings

    }


    }

    void ADC_init(void)
    {
    SysCtlPeripheralEnable(SYSCTL_PERIPH_ADC0);
    SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOE);
    //SysCtlADCSpeedSet(SYSCTL_ADCSPEED_250KSPS);

    // Enable hardware averaging on ADC0
    ADCHardwareOversampleConfigure(ADC0_BASE, 64);//
    ADCSequenceDisable(ADC0_BASE, 1);

    // Configure to use ADC0, sample sequencer 0, processor to trigger sequence and use highest priority
    ADCSequenceConfigure(ADC0_BASE, 1, ADC_TRIGGER_PWM0, 1);
    // Configure PB4 as Analog Input Pin
    //GPIOPinTypeADC(GPIO_PORTE_BASE, GPIO_PIN_3);
    // Configure all 8 steps on sequencer 0 to sample temperature sensor

    ADCSequenceStepConfigure(ADC0_BASE, 1, 0, ADC_CTL_CH0 );
    //ADCSequenceStepConfigure(ADC0_BASE, 1, 1, ADC_CTL_CH0 );
    //ADCSequenceStepConfigure(ADC0_BASE, 1, 2, ADC_CTL_CH0 );
    //ADCSequenceStepConfigure(ADC0_BASE, 1, 3, ADC_CTL_CH0 );
    /*ADCSequenceStepConfigure(ADC0_BASE, 1, 4, ADC_CTL_CH0 );
    ADCSequenceStepConfigure(ADC0_BASE, 1, 5, ADC_CTL_CH0 );
    ADCSequenceStepConfigure(ADC0_BASE, 1, 6, ADC_CTL_CH0 );*/

    // Mark as last conversion on sequencer 0 and enable interrupt flag generation on sampling completion
    ADCSequenceStepConfigure(ADC0_BASE, 1, 1, ADC_CTL_CH0|ADC_CTL_IE|ADC_CTL_END);
    ADCIntEnable(ADC0_BASE, 1);
    ADCIntRegister(ADC0_BASE, 1, handler_ADC);

    // Enable Sequencer 0
    ADCSequenceEnable(ADC0_BASE, 1);
    //ADCIntClear(ADC0_BASE, 0);
    //ADCIntEnable(ADC0_BASE, 0);
    //IntEnable(ADC_INT_SS0);
    ADCProcessorTrigger(ADC0_BASE, 1);

    ADCIntClear(ADC0_BASE, 0);
    ADCIntEnable(ADC0_BASE, 0);
    //IntEnable(ADC_INT_SS0);

    }

    void PWM_init(void)
    {
    // Initialise PB7 M0PWM1
    SysCtlPWMClockSet(SYSCTL_PWMDIV_1); // clock defined in sysctl.c
    SysCtlPeripheralEnable(SYSCTL_PERIPH_PWM0); // TM4C123GH6PM has two modules (0 and 1)
    //SysCtlPeripheralEnable(SYSCTL_PERIPH_PWM1); // TM4C123GH6PM has two modules (0 and 1)
    SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOB);
    //GPIOPinTypePWM(GPIO_PORTB_BASE, GPIO_PIN_7);
    GPIOPinTypePWM(GPIO_PORTB_BASE, GPIO_PIN_6);
    GPIOPinConfigure(GPIO_PB6_M0PWM0);
    //GPIOPinConfigure(GPIO_PB7_M0PWM1);
    //IntEnable(INT_PWM0_0_TM4C123);


    PWMGenConfigure(PWM0_BASE, PWM_GEN_0, PWM_GEN_MODE_UP_DOWN | PWM_GEN_MODE_NO_SYNC);
    ui32Load = (SysCtlClockGet() / 25000) ;
    /*PWMGenPeriodSet(PWM0_BASE, PWM_GEN_0, ui32Load);
    PWMPulseWidthSet(PWM0_BASE, PWM_OUT_1, 900);
    PWMOutputState(PWM0_BASE, PWM_OUT_1_BIT, true);
    PWMGenEnable(PWM0_BASE, PWM_GEN_0);*/

    PWMGenConfigure(PWM0_BASE, PWM_GEN_0, PWM_GEN_MODE_UP_DOWN | PWM_GEN_MODE_NO_SYNC);
    PWMGenPeriodSet(PWM0_BASE, PWM_GEN_0, ui32Load);
    PWMGenIntTrigEnable(PWM0_BASE, PWM_GEN_0, PWM_TR_CNT_LOAD | PWM_TR_CNT_ZERO |PWM_INT_CNT_ZERO | PWM_INT_CNT_LOAD |
    PWM_INT_CNT_AU | PWM_INT_CNT_AD | PWM_INT_CNT_BU |
    PWM_INT_CNT_BD | PWM_TR_CNT_ZERO |
    PWM_TR_CNT_LOAD | PWM_TR_CNT_AU | PWM_TR_CNT_AD |
    PWM_TR_CNT_BU | PWM_TR_CNT_BD );

    PWMGenEnable(PWM0_BASE, PWM_GEN_0);
    PWMPulseWidthSet(PWM0_BASE, PWM_OUT_0, 2700);
    PWMOutputState(PWM0_BASE, PWM_OUT_0_BIT, true);
    }

    void handler_ADC(void)
    {
    ADCIntClear(ADC0_BASE, 1);
    ADCSequenceDataGet(ADC0_BASE, 1, &ui32ADC0Value[0]);
    ADCSequenceDataGet(ADC0_BASE, 1, &ui32ADC0Value[1]);
    ADCSequenceDataGet(ADC0_BASE, 1, &ui32ADC0Value[2]);
    ADCSequenceDataGet(ADC0_BASE, 1, &ui32ADC0Value[3]);
    ADCSequenceDataGet(ADC0_BASE, 1, &ui32ADC0Value[4]);
    ADCSequenceDataGet(ADC0_BASE, 1, &ui32ADC0Value[5]);
    ADCSequenceDataGet(ADC0_BASE, 1, &ui32ADC0Value[6]);
    ADCSequenceDataGet(ADC0_BASE, 1, &ui32ADC0Value[7]);
    cnt++;
    ui32ADCAvg = (ui32ADC0Value[0]+ui32ADC0Value[1]+ui32ADC0Value[2]+ui32ADC0Value[3]+ui32ADC0Value[4]+ui32ADC0Value[5]+ui32ADC0Value[6]+ui32ADC0Value[7])/8;

    }

  • Some comments:

    - in your ADC_init() you only setup step 0 and 1 in sequencer 1. You got several steps commented out. 

    - In your handler_ADC you try to read from sequencer 1 for eight steps. Sequencer 1 can only take 4 samples.  See below from the datasheet.  So that is the first problem. Even if you use sequencer 0 which support 8 samples, it will not work in your code. The reason is that you only take two samples. Therefore, only ui32ADC0Value[0] and ui32ADC0Value[1] holds the valid data. Others do not. As I mentioned in my original reply, you need to use SS0 if you want to take 8 samples. 

     -You are taking the average of values from ui32ADC0Value[7:0] in which some of them are not valid. 

     - Don't call ADCHardwareOversampleConfigure() until you can get the basic to work. Besides, if you are using ADCHardwareOversampleConfigure, you are already taking the average using hardware. Why do you want to take measurement of ADC_CTL_CH0 in 8 different steps and then average them?

  • I won't call ADCHardwareOversampleConfigure() and after your explanation above I realized the error but it still doesn't help me achieve what I want. Do you understand what I want?