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 triggered by timer configuratio

Other Parts Discussed in Thread: TM4C123GH6PM

Hi everyone!

I want to make a simple program to understand the basic use of the ADC module of my Tiva TM4C123G launchpad. The idea is to configure a Timer to interrupt in a certain period of time, and once in the interrupt tell the processor to trigger a concversion. I already made the code, but there must be something wrong in the ADC config. that don´t allow me to make more than one conversion.... Here is the code:

#include <stdint.h>
#include <stdbool.h>
#include "inc/tm4c123gh6pm.h"
#include "inc/hw_memmap.h"
#include "inc/hw_types.h"
#include "driverlib/sysctl.h"
#include "driverlib/interrupt.h"
#include "driverlib/gpio.h"
#include "driverlib/timer.h"
#include "driverlib/adc.h"

uint32_t muestra;
uint32_t i;
uint32_t datos[10];

void main(void) {

int32_t ui32Period;
i = 0;

// Clock: 40MHz
SysCtlClockSet(SYSCTL_SYSDIV_5|SYSCTL_USE_PLL|SYSCTL_XTAL_16MHZ|SYSCTL_OSC_MAIN);

//control LEDs:
SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOF);
GPIOPinTypeGPIOOutput(GPIO_PORTF_BASE, GPIO_PIN_1|GPIO_PIN_2|GPIO_PIN_3);

// ********** Timer Config  ********** //
SysCtlPeripheralEnable(SYSCTL_PERIPH_TIMER0);
TimerConfigure(TIMER0_BASE, TIMER_CFG_PERIODIC);
ui32Period = SysCtlClockGet()/2; // Interrupts evrey half second
TimerLoadSet(TIMER0_BASE, TIMER_A, ui32Period -1);

// ********** ADC Config  ********** //

SysCtlPeripheralEnable(SYSCTL_PERIPH_ADC0);
SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOE);

GPIOPinTypeADC(GPIO_PORTE_BASE, GPIO_PIN_3);

// Select sequencer 3 (FIFO depth 1)

ADCSequenceDisable(ADC0_BASE, 3);
ADCSequenceConfigure(ADC0_BASE, 3, ADC_TRIGGER_PROCESSOR, 0);

//Only one step config:

ADCSequenceStepConfigure(ADC0_BASE, 3, 0, ADC_CTL_CH0 | ADC_CTL_IE | ADC_CTL_END);

ADCSequenceEnable(ADC0_BASE, 3);

//ADCIntClear(ADC0_BASE, 3);

//Interrupts enable

IntEnable(INT_TIMER0A);
TimerIntEnable(TIMER0_BASE, TIMER_TIMA_TIMEOUT);
IntMasterEnable();
ADCIntEnable(ADC0_BASE, 3);
IntEnable(INT_ADC0SS3); //habilitamos la interrupcion del secuenciador 3
TimerEnable(TIMER0_BASE, TIMER_A);

while(1){}

}

//Timer IRS:

void InterrupcionTimer0(void){

// Clear Flags
TimerIntClear(TIMER0_BASE, TIMER_TIMA_TIMEOUT);
ADCIntClear(ADC0_BASE, 3);
//Trigger the conversion (by the processor):
ADCProcessorTrigger(ADC0_BASE, 3);
//Wait for the conversion
while(!ADCIntStatus(ADC0_BASE, 3, false)){}

ADCSequenceDataGet(ADC0_BASE, 3, &muestra);
if (i<10)
datos[i] = muestra;

i = i + 1;


if(GPIOPinRead(GPIO_PORTF_BASE, GPIO_PIN_2)){

GPIOPinWrite(GPIO_PORTF_BASE, GPIO_PIN_1|GPIO_PIN_2|GPIO_PIN_3, 0);
}
else
{
GPIOPinWrite(GPIO_PORTF_BASE, GPIO_PIN_2, 4);
}
SysCtlDelay(SysCtlClockGet() / 12);
}

  • Hello Denis,

    Why is there a big delay loop in the Interrupt Handler? Why is timer interrupt being used along with processor trigger?

    If the intent is to perform ADC conversions based on timer, then it would be timer trigger an ADC directly instead of processor trigger and ADC interrupt handler being used to retrieve the data.

    I have a similar code except that I only trigger ADC in timer interrupt handler and use the ADC interrupt handler to retrieve the data.

    Regards
    Amit
  • Hi Amit!

    Thanks for replay... You are totally rigth! I changed my code, now the timer is the one how triggers the adc and it works perfectly, without wasting processor cycles!

    But in my code i only work with ADC0 SS3 interrupt, the timer automaticaly triggers the ADC, when the count ends, i don´t need to do anything in the timer interrupt, even more i don´t have (or need) an interrupt handler for the timer. Do i missing something?

    Thanks again!

    Best regards.

  • Hello Denis,

    No you do not not need to do anything. The only care that must be taken is when stopping the Timer triggered ADC Sampling. the timer must be first disabled and then before starting again, you may want to reload the timer to make sure timer is consistent for the next trigger.

    Regards
    Amit
  • Hi Amit,

    Thanks for the advice!

    Regards.

  • Hello Denis

    I have a small code that is used for timer triggered ADC and read out from ADC Interrupt handler, if you are interested.

    Regards
    Amit
  • Hi Amit,

    I appreciate your offer, but my code is already working very well!!

    I went a bit further, and put a potenciometer in the ADC input, and with the data read I change the pwm duty cicle of an on board LED.

    In my first try, I had a problem with the pwm duty cicle, because the LED light was not homogeneous, but then I realized that pwm was not the problem, the ADC samples were changing from one sample to another in large amounts although the poteciometer was static... The solution was very clear, oversampling. So I implement a hardware (x16) and software (x4) oversampling, changing SS3 for SS2 (to make possible software oversample), and problem solved!!

    Thanks again for your help and advices!!

    Regards.

    Here it is a video of what I done!

  • Hello Denis,

    You are welcome. Hope that the rest of your project goes well and in case you have an issue, you can post to the forum.

    Regards
    Amit