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.

Simple ADC Configuration

Other Parts Discussed in Thread: TM4C129XNCZAD

I have spent hours upon days trying to figure out how to configure the ADC  to work. I am pretty sure it's a clocking problem because I am doing everything exactly how the tiva examples show as well as many online examples. I am short on time and could use some help. This is for my dad's business. 

I am using the TM4CXNCZAD.

Relevant code is as follows:

#include <stdbool.h>
#include <stdint.h>
#include "inc/hw_types.h"
#include "inc/hw_memmap.h"
#include "inc/hw_ints.h"
#include "inc/hw_pwm.h"
#include "driverlib/sysctl.h"
#include "driverlib/interrupt.h"
#include "driverlib/gpio.h"
#include "driverlib/systick.h"
#include "driverlib/pwm.h"
#include "driverlib/adc.h"
#include "driverlib/uart.h"
#include "utils/uartstdio.h"

uint32_t ADC_Data[1];

void ConfigADC()
{
    SysCtlPeripheralEnable(SYSCTL_PERIPH_ADC0);//The ADC0 peripheral must be enabled for use.
    SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOE);

    //ADCHardwareOversampleConfigure(ADC0_BASE, 64);
    //ADCReferenceSet(ADC0_BASE, ADC_REF_INT);

    GPIOPinTypeADC(GPIO_PORTE_BASE, GPIO_PIN_0);//Select the analog ADC function

    // Enable the first sample sequencer to capture the value of channel 0 when
    // the processor trigger occurs.
    ADCSequenceDisable(ADC0_BASE, 3);
    ADCSequenceConfigure(ADC0_BASE, 3, ADC_TRIGGER_PROCESSOR, 0);
    ADCSequenceStepConfigure(ADC0_BASE, 3, 0, ADC_CTL_CH0 | ADC_CTL_IE | ADC_CTL_END);

    //ADCIntRegister(ADC0_BASE, 3, ADC0Handler);

    ADCSequenceEnable(ADC0_BASE, 3);

    ADCIntClear(ADC0_BASE, 3);//to make sure the interrupt flag is cleared before we sample.

   while(1)
   {
    ADCProcessorTrigger(ADC0_BASE, 3);//Trigger the ADC conversion.
    while(!ADCIntStatus(ADC0_BASE, 3, false)){}//Wait until the sample sequence has completed.
    ADCIntClear(ADC0_BASE, 3);//Clear the ADC interrupt flag.

    ADCSequenceDataGet(ADC0_BASE, 3, ADC_Data);//Read the value from the ADC (stored in ADC_Data).

    SystickDelay5ms();
    }
}

