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.

EK-TM4C123GXL to handle ADC interrupt

Other Parts Discussed in Thread: TM4C123GH6PM

Hi,

i was learning to use TM4C123GXL eval kit.I also tried executing the example projects provided in the tivaware.

Now, i made modifications to the ADC sample code with interrupt handler rather than polling method provided in the example.

 the issue i am facing is while debugging i put beakpoint inside interrupt handler function i defined but it is not hitting the interrupt handler

here is my code,

please resolve my issue..

thanks for any help.....


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


#define SAMPLE_COUNT    ((uint8_t)8)
uint32_t pui32ADC0Value[SAMPLE_COUNT];

void ADC_Init(void ){


        ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_ADC0);

        ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOE);

        ROM_GPIOPinTypeADC(GPIO_PORTE_BASE, GPIO_PIN_3);

        ROM_SysCtlADCSpeedSet(SYSCTL_ADCSPEED_500KSPS);

        ROM_ADCSequenceConfigure(ADC0_BASE, 3, ADC_TRIGGER_PROCESSOR, 0);

        ROM_ADCSequenceStepConfigure(ADC0_BASE, 3, 0, ADC_CTL_CH1| ADC_CTL_IE |ADC_CTL_END);

        ROM_ADCSequenceEnable(ADC0_BASE, 3);

        ROM_IntMasterEnable();

        ROM_ADCIntEnable(ADC0_BASE, 3);

        ROM_IntEnable(INT_ADC0SS1);

        ROM_ADCIntClear(ADC0_BASE, 3);



}

void ADC_GetAvg(uint32_t ui32Base, uint32_t ui32SequenceNum)
{

      ROM_ADCProcessorTrigger(ui32Base, ui32SequenceNum);

}

