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.

SW-EK-TM4C129EXL: EK-TM4C129EXL

Part Number: SW-EK-TM4C129EXL
Other Parts Discussed in Thread: EK-TM4C129EXL

Dear Sir,

I have a problem for receiving  data form uart0 in ek-tm4c129exl board. I want to receive a data stream one by one like (one start bit, 17,03,00,04,45,77,one stop bit.). But I don't understand logic. How can I receive data from uart0 FIFO. Please help me. My code is given below--


#include <stdint.h>
#include <stdbool.h>
#include <string.h>
#include "inc/hw_ints.h"
#include "inc/hw_memmap.h"
#include "driverlib/debug.h"
#include "driverlib/gpio.h"
#include "driverlib/pin_map.h"
#include "driverlib/sysctl.h"
#include "driverlib/rom.h"
#include "driverlib/rom_map.h"
#include "driverlib/uart.h"
#include "driverlib/interrupt.h"
//#include "utils/uartstdio.h"


//****************************************************************************
//
// System clock rate in Hz.
//
//****************************************************************************
uint32_t g_ui32SysClock;


unsigned char MY_SLAVE_ID =17u;

#define MaxFrameIndex 255u
#define fc3_HoldingRegMax 125u
#define fc3_HoldingRegOffset 40001u

volatile unsigned char ResponseFrameSize;

volatile unsigned char data_in[MaxFrameIndex+1];
volatile unsigned int DataPos;


//Holding Register Array
static unsigned int HoldingRegisters[] = {
24288, 30717, 52317, 58320, 53844, 7596, 50869, 64892, 58209, 15124, //0-9
38131, 16852, 62343, 25973, 11963, 49434, 31745, 48278, 50955, 50027, //10-19
62940, 38520, 51144, 54693, 60394, 14244, 62402, 62647, 65457, 56695, //20-29
40971, 29608, 37659, 60486, 3321, 769, 52458, 61584, 55023, 61523, //30-39
50744, 51336, 3649, 48678, 29801, 43147, 1325, 32661, 49277, 32353, //40-49
48858, 41522, 32167, 13748, 24501, 2375, 6957, 45371, 53417, 34799, //50-59
51057, 3290, 13510, 48962, 65080, 22597, 38672, 14315, 48621, 49290, //60-69
30178, 1793, 13119, 54566, 1570, 31355, 1754, 21305, 5750, 25520, //70-79
23688, 54689, 64511, 17349, 33911, 31220, 64245, 17176, 43586, 30999, //80-89
12761, 42338, 62682, 7424, 6981, 36057, 63189, 4897, 52723, 61279, //90-99
};

unsigned short CRC16 (volatile unsigned char *puchMsg, unsigned short usDataLen );
unsigned int MBRegisterCount(void);
void AppendDatatoMBRegister(unsigned int StAddr,unsigned int count, unsigned int *inreg, volatile unsigned char *outreg);
unsigned int MBStartAddress(void);
void MBSendData(unsigned char count);
void AppendCRCtoMBRegister(unsigned char packtop);
void MBException(unsigned char exceptionCode);
void MBProcessRegisters(unsigned char fcCode);


//*****************************************************************************
//
// The error routine that is called if the driver library encounters an error.
//
//*****************************************************************************
#ifdef DEBUG
void
__error__(char *pcFilename, uint32_t ui32Line)
{
}
#endif

