UART building a string

Tip / Sign in to post questions, reply, level up, and achieve exciting badges. Know more

cross mob
lock attach
Attachments are accessible only for community members.
magic_3776931
Level 2
Level 2

Good morning,

I'm using Uart but I have some problems because I can't copy the characters  i saved in a software buffer in a string and then send it back.

If i send back the RxBuffer using UART_PutString(),it works!

I Checked the examples on this forum but I would to realize something extremely simple to understand how Uart component works.

Where I'm getting wrong?

0 Likes
1 Solution

The nature of UART is asynchronous and character oriented. This implies a couple of  restrictions.

At first there is no standard protocol using UART. When you want to handle messages (i.e.. a "string") you need to implement this yourself. Done easiest by defining an end-of-message character as EOL or NULL

Since asynchronous means you do not know when characters will be transmitted and nobody knows if at that moment you have time to poll for incoming chars best practice is to have a buffer defined and let the component handle thie get and puts from/to the buffer.

Bob

View solution in original post

0 Likes
5 Replies
odissey1
Level 9
Level 9
First comment on KBA 1000 replies posted 750 replies posted

marcogiorio,

There are many issues In your code:

CY_ISR(RxIsr_Handling){

    rx_ClearPending();

    RxWriteIndx=RxBuffer;

  

     //Check on interrupt

    while((UART_RX_STS_FIFO_NOTEMPTY) != 0u && UART_GetRxBufferSize()!=0){

        *RxWriteIndx++=UART_ReadRxData();

    }

    *RxWriteIndx='\0'; // this just killed last character received !!!

    // UART_PutString(RxBuffer);//check on interrupt    // Do not put slow UART communication inside interrupt!!!

    flag_rx=1;

}

int main(void)

{

    CyGlobalIntEnable;

    UART_Start();

    UART_PutString("Hello world");

    rx_StartEx(RxIsr_Handling);

    for(;;){

     

   

      if(flag_rx==1){

       flag_rx=0;

    

       for(i=0;RxBuffer!='\0';i++)

       MyString=RxBuffer;

       //MyString='\0';  // This line kills current character !!!

    

       UART_PutString(MyString);

    

       UART_ClearRxBuffer();

       UART_ClearTxBuffer();}      

}}

The CY_ISR(RxIsr_Handling) above does not guaranty receiving long message, it is basically starts from scratch on any CY_ISR interrupt - no good for anything besides 1-byte message. UART communication protocol usually has some termination character to indicate the end of the message (LF, CR). You can find example of UART command messaging here:

UART string reception garbage value

/odissey1

lock attach
Attachments are accessible only for community members.
MotooTanaka
Level 9
Level 9
Distributor - Marubun (Japan)
First comment on blog Beta tester First comment on KBA

Hi,

I modified your main.c as below

in this example, when SPACE(' '), TAB('\t'), CR('\r') or LF(\n') is detected

program complete current word and print out it with a new line.

The device is changed to CY8C5868AXI-LP035 for CY8CKIT-050

but main.c should work for your board, too.

main.c

=======================

#include "project.h"

#define SIZE  80  

#define SPACE ' '

#define TAB  '\t'

#define LF    '\n'

#define CR    '\r'

uint8 flag_rx=0;

char RxBuffer[SIZE];

char *RxWriteIndx;

char MyString[SIZE];

int BufIndex = 0 ;

CY_ISR(RxIsr_Handling)

{

    uint8_t c ;

  

    rx_ClearPending();

    if (UART_GetRxBufferSize() > 0) {

        c = UART_GetChar() ;

//        if ((c == LF) || (c == CR)) { // allow space and tab in a word

        if ((c == SPACE) || (c == TAB) || (c == LF) || (c == CR)) {

            RxBuffer[BufIndex] = (char)NULL ;

            flag_rx = 1 ;

            BufIndex = 0 ;

        } else {

            RxBuffer[BufIndex++] = c ;

        }

    }

}

int main(void)

{

    int i ;

  

    CyGlobalIntEnable;

    UART_Start();

    UART_PutString("\n\rHello world\n\r"); /* new line added */

  

    rx_ClearPending() ;

    rx_StartEx(RxIsr_Handling);

    for(;;){

      if(flag_rx == 1){

        flag_rx=0;

#if 1 // I don't think we need to copy RxBuffer to My String

      // So if you use only RxBuffer, change 1 to 0

            for(i=0;RxBuffer!='\0';i++) {

                MyString=RxBuffer;

            }

            MyString='\0';

    

            UART_PutString(MyString);      

#else

            UART_PutString(RxBuffer) ;

#endif

            UART_PutString("\n\r") ;

        }

    }

}

=======================

FYI,

actually following three lines should work

==================

    for(i=0;RxBuffer!='\0';i++)

    MyString=RxBuffer;

    MyString='\0';

==================

but I recommend you

(1) at least use indentation

==================

    for(i=0;RxBuffer!='\0';i++)

        MyString=RxBuffer;

    MyString='\0'; /* this line is not in the loop */

==================

(2) even for better maintenance use { }

==================

    for(i=0;RxBuffer!='\0';i++) {

        MyString=RxBuffer;

    }

    MyString='\0';

==================

moto

Guys, thank you!!!!

Actually you let me to understand how the UART module works.

I thought the internal interrupt could store in my software buffer all the ASCII string I sent by terminal in only one time,i.e it is executed just one time to move all data from internal hardware buffer to my software buffer.

I didn't understand why this isn't possible, is it a psoc limit? or this happen to all mcu?

Anyway I understood the interrupt is executed for every single ASCII, UART_GetChar() let me to read char by char and store it in a software buffer in order to manage a string as I want.

Please tell me if I'm getting wrong.

0 Likes
MotooTanaka
Level 9
Level 9
Distributor - Marubun (Japan)
First comment on blog Beta tester First comment on KBA

Hi,

I think your understanding is correct.

But please note that there are "many" ways to do a thing correctly.

And I'm afraid that I have one more thing I should mention,

which I did not cover in my sample, is "buffer overrun".

If the currently receiving word is "longer" than SIZE-1 we are in trouble with my sample.

So if you'd like to also take care of it (usually we must) modify the line

>             RxBuffer[BufIndex++] = c ;

to

                RxBuffer[BufIndex++] = c ;

               if (BufIndex >= (SIZE-1)) {

                    RxBuffer[BufIndex] = (char)NULL ;

                    flag_rx = 1 ;

                    BufIndex = 0 ;

               }

to terminate the word before causing buffer overrun.

moto

                   

0 Likes

The nature of UART is asynchronous and character oriented. This implies a couple of  restrictions.

At first there is no standard protocol using UART. When you want to handle messages (i.e.. a "string") you need to implement this yourself. Done easiest by defining an end-of-message character as EOL or NULL

Since asynchronous means you do not know when characters will be transmitted and nobody knows if at that moment you have time to poll for incoming chars best practice is to have a buffer defined and let the component handle thie get and puts from/to the buffer.

Bob

0 Likes