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 Interrupt

Hi !

I wrote the simple code just to configure and test the ADC of TM4C1294. I configured the four channels(PE4,PE5,PB4,PB5) to ADC0 module. i configurered the ADC Interrupt for sample seuqence2,(ADC0SS2) but the ADC does not triggers the interrupt.

Below is the code, i wrote , please let me know about the bugs in my code.

Thanks in Advance.

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

uint32_t pui32ADC0Value[4];
void  ADC0SS2IntHandler(void);
void  ADC0SS2IntHandler(void){
ADCSequenceDataGet(ADC0_BASE, 2,pui32ADC0Value);
ADCIntClear(ADC0_BASE, 2);		// CLEAR THE ADC INTERRUPT FOR SAMPLE SEQUENCE-3
}
///////////////////////Main_Program////////////////////////////////////////////
int main(void) {

volatile uint32_t adc0,adc1,adc2,adc3;	//declare separate varibles to get separate the each channel output from buffer

volatile float  signal_ch0,signal_ch1,signal_ch2,signal_ch3;  //declare float variable to get actual analog input value using 								conversion expression

SysCtlPeripheralEnable(SYSCTL_PERIPH_GPION);		//ENABLING GPIO PORTN

SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOB);		//ENABLING GPIO PORTB USED FOR ADC INPUT

GPIOPinTypeGPIOOutput(GPIO_PORTN_BASE,GPIO_PIN_0);	//ENABLING PINO FOR LED BLINKING DURING DELAY

SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOE);		//ENABLING GPIO PORTE USED FOR ADC INPUT

GPIOPinTypeADC(GPIO_PORTE_BASE,GPIO_PIN_4);		//ENABLING THE PINS USED FOR ADC INPUT
GPIOPinTypeADC(GPIO_PORTE_BASE,GPIO_PIN_5);		//
GPIOPinTypeADC(GPIO_PORTB_BASE,GPIO_PIN_4);		//
GPIOPinTypeADC(GPIO_PORTB_BASE,GPIO_PIN_5);		//

SysCtlClockFreqSet((SYSCTL_XTAL_25MHZ|SYSCTL_OSC_MAIN|SYSCTL_USE_PLL|SYSCTL_CFG_VCO_480),120000000); //ENABLING THE CLOCK

SysCtlPeripheralEnable(SYSCTL_PERIPH_ADC0);		// ENABLE THE ADC0-MODULE

ADCHardwareOversampleConfigure(ADC0_BASE,64);		//ENABLE THE HARDWARE AVERAGER FOR BETTER ACCURACY

ADCSequenceConfigure(ADC0_BASE,2,ADC_TRIGGER_PROCESSOR,0);  //CONFIGURE THE ADC SAMPLE SEQUENCER THAT U WANA USE

ADCSequenceStepConfigure(ADC0_BASE,2,0, ADC_CTL_CH9 );		//CONFIGURE THE STEPS OF SAMPLE SEQUENCER

ADCSequenceStepConfigure(ADC0_BASE,2,1, ADC_CTL_CH8 );		//

ADCSequenceStepConfigure(ADC0_BASE,2,2, ADC_CTL_CH10 );		//

ADCSequenceStepConfigure(ADC0_BASE,2,3, ADC_CTL_CH11|ADC_CTL_IE|ADC_CTL_END );	//
IntEnable(INT_ADC0SS2);
ADCIntEnable(ADC0_BASE,2);
 IntMasterEnable();
 ADCIntRegister(ADC0_BASE,2,ADC0SS2IntHandler);