//*****************************************************************************
//
// The UART interrupt handler.
//
//*****************************************************************************
void UARTIntHandler(void)
{
uint32_t ui32Status;

uint8_t i;

//
// Get the interrrupt status.
//
ui32Status = MAP_UARTIntStatus(UART0_BASE, true);

//
// Clear the asserted interrupts.
//
MAP_UARTIntClear(UART0_BASE, ui32Status);

//
// Loop while there are characters in the receive FIFO.
//
while(MAP_UARTCharsAvail(UART0_BASE))
{
//
// Read the next character from the UART and write it back to the UART.
//
for(i=0;i<11;i++)
{
data_in[10] = (uint8_t)MAP_UARTCharGetNonBlocking(UART0_BASE);
i++;
}

if((DataPos>=8u)&(data_in[0]=MY_SLAVE_ID))
{
DataPos=0;

switch(data_in[1])
{
case 0x03:
{
MAP_GPIOPinWrite(GPIO_PORTN_BASE, GPIO_PIN_0, GPIO_PIN_0);
}
break;
default:
{
MAP_GPIOPinWrite(GPIO_PORTN_BASE, GPIO_PIN_0, 0);
}
break;
}
}


}

/*MAP_UARTCharPutNonBlocking(UART0_BASE,
a );
MAP_GPIOPinWrite(GPIO_PORTN_BASE, GPIO_PIN_0, GPIO_PIN_0);*/


// MAP_UARTCharPutNonBlocking(UART0_BASE,
// data );

//
// Blink the LED to show a character transfer is occuring.
//
// MAP_GPIOPinWrite(GPIO_PORTN_BASE, GPIO_PIN_0, GPIO_PIN_0);


//
// Delay for 1 millisecond. Each SysCtlDelay is about 3 clocks.
//
//SysCtlDelay(g_ui32SysClock / (1000 * 3));

//
// Turn off the LED
//
// else MAP_GPIOPinWrite(GPIO_PORTN_BASE, GPIO_PIN_0, 0);

}

//*****************************************************************************
//
// Send a string to the UART.
//
//*****************************************************************************
void
UARTSend(const uint8_t *pui8Buffer, uint32_t ui32Count)
{
//
// Loop while there are more characters to send.
//
while(ui32Count--)
{
//
// Write the next character to the UART.
//
MAP_UARTCharPutNonBlocking(UART0_BASE, *pui8Buffer++);
}
}

//*****************************************************************************
//
// This example demonstrates how to send a string of data to the UART.
//
//*****************************************************************************
int
main(void)
{
MY_SLAVE_ID=17u;
//
// Run from the PLL at 120 MHz.
// Note: SYSCTL_CFG_VCO_240 is a new setting provided in TivaWare 2.2.x and
// later to better reflect the actual VCO speed due to SYSCTL#22.
//
g_ui32SysClock = MAP_SysCtlClockFreqSet((SYSCTL_XTAL_25MHZ |
SYSCTL_OSC_MAIN |
SYSCTL_USE_PLL |
SYSCTL_CFG_VCO_240), 120000000);

//
// Enable the GPIO port that is used for the on-board LED.
//
MAP_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPION);

//
// Enable the GPIO pins for the LED (PN0).
//
MAP_GPIOPinTypeGPIOOutput(GPIO_PORTN_BASE, GPIO_PIN_0);

//
// Enable the peripherals used by this example.
//
MAP_SysCtlPeripheralEnable(SYSCTL_PERIPH_UART0);
MAP_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOA);

//
// Enable processor interrupts.
//
MAP_IntMasterEnable();

//
// Set GPIO A0 and A1 as UART pins.
//
MAP_GPIOPinConfigure(GPIO_PA0_U0RX);
MAP_GPIOPinConfigure(GPIO_PA1_U0TX);
MAP_GPIOPinTypeUART(GPIO_PORTA_BASE, GPIO_PIN_0 | GPIO_PIN_1);

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

//
// Enable the UART interrupt.
//
MAP_IntEnable(INT_UART0);
MAP_UARTIntEnable(UART0_BASE, UART_INT_RX | UART_INT_RT);

//
// Prompt for text to be entered.
//
//UARTSend((uint8_t *)"\033[2JEnter text: ", 16);


//
// Loop forever echoing data through the UART.
//
while(1)
{
}
}

Regards 

