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.

TM4C1294NCPDT: Multiple ADCs with PWM not working properly

Part Number: TM4C1294NCPDT

Dear support,

I'm trying to read 4 ADC signals with a potentiometer and generate a PWM to test it.

I've followed the following code: e2e.ti.com/.../374763

Although I'm connecting different Ports physically, the value is always changed in the ui32adcValues[0]. Maybe I didn't get or understand the code correctly.

//*****************************************************************************
// Libraries
//*****************************************************************************

#include <stdint.h>
#include <stdbool.h>

#include "driverlib/gpio.h"
#include "driverlib/pin_map.h"
#include "driverlib/rom.h"
#include "driverlib/rom_map.h"
#include "driverlib/sysctl.h"
#include "driverlib/adc.h"
#include "driverlib/timer.h"
#include "driverlib/uart.h"
#include "driverlib/pwm.h"

#include "drivers/pinout.h"

#include "inc/hw_gpio.h"
#include "inc/hw_ints.h"        // Added for the Timer
#include "inc/hw_memmap.h"
#include "inc/hw_types.h"
#include "inc/hw_adc.h"
#include "inc/hw_timer.h"
#include "inc/hw_nvic.h"
#include "inc/hw_sysctl.h"

#include "utils/uartstdio.h"

//*****************************************************************************
// Variable Declaration
//*****************************************************************************

// ADC
uint32_t ui32adcValues[4],ui32Count,ui32adc0Values[1],ui32adc1Values[1],ui32adc2Values[1],ui32adc3Values[1];

// PWM
long analogValue = 0, analogAvg = 0, adcToPwmRatio = 0;
uint32_t sumCounter = 0, iSamples = 10000, pwmValue = 0;
uint32_t pwmMax = 24000;        // 120 MHz / 5 kHz

// System
uint32_t g_ui32SysClock;        // System clock rate in Hz.

//*****************************************************************************
//
// The error routine that is called if the driver library encounters an error.
//
//*****************************************************************************
#ifdef DEBUG
void
__error__(char *pcFilename, uint32_t ui32Line)
{
}
#endif

//*****************************************************************************
// ADC Initialization
//*****************************************************************************

void
ConfigureADC(void)
{


        SysCtlPeripheralReset(SYSCTL_PERIPH_GPIOE);
        SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOE);
        SysCtlPeripheralReset(SYSCTL_PERIPH_ADC0);
        SysCtlPeripheralEnable(SYSCTL_PERIPH_ADC0);
        SysCtlDelay(10);

        GPIOPinTypeADC(GPIO_PORTE_BASE, GPIO_PIN_3 | GPIO_PIN_2 | GPIO_PIN_1 | GPIO_PIN_0 );

        ADCClockConfigSet(ADC0_BASE, ADC_CLOCK_SRC_PLL | ADC_CLOCK_RATE_EIGHTH, 30);

        // Choose Sequencer 2 and set it at the highest Priority.
        ADCSequenceConfigure(ADC0_BASE, 0, ADC_TRIGGER_ALWAYS,  0);
        ADCSequenceConfigure(ADC0_BASE, 1, ADC_TRIGGER_ALWAYS,  1);
        ADCSequenceConfigure(ADC0_BASE, 2, ADC_TRIGGER_ALWAYS,  2);
        ADCSequenceConfigure(ADC0_BASE, 3, ADC_TRIGGER_ALWAYS,  3);

            // Choose Step 0 in Sequencer 2 as Data Buffer, set it as last Step and enable Interrupts


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


        ADCSequenceEnable(ADC0_BASE, 0);
        ADCSequenceEnable(ADC0_BASE, 1);
        ADCSequenceEnable(ADC0_BASE, 2);
        ADCSequenceEnable(ADC0_BASE, 3);

}

