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.

CCS/TM4C1294NCPDT: Timer ADC interrupt

Part Number: TM4C1294NCPDT

Tool/software: Code Composer Studio

I am using Tiva C TM4C1294 connected launchpad to read ADC data from a sensor. I am sampling the ADC using timer interrupt. My code is shown below. In this program, I want the index of the array read_data to go to 0 once the whole of it is filled and the ADC should continuously fill new data to the array but if(i==99) condition does not execute and read_data array does not continuously get updated instead it remains the same after the first 100 fillings. Please, if someone can let me know where I am going wrong.  

#include <stdbool.h>
#include <stdint.h>
#include <stdio.h>
#include "inc/hw_ints.h"
#include "inc/hw_memmap.h"
#include "driverlib/interrupt.h"
#include "driverlib/adc.h"
#include "driverlib/gpio.h"
#include "driverlib/pin_map.h"
#include "driverlib/sysctl.h"
#include "driverlib/timer.h"


    uint32_t pui32ADC0Value[1];
    uint32_t read_data[100];
    uint16_t i = 0

int
main(void)
{
    uint32_t ui32SysClock;

    ui32SysClock = SysCtlClockFreqSet((SYSCTL_XTAL_25MHZ |
                                       SYSCTL_OSC_MAIN |
                                       SYSCTL_USE_PLL |
                                       SYSCTL_CFG_VCO_480), 120000000);

    SysCtlPeripheralEnable(SYSCTL_PERIPH_TIMER0);

    SysCtlPeripheralEnable(SYSCTL_PERIPH_ADC0);

    SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOE);

    GPIOPinTypeADC(GPIO_PORTE_BASE, GPIO_PIN_3);

    ADCSequenceConfigure(ADC0_BASE, 3, ADC_TRIGGER_PROCESSOR, 0);

    TimerConfigure(TIMER0_BASE, TIMER_CFG_SPLIT_PAIR | TIMER_CFG_B_PERIODIC);

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

    TimerLoadSet(TIMER0_BASE, TIMER_B, ui32SysClock / 1000);

    IntMasterEnable();

    TimerIntEnable(TIMER0_BASE, TIMER_TIMB_TIMEOUT);

    IntEnable(INT_TIMER0B);

    ADCSequenceEnable(ADC0_BASE, 3);

    ADCIntClear(ADC0_BASE, 3);

    TimerEnable(TIMER0_BASE, TIMER_B);

    while(1)
    {
    	if(i==99){
    		i=0;
    	}
    }
}


void
Timer0BIntHandler(void)
{

	TimerIntClear(TIMER0_BASE, TIMER_TIMB_TIMEOUT);

	ADCProcessorTrigger(ADC0_BASE, 3);

	while(!ADCIntStatus(ADC0_BASE, 3, false))
	{
	}

	ADCIntClear(ADC0_BASE, 3);

	ADCSequenceDataGet(ADC0_BASE, 3, pui32ADC0Value);
	read_data[i]=pui32ADC0Value[0];
	i++;
}

  • What happens if/when  i > 99 ?

    You've committed the sins of

    • updating a shared value in multiple places without interlocks
    • performing no boundary checks

    As well by performing the A/D operation within the timer interrupt you have a long interrupt response. I can think of two better approaches.

    Robert

  • Agreed... (low hanging fruit here)

    If such escapes "boundary checks" - poster's use of:

    "if(i==99)
    {
    i=0;
    }

    would be made more robust via "if(i>=99)" as this disables a "noise glitch/other gremlin" from, "continuing the "if test" (forever!")

  • In addtion to what cb1/Robert mentioned, I also recommend using Volatile declaration for variables which are being changed within an ISR.

    Also, there is really no benefit to having your i=99 check in the while(1)... may as well have ISR be:

    if (i <= 99)
    {
       i++;
    }
    else
    {
       i = 0;
    }

  • Thank you Ralph, Robert, cb1_mobile for all your help. Declaring i as volatile type helped me solve the problem. 

    I will study more about interlocks and boundary checks.

    I also want to know about the two better methods you are thinking about Robert.

    Regards,

    Sourav