// USE LOOP FOR EVER CONVERSION OF ADC
while(1){

	ADCProcessorTrigger(ADC0_BASE,2);

		//TRIGGER THE ADC BY PROCESSOR

 		//GET THE CAPTURED DATA FROM SEQUENCER FIFO
 adc0=pui32ADC0Value[0];					//PUT THE FIF0 VALUE IN ADC0
 adc1=pui32ADC0Value[1];					//PUT THE FIF1 VALUE IN ADC1
 adc2=pui32ADC0Value[2];					//PUT THE FIF2 VALUE IN ADC2
 adc3=pui32ADC0Value[3];					//PUT THE FIF3 VALUE IN ADC3
 
	   //SIGNAL COVERSION FROM DIGITAL TO ANALOG VOLATGE SIGNAL TO CONFIRM THE RESULTS-SEE ATTACHMENT FILE PICTURE
 signal_ch0=(((adc0)/4095)*(3.3));
 signal_ch1=(((adc1)/4095)*(3.3));
 signal_ch2=(((adc2)/4095)*(3.3));
 signal_ch3=(((adc3)/4095)*(3.3));

}

}

  • Hi Ali,

    Try this below changes.

    SysCtlClockFreqSet((SYSCTL_XTAL_25MHZ|SYSCTL_OSC_MAIN|SYSCTL_USE_PLL|SYSCTL_CFG_VCO_480),120000000); //ENABLING THE CLOCK
    SysCtlPeripheralEnable(SYSCTL_PERIPH_GPION); //ENABLING GPIO PORTN
    SysCtlPeripheralEnable(SYSCTL_PERIPH_ADC0); // ENABLE THE ADC0-MODULE
    SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOB); //ENABLING GPIO PORTB USED FOR ADC INPUT

    and then the rest of your ADC code.

    - kel
  • It's past been reported that you (sometimes) answer posts when tired or less than fully focused.   (some such reports flow from your pen...)

    Poster's code - which I've "cut/pasted" (below) - appears to have included EACH/EVERY one of the four function calls you suggested!    And - beyond that - his code included calls to Port "E" which bore 2 of his desired ADC channels.   (your code missed that)

    "DUI" is a crime w/in the USA & many countries.   "PUI" may require a new statute - you may want to review poster's code (bit better) in the future...

    SysCtlPeripheralEnable(SYSCTL_PERIPH_GPION);        //ENABLING GPIO PORTN
     
    SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOB);        //ENABLING GPIO PORTB USED FOR ADC INPUT
     
    GPIOPinTypeGPIOOutput(GPIO_PORTN_BASE,GPIO_PIN_0);  //ENABLING PINO FOR LED BLINKING DURING DELAY
     
    SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOE);        //ENABLING GPIO PORTE USED FOR ADC INPUT
     
    GPIOPinTypeADC(GPIO_PORTE_BASE,GPIO_PIN_4);     //ENABLING THE PINS USED FOR ADC INPUT
    GPIOPinTypeADC(GPIO_PORTE_BASE,GPIO_PIN_5);     //
    GPIOPinTypeADC(GPIO_PORTB_BASE,GPIO_PIN_4);     //
    GPIOPinTypeADC(GPIO_PORTB_BASE,GPIO_PIN_5);     //
     
    SysCtlClockFreqSet((SYSCTL_XTAL_25MHZ|SYSCTL_OSC_MAIN|SYSCTL_USE_PLL|SYSCTL_CFG_VCO_480),120000000); //ENABLING THE CLOCK
     
    SysCtlPeripheralEnable(SYSCTL_PERIPH_ADC0);     // ENABLE THE ADC0-MODULE

  • Markel Robregado said:
    SysCtlClockFreqSet((SYSCTL_XTAL_25MHZ|SYSCTL_OSC_MAIN|SYSCTL_USE_PLL|SYSCTL_CFG_VCO_480),120000000); //ENABLING THE CLOCK
    SysCtlPeripheralEnable(SYSCTL_PERIPH_GPION); //ENABLING GPIO PORTN
    SysCtlPeripheralEnable(SYSCTL_PERIPH_ADC0); // ENABLE THE ADC0-MODULE
    SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOB); //ENABLING GPIO PORTB USED FOR ADC INPUT

    cb1 - I did not notice anything wrong with the OP ADC interrupt setup code. But noticed that SysCtlClockFreqSet() is called after a few code lines which is not normal practice. Same with,

    SysCtlPeripheralEnable(SYSCTL_PERIPH_ADC0);

    which was called after, 

    SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOB); and SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOE);

    which is also not normal practice.

    So I am just suggesting to re-arrange the calling of these API's to normal practice. But, I have not checked at datasheets yet if doing that will make the program work at the time of my reply. So, I have not put the explanation that I am replying now.

    - kel

  • Kel,
    Your explanation (now) - right or wrong - regarding the sequence of function calls - makes far more sense than the manner in which your initial post presented.

    If we speak of "normal practice" - should not Port "E" have received (some) mention in your code review?

    The importance (if any) of such sequencing may be easily checked - such is left for o.p..

  • Hello cb1

    The poster's original post does not mention what is not working. Is there a Bus Fault, or code simply loops without values getting updated. Also let us all note that the values are being used after Processor Trigger without having a check to see if the conversion has happened or not. There is a clear lack of software interlock between application and interrupt handler.

    Regards
    Amit
  • Hi Amit,

    Only thing I could note was poster's report of, "No ADC Interrupt" - no fault was announced.

    Suggested code changes by another seemed uninspired and missed a critical MCU Port. (E)
  • Hello cb1

    Even if the No interrupt is announced a solid lead is to understand what the CPU is doing. I too wanted to highlight this (time and again) to the poster(s). Besides the obvious miss of the interlock.

    Regards
    Amit
  • Hi EveryOne!

    Rearranging of APIs did'nt work and same result , no interrupt triggers . However, i wrote again the code and it is working ok.

    here is the code shown below.

    #include <stdbool.h>
    #include <stdint.h>
    #include "inc/hw_memmap.h"
    #include"inc/hw_types.h"
    #include"inc/hw_ints.h"
    #include "driverlib/adc.h"
    #include "driverlib/gpio.h"
    #include "driverlib/pin_map.h"
    #include "driverlib/sysctl.h"
    #include"driverlib/interrupt.h"
    
    
    uint32_t pui32ADC0Value[4];
    void ADC0SS2IntHandler(void);
    
    void ADC0SS2IntHandler(void){
    
    	ADCSequenceDataGet(ADC0_BASE, 2,pui32ADC0Value);
    
    	 ADCIntClear(ADC0_BASE, 2);
    }
    
    int main(void) {
    	volatile  uint32_t ui32Loop;
    
    	volatile uint32_t adc0,adc1,adc2,adc3;
    volatile float  signal_ch0,signal_ch1,signal_ch2,signal_ch3;
    
    
    
    SysCtlPeripheralEnable(SYSCTL_PERIPH_GPION);
    SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOB);
    GPIOPinTypeGPIOOutput(GPIO_PORTN_BASE,GPIO_PIN_0);
    SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOE);
    //GPIOPinTypeGPIOInput(GPIO_PORTE_BASE,GPIO_PIN_5);
    
    GPIOPinTypeADC(GPIO_PORTE_BASE,GPIO_PIN_4);
    GPIOPinTypeADC(GPIO_PORTE_BASE,GPIO_PIN_5);
    GPIOPinTypeADC(GPIO_PORTB_BASE,GPIO_PIN_4);
    GPIOPinTypeADC(GPIO_PORTB_BASE,GPIO_PIN_5);
    
    SysCtlClockFreqSet((SYSCTL_XTAL_25MHZ|SYSCTL_OSC_MAIN|SYSCTL_USE_PLL|SYSCTL_CFG_VCO_480),120000000);
    
    SysCtlPeripheralEnable(SYSCTL_PERIPH_ADC0);
    ADCHardwareOversampleConfigure(ADC0_BASE,64);
    
    ADCSequenceConfigure(ADC0_BASE,2,ADC_TRIGGER_PROCESSOR,0);
    
    ADCSequenceStepConfigure(ADC0_BASE,2,0, ADC_CTL_CH9 );
    ADCSequenceStepConfigure(ADC0_BASE,2,1, ADC_CTL_CH8 );
    ADCSequenceStepConfigure(ADC0_BASE,2,2, ADC_CTL_CH10 );
    ADCSequenceStepConfigure(ADC0_BASE,2,3, ADC_CTL_CH11|ADC_CTL_IE|ADC_CTL_END );
    //||ADC_CTL_IE
    ADCSequenceEnable(ADC0_BASE, 2);
    
    //Interrupt Enabling
    IntMasterEnable();
    IntEnable(INT_ADC0SS2);
    ADCIntEnable(ADC0_BASE,2);
    ADCIntRegister(ADC0_BASE,2,ADC0SS2IntHandler);
    
    //
    while(1){
    
    
    	ADCProcessorTrigger(ADC0_BASE,2);
    		 adc0=pui32ADC0Value[0];
    		 adc1=pui32ADC0Value[1];
    		 adc2=pui32ADC0Value[2];
    		 adc3=pui32ADC0Value[3];
    
    ////////////////get the floating values//////////////////////////////////
    		 signal_ch0=(((adc0)/4095)*(3.3));
    		 signal_ch1=(((adc1)/4095)*(3.3));
    		 signal_ch2=(((adc2)/4095)*(3.3));
    		 signal_ch3=(((adc3)/4095)*(3.3));
    
    		for(ui32Loop = 0; ui32Loop < 2000000; ui32Loop++)
    			     {GPIOPinWrite(GPIO_PORTN_BASE,GPIO_PIN_0,1);
    			}
    
    		for(ui32Loop = 0; ui32Loop < 2000000; ui32Loop++)
    			     {GPIOPinWrite(GPIO_PORTN_BASE,GPIO_PIN_0,0);
    		  }
    }}
    
    
    

  • Hi,

    Several problems with your latest code version:

    1. It is not clear if you updated/modified the startup_ccs.c file to take into account your interrupt> The interrupt vectors array should contain the name of your interrupt, at the right place.
    2. Usually, if you need an interrupt, then you collect the results of conversion inside that interrupt - you cannot start the ADC conversion and immediately get the results as you do in the while(1) loop, because the processor is simple much faster than the ADC, and no results are available. Use a flag to send messages between interrupt and the main function. (OK, you may wait for conversions to be completed, but the interrupt is not anymore needed - this is “polling” and you may want to avoid it)
    3. The adc0…adc3 values are integers, smaller than 4095, so the direct division adc0/4095 will give you always 0. Instead, you may use engineering values - let’s say you can like to see the values in mV - in this case you may write (adc0*3300)/4095 - giving you the result in integer values. If floating point is needed, keep the same style but cast to float - ((float)adc0 * 3.3f)/4095.0f.

  • Hello Ali,

    Which version of TivaWare are you using?

    Regards
    Amit