I'm having the same problem

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

Hey guys, i have working code and i want add a function to read some char´s from terminal to atmega328P.

Is there anything wrong with this function?

 uint8_t read_char(void)
{
char buffer[50];
int i=0;

	while ( !(UCSR0A & (1<<RXC0)) ); // wait till ready to receive
	/*receiving data from buffer */
		for(i=0;UDR0=="\n";i++)
			buffer[i]=UDR0;
// calling another function which is working
		sendString("O nome inserido foi :\r\n");
//calling the same function to pass the array
		sendString(buffer);
	
}

All i got from here is waiting for press a key (on for cycle) and after pressing a key the program moves on and print the 1st string. The second one (the buffer) does nothing.
What should i do here to fill the buffer till i got "\n" and why is not sending the data?

The sendstring function is receiving a pointer. (*data)
Thank you all

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

Not only was your post in the wrong forum but it's not nice to crash on someone else's thread.

I have created a new thread for you.

John Samperi

Ampertronics Pty. Ltd.

www.ampertronics.com.au

* Electronic Design * Custom Products * Contract Assembly

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

Oh sorry, just put it there because it was the same problem

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0
  for(i=0;UDR0=="\n";i++) {
    buffer=UDR0;
  }

Reading UDR0 removes the received byte from the receive buffer. Reading it a second time will read the next received byte if there's one waiting, not the same byte again. You should read only once.

Also, this won't do what you think it will:

UDR0=="\n"

You're comparing a char with a pointer to char. You need to compare against the char '\n'

The test is also the opposite of what it should be. I assume you want to fill buffer with characters [i]until a new-line arrives.

You're also not waiting for the next character to be received within the loop.

You also have no bounds checking. What happens if you receive more than 50 characters before a new-line?

And you're not null-terminating buffer before calling sendString().

And why would a function that reads a new-line terminated string be called read_char()?

  char buffer[50];
  uint8_t c = 0;
  uint8_t i = 0;
  
  while ((i < 49) && (c != '\n')) {
    while (!(UCSR0A & (1<<RXC0)));
    c = UDR0;
    buffer[i++];
  }
  buffer[i] = 0;

Untested.

"Experience is what enables you to recognise a mistake the second time you make it."

"Good judgement comes from experience.  Experience comes from bad judgement."

"Wisdom is always wont to arrive late, and to be a little approximate on first possession."

"When you hear hoofbeats, think horses, not unicorns."

"Fast.  Cheap.  Good.  Pick two."

"We see a lot of arses on handlebars around here." - [J Ekdahl]

 

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

Thanks for your reply, and forgive my inexperience.
My sendstring function is receiving a pointer.
That way i can´t pass the buffer as it is only being position incremented and don't get the byte received.
That way, i think i should do a cast, correct? and then send it.

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

Quote:
My sendstring function is receiving a pointer.
That way, i think i should do a cast, correct? and then send it.

void sendString(char* string);

char buffer[50];
sendString(buffer);

No cast needed here.
The name of an array (or string) is a pointer.

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

Ok, but when i try to read a string i have to pass the value from UDR to a variable and i can't pass it to an array correct?

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

Quote:

Ok, but when i try to read a string i have to pass the value from UDR to a variable and i can't pass it to an array correct?

Why not?

Most people design UART (and anything else for that matter) to be modular so you provide core functions such as UART_init(), UART_sendchar() and UART_getchar() or whatever then build the more complex stuff upon these building blocks. Often the UART_getchar() is simply a synchronous/polling routine that sits in a while() loop waiting to see the RXC bit set and when it does it then reads UDR and returns it. Something like:

uint8_t UART_getchar(void) {
  while (!(UCSR0A & (1 << RXC0)))'
  return UDR;
}

So that's your initial "building block" then you can either use it individually:

uint8_t rx_byte;
rx_byte = UART_getchar();

and after the call rx_byte will hold the single received character. Or you may then choose to use it as a building block to build a more complex UART_getstring():

void UART_getstring(uint8_t * str) {
  uint8_t byte;
  do {
    byte = UART_getchar();
    *str++ = byte;
  } while (byte != '\n');
  *str = 0;
}

You then use that like:

uint8_t rx_array[50];
UART_getstring(rx_array);

And say the code is sent "hello world\n" then this will store that into rx_array (it even adds a terminating 0 just in case you plan to treat the data as a C string).

The key thing here is that the low level UCSR0A stuff and the high level reading string stuff don't meet in a single routine. There's a high level UART_getstring() that relies on a lower level UART_getchar();

To be honest, once you have UART_getchar() it's probably not worth writing things like UART_getstring() yourself. Your C compiler probably has some way to connect UART_getchar() to the input stream called "stdin". If you do that you just need to write that one low level UART_getchar() then all the standard functions in like getchar(), gets(), scanf(), etc) can be used to read input and they'll all go via the UART_getchar() you wrote to get the individual characters.

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

Thanks clawson, but meanwhile i have done a function, which maybe not that simple but it's working, and for me as begginner is really helpfull this forum. Anyway i'll put here my function. I created it with the possibility to erase some characters using backspace. Maybe that will be too easy for most of forum users but for me it was great to get it working. Try and error of course but it's done, and working has it should. i'm accepting any comment as i need to learn a lot on this.
Here is my function code.

uint8_t read_char(void)
{
char buffer[50]={0};//inicialize a clear array
int i=0;

	for(i=0;i<49;i++)//running all array positions
	{	
	   while ( !(UCSR0A & (1<<RXC0)) );//wait till buffer is ready to receive data
			buffer[i]=UDR0;	// reading string via Rx to array, char by char
			
			if (buffer[i]=='\b')//checking if backspace was pressed
				
			  buffer[i]='\b';//cleaning last array position
							
			if(buffer[i]=='\r')//checking if enter was pressed
			{	
			  sendString("\rO nome inserido foi :\r");	//sending string via Tx
			  sendString(buffer);//sending data within the array
			  return;//exit function(all done)
			}
			
			sendChar(buffer[i]);						//send char by char what is being introduced in the array "real time"
	}					
			sendString("\rcaracteres a mais\r");// sending string "too much characters"
			sendString(buffer);								//sending the data inserted in array when data overflows the array
}

Any comment is regarded, thanks ;)

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0
   if (buffer[i]=='\b') //checking if backspace...            
       buffer[i]='\b'; //cleaning last array position

These two lines do nothing.
It is the same as

If a=b then a=b

If you want to clear last array position, do

   if (buffer[i]=='\b') //checking if backspace...            
       i = i - 2;       //cleaning last array position

Also, after receiving the complete message, you should add ending '\0' to the buffer.