int main(void)
{
//SysCtlClockSet(SYSCTL_OSC_MAIN | SYSCTL_XTAL_16MHZ);
//SysCtlClockSet(SYSCTL_OSC_MAIN);
//SysCtlClockSet(SYSCTL_SYSDIV_2_5 | SYSCTL_USE_PLL | SYSCTL_OSC_MAIN | SYSCTL_XTAL_16MHZ);
SysCtlClockSet(SYSCTL_SYSDIV_10 | SYSCTL_USE_PLL | SYSCTL_OSC_MAIN | SYSCTL_XTAL_16MHZ);//taken from and for the ADC example
//SysCtlClockSet(SYSCTL_SYSDIV_1 | SYSCTL_USE_OSC | SYSCTL_OSC_MAIN | SYSCTL_XTAL_16MHZ);//taken from and for the UART example

ConfigSystickTimer();
ConfigGPIOExample();
ConfigPWMs();
ConfigUART();
ConfigADC();
IntMasterEnable();//Enable the processor interrupt(possibly needed for all interupts to work)

while(1){}
}

 

  • Hi Marshall,

    Marshall Folkman said:
    ADCSequenceStepConfigure(ADC0_BASE, 3, 0, ADC_CTL_CH0 | ADC_CTL_IE | ADC_CTL_END);

    Based from TM4C129XNCZAD datasheet, PE0 alternates as AIN3. Try ADC_CTL_CH3 instead of ADC_CTL_CH0 from the code line above.

    -kel

  • Hi Marshall,

    I had a look at the other post as well. So if the issue of the clock is the case here then this what you have to do

    SysCtlClockSet(SYSCTL_SYSDIV_10 | SYSCTL_USE_PLL | SYSCTL_OSC_MAIN | SYSCTL_XTAL_16MHZ)

    Before the above line do the following steps

    SysCtlPeripheralEnable(SYSCTL_PERIPH_ADC0);

    HWREG(ADC0_BASE+ADC_O_CC) = 0x1;

    SysCtlClockSet(SYSCTL_SYSDIV_10 | SYSCTL_USE_PLL | SYSCTL_OSC_MAIN | SYSCTL_XTAL_16MHZ)

    Amit

  • Hi,

    Marshall, what is wrong with your code is a misplaced while(1) loop inside ConfigADC function - running the code stops inside that loop so globally enabling interrupts never take place. Move that inside while in the main function.

    Also, verify the system clock - be sure to be higher than 16MHz, which is minimum for ADC to work.

    Petrei

    EDIT: your micro has external reference only, so it is wise to configure for external reference use.

  • Hi Marshall,

         I agree with Petrei.

        Your, ADC code is mainly based from the ADC example code at Tivaware. Try that ADC example code first to test the ADC functionality, with our recommended modifications and without the other additional codes.

        Your clock settings is okay, as that configuration sets the system clock at 20MHz.

    -kel

  • Hi amit,

    which systemclock should I configure with ADC & timer module ( I am using both module in same code)..??

    SysCtlClockSet(SYSCTL_SYSDIV_2_5 | SYSCTL_USE_PLL | SYSCTL_OSC_MAIN | SYSCTL_XTAL_16MHZ);  freq = SysCtlClockGet();      // 80MHz
    SysCtlClockSet(SYSCTL_SYSDIV_4 | SYSCTL_USE_PLL | SYSCTL_OSC_MAIN | SYSCTL_XTAL_16MHZ);  freq = SysCtlClockGet();      // 50MHz                                                   SysCtlClockSet(SYSCTL_SYSDIV_5 | SYSCTL_USE_PLL | SYSCTL_OSC_MAIN | SYSCTL_XTAL_16MHZ);  freq = SysCtlClockGet();      // 40MHz

    If I dont write any of above, I get :: freq = SysCtlClockGet();      // 16MHz

    My requirement is lowest execution time.                                                                                                                                                                                                                                                                                                       Should I configure to 80MHz..??                

    If I do so will both ADC and Timers will work fine..??                                                                                                                                                                                                                                                                                              Is any extra configuration needed..like you said in last post..?

    SysCtlPeripheralEnable(SYSCTL_PERIPH_ADC0);                                                                                                                                                                                                                             HWREG(ADC0_BASE+ADC_O_CC) = 0x1;   // what this line means                                                                                                                                                                                               SysCtlClockSet(SYSCTL_SYSDIV_10 | SYSCTL_USE_PLL | SYSCTL_OSC_MAIN | SYSCTL_XTAL_16MHZ)

  • According to datasheet, if I set system clock 16 Mhz then only for 1msps setting, conversion time will be 1us.

    What will be conversion time if I set System clock 40 Mhz, 1msps setting..?? OR

    What will be conversion time if I set System clock 80 Mhz, 1msps setting..??

  • Hello Krishnat

    On the TM4C123x device the ADC works of the PIOSC or the PLL divided by a divisor value leading to 16MHz ADC clock. So whatever be the setting of the system clock, the ADC must get 16MHz.
  • Hi amit,

    In my application I config. ADC to 1 msps always trigger mode. system clock to 80 Mhz.

    If i read ADC twice in 1 us, it will give me same reading, according what u said.

    ADCSequenceDataGet(ADC0_BASE, 3, result);  // Currently this line executes after every 0.85 us in my code

    In this case, do I need to wait for 1 us to take next sample.  

    Thanx and regards,

    Krishnat

  • Hello Krishnat

    You must wait for the conversion to be completed by means of calling the ADCIntStatus function for end of conversion before reading the data.
  • Hi amit,

    Thanx for reply.
    I think I made mistake. In my code, ADC is always mode, I have made SS3 Interrupt Masked.
    And without using polling or using ADC interrupt ISR , I just reading ADCFIFO.
    I thought in always mode, we just have to read ADCFIFO.
    But when I debug, I get correct sample values. I don't understand if I made config. wrong , still it is showing sample values correct. How??

    Regrads,
    Krishnat

  • Hello Krishnat

    Reading the FIFO register without knowing if the sample is present would lead to a case of an underflow. Use the interrupt status bit before a read and after the interrupt status show a valid conversion, ensure that the status bit is cleared before going to the actual FIFO read is performed. The example code in TivaWare would show how to do so.

    D:\ti\TivaWare_C_Series-2.1.3.156\examples\peripherals\adc\single_ended.c