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.

TM4C1290NCPDT: adc code

Part Number: TM4C1290NCPDT


hi,

  i want to read 1024 samples from an ADC channel within a second (1ksps), i am using tm4c129 board i have gone through the following code but i am getting only 75 samples within a second so can anyone help me to get that output, i recently started working on this board , here i am attaching the code.

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


uint32_t g_ui32SysClock;
//*****************************************************************************
//
//! \addtogroup adc_examples_list
//! <h1>Single Ended ADC (single_ended)</h1>
//!
//! This example shows how to setup ADC0 as a single ended input and take a
//! single sample on AIN0/PE7.
//!
//! This example uses the following peripherals and I/O signals. You must
//! review these and change as needed for your own board:
//! - ADC0 peripheral
//! - GPIO Port E peripheral (for AIN0 pin)
//! - AIN0 - PE7
//!
//! The following UART signals are configured only for displaying console
//! messages for this example. These are not required for operation of the
//! ADC.
//! - UART0 peripheral
//! - GPIO Port A peripheral (for UART0 pins)
//! - UART0RX - PA0
//! - UART0TX - PA1
//!
//! This example uses the following interrupt handlers. To use this example
//! in your own application you must add these interrupt handlers to your
//! vector table.
//! - None.
//
//*****************************************************************************

//*****************************************************************************
//
// This function sets up UART0 to be used for a console to display information
// as the example is running.
//
//*****************************************************************************
void
ConfigureUART0(void)
{
//
// Enable the GPIO Peripheral used by the UART.
//
SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOA);

//
// Enable UART0
//
SysCtlPeripheralEnable(SYSCTL_PERIPH_UART0);

//
// Configure GPIO Pins for UART mode.
//
GPIOPinConfigure(GPIO_PA0_U0RX);
GPIOPinConfigure(GPIO_PA1_U0TX);
GPIOPinTypeUART(GPIO_PORTA_BASE, GPIO_PIN_0 | GPIO_PIN_1);

//
// Initialize the UART for console I/O.
//
UARTStdioConfig(0,9600,g_ui32SysClock);
}


//*****************************************************************************
//
// Configure ADC0 for a single-ended input and a single sample. Once the
// sample is ready, an interrupt flag will be set. Using a polling method,
// the data will be read then displayed on the console via UART0.
//
//*****************************************************************************
int
main(void)
{
//0
// This array is used for storing the data read from the ADC FIFO. It
// must be as large as the FIFO for the sequencer in use. This example
// uses sequence 3 which has a FIFO depth of 1. If another sequence
// was used with a deeper FIFO, then the array size must be changed.
//
uint32_t pui32ADC0Value[1];


//
// Set the clocking to run at 20 MHz (200 MHz / 10) using the PLL. When
// using the ADC, you must either use the PLL or supply a 16 MHz clock
// source.
// TODO: The SYSCTL_XTAL_ value must be changed to match the value of the
// crystal on your board.
//
g_ui32SysClock = SysCtlClockFreqSet((SYSCTL_XTAL_25MHZ |
SYSCTL_OSC_MAIN | SYSCTL_USE_PLL |
SYSCTL_CFG_VCO_480), 120000000);
//
// Set up the serial console to use for displaying messages. This is
// just for this example program and is not needed for ADC operation.
//
ConfigureUART0();

//
// Display the setup on the console.
//

//
// The ADC0 peripheral must be enabled for use.
//
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);

ADCSequenceEnable(ADC0_BASE, 0);


ADCIntClear(ADC0_BASE,0);

SysCtlPeripheralEnable(SYSCTL_PERIPH_HIBERNATE);
HibernateEnableExpClk(SYSCTL_OSC_EXT32);
HibernateClockConfig(HIBERNATE_OSC_HIGHDRIVE);
HibernateRTCDisable();

HibernateRTCSet(0); // this code is for time stamps
HibernateRTCEnable();

unsigned long long sec = HibernateRTCGet();
unsigned int subsec = HibernateRTCSSGet();

while(sec<1) // i want to take the samples upto 1 sec time
{

ADCProcessorTrigger(ADC0_BASE, 0);


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


ADCIntClear(ADC0_BASE, 0);

ADCSequenceDataGet(ADC0_BASE, 0, pui32ADC0Value);

sec = HibernateRTCGet();
subsec = HibernateRTCSSGet();

UARTprintf("AIN0 = %4d\n", pui32ADC0Value[0]);

}

