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.

TM4C129ENCPDT: ADC Not Reading Values Using Tivaware

Part Number: TM4C129ENCPDT
Other Parts Discussed in Thread: EK-TM4C1294XL, EK-TM4C129EXL,

I'd appreciate some help getting my ADC off the ground using Tivaware and the pinmux tool outputs.  Presently, I see no variation in my output (adc_buffer) in the expressions watch window when set to continuously refresh.  I've tried to follow the example from "Creating IoT Solutions with the Tiva C Series Connected LaunchPad Workshop" with minor modifications to fit my program structure.  Any advice?

Excerpt from pinmux.c showing configuration of these pins for analog inputs when PinoutSet() is called:

// Configure the GPIO Pin Mux for PE3

// for AIN0
//
MAP_GPIOPinTypeADC(GPIO_PORTE_BASE, GPIO_PIN_3);

//
// Configure the GPIO Pin Mux for PE1
// for AIN2
//
MAP_GPIOPinTypeADC(GPIO_PORTE_BASE, GPIO_PIN_1);

//
// Configure the GPIO Pin Mux for PE2
// for AIN1
//
MAP_GPIOPinTypeADC(GPIO_PORTE_BASE, GPIO_PIN_2);

//
// Configure the GPIO Pin Mux for PE0
// for AIN3
//
MAP_GPIOPinTypeADC(GPIO_PORTE_BASE, GPIO_PIN_0);

Main code:

#define TARGET_IS_TM4C129_RA2

//#include standard C libraries
#include <stdint.h>
#include <stdbool.h>

//#include Pinmux files
#include "pinout.h"

//#include Tivaware libraries
#include <hw_adc.h>
#include <adc.h>
#include <hw_can.h>
#include <hw_gpio.h>
#include <hw_ints.h>
#include <hw_memmap.h>
#include <hw_pwm.h>
#include <hw_ssi.h>
#include <hw_uart.h>
#include <sysctl.h>
#include <systick.h>
#include <rom.h>
#include <rom_map.h>
#include <gpio.h>

//#include <tm4c129encpdt.h> //inclusion generates 100+ warnings about incompatible redefinition of macros (?)

//Variable declarations
uint32_t timer_count;
const uint32_t timer_max = 99999;


//ADC read variables
uint32_t adc_buffer[4];
volatile uint32_t rail_voltage_24v;
volatile uint32_t rail_voltage_5v;
volatile uint32_t rail_voltage_3v3;
volatile uint32_t tiva_temperature;


//Function declarations
void processor_setup(void);
void peripheral_setup(void);
void delay_time(void);
void systick_int_handler(void);



/**
 * main.c
 */
void main(void)
{
	processor_setup();
	peripheral_setup();

	//Main infinite loop
	for (;;)
	{
		//First Half
		delay_time();
		GPIOPinWrite(GPIO_PORTH_BASE, GPIO_PIN_3, GPIOPinRead(GPIO_PORTH_BASE,0xFF)^0xFF);

		ADCIntClear(ADC0_BASE, 0); //base, SequenceNumber
		ADCProcessorTrigger(ADC0_BASE, 0); //base, SequenceNumber

		//Second Half
		delay_time();
		while(!SysCtlPeripheralReady(SYSCTL_PERIPH_ADC0))
		{
		}
		ADCSequenceDataGet(ADC0_BASE, 0, adc_buffer);
		rail_voltage_24v = adc_buffer[0];
		rail_voltage_5v = adc_buffer[1];
		rail_voltage_3v3 = adc_buffer[2];
		tiva_temperature = adc_buffer[3];

	}
}