//*****************************************************************************
// PWM Initialization - 13.09.2020
//*****************************************************************************
void Init_PWM(){

    // 1.
    SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOF);        // Enable Port F
    while(!SysCtlPeripheralReady(SYSCTL_PERIPH_GPIOF));

    // 2.
    SysCtlPWMClockSet(SYSCTL_PWMDIV_16);
    SysCtlPeripheralDisable(SYSCTL_PERIPH_PWM0);
    SysCtlPeripheralReset(SYSCTL_PERIPH_PWM0);
    SysCtlPeripheralEnable(SYSCTL_PERIPH_PWM0);
    while(!(SysCtlPeripheralReady(SYSCTL_PERIPH_PWM0)));


    // PWM0_BASE: 0 -> 0 from M_0_PWM1
    // PWM_OUT_1 and PWM_OUT_1_BIT: 1 from M0PWM_1
    // PWM_GEN_0: GEN_0 for PWM0 and PWM1, GEN_1 for PWM2 and PWM3...


    SysCtlPWMClockSet(SYSCTL_PWMDIV_1);                 // 120 MHz / 1 = 120 MHz

    GPIOPinTypePWM(GPIO_PORTF_BASE, GPIO_PIN_1);        // Pin 1 from PortF - PF1
    GPIOPinConfigure(GPIO_PF1_M0PWM1);
    PWMGenConfigure(PWM0_BASE, PWM_GEN_0, PWM_GEN_MODE_DOWN | PWM_GEN_MODE_NO_SYNC);
    PWMGenPeriodSet(PWM0_BASE, PWM_GEN_0, pwmMax);       // 120 MHz / pwmMax = pwmPeriod
    PWMPulseWidthSet(PWM0_BASE, PWM_OUT_1, 1);
    PWMGenEnable(PWM0_BASE, PWM_GEN_0);
    PWMOutputState(PWM0_BASE, PWM_OUT_1_BIT, true);

    PWMIntEnable(PWM0_BASE, PWM_INT_GEN_0);
    IntMasterEnable();
    PWMGenIntTrigEnable(PWM0_BASE, PWM_GEN_0, PWM_TR_CNT_ZERO);
    IntEnable(INT_PWM0_0);

}

//*****************************************************************************
// Wait and Read ADC Functions
//*****************************************************************************
uint32_t
WaitAndReadADC(uint32_t *adcValues)
{

    ADCProcessorTrigger(ADC0_BASE,0);
    // Wait until the sample sequence has completed.

    while(!ADCIntStatus(ADC0_BASE, 0, false)) { }
    // Read the value from the ADC.

    return(ADCSequenceDataGet(ADC0_BASE, 0, adcValues));
}


uint32_t
WaitAndReadADC1(uint32_t *adcValues)
{

    ADCProcessorTrigger(ADC0_BASE,1);
    // Wait until the sample sequence has completed.

    while(!ADCIntStatus(ADC0_BASE, 1, false)) { }
    // Read the value from the ADC.

    return(ADCSequenceDataGet(ADC0_BASE, 1, adcValues));
}

uint32_t
WaitAndReadADC2(uint32_t *adcValues)
{

    ADCProcessorTrigger(ADC0_BASE,2);
    // Wait until the sample sequence has completed.

    while(!ADCIntStatus(ADC0_BASE, 2, false)) { }
    // Read the value from the ADC.

    return(ADCSequenceDataGet(ADC0_BASE, 2, adcValues));
}

uint32_t
WaitAndReadADC3(uint32_t *adcValues)
{

    ADCProcessorTrigger(ADC0_BASE,3);
    // Wait until the sample sequence has completed.

    while(!ADCIntStatus(ADC0_BASE, 3, false)) { }
    // Read the value from the ADC.

    return(ADCSequenceDataGet(ADC0_BASE, 3, adcValues));
}


