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.

ADC Trigger using PWM

Other Parts Discussed in Thread: TM4C123GH6PM

Dear All 

 I am trying to configure the ADC trigger using PWM i am trying to get RGB values from a color sensor i have configured my PWM to operate at 633Khz i want to trigger the ADC for sensing the analoge voltage and the same rate for that i need to configure the ADC trigger from PWM 

here with i am attaching the code for the same i am unable to get the ADC interrupt , i have assigned the proper interrupt in  tm4c123gh6pm_startup_ccs.c

pls let me know what is the mistake i have done in this code 

i ma trying to switch on the RGB led based on the pulse generated  in the PWM interrupt itself .

#include <stdbool.h>
#include <stdint.h>
#include "inc/hw_ints.h"
#include "inc/hw_memmap.h"
#include "driverlib/gpio.h"
#include "driverlib/interrupt.h"
#include "driverlib/pin_map.h"
#include "driverlib/pwm.h"
#include "driverlib/sysctl.h"
#include "driverlib/uart.h"
#include "utils/uartstdio.h"
#include "driverlib/adc.h"

int Count;
uint32_t ui32ADC0Value[4];
//*****************************************************************************
//
// The interrupt handler for the for PWM0 interrupts.
//
//*****************************************************************************
void
PWM0IntHandler(void)
{
//
// Clear the PWM0 LOAD interrupt flag. This flag gets set when the PWM
// counter gets reloaded.
//
PWMGenIntClear(PWM0_BASE, PWM_GEN_0, PWM_INT_CNT_LOAD);
Count++;
if(Count==2)GPIOPinWrite(GPIO_PORTF_BASE, GPIO_PIN_2,0);
////RED LED ON
if(Count==83)GPIOPinWrite(GPIO_PORTC_BASE, GPIO_PIN_4,GPIO_PIN_4);
if(Count==253)
{
GPIOPinWrite(GPIO_PORTC_BASE, GPIO_PIN_4,0);
GPIOPinWrite(GPIO_PORTF_BASE, GPIO_PIN_2,GPIO_PIN_2);
}
if(Count==254)GPIOPinWrite(GPIO_PORTF_BASE, GPIO_PIN_2,0);
if(Count==336)GPIOPinWrite(GPIO_PORTC_BASE, GPIO_PIN_5,GPIO_PIN_5);
if(Count==506)
{
GPIOPinWrite(GPIO_PORTC_BASE, GPIO_PIN_5,0);
GPIOPinWrite(GPIO_PORTF_BASE, GPIO_PIN_2,GPIO_PIN_2);
}
if(Count==507)GPIOPinWrite(GPIO_PORTF_BASE, GPIO_PIN_2,0);
if(Count==589)GPIOPinWrite(GPIO_PORTC_BASE, GPIO_PIN_6,GPIO_PIN_6);
if(Count==759)
{
GPIOPinWrite(GPIO_PORTC_BASE, GPIO_PIN_6,0);
GPIOPinWrite(GPIO_PORTF_BASE, GPIO_PIN_2,GPIO_PIN_2);

Count=0;
}

if(Count>=85)
{
}

}


void ADCIntHandler(void)
{

ADCIntClear(ADC0_BASE, 0);
ADCSequenceDataGet(ADC0_BASE, 0, ui32ADC0Value);
}

//*****************************************************************************
//
// Configure PWM0 for a load interrupt. This interrupt will trigger everytime
// the PWM0 counter gets reloaded. In the interrupt, 0.1% will be added to
// the current duty cycle. This will continue until a duty cycle of 75% is
// received, then the duty cycle will get reset to 0.1%.
//
//*****************************************************************************
int main(void)
{
SysCtlClockSet(SYSCTL_SYSDIV_2 | SYSCTL_USE_PLL| SYSCTL_OSC_MAIN | SYSCTL_XTAL_16MHZ);
SysCtlPWMClockSet(SYSCTL_PWMDIV_1);
SysCtlPeripheralEnable(SYSCTL_PERIPH_PWM0);
SysCtlPeripheralEnable(SYSCTL_PERIPH_ADC0);
SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOE);
SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOB);
SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOF);
SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOC);
GPIOPinTypeGPIOOutput(GPIO_PORTF_BASE, GPIO_PIN_3|GPIO_PIN_2|GPIO_PIN_1);
GPIOPinTypeGPIOOutput(GPIO_PORTB_BASE, GPIO_PIN_3);
GPIOPinTypeGPIOOutput(GPIO_PORTC_BASE, GPIO_PIN_4|GPIO_PIN_5|GPIO_PIN_6);//FOR Blue Led
GPIOPinConfigure(GPIO_PB6_M0PWM0);
GPIOPinTypePWM(GPIO_PORTB_BASE, GPIO_PIN_6);
GPIOPinTypeADC(GPIO_PORTE_BASE, GPIO_PIN_0|GPIO_PIN_1|GPIO_PIN_2);