void ADC_INTRHandler(void)
{
      ROM_ADCIntClear(ADC0_BASE, 0);



      // Read ADC Value.
      ROM_ADCSequenceDataGet(ADC0_BASE, 0, pui32ADC0Value);

      static int ledstate=0;
           if(ledstate==1)
           {
                  ROM_GPIOPinWrite(GPIO_PORTF_BASE, GPIO_PIN_2, 0);
                  ledstate=0;
           }
           else
           {
                 ROM_GPIOPinWrite(GPIO_PORTF_BASE, GPIO_PIN_2, 0XFF);
                 ledstate=1;


          }

}
int main(void)
{

    ROM_SysCtlClockSet(SYSCTL_SYSDIV_25 | SYSCTL_USE_PLL | SYSCTL_OSC_MAIN |SYSCTL_XTAL_16MHZ);

     // Enable the GPIO port that is used for the on-board LED.
     ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOF);

        // Enable the GPIO pins for the LED (PF2).
     ROM_GPIOPinTypeGPIOOutput(GPIO_PORTF_BASE,GPIO_PIN_2);

    ADC_Init();

    ADC_GetAvg (ADC0_BASE, 0);

    while(1)
    {
    }
}

  • Hi,

    Some observations reading your code:

    a) SysCtlADCSpeedSet is known to be not-working on TM4C, so the cure is highlighted in this thread.

    b) In this function ADCSequenceStepConfigure(ADC0_BASE, 3,…  you select the sequencer #3, but further, you enable sequencer #1 for interrupts (INT_ADC0SS1). Check also your Tiva version, this name could be changed.

    c) To make the things worse, further, you have ADC_GetAvg called only once, but with second parameter 0, so no chance to have interrupts.

    d) inside interrupt routine you have this instruction: static int ledstate=0; so every time the interrupt is triggered, this variable will be initialized with 0. Do you really need this?

    e) try to avoid the empty while(1) block, or at least do not make a habit to use that at the learning phase. Maybe later.

    Petrei


  • Thanks a lot for your findings Petrei,

    i have made changes as u said..but i am not clear about the third point u mentioned

    " To make the things worse, further, you have ADC_GetAvg called only once, but with second parameter 0, so no chance to have interrupts."

    The second parameter is specifying the sequence no:which is sequencer 0 in my case.

    I Have modified the code as below..

    kindly help me to understand the reason for  not entering  the  interrupt.

    awaiting for the response and thanks in advance


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


    #define SAMPLE_COUNT    ((uint8_t)8)
    uint32_t pui32ADC0Value[SAMPLE_COUNT];

    void ADC_Init(void ){


            ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_ADC0);

            ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOE);

            ROM_GPIOPinTypeADC(GPIO_PORTE_BASE, GPIO_PIN_3);

            HWREG(ADC0_BASE + ADC_O_PC) = (ADC_PC_SR_500K);

            ROM_ADCSequenceConfigure(ADC0_BASE, 0, ADC_TRIGGER_PROCESSOR, 0);

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

            ROM_ADCSequenceEnable(ADC0_BASE, 0);

            ROM_IntMasterEnable();

            ROM_ADCIntEnable(ADC0_BASE, 0);

            ROM_IntEnable(INT_ADC0SS0);

           ROM_ADCIntClear(ADC0_BASE, 0);

            ROM_ADCProcessorTrigger(ADC0_BASE, 0);


    }

    void ADC_GetAvg(uint32_t ui32Base, uint32_t ui32SequenceNum)
    {

          ROM_ADCProcessorTrigger(ui32Base, ui32SequenceNum);

    }


    void ADC_INTRHandler(void)
    {
          ROM_ADCIntClear(ADC0_BASE, 0);

          int ledstate=1;

          // Read ADC Value.
          ROM_ADCSequenceDataGet(ADC0_BASE, 0, pui32ADC0Value);


               if(ledstate==1)
               {
                      ROM_GPIOPinWrite(GPIO_PORTF_BASE, GPIO_PIN_2, 0);
                      ledstate=0;
               }
               else
               {
                     ROM_GPIOPinWrite(GPIO_PORTF_BASE, GPIO_PIN_2, 0XFF);
                     ledstate=1;


              }

    }
    int main(void)
    {

        ROM_SysCtlClockSet(SYSCTL_SYSDIV_25 | SYSCTL_USE_PLL | SYSCTL_OSC_MAIN |SYSCTL_XTAL_16MHZ);

         // Enable the GPIO port that is used for the on-board LED.
         ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOF);

            // Enable the GPIO pins for the LED (PF2).
         ROM_GPIOPinTypeGPIOOutput(GPIO_PORTF_BASE,GPIO_PIN_2);

        ADC_Init();
        
        
        ADC_GetAvg (ADC0_BASE, 0);
        

    }

  • Hi,

    Still you have multiple mistakes, please do not rush and read carefully the documentation:
    a) You like to work with sequencer 0: in this case, the parameters passed to some functions must reflect that. For instance:
      ADCSequenceStepConfigure(ADC0_BASE, 0, 0, ADC_CTL_CH0 | ADC_CTL_IE | ADC_CTL_END );
    b) Your ADC is triggered only once; it is wise to trigger repeatedly.
    c) My previous advise was to avoid empty while(1) loop - this does not means to remove it, just to use it - it is a perfect place to place here a command to trigger the ADC - repeatedly command,.
    d) It is wise that when initializing the ADC, to disable the sequence to work with, so after enabling the ADC, use a small delay, then ADCSequenceDisable(ADC_BASE, 0);
    e) Did you also modified the startup_css.c file to reflect the ADC interrupt routine?
    f) You try to set on/off a led in your interrupt routine: this routine is executed very fast, no chance to see a led lit; a minimum time for such thing is around 100ms. Shorter blinks could not be perceived by some people. So again, a good place to manage the led is the while(1) loop.
    g) the variable ledstate is local, get always initialized with 1, no chance to change its state next interrupt. Use static, but without any initialization (it is automatically initialized by startup routines).
    Petrei
  • Hi,

    yes i am using sequencer 0.

    by using ROM_ADCSequenceStepConfigure(ADC0_BASE, 0, 3, ADC_CTL_CH0| ADC_CTL_IE |ADC_CTL_END);

    i intended to get interrupt at every 3rd sample of the sequencer 0.ie., why i passed the third parameter as 3 in the function

    correct me if I am wrong.

    i have  also modified the startupccs.c as follows

    //*****************************************************************************
    //
    // External declaration for the interrupt handler used by the application.
    //
    //*****************************************************************************
    extern void ADC_INTRHandler(void);

    in the vector table

    IntDefaultHandler,                      // Quadrature Encoder 0
     ADC_INTRHandler,                      // ADC Sequence 0

    i have made the changes as you specified as below.hope these changes are inline with your points .thanks for the corrections

    but then now when i debug after   ADC_Init();

    it is entering into FaultISR();


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




    #define SAMPLE_COUNT    ((uint8_t)8)
    uint32_t pui32ADC0Value[SAMPLE_COUNT];

    void ADC_Init(void ){


            ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_ADC0);

            ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOE);

            ROM_GPIOPinTypeADC(GPIO_PORTE_BASE, GPIO_PIN_3);

            HWREG(ADC0_BASE + ADC_O_PC) = (ADC_PC_SR_500K);
        
            ROM_SysCtlDelay(2000000);

            ROM_ADCSequenceDisable(ADC0_BASE, 1);

            ROM_ADCSequenceConfigure(ADC0_BASE, 0, ADC_TRIGGER_PROCESSOR, 0);

            ROM_ADCSequenceStepConfigure(ADC0_BASE, 0, 0, ADC_CTL_CH0| ADC_CTL_IE |ADC_CTL_END);

            ROM_ADCSequenceEnable(ADC0_BASE, 0);

            ROM_IntMasterEnable();

            ROM_ADCIntEnable(ADC0_BASE, 0);

            ROM_IntEnable(INT_ADC0SS0);

           ROM_ADCIntClear(ADC0_BASE, 0);




    }

    void ADC_GetAvg(uint32_t ui32Base, uint32_t ui32SequenceNum)
    {

          ROM_ADCProcessorTrigger(ui32Base, ui32SequenceNum);
          volatile int32_t status = status = ROM_ADCIntStatus(ADC0_BASE,0,false);

    }


    void ADC_INTRHandler(void)
    {
          ROM_ADCIntClear(ADC0_BASE, 0);



          // Read ADC Value.
          ROM_ADCSequenceDataGet(ADC0_BASE, 0, pui32ADC0Value);


          while(1)
              {
                  //
                  // Turn on the LED
                  //
                  GPIOPinWrite(GPIO_PORTF_BASE, GPIO_PIN_2, 0xFF);

                  //
                  // Delay for a bit
                  //
                  SysCtlDelay(2000000);

                  //
                  // Turn on the LED
                  //
                  GPIOPinWrite(GPIO_PORTF_BASE, GPIO_PIN_2, 0);

                  //
                  // Delay for a bit
                  //
                  SysCtlDelay(2000000);
              }

    }
    int main(void)
    {

        ROM_SysCtlClockSet(SYSCTL_SYSDIV_25 | SYSCTL_USE_PLL | SYSCTL_OSC_MAIN |SYSCTL_XTAL_16MHZ);

         // Enable the GPIO port that is used for the on-board LED.
         ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOF);

            // Enable the GPIO pins for the LED (PF2).
         ROM_GPIOPinTypeGPIOOutput(GPIO_PORTF_BASE,GPIO_PIN_2);

        ADC_Init();

     while(1)
     {
        ADC_GetAvg (ADC0_BASE, 0);
     }


    }

  • Hi,

    Some observations about the sequencer: it is an automatic machine to cycle through a number of ADC channels and convert the voltage at that channel. You cannot jump directly to channel 3 without initializing and using channels 0, 1, 2. The scanning order is fixed, that's why you have the sequence configuration - i.e. use first channel 4, 7, 5 before channel 3. Try as suggested.

    While(1) should be used only in main, not in interrupt routine.

    Petrei

  • yes Petrei,

    i have configured channel 0.hope the below function used in the code configures it

    ROM_ADCSequenceStepConfigure(ADC0_BASE, 0, 0, ADC_CTL_CH0| ADC_CTL_IE |ADC_CTL_END);

    and kindly please explain "use first channel 4, 7, 5 before channel 3

     you meant to configure  ROM_GPIOPinTypeADC(GPIO_PORTE_BASE, GPIO_PIN_4);

    instead of

     ROM_GPIOPinTypeADC(GPIO_PORTE_BASE, GPIO_PIN_3);




  • Hi,

    That is only an example - you don'have to configure anything else. You did not told the result: is your interrupt taken or not? Use a breakpoint inside interrupt.

    Petrei

  • no  as i said it was entering into the fault ISR not hitting the ADC interrupt

  • Hi,

    Your parameter SYSCTL_SYSDIV_25 is wrong; should be ..._2_5 otherwise the ADC does not work, needs a 16MHz clock to work correctly. If still fault interrupts, see on micro page an application note describing how to deal with fault interrupts. Take this seriously, learn it, since you will drop on such thing many times and must be able to discover by yourself the cause of fault.

    Petrei

  • hi...

    now my code is hitting the interrupt...thanks petrei

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



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



    #define SAMPLE_COUNT    ((uint8_t)8)
    uint32_t pui32ADC0Value[SAMPLE_COUNT];

    void ADC_Init(void ){


         SysCtlPeripheralEnable(SYSCTL_PERIPH_ADC0);

                SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOE);

                GPIOPinTypeADC(GPIO_PORTE_BASE, GPIO_PIN_3);


                ADCSequenceConfigure(ADC0_BASE, 0, ADC_TRIGGER_PROCESSOR, 0);

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

                ADCIntEnable(ADC0_BASE, 0);

                IntEnable(INT_ADC0SS0);

                ADCSequenceEnable(ADC0_BASE, 0);

               ADCIntClear(ADC0_BASE, 0);

                while(1)
                {
                    ADCProcessorTrigger(ADC0_BASE, 0);
                }
    }


    static int ledstate=1;
    void
    ADC_INTRHandler(void)
    {


         IntMasterDisable();
             ADCIntDisable(ADC0_BASE, 0);
             ADCIntClear(ADC0_BASE, 0);
             ADCSequenceDataGet(ADC0_BASE, 0, pui32ADC0Value);


            if(ledstate==1)
               {
               GPIOPinWrite(GPIO_PORTF_BASE, GPIO_PIN_2, 0);
               ledstate=0;
               }
               else
               {
                   GPIOPinWrite(GPIO_PORTF_BASE, GPIO_PIN_2, 0XFF);
                   ledstate=1;
               }

            ADCIntEnable(ADC0_BASE, 0);
            IntMasterEnable();
    }



    int
    main(void)
    {

        SysCtlClockSet(SYSCTL_SYSDIV_2_5 | SYSCTL_USE_PLL | SYSCTL_OSC_MAIN |SYSCTL_XTAL_16MHZ);

         // Enable the GPIO port that is used for the on-board LED.
         SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOF);

            // Enable the GPIO pins for the LED (PF2).
        GPIOPinTypeGPIOOutput(GPIO_PORTF_BASE,GPIO_PIN_2);

        IntMasterEnable();

        ADC_Init();


    }