int
main(void)
{

    //
    // Run from the PLL at 120 MHz.
    //
    g_ui32SysClock = MAP_SysCtlClockFreqSet((SYSCTL_XTAL_25MHZ |
                SYSCTL_OSC_MAIN | SYSCTL_USE_PLL |
                SYSCTL_CFG_VCO_480), 120000000);

    //
    // Configure the device pins.
    //
    PinoutSet(false, false);

    //
    // Enable the GPIO pins for the LED D1 (PN1).
    //
    ROM_GPIOPinTypeGPIOOutput(GPIO_PORTN_BASE, GPIO_PIN_1);

    //
    // Initialize the UART.
    //
    ConfigureADC();
    Init_PWM();

    adcToPwmRatio = pwmMax/4095;        // 2^12 bits

    // Infinite loop
    while(1)
    {

        //ui32Count = WaitAndReadADC1(ui32adcValues);
        //ui32Count = WaitAndReadADC2(ui32adcValues);
        //ui32Count = WaitAndReadADC3(ui32adcValues);
        ui32Count = WaitAndReadADC(ui32adcValues);

        // Sum filter
        if (sumCounter < iSamples) {

            analogValue = ui32adcValues[0] + analogValue;

            sumCounter++;

        } else {

            analogAvg = analogValue / iSamples;

            // PWM
            pwmValue = analogAvg*adcToPwmRatio;

            // PWM Min Limit
            if (pwmValue < 30) {
                pwmValue = 1;       // pwmValue can never be zero
            }

            // PWM Max Limit
            if (pwmValue > (pwmMax - 30)) {
                pwmValue = pwmMax;
            }

            // Change PWM Value
            PWMPulseWidthSet(PWM0_BASE, PWM_OUT_1, pwmValue);

            // Reset Sum Filter Variables
            analogValue = 0;
            sumCounter = 0;

        }

    }
}

Could you please provide some help?

Best regards,