void processor_setup(void){
	//Processor Pin configuration (from pinmux tool)
	PinoutSet();

	//SysTick Timer Setup for ~0.5s intervals (1 sec LED toggles)
	SysTickPeriodSet(25000000);
	SysTickEnable();
	SysTickIntEnable();
	SysTickIntRegister(systick_int_handler);

	//Onboard ADC Configuration to read 3 external analog inputs on pins 13,14,15 and internal temperature
	//read on sequence 0 with highest priority
	SysCtlPeripheralEnable(SYSCTL_PERIPH_ADC0); //p.501 of Tivaware manual
	SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOE);
	while(!SysCtlPeripheralReady(SYSCTL_PERIPH_ADC0))
	{
	}
	//ADCSequenceConfigure(ADC0_BASE, 0, ADC_TRIGGER_ALWAYS, 0); //Base, SequenceNum, Trigger, Priority
	ADCSequenceConfigure(ADC0_BASE, 0, ADC_TRIGGER_PROCESSOR, 0); //Base, SequenceNum, Trigger, Priority
	ADCSequenceStepConfigure(ADC0_BASE, 0, 0, (ADC_CTL_CH1)); //Base, SequenceNum, Step, Config
	ADCSequenceStepConfigure(ADC0_BASE, 0, 1, (ADC_CTL_CH2)); //Base, SequenceNum, Step, Config
	ADCSequenceStepConfigure(ADC0_BASE, 0, 2, (ADC_CTL_CH3)); //Base, SequenceNum, Step, Config
	ADCSequenceStepConfigure(ADC0_BASE, 0, 3, (ADC_CTL_TS | ADC_CTL_IE | ADC_CTL_END)); //Base, SequenceNum, Step, Config
	ADCReferenceSet(ADC0_BASE, ADC_REF_EXT_3V);
	ADCSequenceEnable(ADC0_BASE, 0); //Base, SequenceNum


	//Load
	//VAL
	//CTRL

	//CAN Configuration
	//SPI Configuration
}

void peripheral_setup(void){
	////Peripheral setup////
	//includes thermocouple input ADCs, 4to20 mA ADCs and DACs
	//4-20 Transmitter Configuration
	//4-20 Reciever Configuration
	//Thermocouple Configuration
}

void delay_time(void){
	for (timer_count = 1; timer_count <= timer_max/2; timer_count++) {
	}
}