//////////ADC Configuration

ADCSequenceConfigure(ADC0_BASE, 3, ADC_TRIGGER_PWM0 , 0);
ADCSequenceStepConfigure(ADC0_BASE, 3, 0, ADC_CTL_CH0);
ADCSequenceStepConfigure(ADC0_BASE, 3, 1,ADC_CTL_CH1);
ADCSequenceStepConfigure(ADC0_BASE, 3, 2, ADC_CTL_CH2| ADC_CTL_IE | ADC_CTL_END);
ADCSequenceEnable(ADC0_BASE, 3);
ADCIntClear(ADC0_BASE, 3);
ADCIntEnable(ADC0_BASE, 3);

////PWM COnfiguration

PWMGenConfigure(PWM0_BASE, PWM_GEN_0,PWM_GEN_MODE_DOWN | PWM_GEN_MODE_NO_SYNC);
PWMGenPeriodSet(PWM0_BASE, PWM_GEN_0, 100);
PWMPulseWidthSet(PWM0_BASE, PWM_OUT_0, 50);
IntMasterEnable();
PWMIntEnable(PWM0_BASE, PWM_INT_GEN_0);
PWMGenIntTrigEnable(PWM0_BASE, PWM_GEN_0, PWM_INT_CNT_LOAD);
IntEnable(INT_PWM0_0);
IntEnable(INT_ADC0SS3);
PWMOutputState(PWM0_BASE, PWM_OUT_0_BIT, true);
PWMGenEnable(PWM0_BASE, PWM_GEN_0);
GPIOPinWrite(GPIO_PORTF_BASE, GPIO_PIN_2,GPIO_PIN_2);
while(1)
{

}
}

  • Hello Vijay

    SysCtlClockSet(SYSCTL_SYSDIV_2 | SYSCTL_USE_PLL| SYSCTL_OSC_MAIN | SYSCTL_XTAL_16MHZ);

    is not correct. The System Clock Divider must be 2.5 at least for 80MHz system clock.

    Secondly you have an Interrupt enable for PWM but no interrupt handler for the PWM. It may cause the PWM to go to a while(1) loop of the default interrupt handler. Can you check what your current code is executing?
  • the system is currently executing void PWM0IntHandler(void); function for PWM interrupt
  • Hello Vijay

    So it is stuck in the PWM interrupt handler. Due to the load time of 100 (system clock) the PWM is taking almost all of CPU bandwidth. As an experiment, can you disable the PWM interrupt and see if the ADC interrupt handler is getting processed?
  • I have disabled PWM and checked it is not getting processed ???

    Just one doubt is there any possibility of running 4 PWM in parallel so that i can generate a specific RGB on and OFF sequence and reduce the load on this PWM Block , is there any sample code which tells us how to run multiple PWM blocks in Parallel
  • Hi VR,

    Seems you may not have the correct (trigger) set for the sequencer to start samples from PWM0 load. Have a look at the other directives and be sure to set the sequencer interrupt vector.
  • Hello Vijay

    Yes, all PWM generators are independent of each other but can be forced to work together using SYNC.

    When you mentioned that you have disabled PWM, what is not getting processed?
  • Hi Amith Ashara

    I have disbled the PWM Interrupt and in debug mode i placed an brak point in the ADC Interrupt but still it is not working , i have decided to run 5 different PWM for CLOCK PULSE , R ,G,B on sequence and For ADC trigger , i will get back to you as soon as i test the PWM Module
  • Hi Amith Ashara

    here is the reworked code i have initilised 2 PWM GEN in PWM 1 module i havce created one 50% duty cycle and the other at 90% duty cycle i have sucessfully got the PWM outputs ant the ports here is the revised code

    #include <stdbool.h>
    #include <stdint.h>
    #include "inc/hw_ints.h"
    #include "inc/hw_memmap.h"
    #include "driverlib/gpio.h"
    #include "driverlib/interrupt.h"
    #include "driverlib/pin_map.h"
    #include "driverlib/pwm.h"
    #include "driverlib/sysctl.h"
    #include "driverlib/uart.h"
    #include "utils/uartstdio.h"
    #include "driverlib/adc.h"

    int Count,PWM_FREQUENCY,ui8Adjust,ui32Load, ui32PWMClock;
    uint32_t ui32ADC0Value[4];
    //*****************************************************************************
    //
    // The interrupt handler for the for PWM0 interrupts.
    //
    //*****************************************************************************
    void
    PWM0IntHandler(void)
    {

    }

    //void ADCIntHandler(void)
    //{
    //
    // ADCIntClear(ADC0_BASE, 0);
    // ADCSequenceDataGet(ADC0_BASE, 0, ui32ADC0Value);
    //}

    //*****************************************************************************
    //
    // Configure PWM0 for a load interrupt. This interrupt will trigger everytime
    // the PWM0 counter gets reloaded. In the interrupt, 0.1% will be added to
    // the current duty cycle. This will continue until a duty cycle of 75% is
    // received, then the duty cycle will get reset to 0.1%.
    //
    //*****************************************************************************
    int main(void)
    {
    SysCtlClockSet(SYSCTL_SYSDIV_4 | SYSCTL_USE_PLL| SYSCTL_OSC_MAIN | SYSCTL_XTAL_16MHZ);
    SysCtlPWMClockSet(SYSCTL_PWMDIV_1);
    SysCtlPeripheralEnable(SYSCTL_PERIPH_PWM1);
    SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOD);
    SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOE); // connector J1, pin PE4 and PE5
    SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOF); // connector J3, pin PD0 and PD1

    // GPIOPinTypeGPIOOutput(GPIO_PORTF_BASE, GPIO_PIN_3|GPIO_PIN_2|GPIO_PIN_1);

    GPIOPinTypePWM(GPIO_PORTD_BASE, GPIO_PIN_0);
    GPIOPinConfigure(GPIO_PD0_M1PWM0);

    // PWM PD1, motor B
    GPIOPinTypePWM(GPIO_PORTD_BASE, GPIO_PIN_1);
    GPIOPinConfigure(GPIO_PD1_M1PWM1);

    // PWM PE4, motor C
    GPIOPinTypePWM(GPIO_PORTE_BASE, GPIO_PIN_4);
    GPIOPinConfigure(GPIO_PE4_M1PWM2);

    // PWM PE5, motor D
    GPIOPinTypePWM(GPIO_PORTE_BASE, GPIO_PIN_5);
    GPIOPinConfigure(GPIO_PE5_M1PWM3);

    PWMGenConfigure(PWM1_BASE, PWM_GEN_0,PWM_GEN_MODE_DOWN );
    PWMGenConfigure(PWM1_BASE, PWM_GEN_1,PWM_GEN_MODE_DOWN );


    PWMGenPeriodSet(PWM1_BASE, PWM_GEN_0, 60);
    PWMGenPeriodSet(PWM1_BASE, PWM_GEN_1, 60);

    PWMPulseWidthSet(PWM1_BASE, PWM_OUT_0, 30);
    PWMPulseWidthSet(PWM1_BASE, PWM_OUT_1, 54);



    PWMOutputState(PWM1_BASE, PWM_OUT_0_BIT|PWM_OUT_1_BIT, true);
    PWMOutputInvert(PWM1_BASE, PWM_OUT_1_BIT, true);



    PWMGenEnable(PWM1_BASE, PWM_GEN_1);
    IntMasterEnable();
    PWMIntEnable(PWM1_BASE, PWM_INT_GEN_1);
    PWMGenIntTrigEnable(PWM1_BASE, PWM_GEN_1,PWM_INT_CNT_LOAD);
    // IntEnable(INT_PWM1_1);

    ////ADC Configuration
    ADCSequenceConfigure(ADC0_BASE, 3, ADC_TRIGGER_PWM1|ADC_TRIGGER_PWM_MOD1, 0);
    ADCSequenceStepConfigure(ADC0_BASE, 3, 0, ADC_CTL_CH0);
    ADCSequenceStepConfigure(ADC0_BASE, 3, 1,ADC_CTL_CH1);
    ADCSequenceStepConfigure(ADC0_BASE, 3, 2, ADC_CTL_CH2| ADC_CTL_IE | ADC_CTL_END);
    ADCSequenceEnable(ADC0_BASE, 3);
    ADCIntClear(ADC0_BASE, 3);
    ADCIntEnableEx(ADC0_BASE, 3);
    PWMGenEnable(PWM1_BASE, PWM_GEN_0|PWM_GEN_1);
    while(1)
    {

    }
    }

    the problem i am now facing is if i run the code in debug mode i am getting a fault ISR in

    ADCSequenceConfigure(ADC0_BASE, 3, ADC_TRIGGER_PWM1|ADC_TRIGGER_PWM_MOD1, 0);

    this Sequence configure is for triggering the ADC at PWM gen 1 Interrupt , for module 1

    i coudnt figure out the problems pls correct me where i have gone wrong
  • Hi Amith Ashara

    i have not enable to the Peripheral enable for ADC now the code is not entering into the fault ISR , i am working on the ADC interrupt will update asap
  • Hi Amith

    i have managed to get the PWM working and ADC interrupt as well here is the code that i have done , i facing only one problem here i able to get the ADC interrupt only for the one step configuration

    if i have the step configured ADCSequenceStepConfigure(ADC0_BASE, 3, 0, ADC_CTL_CH0 | ADC_CTL_IE | ADC_CTL_END);

    i am able to get the ADC interrupt but if i configured 3 channels like below my interrupt is not generating

    ADCSequenceStepConfigure(ADC0_BASE, 3, 0, ADC_CTL_CH0);
    ADCSequenceStepConfigure(ADC0_BASE, 3, 1, ADC_CTL_CH1);
    ADCSequenceStepConfigure(ADC0_BASE, 3, 2, ADC_CTL_CH2 | ADC_CTL_IE | ADC_CTL_END);


    for the forum reference i am attaching the full code again

    #include <stdbool.h>
    #include <stdint.h>
    #include "inc/hw_ints.h"
    #include "inc/hw_memmap.h"
    #include "driverlib/gpio.h"
    #include "driverlib/interrupt.h"
    #include "driverlib/pin_map.h"
    #include "driverlib/pwm.h"
    #include "driverlib/sysctl.h"
    #include "driverlib/uart.h"
    #include "utils/uartstdio.h"
    #include "driverlib/adc.h"

    int Count,PWM_FREQUENCY,ui8Adjust,ui32Load, ui32PWMClock,FLAG_ADC;
    uint32_t ui32ADC0Value[4];
    //*****************************************************************************
    //
    // The interrupt handler for the for PWM0 interrupts.
    //
    //*****************************************************************************
    void
    PWM0IntHandler(void)
    {
    if(FLAG_ADC==0)ADCProcessorTrigger(ADC0_BASE, 3);
    while(!ADCIntStatus(ADC0_BASE, 3, false))
    {
    FLAG_ADC=1;
    }
    if(FLAG_ADC==1)
    {


    }

    }

    void ADCIntHandler(void)
    {
    ADCIntClear(ADC0_BASE, 3);
    ADCSequenceDataGet(ADC0_BASE, 3, ui32ADC0Value);
    FLAG_ADC = 0;

    }

    //*****************************************************************************
    //
    // Configure PWM0 for a load interrupt. This interrupt will trigger everytime
    // the PWM0 counter gets reloaded. In the interrupt, 0.1% will be added to
    // the current duty cycle. This will continue until a duty cycle of 75% is
    // received, then the duty cycle will get reset to 0.1%.
    //
    //*****************************************************************************
    int main(void)
    {
    SysCtlClockSet(SYSCTL_SYSDIV_4 | SYSCTL_USE_PLL| SYSCTL_OSC_MAIN | SYSCTL_XTAL_16MHZ);
    SysCtlPWMClockSet(SYSCTL_PWMDIV_1);
    SysCtlPeripheralEnable(SYSCTL_PERIPH_PWM1);
    SysCtlPeripheralEnable(SYSCTL_PERIPH_ADC0);
    SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOD);
    SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOE); // connector J1, pin PE4 and PE5
    SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOF); // connector J3, pin PD0 and PD1
    GPIOPinTypeADC(GPIO_PORTE_BASE, GPIO_PIN_0|GPIO_PIN_1|GPIO_PIN_2);
    // GPIOPinTypeGPIOOutput(GPIO_PORTF_BASE, GPIO_PIN_3|GPIO_PIN_2|GPIO_PIN_1);

    GPIOPinTypePWM(GPIO_PORTD_BASE, GPIO_PIN_0);
    GPIOPinConfigure(GPIO_PD0_M1PWM0);

    // PWM PD1, motor B
    GPIOPinTypePWM(GPIO_PORTD_BASE, GPIO_PIN_1);
    GPIOPinConfigure(GPIO_PD1_M1PWM1);

    // PWM PE4, motor C
    GPIOPinTypePWM(GPIO_PORTE_BASE, GPIO_PIN_4);
    GPIOPinConfigure(GPIO_PE4_M1PWM2);

    // PWM PE5, motor D
    GPIOPinTypePWM(GPIO_PORTE_BASE, GPIO_PIN_5);
    GPIOPinConfigure(GPIO_PE5_M1PWM3);

    PWMGenConfigure(PWM1_BASE, PWM_GEN_0,PWM_GEN_MODE_DOWN );
    PWMGenConfigure(PWM1_BASE, PWM_GEN_1,PWM_GEN_MODE_DOWN );


    PWMGenPeriodSet(PWM1_BASE, PWM_GEN_0, 60);
    PWMGenPeriodSet(PWM1_BASE, PWM_GEN_1, 60);

    PWMPulseWidthSet(PWM1_BASE, PWM_OUT_0, 30);
    PWMPulseWidthSet(PWM1_BASE, PWM_OUT_1, 54);



    PWMOutputState(PWM1_BASE, PWM_OUT_0_BIT|PWM_OUT_1_BIT, true);
    PWMOutputInvert(PWM1_BASE, PWM_OUT_1_BIT, true);


    PWMGenEnable(PWM1_BASE, PWM_GEN_0);
    PWMGenEnable(PWM1_BASE, PWM_GEN_1);

    PWMIntEnable(PWM1_BASE, PWM_INT_GEN_1);
    PWMGenIntTrigEnable(PWM1_BASE, PWM_GEN_1,PWM_INT_CNT_LOAD);

    ////ADC Configuration
    ADCSequenceConfigure(ADC0_BASE,3,ADC_TRIGGER_PROCESSOR, 0);
    ADCSequenceStepConfigure(ADC0_BASE, 3, 0, ADC_CTL_CH0);
    ADCSequenceStepConfigure(ADC0_BASE, 3, 1, ADC_CTL_CH1);
    ADCSequenceStepConfigure(ADC0_BASE, 3, 2, ADC_CTL_CH2 | ADC_CTL_IE | ADC_CTL_END);
    ADCSequenceEnable(ADC0_BASE, 3);
    ADCIntClear(ADC0_BASE, 3);
    ADCIntEnable(ADC0_BASE, 3);
    IntEnable(INT_ADC0SS3);
    PWMGenEnable(PWM1_BASE, PWM_GEN_0|PWM_GEN_1);
    IntEnable(INT_PWM1_1);
    IntMasterEnable();
    while(1)
    {


    }
    }


    pls clarify
  • I have got the output i have wrongly set the sample sequencer thanks for the help provided now i am able to get 3 channel sample
  • Vijayanarayana R said:

    PWMGenPeriodSet(PWM1_BASE, PWM_GEN_0, 60);
    PWMGenPeriodSet(PWM1_BASE, PWM_GEN_1, 60);

    With your PWM clock set as: "SysCtlPWMClockSet(SYSCTL_PWMDIV_1);"

    and your 2 digit PWM Period - you've set your PWM frequency extremely high.   

    Why have you done that?    And what are the likely consequences of so high a PWM frequency?

  • I AM TRYING TO GET DATA FROM A cis SENSOR DATA
  • VR,

    Remain curious how did you get the PWM load count interrupt to trigger the ADC sample sequencer with your source code?  

    Please explain how the interrupt hander for sequencer 3 is now being called by your source code.

    Perhaps your source PWM is not properly configured?

    PWMGenIntTrigEnable(PWM0_BASE, PWM_GEN_0, PWM_INT_CNT_LOAD);

    ADCSequenceConfigure(ADC0_BASE, 3, ADC_TRIGGER_PWM0 , 0);

  • VR,

    >I have got the output i have wrongly set the sample sequencer thanks for the help provided now i am able to get 3 channel sample

    Yet who alerted you only to later see self awarded answer flag? Never look back thank all helpers for making you aware of configuration issue :(