TIVAC - ADC Value Issue(12 bit)

Hi Experts ,

currently i am working TIVAC with ADC, i know the ADC is 12bit so we get 0-4098 value but i get 4900,5000, i don't know the reason for this error value, the adc input voltage is 0-3V but why this value is going to greater than 12bit value, i have shared my serial log and code for your reference kindly check and point out the mistake

#include <stdint.h>
#include <stdbool.h>
#include "inc/hw_types.h"
#include "inc/hw_memmap.h"
#include "driverlib/sysctl.h"
#include "driverlib/gpio.h"
#include "driverlib/adc.h"
#include "driverlib/rom.h"
#include "driverlib/uart.h"
#include "utils/uartstdio.h"
#include "inc/hw_ints.h"
#include "inc/hw_nvic.h"
#include "inc/hw_types.h"
#include "driverlib/debug.h"
#include "driverlib/fpu.h"
#include "driverlib/interrupt.h"
#include "driverlib/pin_map.h"
#include "driverlib/sysctl.h"
#include "driverlib/systick.h"

void ConfigureUART(void)
{
ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOA);
ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_UART0);
ROM_GPIOPinConfigure(GPIO_PA0_U0RX);
ROM_GPIOPinConfigure(GPIO_PA1_U0TX);
ROM_GPIOPinTypeUART(GPIO_PORTA_BASE, GPIO_PIN_0 | GPIO_PIN_1);
UARTClockSourceSet(UART0_BASE, UART_CLOCK_PIOSC);
UARTStdioConfig(0, 115200, 16000000);
}

int main(void)
{
int ulADC0Value[4];
volatile unsigned long ulTempAvg;

SysCtlPeripheralEnable(SYSCTL_PERIPH_ADC0);
ADCHardwareOversampleConfigure(ADC0_BASE, 64);
ADCSequenceDisable(ADC0_BASE, 1);

SysCtlClockSet(SYSCTL_SYSDIV_10 | SYSCTL_USE_PLL | SYSCTL_OSC_MAIN | SYSCTL_XTAL_16MHZ);

SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOE);

SysCtlPeripheralEnable(SYSCTL_PERIPH_ADC0);

while(!SysCtlPeripheralReady(SYSCTL_PERIPH_GPIOE))
{
}

while(!SysCtlPeripheralReady(SYSCTL_PERIPH_ADC0))
{
}
GPIOPinTypeADC(GPIO_PORTE_BASE, GPIO_PIN_3 | GPIO_PIN_2);


ADCSequenceConfigure(ADC0_BASE, 1, ADC_TRIGGER_PROCESSOR, 0);
ADCSequenceStepConfigure(ADC0_BASE, 1, 0, ADC_CTL_CH0 );
ADCSequenceStepConfigure(ADC0_BASE, 1, 1, ADC_CTL_CH1 | ADC_CTL_IE | ADC_CTL_END);
ADCSequenceEnable(ADC0_BASE,1);
ADCIntClear(ADC0_BASE, 1);
ADCClockConfigSet(ADC0_BASE, ADC_CLOCK_SRC_PIOSC | ADC_CLOCK_RATE_FULL, 1);

ConfigureUART();

UARTprintf("Hello, world!\n");

while(1)
{

ADCProcessorTrigger(ADC0_BASE, 1);

while(!ADCIntStatus(ADC0_BASE, 1, false))
{
}

ADCIntClear(ADC0_BASE, 1);

ADCSequenceDataGet(ADC0_BASE, 1, ulADC0Value);

ulTempAvg = (ulADC0Value[0] + ulADC0Value[1] + ulADC0Value[2] + ulADC0Value[3]);
UARTprintf("ADC=%d\n",ulTempAvg);
SysCtlDelay(SysCtlClockGet() / 5 / 3);
}

  • ulTempAvg = (ulADC0Value[0] + ulADC0Value[1] + ulADC0Value[2] + ulADC0Value[3]);
    UARTprintf("ADC=%d\n",ulTempAvg);

    The code has a variable called ulTempAvg which suggests it should contain the average of a number of ADC samples. Yet, the code reports the sum of 4 ADC samples and not the average.

    Try using a divide-by-4 to get the average:

    ulTempAvg = (ulADC0Value[0] + ulADC0Value[1] + ulADC0Value[2] + ulADC0Value[3]) / 4;
    UARTprintf("ADC=%d\n",ulTempAvg);

    Also, the code ignores the return value from ADCSequenceDataGet() which is the number of samples copied to the buffer. I.e. not all 4 entries in the ulADC0Value array may be populated, leading to ulTempAvg potentially being calculated from undefined data.

  • Hi @Chester Gillon

    Thanks for the reply i have changed my code as follows, but i am a newbie to TI so this ADC has little bit confused, this ADC read have four types of sequence for what?, i can't understand this ADC config,  now i am trying to read 4-20ma input through a 150ohm resistor, i have checked with a multimeter it's perfectly varied from 600ma to 3v but i don't know how to show the voltage in UART based on the ADC value, 

    int main(void)
    {
    uint32_t pui32ADC0Value[1];
    SysCtlClockSet(SYSCTL_SYSDIV_10 | SYSCTL_USE_PLL | SYSCTL_OSC_MAIN |
    SYSCTL_XTAL_16MHZ);
    InitConsole();
    UARTprintf("ADC ->\n");
    UARTprintf(" Type: Single Ended\n");
    UARTprintf(" Samples: One\n");
    UARTprintf(" Update Rate: 250ms\n");
    UARTprintf(" Input Pin: AIN0/PE3\n\n");
    SysCtlPeripheralEnable(SYSCTL_PERIPH_ADC0);
    SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOE);
    GPIOPinTypeADC(GPIO_PORTE_BASE, GPIO_PIN_3);
    ADCSequenceConfigure(ADC0_BASE, 3, ADC_TRIGGER_PROCESSOR, 0);
    ADCSequenceStepConfigure(ADC0_BASE, 3, 0, ADC_CTL_CH0 | ADC_CTL_IE |
    ADC_CTL_END);
    ADCSequenceEnable(ADC0_BASE, 3);
    ADCIntClear(ADC0_BASE, 3);
    while(1)
    {
    ADCProcessorTrigger(ADC0_BASE, 3);
    while(!ADCIntStatus(ADC0_BASE, 3, false))
    {
    }

    ADCIntClear(ADC0_BASE, 3);
    ADCSequenceDataGet(ADC0_BASE, 3, pui32ADC0Value);

    UARTprintf("AIN0 = %4d\r\n", pui32ADC0Value[0]/7);
    SysCtlDelay(SysCtlClockGet() / 12);
    }
    }

  • The simplified function UARTprintf() does not support printing floating point numbers, but using floating point is the easiest way to scale the ADC reading to a voltage. Here is a simple trick to break the floating point value into two integers that can then be printed to look like the floating point value.

    void
    main(void)
    {
        unsigned int adcValue;
        unsigned int fracPart;
        unsigned int intPart;
        float fAdcValue;
    
        MAP_FPULazyStackingEnable();
        MAP_SysCtlClockSet(SYSCTL_SYSDIV_4 | SYSCTL_USE_PLL | SYSCTL_XTAL_16MHZ |
                           SYSCTL_OSC_MAIN);
        ConfigureUART();
        UARTprintf("Print floating point using UARTprintf()\n");
        adcValue = 3300; // Example value from ADC
        fAdcValue = (float)adcValue * 3.3 / 4095.0;
        intPart = (int)fAdcValue;
        fracPart = (int)((fAdcValue - intPart) * 100.0);
        UARTprintf(" Voltage = %d.%02dV\n", intPart, fracPart);
    }