Imtiaj

  • Hello Imtiaj,

    Your UART code seems to be receiving data fine but the logic in your ISR doesn't look correct.

    For example:

            //
            // Read the next character from the UART and write it back to the UART.
            //
            for(i=0;i<11;i++)
            {
                data_in[10] = (uint8_t)MAP_UARTCharGetNonBlocking(UART0_BASE);
                i++;
            }
    
            if((DataPos>=8u)&(data_in[0]=MY_SLAVE_ID))
            {
                DataPos=0;
    
                switch(data_in[1])
                {
                case 0x03:
                {
                    MAP_GPIOPinWrite(GPIO_PORTN_BASE, GPIO_PIN_0, GPIO_PIN_0);
                }
                break;
                default:
                {
                    MAP_GPIOPinWrite(GPIO_PORTN_BASE, GPIO_PIN_0, 0);
                }
                break;
                }
            }

    You are receiving all data by overwriting the same buffer spot in your array, spot 10.

    Then you look for the slave address at data_in[0].

    I think you need to change data_in[10] to be data_in[i] and then try again.

  • Dear Jacobi,

    I did it and program are running very good. But my intention is to check the data is 8bit and then first index value in array are slave id. Then  next action is complete. the running program is given below--

    /
    while(MAP_UARTCharsAvail(UART0_BASE))
    {
    //
    // Read the next character from the UART and write it back to the UART.
    //

    data_in[i] = (uint8_t)MAP_UARTCharGetNonBlocking(UART0_BASE);

    i++;


    if(data_in[0]=MY_SLAVE_ID)
    {
    DataPos=0;

    switch(data_in[1])
    {
    case 0x03:
    {
    MAP_GPIOPinWrite(GPIO_PORTN_BASE, GPIO_PIN_0, GPIO_PIN_0);
    }
    break;
    default:
    {
    MAP_GPIOPinWrite(GPIO_PORTN_BASE, GPIO_PIN_0, 0);
    }
    break;
    }
    }

    But my program it can't check the upcoming 8 bit.

    Best regards

    Imtiaj 

  • Hello Imtiaj,

    Have you used a breakpoint after reception finishes to check the contents of your data_in array? I would start there to make sure the data is ordered as you expect and is correct. I am not sure your type casting is going to work the way you want.

  • Dear Jacobi,

    Yes , I use a breakpoint at first check the value of index 0 (data_in[0]). How can I typecast the data which I received in FIFO as 1 byte hex value.

    Another problem is that I can't show  the data_in array in variable ,when I debug.

    Best regards

    Imtiaj

  • Hello Imtiaj,

    Okay I had time today to step through your code more carefully and I found the issue with your original code I think.

    The typecasting is working fine actually from what I can tell. At least I am not seeing any data loss there.

    The data_in buffer however had data stored at every other digit.

    The reason for this is because you were double incrementing the array variable:

        while(MAP_UARTCharsAvail(UART0_BASE))
        {
            //
            // Read the next character from the UART and write it back to the UART.
            //
            for(i=0;i<11;i++)
            {
                data_in[i] = (uint8_t)MAP_UARTCharGetNonBlocking(UART0_BASE);
                i++;
            }

    After, I also took your adjusted your newest code which removed the for loop. So I ran that version too:

        while(MAP_UARTCharsAvail(UART0_BASE))
        {
            //
            // Read the next character from the UART and write it back to the UART.
            //
        	data_in[i] = (uint8_t)MAP_UARTCharGetNonBlocking(UART0_BASE);
        	i++;
    
            if(data_in[0]=MY_SLAVE_ID)
            {
                DataPos=0;
    
                switch(data_in[7])
                {
                case 0x7E:
                {
                    MAP_GPIOPinWrite(GPIO_PORTN_BASE, GPIO_PIN_0, GPIO_PIN_0);
                }
                break;
                default:
                {
                    MAP_GPIOPinWrite(GPIO_PORTN_BASE, GPIO_PIN_0, 0);
                }
                break;
                }
            }

    And it worked fine for me as well. I did change the Switch statement to look deeper in a packet and I was sending ASCII characters for simplicity for my testing, but this would work for you as well.

    Going through the buffer, I verified that the data has been typecast to an 8-bit character correctly too. So I think this is actually everything you needed.

  • Dear Jacobi,

    Actually, I want to Modbus RTU communication for EK-TM4C129EXL board. I have some problem during debug. Please follow the link and download the whole code. Reply me what is my problem.

    https://github.com/imtiaj-87/Modbus_RTU

    Thanks & regards 

    Imtiaj

  • Dear Jacobi,

    Sorry for that. I use ek- tm4c129exl as modbus slave device and my computer as master. For master device , I use modbus poll software which I download modbus website. I want read holding registers which I define as dummy registers.

    Thanks & regards

    Imtiaj

  • Hello Imtiaj,

    I am a device expert for TM4C but I don't have much experience with Modbus protocol and certainly not third party code for it. We do not offer general debug support for application specific code or whole code reviews. If you have an issue that you identify is related to TM4C drivers where you need to understand how to configure the device properly then let me know the details of the issue and I can guide you.

  • Dear jaccobi,

    Hope you are well. You just tell me in handler function how can I get the whole data in data_ in array . So that I use a variable which is for checking the data is 8 byte or not. After that I process rest of function.

    Thanks & regards

    Imtiaj

  • Hello Imtiaj,

    I'm sorry but I am not really understanding your question here because I have not seen any issues with getting all the data in the array. I reran your code with the modifications I made and send an 8 byte packet and I see everything working fine.

  • Dear Jacobi,

    Sir I need a logic in handler function where all 8 byte data are received at time after that I response this 8 byte data and then next 8 byte I will be check. Following below After receive---

    while(MAP_UARTCharsAvail(UART0_BASE))
    {
    //
    // Read the next character from the UART and write it back to the UART.
    //

    data_in[i] = (uint8_t)MAP_UARTCharGetNonBlocking(UART0_BASE);

    i++;


    if (DataPos=8u && data_in[0]=MY_SLAVE_ID)
    {
    DataPos=0;

    I use a for loop before if statement but it's not working. All data  check 1 byte by 1 byte. Which is not needed in my application. I need 8 byte at a time and then next 8 byte  and so on. 

    Thanks & regards 

    Imtiaj

  • I'm trying to follow what you are trying to do here ... so perhaps I don't quite get it. But here is some general advice.

    A UART is rather slow. Your read handler is mostly correct. As long as characters are available write them to a software FIFO. Since you know you are expecting 8-byte packets, it's reasonable to have an incoming byte counter in the ISR. When you've received the 8th byte, simply set a flag. Your main program loop should check for that flag, and then it can pop the FIFO and get the entire packet. Then it can inspect the packet as necessary. But the point here is that each time the UART incoming-data interrupt is invoked, there will be only one character available, so there will be multiple interrupts until you have your entire packet. 

    (Note that it's a software FIFO, not in hardware, so you need to maintain read and write pointers and all of it. Pretty much every UART example has such a construct.)

  • Hello Imtiaj,

    Andy described the solution to this very well. Make sure the flag you use is set as a volatile variable so it is properly changed in the ISR.

  • Dear Andy,

    I don't understand what are you saying. Can you explain in detail with code. My detail code is shear.

    Thanks & regards 

    Imtiaj

  • Dear Jacobi,

     I don't understand what Andy saying. Can you explain in detail with code example?

    Thanks & regards 

    Imtiaj

  • Hello Imtiaj,

    You would use a counter variable to count until you have received 8 bytes.

    Once you hit BytesReceived = 8, you set a flag of a volatile variable like 'DataReady' = true.

    Then in your main while(1) loop, you look for if(DataReady == true) and inside there, you process the UART FIFO data.

    Andy is suggesting you don't read the UART data until you get 8 bytes received as the FIFO is 8 spaces deep, so you would read all 8 bytes into your data_in buffer at that time. You could also read the bytes into data_in durign the ISR and the flag just indicates that data_in is now full of 8 bytes of data and ready to be processed. 

    In any case, you'd get 8 interrupts total before getting the 8 bytes of data, so it is a matter of keeping track of that.

    You will need to write the code for this, it's specific to your application, but I can try and review it if you can't it working.