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.

UART Communication and ADC values

Other Parts Discussed in Thread: LM3S811

Hi!

I need some help, I'm trying to do an application where the Stellaris LaunchPad reads an analog signal with a frequency of 2kHz, after the value is read this will be sent from the UART to a Matlab application, now  I'm putting a Sin signal in the stellaris and I want to see the same signal in matlab but the plot in matlab is not even close to the signal in the Stellaris, so I was wondering if the problem is in the code of the Stellaris

Here the code that I did, I hope someone can help me:

//Function libraries related with the project have to be declared
#include "SAMP.h"
#include "inc/hw_memmap.h"
#include "inc/hw_ssi.h"
#include "inc/hw_types.h"
#include "inc/hw_ints.h"
#include "inc/hw_timer.h"

#include "driverlib/ssi.h"
#include "driverlib/uart.h"
#include "driverlib/debug.h"
#include "driverlib/sysctl.h"
#include "driverlib/interrupt.h"
#include "driverlib/gpio.h"
#include "driverlib/timer.h"
#include "driverlib/adc.h"
#include "drivers/buttons.h"

#include "driverlib/rom.h"

//****************************************************************
//
//Error Routine
//
//****************************************************************

#ifdef DEBUG
void
__error__(char *pcFilename, unsigned long ulLine)
{
}
#endif

//****************************************************************
//
//Global Variables
//
//****************************************************************
int LED = 2;

unsigned long ulDataRx;        // SPI receiving variable (16 bits)

//***************************************************************
//
//Interrupts initialization
//
//***************************************************************
static volatile unsigned long ulHibModeEntryCount;

//*********************Timer 0************************************
void
Timer0IntHandler(void)
{

    // Clear the timer interrupt.
    ROM_TimerIntClear(TIMER0_BASE, TIMER_TIMA_TIMEOUT);

    //    ROM_UARTCharPut(UART1_BASE,'S');
    //    SysCtlDelay(100);
    ROM_UARTCharPut(UART1_BASE,ulDataRx >> 8);
    //    SysCtlDelay(100);
    ROM_UARTCharPut(UART1_BASE,ulDataRx & 0x00FF);
    //    SysCtlDelay(100);
    //    ROM_UARTCharPut(UART1_BASE,'E');

    // Cycle through 1000 values
    if (ulDataRx == 10000) {ulDataRx = 0;} else {ulDataRx++;}

}

// Show that the interrupts are working by flashing the led
void
Timer1IntHandler(void)
{

    // Clear the timer interrupt.
    ROM_TimerIntClear(TIMER1_BASE, TIMER_TIMA_TIMEOUT);

    // Turn on the LED
    //GPIOPinWrite(GPIO_PORTF_BASE, GPIO_PIN_1|GPIO_PIN_2|GPIO_PIN_3, LED);

    // Cycle through Red, Green and Blue LEDs
    //if (LED == 8) {LED = 2;} else {LED = LED*2;}

}



//*****************************************************************************
//
// The UART interrupt handler.
//
//*****************************************************************************

// Communication through the virtual port
void
UART0IntHandler(void)
{
    unsigned long ulStatus;
    //
    // Get the interrupt status.
    //
    ulStatus = ROM_UARTIntStatus(UART0_BASE, true);

    //
    // Clear the asserted interrupts.
    //
    ROM_UARTIntClear(UART0_BASE, ulStatus);

    //
    // Loop while there are characters in the receive FIFO.
    //
    while(ROM_UARTCharsAvail(UART0_BASE))
    {
        //
        // Read the next character from the UART and write it back to the UART.
        //
        ROM_UARTCharPutNonBlocking(UART0_BASE,
                ROM_UARTCharGetNonBlocking(UART0_BASE));
    }
}



//*****************************************************************************
//
// Send a string to the UART.
//
//*****************************************************************************
void
UART0Send(const unsigned char *pucBuffer, unsigned long ulCount)
{
    //
    // Loop while there are more characters to send.
    //
    while(ulCount--)
    {
        //
        // Write the next character to the UART.
        //
        ROM_UARTCharPutNonBlocking(UART0_BASE, *pucBuffer++);
    }
}

//Main function

