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/SW-EK-TM4C123GXL: Confusion regarding pin configurations needed to obtain readings from sensor

Part Number: SW-EK-TM4C123GXL
Other Parts Discussed in Thread: LM35, EK-TM4C123GXL, TM4C123GH6PM

Tool/software: Code Composer Studio

Hello !
I am trying to interface a temperture sensor(LM35) with the Tiva Launchpad(EK-TM4C123GXL).
In order to do so, I modified a source code taken from an example. I configured the PE_3 pin as an ADC input pin.
But at the same time, I went through the Driver Peripheral Library for tm4c123gh6pm and saw an example for using the GPIO pins as an input pin.
So, accordingly, I modified my code and configured PE_2 as an input pin.
Both the configurations were made in the same code so that I could understand the difference between them.
But I am unable to do so, can you please tell me which of the either configurations would take in the output of the LM35 sensor, send it to the ADC and give me the corresponding values.

//Header Files needed to access the TIVA APIs
#include <stdint.h>
#include <stdbool.h>
#include "inc/hw_memmap.h"
#include "inc/hw_types.h"
#include "driverlib/debug.h"
#include "driverlib/sysctl.h"
#include "driverlib/gpio.h"
#include "driverlib/adc.h"  //contains definitions for the ADC driver

int main(void)
{
    //Var for the input GPIO
    int32_t i32Val;
    //Using Sequencer 1 of FIFO size = 4, hence creating an array to store its data
    uint32_t ui32ADC0Value[4];
    // var for storing the average of the temperature.
    volatile uint32_t ui32TempAvg; //volatile makes them un-optimizable for the compiler
    volatile uint32_t ui32TempValueC;
    volatile uint32_t ui32TempValueF;

    //Set up the system clock again to run at 40MHz
    /* # PLL runs on 400 MHz
     * -- this frequency is divided by 2 by default
     * -- additional dividing factors between 5 & 25 can be used
     * -- Here we use 5 (a total of 2+5=10)
     * -Use PLL
     * -Use main OSC as the system clock
     * -Run it at 16 MHz
     */
    SysCtlClockSet(SYSCTL_SYSDIV_5|SYSCTL_USE_PLL|SYSCTL_OSC_MAIN|SYSCTL_XTAL_16MHZ);
    //Enable the ADC0
    SysCtlPeripheralEnable(SYSCTL_PERIPH_ADC0);

    //Enable the PE3 to be an input pin
    SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOE);   //Enables the clock to PORT E
    // Wait for the GPIOA module to be ready.
    while(!SysCtlPeripheralReady(SYSCTL_PERIPH_GPIOA))
    {}
    //Register the port level interrupt handler for all the pin interrupts
    //GPIOIntRegister(GPIO_PORTE_BASE, PortEIntHandler);

    /* PE_2 : INPUT PIN
     * PE_3 : ADC INPUT PIN
     */
    GPIOPinTypeGPIOInput(GPIO_PORTE_BASE,GPIO_PIN_2);
    GPIOPinTypeADC(GPIO_PORTE_BASE, GPIO_PIN_3);

    /* Configuring the ADC sequencer (AND NOT TRIGGER!):-
     * ->Use ADC0 (STEP 1)
     * ->Use Sample Sequencer 1 (STEP 2)
     * ->Ask the processor to trigger the sequence (STEP 3)
     * ->Use the highest priority (STEP 4)
     * # allow the ADC12 to run at its default rate of 1Msps
     */
    ADCSequenceConfigure(ADC0_BASE, 1, ADC_TRIGGER_PROCESSOR, 0);

    //Next we need to configure all four steps in the ADC sequencer
    ADCSequenceStepConfigure(ADC0_BASE, 1, 0, ADC_CTL_CH0);
    ADCSequenceStepConfigure(ADC0_BASE, 1, 1, ADC_CTL_CH0);
    ADCSequenceStepConfigure(ADC0_BASE, 1, 2, ADC_CTL_CH0);
    // Perform last step and set the interrupt flag (ADC_CTL_IE) as the last sample is done.
    // Also, tell the ADC logic that this is the last conversion on SS1 (ADC_CTL_END)
    ADCSequenceStepConfigure(ADC0_BASE, 1 ,3 ,ADC_CTL_CH0|ADC_CTL_IE|ADC_CTL_END);

    //Enabling the SS1 (AND NOT TRIGGER!)
    ADCSequenceEnable(ADC0_BASE, 1);

    //An infinite loop
    while(1)
    {
        //Read pin PE_2
        i32Val = GPIOPinRead(GPIO_PORTE_BASE,GPIO_PIN_2);
        GPIOPinRead(GPIO_PORTE_BASE, GPIO_PIN_3);

        //Clearing the ADC interrupt status flag
        ADCIntClear(ADC0_BASE, 1);
        //Trigger the ADC conversion
        ADCProcessorTrigger(ADC0_BASE, 1);
        //Get the current Interrupt status | false indicates that "raw" interrupt status is reqd and not "masked"
        //And wait until the status comes out to be 1 . i.e, the conversion is complete
        while(!ADCIntStatus(ADC0_BASE, 1, false))
        { }
        //Copy the ADC values from the SS1 into a buffer. SS1 -> (array)ui32ADC0Value
        ADCSequenceDataGet(ADC0_BASE, 1, ui32ADC0Value);
        ui32TempAvg = (ui32ADC0Value[0] + ui32ADC0Value[1] + ui32ADC0Value[2] + ui32ADC0Value[3] + 2)/4;    //2 is for rounding
        //TEMP = 147.5 – ((75 * (VREFP – VREFN) * ADCVALUE) / 4096) | We need to multiply everything by 10 to stay within the precision needed
        ui32TempValueC = (1475 - ((2475 * ui32TempAvg)) / 4096)/10;
        ui32TempValueF = ((ui32TempValueC * 9) + 160) / 5;
    }
}

  • Hello Prashant,

    When you configure a pin for the ADC, you should not do calls like GPIOPinRead with that pin afterwards. What you do by using GPIOPinTypeADC(GPIO_PORTE_BASE, GPIO_PIN_3); is setting the GPIO multiplexer function for the ADC peripheral, at that point you should not treat it as a typical GPIO until you reconfigure it.

    In general to use the ADC you would want to use only PE3, and you don't need a GPIO to read in the input from the LM35.

    As you are trying to get an initial reading, I'd suggest using only one sequence step to start, and then add in the additional steps you need after you get one working.
  • Hello and Thanks !

    as you said, "don't need a GPIO to read in the input from the LM35", but this is what I saw in the tm4c123gh6pm documentation,

    Doesn't it mean that the GPIO pins include the ADC pin? If no, then why don't I see any different methods (other than configuring GPIOs to function as ADC) for directly using the ADC0 and ADC1 ?

    P.S.  the documentation provides info on the "direct register access model" whereas I find the example codes that use the "software driver model" . Does't it make things complicated?  

  • Hello Prashant,

    Sorry for the confusion, my wording was poor. I meant you don't need a pin with *GPIO functionality* to read the information. You configure your desired ADC pin for ADC operation and use it as an *ADC input pin*, and not as a GPIO input/output pin.

    All GPIO have other peripherals mapped to them, often times multiple peripherals, so if you need to use ADC or other peripherals then you would configure the GPIO for the specific peripheral you want to use on that pin.