while(1);
}

thanks in advance.

  • Hi,
    I think it may have something to do with the UARTprintf statement as it takes time to send the data out of the UART. I think the slower the baudrate you configure (9600 in your code) the slower it takes to complete the UARTprintf API. Try to comment out the UARTprintf and see if it makes some difference. Instead of UARTprintf, you can try to increment a software counter and see how many counts you have got in one second.
  • hi thank for your kind reply , i changed the code as u told and i add some other lines to save that data in an array as in below code , when i put 200 in that array size it is working fine, but if i change to more than 300 it is going infinite loop(faultIsr function), i am not getting the reason is it related to to memory size?, please help me to get 1024 samples within seconds.

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


    uint32_t g_ui32SysClock;
    //*****************************************************************************
    //
    //! \addtogroup adc_examples_list
    //! <h1>Single Ended ADC (single_ended)</h1>
    //!
    //! This example shows how to setup ADC0 as a single ended input and take a
    //! single sample on AIN0/PE7.
    //!
    //! This example uses the following peripherals and I/O signals. You must
    //! review these and change as needed for your own board:
    //! - ADC0 peripheral
    //! - GPIO Port E peripheral (for AIN0 pin)
    //! - AIN0 - PE7
    //!
    //! The following UART signals are configured only for displaying console
    //! messages for this example. These are not required for operation of the
    //! ADC.
    //! - UART0 peripheral
    //! - GPIO Port A peripheral (for UART0 pins)
    //! - UART0RX - PA0
    //! - UART0TX - PA1
    //!
    //! This example uses the following interrupt handlers. To use this example
    //! in your own application you must add these interrupt handlers to your
    //! vector table.
    //! - None.
    //
    //*****************************************************************************

    //*****************************************************************************
    //
    // This function sets up UART0 to be used for a console to display information
    // as the example is running.
    //
    //*****************************************************************************
    void
    ConfigureUART0(void)
    {
    //
    // Enable the GPIO Peripheral used by the UART.
    //
    SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOA);

    //
    // Enable UART0
    //
    SysCtlPeripheralEnable(SYSCTL_PERIPH_UART0);

    //
    // Configure GPIO Pins for UART mode.
    //
    GPIOPinConfigure(GPIO_PA0_U0RX);
    GPIOPinConfigure(GPIO_PA1_U0TX);
    GPIOPinTypeUART(GPIO_PORTA_BASE, GPIO_PIN_0 | GPIO_PIN_1);

    //
    // Initialize the UART for console I/O.
    //
    UARTStdioConfig(0,9600,g_ui32SysClock);
    }


    //*****************************************************************************
    //
    // Configure ADC0 for a single-ended input and a single sample. Once the
    // sample is ready, an interrupt flag will be set. Using a polling method,
    // the data will be read then displayed on the console via UART0.
    //
    //*****************************************************************************
    int
    main(void)
    {
    //0
    // This array is used for storing the data read from the ADC FIFO. It
    // must be as large as the FIFO for the sequencer in use. This example
    // uses sequence 3 which has a FIFO depth of 1. If another sequence
    // was used with a deeper FIFO, then the array size must be changed.
    //
    uint32_t pui32ADC0Value[1];
    uint32_t data[200]; // to store the adc result
    int cnt=0 // to count no of samples taken


    //
    // Set the clocking to run at 20 MHz (200 MHz / 10) using the PLL. When
    // using the ADC, you must either use the PLL or supply a 16 MHz clock
    // source.
    // TODO: The SYSCTL_XTAL_ value must be changed to match the value of the
    // crystal on your board.
    //
    g_ui32SysClock = SysCtlClockFreqSet((SYSCTL_XTAL_25MHZ |
    SYSCTL_OSC_MAIN | SYSCTL_USE_PLL |
    SYSCTL_CFG_VCO_480), 120000000);
    //
    // Set up the serial console to use for displaying messages. This is
    // just for this example program and is not needed for ADC operation.
    //
    ConfigureUART0();

    //
    // Display the setup on the console.
    //


    //
    // The ADC0 peripheral must be enabled for use.
    //
    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);

    SysCtlPeripheralEnable(SYSCTL_PERIPH_HIBERNATE);
    HibernateEnableExpClk(SYSCTL_OSC_EXT32);
    HibernateClockConfig(HIBERNATE_OSC_HIGHDRIVE);
    HibernateRTCDisable();

    HibernateRTCSet(0); // this code is for time stamps
    HibernateRTCEnable();

    unsigned long long sec = HibernateRTCGet();
    unsigned int subsec = HibernateRTCSSGet();



    while(sec<1) // i want to take the samples upto 1 sec time
    {

    ADCProcessorTrigger(ADC0_BASE, 3);


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


    ADCIntClear(ADC0_BASE, 3);

    ADCSequenceDataGet(ADC0_BASE, 3, pui32ADC0Value);

    data[cnt]=pui32ADC0Value[0];

    sec = HibernateRTCGet();
    subsec = HibernateRTCSSGet();

    cnt++;

    }


    while(1);
    }
  • Hi,

    If your goal is to see how many samples can be taken in a second then you can just comment out data[cnt]=pui32ADC0Value[0] and just find out what is the value of cnt. I think what you have run into is a stack overflow. In a realistic application you would have processed the sampled data as they come in. You wouldn't just store all the ADC sampled data (i.e. 1000 of them) without processing them. For the sake of avoiding the hard fault you can increase the stack size or you can make the cnt a global variable. But at the end the on chip SRAM is limited and you will eventually overflow the stack or the SRAM again if you keep increasing the size of the array.
  • hey thank you for your answers , i tried with counter it is showing 204796 samples i got ,but as u told that i need to process the adc samples data to store in array , so can please tell me how can i do that , i need to store each adc sample with time stamps in an array so can u please help me
  • I don't understand your application as to why you need to store each adc sample with its timestamp. You can't just store infinite samples. Somehow you need to release the memory so it can store new data. Why don't you store in two buffers (two arrays) as in a butterfly or ping-pong fashion? Say one buffer is 100 samples. While you are processing one buffer the ADC can take samples and store the results in another buffer. You will just go back and forth between these two arrays. You can consider using DMA to improve the data transfer too but I will ask you to first realize it using CPU first. Once you get everything working you can move on to improve efficiency. At the end of the day, you just can't store all ADC samples. Somehow you need to process them and forget about of them so new data can come into to the buffer.
  • Greetings Charles,

    First - "HIGH: (tide and (later) baseball season achievement)" to our friends at/around Houston.

    Poster declares "1K analog readings/second" - but never described is the signal to be measured - which may (completely) negate any chance for measurement accuracy - at that measurement rate.    The quality of the "analog front-end" must also be considered - it too remains silent.

    We're not told the duration of this 1K/Sec requirement - is it: "just once", or periodic (unspecified), perhaps continuous?     Are not all such facts required to "blip poster's radar" - and be presented - usually "sooner rather than later?"

    It is noted that our poster chose the "hibernate RTC clock" for the determination of his 1mS intervals.     If accurate time-keeping is a requirement - an MCU's Timer proves far superior - don't you agree?     Generating the ADC trigger from the timer is likely to "completely eliminate" any need for, "time-stamping" as each/every ADC measure will be spaced at precise 1mS intervals.     So long as the "first conversion event is "linked to real time" - all others follow - in "lock-step" - speeding, easing, and greatly reducing the "need for extra SRAM."

    While this project is clearly "theoretically based" - the "real-world" aspects should receive (some) consideration - don't you agree?

  • hi , thank you for responding my query , can u send any example code using timer how we can get 1024 samples / second, and as mentioned in charales reply how to process the adc result in parallel with adc conversion, please help me i didn't know in depth concepts but still i want to get this output
  • Hi cb1,
    Thanks for suggesting the 1ms timer to get 1000 samples.

    Rupendra,
    We don't have ready to use example (using timer to trigger ADC in a pingpong buffer fashion). You will have to invest some effort to realize this. For setting up the timer you can reference the timers examples in <TivaWare_Installation>/examples/peripherals/timers. Below post is a good start point as the post shows some code to use the timer to trigger the ADC. I will suggest you to start with just a timer project. Try to understand the mechanics to use the timer before you integrate the timer code with the ADC code.

    e2e.ti.com/.../361896