Gustavo Wegher

  • Hello Gustavo,

    I am not quite sure why the code Amit posted was setup that way but you need to uncomment these functions too in order to get results from all four channels:

            //ui32Count = WaitAndReadADC1(ui32adcValues);
            //ui32Count = WaitAndReadADC2(ui32adcValues);
            //ui32Count = WaitAndReadADC3(ui32adcValues);

    Once those are uncommented, then each channel should provide you an independent reading.

    I also think you should modify the functions to use individual vectors like this:

            ui32Count = WaitAndReadADC1(ui32adc1Values);
            ui32Count = WaitAndReadADC2(ui32adc2Values);
            ui32Count = WaitAndReadADC3(ui32adc3Values);

    And also use ui32adc0Values for your WaitAndReadADC function (which probably should be named WaitAndReadADC0).

  • Ralph Jacobi said:

    Hello Gustavo,

    I am not quite sure why the code Amit posted was setup that way but you need to uncomment these functions too in order to get results from all four channels:

            //ui32Count = WaitAndReadADC1(ui32adcValues);
            //ui32Count = WaitAndReadADC2(ui32adcValues);
            //ui32Count = WaitAndReadADC3(ui32adcValues);

    Once those are uncommented, then each channel should provide you an independent reading.

    I also think you should modify the functions to use individual vectors like this:

            ui32Count = WaitAndReadADC1(ui32adc1Values);
            ui32Count = WaitAndReadADC2(ui32adc2Values);
            ui32Count = WaitAndReadADC3(ui32adc3Values);

    And also use ui32adc0Values for your WaitAndReadADC function (which probably should be named WaitAndReadADC0).

    Hey Ralph,

    thanks for the quick answer.

    I tried to uncomment these lines, it simply doesn't work.

    I have updated the functions to use individual vectors like you said and tested it again, so now it is:

    //*****************************************************************************
    // Wait and Read ADC Functions
    //*****************************************************************************
    uint32_t
    WaitAndReadADC0(uint32_t *adcValues)
    {
    
        ADCProcessorTrigger(ADC0_BASE,0);
        // Wait until the sample sequence has completed.
    
        while(!ADCIntStatus(ADC0_BASE, 0, false)) { }
        // Read the value from the ADC.
    
        return(ADCSequenceDataGet(ADC0_BASE, 0, adcValues));
    }
    
    [...]
    
    // Infinite loop
        while(1)
        {
            
            ui32Count = WaitAndReadADC0(ui32adc0Values);
            //ui32Count1 = WaitAndReadADC1(ui32adc1Values);
            //ui32Count = WaitAndReadADC2(ui32adc2Values);
            //ui32Count = WaitAndReadADC3(ui32adc3Values);

    When I uncomment the line containing "WaitAndReadADC1" (please note that I updated also the variable calling the function to ui32Count1, to make sure that wasn't the problem), the program runs the first read from ADC0 (I can see, because "sumCounter" is still zero) and it stops in the while loop from the WaitAndReadADC1 function:

    uint32_t
    WaitAndReadADC1(uint32_t *adcValues)
    {
    
        ADCProcessorTrigger(ADC0_BASE,1);
        // Wait until the sample sequence has completed.
    
        while(!ADCIntStatus(ADC0_BASE, 1, false)) { }
        // Read the value from the ADC.
    
        return(ADCSequenceDataGet(ADC0_BASE, 1, adcValues));
    }

    Then I commented the while loop and rebuild it. The ADC1 is still not reading.

    Another issue I've noticed is, I can disconnect the physical cable from the PE0 and connect the PE1, the variable updated is still the "ui32adc0Values".

    Thank you very much for the attention.

    Best regards,

    Gustavo Wegher

  • Hello Gustavo,

    After reviewing the code in full I saw that there were some surprising inconsistencies with what Amit had shared. I think for that specific case it was functional perhaps but I can see why you were having issues with the setup yourself. I went ahead and reworked the code to what I think you need for your own use case. Try this out and see if you are getting your expected results now. I tested with my LaunchPad and got accurate readings on all 4 ADC channels.

    Note two key things you need to do!

    1) Add uartstdio.c to your project, see this guide on how to do so: https://e2e.ti.com/support/microcontrollers/other/f/908/p/753675/2787705#2787705

    2) Add the ADC ISR to your CCS file by using the below line and replace the IntDefaultHandler for ADC Sequence 0 with this ISR.

    extern void ADC0Sequence0ISR(void);

    Once you have done those, your project should compile. I made a number of changes but I don't think I impacted your PWM setup.

    //*****************************************************************************
    // Libraries
    //*****************************************************************************
    
    #include <stdint.h>
    #include <stdbool.h>
    
    #include "driverlib/adc.h"
    #include "driverlib/gpio.h"
    #include "driverlib/interrupt.h"
    #include "driverlib/pin_map.h"
    #include "driverlib/pwm.h"
    #include "driverlib/rom.h"
    #include "driverlib/rom_map.h"
    #include "driverlib/sysctl.h"
    #include "driverlib/timer.h"
    #include "driverlib/uart.h"
    
    #include "drivers/pinout.h"
    
    #include "inc/hw_gpio.h"
    #include "inc/hw_ints.h"        // Added for the Timer
    #include "inc/hw_memmap.h"
    #include "inc/hw_types.h"
    #include "inc/hw_adc.h"
    #include "inc/hw_timer.h"
    #include "inc/hw_nvic.h"
    #include "inc/hw_sysctl.h"
    
    #include "utils/uartstdio.h"
    
    //*****************************************************************************
    // Variable Declaration
    //*****************************************************************************
    
    // ADC
    uint32_t ui32adcValues[4];
    volatile bool bDataReady = false;
    
    // PWM
    long analogValue = 0, analogAvg = 0, adcToPwmRatio = 0;
    uint32_t sumCounter = 0, iSamples = 10000, pwmValue = 0;
    uint32_t pwmMax = 24000;        // 120 MHz / 5 kHz
    
    // System
    uint32_t g_ui32SysClock;        // System clock rate in Hz.
    
    //*****************************************************************************
    //
    // The error routine that is called if the driver library encounters an error.
    //
    //*****************************************************************************
    #ifdef DEBUG
    void
    __error__(char *pcFilename, uint32_t ui32Line)
    {
    }
    #endif
    
    void
    ADC0Sequence0ISR(void)
    {
    	ADCIntClear(ADC0_BASE, 0);
    
    	ADCSequenceDataGet(ADC0_BASE, 0, ui32adcValues);
    
    	if (!bDataReady)
    	{
    		bDataReady = true;
    	}
    }
    
    //*****************************************************************************
    // ADC Initialization
    //*****************************************************************************
    
    void
    ConfigureADC(void)
    {
    	SysCtlPeripheralReset(SYSCTL_PERIPH_GPIOE);
    	SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOE);
    	SysCtlPeripheralReset(SYSCTL_PERIPH_ADC0);
    	SysCtlPeripheralEnable(SYSCTL_PERIPH_ADC0);
    	SysCtlDelay(10);
    
    	GPIOPinTypeADC(GPIO_PORTE_BASE, GPIO_PIN_3 | GPIO_PIN_2 | GPIO_PIN_1 | GPIO_PIN_0 );
    
    	ADCClockConfigSet(ADC0_BASE, ADC_CLOCK_SRC_PLL | ADC_CLOCK_RATE_EIGHTH, 30);
    
        //
        // Wait for the clock configuration to set.
        //
        SysCtlDelay(10);
    
    	// Choose Sequencer 2 and set it at the highest Priority.
    //	ADCSequenceConfigure(ADC0_BASE, 0, ADC_TRIGGER_PROCESSOR,  0);
    	ADCSequenceConfigure(ADC0_BASE, 0, ADC_TRIGGER_ALWAYS,  0);
    
    	ADCSequenceStepConfigure(ADC0_BASE,0,0, ADC_CTL_CH0);
    	ADCSequenceStepConfigure(ADC0_BASE,0,1, ADC_CTL_CH1);
    	ADCSequenceStepConfigure(ADC0_BASE,0,2, ADC_CTL_CH2);
    	ADCSequenceStepConfigure(ADC0_BASE,0,3, ADC_CTL_CH3 | ADC_CTL_IE | ADC_CTL_END);
    
    	ADCSequenceEnable(ADC0_BASE, 0);
    	ADCIntClear(ADC0_BASE, 0);
    	ADCIntEnable(ADC0_BASE, 0);
    	IntEnable(INT_ADC0SS0);
    }
    
    //*****************************************************************************
    // PWM Initialization - 13.09.2020
    //*****************************************************************************
    void Init_PWM(){
    
        // 1.
        SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOF);        // Enable Port F
        while(!SysCtlPeripheralReady(SYSCTL_PERIPH_GPIOF));
    
        // 2.
        SysCtlPWMClockSet(SYSCTL_PWMDIV_16);
        SysCtlPeripheralDisable(SYSCTL_PERIPH_PWM0);
        SysCtlPeripheralReset(SYSCTL_PERIPH_PWM0);
        SysCtlPeripheralEnable(SYSCTL_PERIPH_PWM0);
        while(!(SysCtlPeripheralReady(SYSCTL_PERIPH_PWM0)));
    
    
        // PWM0_BASE: 0 -> 0 from M_0_PWM1
        // PWM_OUT_1 and PWM_OUT_1_BIT: 1 from M0PWM_1
        // PWM_GEN_0: GEN_0 for PWM0 and PWM1, GEN_1 for PWM2 and PWM3...
    
    
        SysCtlPWMClockSet(SYSCTL_PWMDIV_1);                 // 120 MHz / 1 = 120 MHz
    
        GPIOPinTypePWM(GPIO_PORTF_BASE, GPIO_PIN_1);        // Pin 1 from PortF - PF1
        GPIOPinConfigure(GPIO_PF1_M0PWM1);
        PWMGenConfigure(PWM0_BASE, PWM_GEN_0, PWM_GEN_MODE_DOWN | PWM_GEN_MODE_NO_SYNC);
        PWMGenPeriodSet(PWM0_BASE, PWM_GEN_0, pwmMax);       // 120 MHz / pwmMax = pwmPeriod
        PWMPulseWidthSet(PWM0_BASE, PWM_OUT_1, 1);
        PWMGenEnable(PWM0_BASE, PWM_GEN_0);
        PWMOutputState(PWM0_BASE, PWM_OUT_1_BIT, true);
    
        PWMIntEnable(PWM0_BASE, PWM_INT_GEN_0);
        PWMGenIntTrigEnable(PWM0_BASE, PWM_GEN_0, PWM_TR_CNT_ZERO);
        IntEnable(INT_PWM0_0);
    
    }
    
    //*****************************************************************************
    //
    // This function sets up UART0 to be used for a console to display information
    // as the example is running.
    //
    //*****************************************************************************
    void
    InitConsole(void)
    {
        //
        // Enable GPIO port A which is used for UART0 pins.
        // TODO: change this to whichever GPIO port you are using.
        //
        SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOA);
    
        //
        // Configure the pin muxing for UART0 functions on port A0 and A1.
        // This step is not necessary if your part does not support pin muxing.
        // TODO: change this to select the port/pin you are using.
        //
        GPIOPinConfigure(GPIO_PA0_U0RX);
        GPIOPinConfigure(GPIO_PA1_U0TX);
    
        //
        // Enable UART0 so that we can configure the clock.
        //
        SysCtlPeripheralEnable(SYSCTL_PERIPH_UART0);
    
        //
        // Use the internal 16MHz oscillator as the UART clock source.
        //
        UARTClockSourceSet(UART0_BASE, UART_CLOCK_PIOSC);
    
        //
        // Select the alternate (UART) function for these pins.
        // TODO: change this to select the port/pin you are using.
        //
        GPIOPinTypeUART(GPIO_PORTA_BASE, GPIO_PIN_0 | GPIO_PIN_1);
    
        //
        // Initialize the UART for console I/O.
        //
        UARTStdioConfig(0, 115200, 16000000);
    }
    
    int
    main(void)
    {
    
    	//
    	// Run from the PLL at 120 MHz.
    	//
    	g_ui32SysClock = MAP_SysCtlClockFreqSet((SYSCTL_XTAL_25MHZ |
    			SYSCTL_OSC_MAIN | SYSCTL_USE_PLL |
    			SYSCTL_CFG_VCO_480), 120000000);
    
    	//
    	// Configure the device pins.
    	//
    	PinoutSet(false, false);
    
    	//
    	// Set up the serial console to use for displaying messages.  This is
    	// just for this example program and is not needed for ADC operation.
    	//
    	InitConsole();
    
    	//
    	// Enable the GPIO pins for the LED D1 (PN1).
    	//
    	ROM_GPIOPinTypeGPIOOutput(GPIO_PORTN_BASE, GPIO_PIN_1);
    
    	//
    	// Initialize the UART.
    	//
    	ConfigureADC();
    	Init_PWM();
    
    	IntMasterEnable();
    
    	adcToPwmRatio = pwmMax/4095;        // 2^12 bits
    
    	// Infinite loop
    	while(1)
    	{
    		if (bDataReady)
    		{
    			UARTprintf("AIN0 = %4d\r", ui32adcValues[0]);
    			UARTprintf("AIN1 = %4d\r", ui32adcValues[1]);
    			UARTprintf("AIN2 = %4d\r", ui32adcValues[2]);
    			UARTprintf("AIN3 = %4d\r", ui32adcValues[3]);
    
    			bDataReady = false;
    		}
    
    		// Sum filter
    		if (sumCounter < iSamples) {
    
    			analogValue = ui32adcValues[0] + analogValue;
    
    			sumCounter++;
    
    		} else {
    
    			analogAvg = analogValue / iSamples;
    
    			// PWM
    			pwmValue = analogAvg*adcToPwmRatio;
    
    			// PWM Min Limit
    			if (pwmValue < 30) {
    				pwmValue = 1;       // pwmValue can never be zero
    			}
    
    			// PWM Max Limit
    			if (pwmValue > (pwmMax - 30)) {
    				pwmValue = pwmMax;
    			}
    
    			// Change PWM Value
    			PWMPulseWidthSet(PWM0_BASE, PWM_OUT_1, pwmValue);
    
    			// Reset Sum Filter Variables
    			analogValue = 0;
    			sumCounter = 0;
    		}
    	}
    }
    

  • Hey Ralph,

    ok, that was an awesome job. The ADCs work perfectly, the values are getting less variation than before, you even got the UART working (which I got some issues during this weekend). I still haven't tested the PWM, probably will test it by the end of the week.

    If it is not too much trouble, would you please explain why did you used interrupts to make it work?

    I've also noted that I'm getting some trunc or round errors for the pwmValue, which is probably due to int and long variables. Would you have some advices on how to perform these math operations with TM4C1294, or maybe some topics that you solved before? (although this might be matter for another thread).

    Many thanks by the help so far provided!

    Best regards,

    Gustavo Wegher

  • Hello Gustavo,

    Gustavo Wegher1 said:
    If it is not too much trouble, would you please explain why did you used interrupts to make it work?

    It works with polling as well with using ADC_TRIGGER_PROCESSOR but in general ADC operations are using left to interrupt routines so I went that route to provide the example. The way it is set right now, it will run over and over but really you'll want to figure out how you want to trigger it for your system (like with a timer or other means).

    For PWM by the way we have three examples in TivaWare which should give you everything you need for PWM configuration.

    Gustavo Wegher1 said:
    I've also noted that I'm getting some trunc or round errors for the pwmValue, which is probably due to int and long variables. Would you have some advices on how to perform these math operations with TM4C1294, or maybe some topics that you solved before? (although this might be matter for another thread).

    You can use float numbers if you are concerned about this. I don't know if I have any particular general advice. But without floats usually you'll get small errors like that as any decimal will be truncated at the zeroes digit. The trick with floats though can be getting the number back into something you can feed into APIs that need uint32 typing. You could consider using a rounding function to help round up before type casting back to uint32.

  • Hey Ralph,

    thanks again for the advices, I have updated the code to use the float operators with no problem.

    Like you said, I'd like to trigger the ADC through a Timer. The idea is to sample a sine wave of 2 KHz, so I imagine the ADC would have to run in the range from 200 KHz to 1 MHz, or something like that. I have acquired some samples, and it seems that either the ADC has too much error, or the samples doesn't have a defined time between the acquisitions.

    I took a look and saw the API functions related to this, but I'm still not certain in how to do it. The codes that I looked:

    I understand that I have to change the configuration:

    ADCSequenceConfigure(ADC0_BASE, 0, ADC_TRIGGER_TIMER,  0);

    But I'm kinda confused about the next steps. The ADC function should be called by the TimerInterrupt, and the CCS file should not contain anymore the ADC Interruption, but only the Timer Interruption?

    If you could please provide some information in this matter. Thank you in advance.

    Best regards,

    Gustavo Wegher

  • Hello Gustavo,

    You can also look at the completed TivaWare example adc_udma_pingpong for further help with the ADC - Timer setup.

    There is no need for a Timer ISR. Once the Timer is configured, the ADC ISR will be entered after each timeout. You would still use the ADC interrupt for the sequence you configure. For example, for adc_udma_pingpong, Sequence 0 is used so the ADC interrupt is ADCSeq0Handler assigned to ADC Sequence 0 and there are no ISRs associated with the Timer peripheral.

    Gustavo Wegher1 said:
    The idea is to sample a sine wave of 2 KHz, so I imagine the ADC would have to run in the range from 200 KHz to 1 MHz, or something like that.

    That seems excessive... you shouldn't need to run it at more than just over 2x the frequency. Running it higher just lets you get more granular data, but you can reconstruct the sine wave based of what you get at 4kHz.