Store a string and then print it..using UART

Go To Last Post
19 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hello!
Im having troubles with a simple code on UART, I want to get a string and then show it.

For example:

put_string("Your name:");
now store the name Juan, (similar to scanf) then put using put_string and see "Welcome Juan"

I know this is basic, I already google search but I can´t find, perhaps because I speak little English, if my post is annoying and repeated, can you help me at least with a link :S.

Thank you in advance.

PS. I am writing a code for a RTC, and need to use commands for setting the time and date. So I want to store strings that can be used for a simple comparison with strcmp.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

You haven't actually said what computer language you are talking about though I guess the mentions of scanf and strcmp suggest C.

It's also not clear what part you are having a problem with. I guess you realise that to store a typed in name like "Juan" you are going to need an array of characters? So something like:

char name[20];

While your "pseudo code" mentions scanf it can actually quite complex to make that work so maybe just start simple with something like:

uart_getstring(name);

to implement a function like that you are further going to need a function that can receive one character at a time. Maybe something like:

char c = uart_getchar();

Each time it is called it gets the next typed character from the UART. So the function to get the whole string is then something like:

void uart_getstring(char * name) {
 char c;
 do {
  c = uart_getchar();
  if (c != '\n') {
    *name++ = c;
  }
 } while (c != '\n');
 *name = 0;
}

This keeps calling uatr_getchar and storing the received characters into the name[] array until the character '\n' (new line) is seen because [Enter] was pressed.

So next there is the question of what uart_getchar() looks like. Basically the UARt will set the RXC (receive complete) bit every time a character is received so you just need to see this become set then you can collect the character that has arrived from UDR. So something like:

char uart_getchar(void) {
 while(!(UCSRA & (1<<RXC)));
 return UDR;
}

This should be enough to get a string typed in though the registers and bit names may be different for your particular AVR.

To finally output "Welcome " you'd then use something like:

char output[28];
strcpy(output, "Welcome ");
strcat(output, name);
put_string(output);

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

What programming environment? And assembler or C?

Where are you displaying the string(s)?

Often put_string() is used to write a string to the console screen in a desktop machine. You speak of "UART". Your put_string needs to write to the UART. If you use Studio6, there are excellent examples in the avrlibc manual. You can find it online and in the Studio6 installed folders.

You also speak of "commands for setting time and date". This suggests that you will have a display of some sort. You really do need to look at that manual because it tells you how to use the various string functions such as strcmp().

Jim

Jim Wagner Oregon Research Electronics, Consulting Div. Tangent, OR, USA http://www.orelectronics.net

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Thanks for the info Clawson and Jim, i´m using IAR Embedded Workbench and writing in C.
I wrote a code in Atmel Studio and it works, but I used fdevopen function to associate my putchar and getchar functions, but now in IAR I want to use my own functions.

I will try what you said Clawson. If you want to see my Atmel studio code just tell me.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

My functions in my library uart.c are:

void putcaracter(unsigned char dato)
{
    /* Esperar a que haya espacio en el buffer de transmisión */
    while ((UCSR0A & (1<<UDRE0)) == 0 );

    /* Colocar dato en el buffer de transmisión */
    UDR0 = dato;
    
}
char getcaracter(void)
{
    /* Esperar a que haya al menos un dato en el buffer de recepción */
    while ((UCSR0A & (1<<RXC0)) == 0 );  
    return UDR0;
}
void putcadena(const char * s)
{
  while( *s )
    putchar(*s++);
}
void getcadena( char * command )
{
  char c;
  do
  {
    c = getcaracter();
    if ( c != '\n' )
    {
      * command++ = c;
    }
  } while ( c != '\n');
  * command = 0;
}

Then in my main.c:

#include"iom328p.h"
#include "usart.h"
void main(void)
{
    char output[20];  
    usart_init();
    putcadena("\n\r - USING USART \n\r - ");
    strcpy(output, "Welcome ");
    strcat(output, command);
    putcadena(output);
  
    
    while(1);
}

But show me 1 error:
Error[Pe020]: identifier "command" is undefined
So I could declare command as a global value, but still I can not read anything in my virtual terminal. Im using proteus and a virtual terminal and ATMEGA644P

Im looking for my mistake

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

But there's nothing called "command" defined in that program? You are bound to get an undefined error aren't you?

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Well, may be
command should be defined as an 80 character string (to avoid such long names as "Marco Polo, baron de Circasia y otros locos"
char command [80];
of course, output should be very long, too... (and usually, AVRs such as 644 have enough RAM

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

When I've implemented address books and things the name I used to check that there was enough room was "Djamolidine Abdoujaparov" (he's a Russian cyclist).

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Razafinandriampoimerina Albert,Auguste, Cedric (He whose grandfather was the Lord, heart of Imerina -this is the way Malagasy names ought to be done-) is not that bad, too

Edited : as his grandfather was a king, a numero should be added (voalohany, 1rst, say) ....

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Ok if I define command, still to do nothing.. so maybe I have another error, thanks for your time thats help me a lot. Gracias gente. :D

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Well, you should give a value to "command" (telling it is a char* is not enough) :
either you type it ( thus using "getcadena" which sounds sound/OK) or, for a test :
char command [80] = "A_short_name";

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Quote:

void getcadena( char * command ) 
{ 
  char c; 
  do 
  { 
    c = getcaracter(); 
    if ( c != '\n' ) 
    { 
      * command++ = c; 
    } 
  } while ( c != '\n'); 
  * command = 0; 
} 

I think the problem is that a Enter is a carriage return (a '\r') and not a new line feed ('\n'). So the loop won't end since it won't receive the '\n' until you hit (i believe) ctrl+enter. so i think the correct code would be
do 
  { 
    c = getcaracter(); 
    if ( c != '\r' ) 
    { 
      * command++ = c; 
    } 
  } while ( c != '\r'); 

I hope that helps

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Quote:

So the loop won't end since it won't receive the '\n' until you hit (i believe) ctrl+enter.

Err no. A Window system will always send \r\n for the press of the [Return/Enter] key. A Unix/Linux system will only send \n. So it's best to always use \n as the line termination indicator because then it will work with both Windows and Linux systems.

(some terminal programs are configurable to say exactly what they send for a press of Enter/Return in fact).

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

in the original getcadena

 * command++ = c; 

might be replaced with (makes \r to be fully ignored : very exotic platforms - spectrum, appleII according to wikipedia newline - use \r (at least without \n) as line delimiter) :

 if ( c != '\r' ) * command++ = c; 

(windows sends a \n with its \r : detecting \n is enough, GNUlinux "only" sends \n)

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Quote:
Err no. A Window system will always send \r\n for the press of the [Return/Enter] key.
Ok, I checked it, and indeed, windows itself will produce a "\r\n" in for instance notepad. But, the reason why I assumed it, is because for instance PUTTy does insert only a '\r'(with the default settings). So maybe it's wise to agree that the following would be best;) :
while(c!='\r' && c!='\n'){...}
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

It's an extremely odd terminal that only sends \r but if you really have found one then I guess checking for both is wise.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Thats no problem, I always use '\r', but now I think know the difference between the two, one again thanks to all, I'm understanding how AVR's and C work

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Main issue might be that, with a classical window terminal, extra empty lines will be added/created... (omething like that

or that

)

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Okay, thanks to all, now its working only works using '\r' not '\n'...

Once again Thank you so much