void systick_int_handler(void){
	GPIOPinWrite(GPIO_PORTH_BASE, GPIO_PIN_2, GPIOPinRead(GPIO_PORTH_BASE,0xFF)^0xFF);
}

  • Hello Jack,

    It looks like the code is going into FaultISR after the first loop.

    Edit: Okay I found the core issue with the FaultISR, and it may not affect your system. If your PinMux is setup correctly anyways. In my case since you didn't provide the full code, I didn't have the enabling for GPIO H in it.

    This API call was causing the FaultISR to trigger on my testing:

    		GPIOPinWrite(GPIO_PORTH_BASE, GPIO_PIN_3, GPIOPinRead(GPIO_PORTH_BASE,GPIO_PIN_3)^0xFF);
    

    After resolving the FaultISR, I am able to see the values update with breakpoints. I am not familiar with the term you used to watch with 'continuous refresh' though, if that is what is not working and you are getting readings with breakpoints, maybe you can explain this more so I can look into that further?

    Also I noticed you have variable names for 5V and 24V, I hope you are planning to divide these values down to 3.3V level before reading them in. The GPIO pins are 3.3V tolerant so you can't input such large voltages into them.

  • Hi Ralph,

    I greatly appreciate the help. There are voltage dividers for the 5 and 24V inputs, so no worries there.

    The processor is clearly getting into the main loop and running there continuously (I can watch the LED's toggle and the timer_counter variable continually ramp up and reset in expression window).

    I had put ADC development on hold and continued with some SPI development last night. At some point, I noticed the ADC was working and reporting correct values. BUT it doesn't work now after everything rebooted. I ran a diff checker on the code when this was observed and had only addedd #include statements for ssi.h and sysctl.h and one function sys_clk = SysCtlClockFreqSet(SYSCTL_XTAL_25MHZ | SYSCTL_USE_OSC, 25000000);. These seem unrelated, but possibly there's a clue there? I'm at a loss for what was different.
  • When I say "continuous refresh," I'm referring to the continuous update of expressions in the debug view.
  • Hello Jack,

    Okay I understand better now, sorry I haven't used that mode before but I've figured out how to watch the values. I don't know if that can be done in the Expressions window, you'd need to ask on the CCS forum if that feature exists, but for continuous debug what I did find for CCS is watching the variable in the Memory Browser.

    So you would right click your variable in the Expression Window and Select "View Memory"

    Then in the Memory Browser look for a rotating pair of Arrows titled 'Continuous Refresh'. There's also one for Refresh, so make sure it says Continuous. When enabling this, you will see the ADC buffer values updating in memory.

    If you must have it in the Expressions window where you can see the decimal values etc. I'll have to request you post a general 'how to' request to the CCS folks as that is beyond my knowledge as a TM4C expert.
  • The ADC buffer is all zeros when viewed through the memory browser as well...

    Not sure if it's feasible, but is it possible to view the ADC0 config memory block starting at 0x4003.8000 and compare? Any other suggestions on how to proceed?
  • Hello Jack,

    Alright lets take a step back on the setup.

    I tested this on one of my LaunchPad's, so I took your code and ran it on the EK-TM4C1294XL, and hooked the pins E0, E1, and E2 to 3.3V sources on the LaunchPad to make sure I was getting reading at or near 4095. Your code worked perfect fine for doing this, and I was getting the right readings as a result.

    How does your setup differ from what I did, and can you test it with a similar setup? Perhaps it could be something to do with the hardware setup then.
  • I also have a EK-TM4C129EXL. Connecting 3V3 to PE1 and then uploading the same code base on that board (I'm using the pinmux files from my original code if that matters and I converted the ADC reference to be the internal reference), I'm still not seeing anything when inspecting the adc_buffer in either the Memory Browser or Expression Window.

    I would think it's not hardware-based on that basis.
  • Hello Jack,

    That is very strange because I am getting results on my end... did you cycle through the breakpoint a few times? The first time I paused on the Breakpoint I didn't see a measurement yet.

    Let me post the full code again as I didn't have the PinoutSet API you did so I used typical configs. You'll want to replace the header files since I adjusted their pathing based on TivaWare install:

    #define TARGET_IS_TM4C129_RA2
    
    //#include standard C libraries
    #include <stdint.h>
    #include <stdbool.h>
    
    //#include Tivaware libraries
    #include <inc/hw_adc.h>
    #include <driverlib/adc.h>
    #include <inc/hw_gpio.h>
    #include <inc/hw_ints.h>
    #include <inc/hw_memmap.h>
    #include <inc/hw_pwm.h>
    #include <inc/hw_ssi.h>
    #include <inc/hw_uart.h>
    #include <driverlib/sysctl.h>
    #include <driverlib/systick.h>
    #include <driverlib/rom.h>
    #include <driverlib/rom_map.h>
    #include <driverlib/gpio.h>
    
    //#include <tm4c129encpdt.h> //inclusion generates 100+ warnings about incompatible redefinition of macros (?)
    
    //Variable declarations
    uint32_t timer_count;
    const uint32_t timer_max = 99999;
    
    
    //ADC read variables
    uint32_t adc_buffer[4];
    volatile uint32_t rail_voltage_24v;
    volatile uint32_t rail_voltage_5v;
    volatile uint32_t rail_voltage_3v3;
    volatile uint32_t tiva_temperature;
    
    
    //Function declarations
    void processor_setup(void);
    void peripheral_setup(void);
    void delay_time(void);
    void systick_int_handler(void);
    
    
    
    /**
     * main.c
     */
    void main(void)
    {
        processor_setup();
        peripheral_setup();
    
        //Main infinite loop
        for (;;)
        {
            //First Half
            delay_time();
            GPIOPinWrite(GPIO_PORTH_BASE, GPIO_PIN_3, GPIOPinRead(GPIO_PORTH_BASE,0xFF)^0xFF);
    
            ADCIntClear(ADC0_BASE, 0); //base, SequenceNumber
            ADCProcessorTrigger(ADC0_BASE, 0); //base, SequenceNumber
    
            //Second Half
            delay_time();
            while(!SysCtlPeripheralReady(SYSCTL_PERIPH_ADC0))
            {
            }
            ADCSequenceDataGet(ADC0_BASE, 0, adc_buffer);
            rail_voltage_24v = adc_buffer[0];
            rail_voltage_5v = adc_buffer[1];
            rail_voltage_3v3 = adc_buffer[2];
            tiva_temperature = adc_buffer[3];
    
        }
    }
    
    
    
    
    void processor_setup(void){
        //Processor Pin configuration (from pinmux tool)
    	SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOE);
    	SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOH);
    
    	GPIOPinTypeGPIOOutput(GPIO_PORTH_BASE, GPIO_PIN_3);
    
    	// Configure the GPIO Pin Mux for PE3
    
    	// for AIN0
    	//
    	MAP_GPIOPinTypeADC(GPIO_PORTE_BASE, GPIO_PIN_3);
    
    	//
    	// Configure the GPIO Pin Mux for PE1
    	// for AIN2
    	//
    	MAP_GPIOPinTypeADC(GPIO_PORTE_BASE, GPIO_PIN_1);
    
    	//
    	// Configure the GPIO Pin Mux for PE2
    	// for AIN1
    	//
    	MAP_GPIOPinTypeADC(GPIO_PORTE_BASE, GPIO_PIN_2);
    
    	//
    	// Configure the GPIO Pin Mux for PE0
    	// for AIN3
    	//
    	MAP_GPIOPinTypeADC(GPIO_PORTE_BASE, GPIO_PIN_0);
    
        //SysTick Timer Setup for ~0.5s intervals (1 sec LED toggles)
        SysTickPeriodSet(25000000);
        SysTickEnable();
        SysTickIntEnable();
        SysTickIntRegister(systick_int_handler);
    
        //Onboard ADC Configuration to read 3 external analog inputs on pins 13,14,15 and internal temperature
        //read on sequence 0 with highest priority
        SysCtlPeripheralEnable(SYSCTL_PERIPH_ADC0); //p.501 of Tivaware manual
        SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOE);
    
    	SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOH);
    
    	GPIOPinTypeGPIOOutput(GPIO_PORTH_BASE, GPIO_PIN_3);
    
        while(!SysCtlPeripheralReady(SYSCTL_PERIPH_ADC0))
        {
        }
        //ADCSequenceConfigure(ADC0_BASE, 0, ADC_TRIGGER_ALWAYS, 0); //Base, SequenceNum, Trigger, Priority
        ADCSequenceConfigure(ADC0_BASE, 0, ADC_TRIGGER_PROCESSOR, 0); //Base, SequenceNum, Trigger, Priority
        ADCSequenceStepConfigure(ADC0_BASE, 0, 0, (ADC_CTL_CH1)); //Base, SequenceNum, Step, Config
        ADCSequenceStepConfigure(ADC0_BASE, 0, 1, (ADC_CTL_CH2)); //Base, SequenceNum, Step, Config
        ADCSequenceStepConfigure(ADC0_BASE, 0, 2, (ADC_CTL_CH3)); //Base, SequenceNum, Step, Config
        ADCSequenceStepConfigure(ADC0_BASE, 0, 3, (ADC_CTL_TS | ADC_CTL_IE | ADC_CTL_END)); //Base, SequenceNum, Step, Config
        ADCReferenceSet(ADC0_BASE, ADC_REF_EXT_3V);
        ADCSequenceEnable(ADC0_BASE, 0); //Base, SequenceNum
    
    
        //Load
        //VAL
        //CTRL
    
        //CAN Configuration
        //SPI Configuration
    }
    
    void peripheral_setup(void){
        ////Peripheral setup////
        //includes thermocouple input ADCs, 4to20 mA ADCs and DACs
        //4-20 Transmitter Configuration
        //4-20 Reciever Configuration
        //Thermocouple Configuration
    }
    
    void delay_time(void){
        for (timer_count = 1; timer_count <= timer_max/2; timer_count++) {
        }
    }
    
    void systick_int_handler(void){
        GPIOPinWrite(GPIO_PORTH_BASE, GPIO_PIN_2, GPIOPinRead(GPIO_PORTH_BASE,0xFF)^0xFF);
    }
    

    Also, another idea could be to do a compare for the LED. If the value for PE1 is greater than, say, 4000, have it light up without turning off, otherwise have it toggle. So if it toggles, then you don't have the right reading period, but if it stays solid and you don't get any readings, then it would indicate a CCS issue.

  • Hi Ralph - took a while to get this working (linker search path to driverlib.lib wasn't there originally). I have built and loaded your code on the developer's kit and still see no ADC response.

    In all cases, I'm watching the expression window and memory browser menu while definitely refreshing (seeing other parameters/memory locations respond) and the adc response remains constantly zero. Could I be missing something in the CCS interface? I'm not using any breakpoints if that's relevant (?).

    Thank you for your help!
  • Hello Jack,

    I don't think the Expressions window will update without breakpoints. I would recommend lets separate this issue slightly and use breakpoints to clarify what the exact issue is:

    1) Does the ADC properly read values on the LaunchPad.

    2) How to use CCS to monitor the ADC values.

    For 1), please use a breakpoint with the Expressions window to monitor the results and let me know if you are now seeing the ADC return expected values, which is what I am able to do with your code running on my LaunchPad.

    I ask for this separation because while quite proficient over my years of usage, I am not a CCS expert like some of my colleagues who support CCS daily and I would like to ask them for help with guiding you on 2) once we can confirm that the code is running properly.
  • I'm now running with several hardware breakpoints on ADC functions in the main loop with no observed variations in the ADC outputs of adc_buffer.

  • Hello Jack,

    So they are reading back all 0's but you have measured and confirmed 3.3V on the PE pins?

    Edit: I ask to clarify because 'no variation' could mean it always reads 0xFFE or something, and the voltage measurement is just to sanity check connections since I tried again and still have the previously reported results.

  • It's a fair question - I probably am missing something equally basic. I physically measure 3.298V on PE1 relative to GND on X8 of the eval board using a DMM, and I have physically connected PE1 to 3.3V using the mounting holes for the unpopulated header pin x11.

    And the adc_buffer reads all zeros constantly with no variation/noise.
  • Hello Jack,

    Can you check if R41 is populated? It is located above the TM4C IC and slightly away from JP2. That provides VDD to the VREFA+ for external reference. If that is not populated, it would explain the issue.
  • R41 is populated (this is a stock board other than the connection from 3V3 to PE1. I also tried running with the external reference voltage commented out and the internal reference voltage ( ADCReferenceSet(ADC0_BASE, ADC_REF_INT);) with the same result.

    Currently loading a fresh copy of CCS and Tivaware on another laptop - will let you know if that helps. Other thoughts?
  • Maybe a picture of the board? I've been asking for ideas from my colleagues too since this is definitely a bit of a confounding situation.

    Also I exported the project which was working for me, maybe you can try it as is. Ignore the naming, I use the blinky projects as my default templates when doing things like this :)

    blinky_TM4C1294.zip

  • Ran your code from the post at May 22, 2019 10:52 PM on a different laptop with a fresh copy of CCS and Tivaware with the same results (constant zeroes to adc_buffer).

    I have tried to run the exported blinky project, but I'm getting error messages saying "Error: Program "make" not found in PATH" which I've been unable to resolve so far.
  • Hello Jack,

    One of my colleagues tried to replicate the failure multiple times as well and could not so our only thought at this point is that perhaps somehow the LaunchPad you have is defective in some manner. Do you have another LaunchPad you can try and test with?

    I am not sure why you are getting a path error, do you have TivaWare installed outside of the C/ti directory?

  • Hi Ralph,

    Thanks for your diligent support and patience as I'm learning CCS and its my first use of your Tiva processor. I tested 3 more of my custom control boards with the Tiva TM4C129ENCPDT... and the ADCs work on them with the same code as I temporarily observed ADC function on the first board.

    I'm concerned that something I did on the first board as well as the evalutation kit may have damaged the ADC units? Having the attempted reads fail when using the internal voltage reference and with multiple analog signals, whatever the issue was sounds more sinister than a single bad solder joint. Any pitfalls I should be aware of?

    -Jack
  • Hello Jack,

    The only thing I can think of from the top of my head is ESD...

    Another thing to rule out possible CCS/JTAG issues would be to add UART output and dump the ADC values that way, so you could just load the .out file without CCS. I was going to put that together this afternoon as a final test but hadn't had the time yet. Just a simple serial output of the raw ADC reading would be sufficient, and then you can make sure the ADC not reading isn't just due to CCS for some reason.

    By the way, you should be able to ask for a replacement of the LaunchPad if we confirm even with something like a UART output, it isn't working right. From pictures I saw I don't see any signs that you tampered with the board in a way that would violate any RMA ability and you can use this post/thread as proof if needed.

    That it happened on two boards including the custom board does bother me a bit too, but the LaunchPad issues seem to indicate some sort of malfunction so hard to say what exactly has triggered these odd behaviors...
  • Hi Jack,

    Perhaps configuring the ADC clock source and divisor will produce better results? If such exists in your code it was not easily found. Note too (for(;;)) loop may not produce same results as while(1) loop or stack issues depending on the Thumb instructions being asserted.
  • It appears that explicitly configuring the clock, as suggested by BP101, has solved the issue. I'm presently unclear what was causing the ADC to function/not function, but have observed no issues since adding an ADCClockConfigSet() statement.  Adding a similar statement to the example code referenced in the first post would probably be worthwhile.

    For future reference, I'll mention that we also checked and found no issue with the analog voltage inputs to the processor - the only other common point across all other ADC channels that we could think of.

    Thanks to BP101 for the helpful suggestion!

  • Hi Jack,

    Good to see posting all is well after adding ADC clock. One thing learned over past 35 years is to look for the most obvious, is that Occam's Razor or Murphy's universal laws - IDK?? 

  • Hello Jack,

    Great to hear that solved problem.

    BP101,

    Thanks for the suggestion! Definitely an interesting quirk that multiple LaunchPads and users (Charles tried as well) couldn't get the failure to occur even when lacking the clock config. Something to keep an eye out for in the future for sure.
  • Ralph Jacobi said:
    users (Charles tried as well) couldn't get the failure to occur even when lacking the clock config

    Past we too discussed overclocking ADC still functions, extreme sample speed is not without issues. Just where did I put the link to that Wikipedia discussion on sampling frequency artifacts named after mans name??

  • Mans name; Shannon Nyquist

    Could not find link other CADC issue thread, link was somehow trashed:

    https://en.wikipedia.org/wiki/Nyquist%E2%80%93Shannon_sampling_theorem