int main(void)
{
    // Variables for the ADC
    unsigned char ulADC0_Value[3]; // array of chars to send  for the UART
    unsigned long ulADC0Value [1] ; // ADC Variable

    //Variables for the button
    unsigned char ucButtons, ucChanged, ucRepeat;

    //initialize button dir/drivers/buttons.c it is possible to see the initialization ob the button
    ButtonsInit();

    // Initialize device

    DeviceInit();

    // While function, here it is possible to see the program and the tasks that the micro-controller has to do
    //

    while(1)
    {
        //function ButtonsPoll() to see when the button has been pushed

        ucButtons=ButtonsPoll(&ucChanged, &ucRepeat);
        //when the button is pushed the LED Activates, the value from the ADC is obtained
        //the value of the temperature is converted to char then is sent to the UART
        //it is possible to see the data sent with the PUTTY application



        while (BUTTON_PRESSED(0X01, ucButtons, ucChanged))
        {
            //SysCtlDelay(1000);
            GPIOPinWrite(GPIO_PORTF_BASE, GPIO_PIN_1|GPIO_PIN_2|GPIO_PIN_3, LED);

                    // Cycle through Red, Green and Blue LEDs
            if (LED == 8) {LED = 2;} else {LED = LED*2;}

            ROM_ADCIntClear(ADC0_BASE, 1);
            ROM_ADCProcessorTrigger(ADC0_BASE, 1);

            //
            // Wait for conversion to be completed.
                                    //
            while(!ROM_ADCIntStatus(ADC0_BASE, 1, false))
            {
            }
            //
            // Clear the ADC interrupt flag.
            //


            // Value of ADC when it is ready

            ROM_ADCSequenceDataGet(ADC0_BASE, 1, ulADC0Value);

            // Read ADC Value.
            ulADC0_Value[0] = ( ulADC0Value[0] / 100 ) + 48  ;
            ulADC0_Value[1] = ((ulADC0Value[0] % 100) / 10) + 48;
            ulADC0_Value[2] = ((ulADC0Value[0] % 100) % 10)+ 48 ;

            UART0Send((unsigned  char*) ulADC0_Value, 3);

            // converting value to char

        }

    }
}

void DeviceInit(void)
{

    // Init Clock
    // Set the to 80MHz
    ROM_SysCtlClockSet(SYSCTL_SYSDIV_2_5|SYSCTL_USE_PLL|SYSCTL_XTAL_16MHZ|SYSCTL_OSC_MAIN);
    SysCtlPeripheralEnable(SYSCTL_PERIPH_ADC0);


    // -------------- INIT UART ----------------
    SysCtlPeripheralEnable(SYSCTL_PERIPH_UART0);

    SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOA);

    // Set GPIO A0 AS UART pins.
    GPIOPinConfigure(GPIO_PA0_U0RX);
    GPIOPinConfigure(GPIO_PA1_U0TX);


    // Init pin function
    GPIOPinTypeUART(GPIO_PORTA_BASE, GPIO_PIN_0 | GPIO_PIN_1);


    // Configure the UART for 115,200, 8-N-1 operation.
    UARTConfigSetExpClk(UART0_BASE, SysCtlClockGet(), 115200,
            (UART_CONFIG_WLEN_8 | UART_CONFIG_STOP_ONE |
                    UART_CONFIG_PAR_NONE));


    // Enable the UART interrupt.
    IntEnable(INT_UART0);
    UARTIntEnable(UART0_BASE, UART_INT_RX | UART_INT_RT);


    // -------------- INIT TIMERS -------------------------------------------------------------------

    // Enable peripherals
    SysCtlPeripheralEnable(SYSCTL_PERIPH_TIMER0);
    SysCtlPeripheralEnable(SYSCTL_PERIPH_TIMER1);

    // Enable processor interrupts.
    IntMasterEnable();

    // Configure 32-bit periodic timers.
    TimerConfigure(TIMER0_BASE, TIMER_CFG_PERIODIC);
    TimerConfigure(TIMER1_BASE, TIMER_CFG_PERIODIC);
    TimerLoadSet(TIMER0_BASE, TIMER_A, SysCtlClockGet());
    TimerLoadSet(TIMER1_BASE, TIMER_A, SysCtlClockGet());

    // Setup the interrupts for the timer timeouts.
    IntEnable(INT_TIMER0A);
    IntEnable(INT_TIMER1A);
    TimerIntEnable(TIMER0_BASE, TIMER_TIMA_TIMEOUT);
    TimerIntEnable(TIMER1_BASE, TIMER_TIMA_TIMEOUT);

    // Enable the timers.
    // TimerEnable(TIMER0_BASE, TIMER_A);
    TimerEnable(TIMER1_BASE, TIMER_A);

    //-----------------INIT ADC-------------------------------------------------




    SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOE);

    GPIOPinTypeADC(GPIO_PORTE_BASE, GPIO_PIN_4);


    ROM_SysCtlADCSpeedSet(SYSCTL_ADCSPEED_125KSPS);

    ROM_ADCHardwareOversampleConfigure(ADC0_BASE, 16);
    //INIT PIN FUNCTION

    ROM_ADCSequenceDisable(ADC0_BASE, 1);


    ROM_ADCSequenceConfigure(ADC0_BASE, 1, ADC_TRIGGER_PROCESSOR, 0);

    ROM_ADCSequenceStepConfigure(ADC0_BASE, 1, 0, ADC_CTL_CH0  | ADC_CTL_IE |ADC_CTL_END);


    ROM_ADCSequenceEnable(ADC0_BASE, 1);
    ROM_ADCIntClear(ADC0_BASE, 1);



    // -------------- GPIO ---------------
    // LEDs

    SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOF);

    GPIOPinTypeGPIOOutput(GPIO_PORTF_BASE, GPIO_PIN_1|GPIO_PIN_2|GPIO_PIN_3);

    //**************************************************************************


}

  • Alejandra Zepeda said:
    reads an analog signal with a frequency of 2kHz

    While helpful - you've not provided necessary & sufficient data to enable proper diagnosis.

    Have you been careful to confine the voltage swing of this sine signal w/in the spec'ed limits of your MCU?  (that would be 0V minimum - and 3V3 maximum)  Does the impedance of this signal reasonably match the input impedance of the ADC channel?  (detail provided in manual rear - under ADC specs)

    How are you time-syncing the data from both of your processors?  How sure are you that you are measuring data at the same point in time?

    Lastly - as simple sanity check - suggest that you replace sine signal with mid-range, fixed level - establish that your ADC is working correctly - prior to moving toward the more advanced signal...

  • Hi cb1_mobile

    the sine signal has and amplitude peak to peak of 2.64V, from 0V  to  2.64V, this signal comes from a Function Generator, the channel that I'm using is the Ch0 , and the output impedance of the generator is 50 Ohm.

    About the time-syncing I don't know how I can do that, so I am not sure about meauring the data at the same point in time, I think that this is basically the problem that I have.

    I've checked the reception in different frequencies.

    Thanks and I hope you can help me.

  • also when I'm debugging the program I've put a breakpoint (like in Lab 5 of the workshop) so I can see the values of the ADC in the Code composer window  and the values in Matlab, and I saw that are the same values in both programs, if the problem was synchronization the values would be differents.

    Is it anything else that I should check?

  • Senorita Alejandra:

    Indeed one of the problems is time-synching and hence the signal is "aliasing" -- something...

    Have a look here: http://e2e.ti.com/support/microcontrollers/stellaris_arm_cortex-m3_microcontroller/f/473/t/212263.aspx

    Just put the output to UART in your main loop -- take it out of the interrupt routine -- and it will behave much better.

    What you really want to look at is the way to set the timer to trigger the ADC regularly -- and the Interrupt routine to read the ADC on demand.

    I did not set the UART to buffered, nor did then put the UART interrupt routines in the startup file... Maybe you can figure this out.

    It was for the LM3S811 -- but I have run the same code on the LaunchPad -- though much improved.

    Even a 1250 KHz signal can be a challenge since I am reading four parameters from an ADC device and/or an I2C device on the latest incarnation of this routine. So on the latest -- I turned on the buffering routine and use interrupts for the UART ...

    Always look arounf the forums to see if someone else has done the work beforehand...

  • Alejandra Zepeda said:
    I saw that are the same values in both programs

    This comment conflicts w/your initial post - where little such equality was reported.  " the plot in matlab is not even close to the signal in the Stellaris."  Would you be so good as to amplify/clarify?  Brevity may not be your "true friend" - when diagnostic assets are remote - and seek solid facts...

    If you employ an MCU Timer to "trigger" your ADC Conversion - cannot that same Timer Service Routine drive a GPIO - which in turn triggers your Fnt. Gen?  That - at minimum - provides some starting (T0) reference.  (however - we really don't know precisely when the ADC actually makes its conversion - triggering the ADC does not fully bound nor describe the actual point in time in which that ADC input is processed - imho)  But at least you have some basis with this GPIO trigger - embedded w/in your Timer Service routine.

    I'd find it valuable - as you have (or at least have access to MatLab) for you to acquire one of the normal/customary ADC boards provided or suggested by Matlab.  You may be able to have such a board respond to your MCUs GPIO "trigger" and thus better reveal the similarities between each converter's measurement...

    It remains unclear as to how Matlab receives your Fnt. Gen. output.  Is that provided to both your Stellaris (MCU) and Matlab?  Appears that you are transfering some ADC data via Uart - which adds further time difference between your Matlab and MCU - "time of data reception." 

  • Hi Dave,

    Sorry for the delay, after compare both codes I saw what you mean of the time synching, now  the thing is that I'm analizing the data in Matlab   and plotting it but it seems that there is other things wrong, you can find the images of the data.

    the images are at different frecuencies (2Hz, 20Hz, 200Hz, 2kHz) so you can see that the signals seems to have some noise, i think it is because of the ADC.

    Regards and thanks.

  • Hi Alejandra,  I'm doing something equal for ECG signal on Tiva Launchpad, helpme please.

    1. You got this result with your code or Dave´s code?

    2. In the interface with matlab you plot in real time? I´m using the file exchange Stripchart and you?

    Thanks, I´m very rookie.