Sending Strings over UART

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

Afternoon,

I want to send an array of char over UART and am finding some strange results.

Lets say I have the following array:

char char_array[] = {'a','b','c','d','e',0x00};

I wanted to do something like this:

void send_char(char c)
{
	UDR0 = c;
}


void send_string(char s[])
{
	int i =0;
	
	while (s[i] != 0x00)
	{
		send_char(s[i]);
		i++;
	}
}

This seems to send lots and lots of chars in an order which is not representative of the array in which they are stored.
Should this be possible?

Regards
Ade (Mega128, AVR Studio 4)

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

Why:

char char_array[] = {'a','b','c','d','e',0x00}; 

when you could use:

char char_array[] = { "abcde" }; 

Anyway, your send_char() is wrong - you must wait for the UDRE bit to become set before you can put a character into UDR0

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

Just to elaborate, it takes time for the character to be sent out the uart. Therefore you have to look at the UDRE bit ( usart data register empty) bit to find out when the character has been sent.

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

Hi Clawson
Thanks for the quick reply.
I changed send_char() to include the following:

while ((UCSR0A & (1 << UDRE0)) == 0) {};

As a result my chars are appearing in the correct order, the only remaining issue i have is that the string is being sent to the terminal over and over again once the USART ISR is triggered.



///////////////////////////////////////Includes

#include 
#include 


///////////////////////////////////////Defines

#define USART_BAUDRATE 9600
#define BAUD_PRESCALE (((F_CPU / (USART_BAUDRATE * 16UL)))-1)

///////////////////////////////////////Global Variables

char char_array[] = {"abcde"};

///////////////////////////////////////Function Prototypes

void uart0_init();
void send_char(char c);
void send_string(char s[]);

///////////////////////////////////////Main

int main()
{
	uart0_init();
	while(1)
	{

	}	
}

//////////////////////////////////////Functions

void uart0_init()
{	
	UCSR0B |= (1 << RXEN0) | (1 << TXEN0);							//turn on rx and tx
	UCSR0C |= (1 << UCSZ0) | (1 << UCSZ1);		//set data bits to 8

	UBRR0H = (BAUD_PRESCALE >> 8);								//load upper 8 bits of baud value into high byte of UBBR
	UBRR0L = (BAUD_PRESCALE);									//load lower 8 bits of baud value into high byte of UBBR

	UCSR0B |= (1 << RXCIE0); 									// Enable the USART Recieve Complete interrupt (USART_RXC) 
   	sei(); 														// Enable the Global Interrupt Enable flag so that interrupts can be processed 
}



void send_char(char c)
{
	while ((UCSR0A & (1 << UDRE0)) == 0) {};
	UDR0 = c;
}


void send_string(char s[])
{
	int i =0;
	
	while (s[i] != 0x00)
	{
		send_char(s[i]);
		i++;
	}
}


//////////////////////////////////////Interrupts

ISR(SIG_UART0_RECV)			
{
	send_string(char_array);
}

Can you see why that might be?

Regards

Ade

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

You aren't reading UDR in the RXC ISR() - you need to do that to clear the interrupt condition.

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

So your interrupt routine keeps firing.

Datasheet p.188

Quote:
This flag bit is set when there are unread data in the receive buffer and cleared when the receive buffer is empty (i.e., does not contain any unread data).
Based on this, try to put the data that the micro receives in a temporary variable (actually, just reading them in any way should be enough), so the interrupt flag clears.

edit: Just a bit too slow :)

-Pantelis

Professor of Applied Murphology, University of W.T.F.Justhappened.

Last Edited: Mon. Sep 5, 2011 - 01:17 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

thanks Clawson.

That worked a treat.

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

Cliff, tell me if I am right.

I don't see any form of END of the routine, meaning that if this is your entire code, it continuosly loops.

Don't take my word for it though, I am an ASM programmer. Hence my request to Cliff. I am SLOWLY learning the DARK LETTER

Jim

If you want a career with a known path - become an undertaker. Dead people don't sue! - Kartman

Please Read: Code-of-Conduct

Atmel Studio6.2/AS7, DipTrace, Quartus, MPLAB user

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

Yes Jim, the loop in main() will never end.

Quote:

I am an ASM programmer. Hence my request to Cliff. I am SLOWLY learning the DARK LETTER

Meanwhile, Cliff is making good speed moving towards C++ :D. Resistance is futile..

Happy 75th anniversary to one of the best movies ever made! Rick Blane [Bogart]: "Of all the gin joints, in all the towns, in all the world, she walks into mine."

 

"Some questions have no answers."[C Baird] "There comes a point where the spoon-feeding has to stop and the independent thinking has to start." [C Lawson] "There are always ways to disagree, without being disagreeable."[E Weddington] "Words represent concepts. Use the wrong words, communicate the wrong concept." [J Morin] "Persistence only goes so far if you set yourself up for failure." [Kartman]

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

@JOhan
CRAP!! THis means the 'DARK LETTER' is slowly infecting my brain. ;)

Jim

If you want a career with a known path - become an undertaker. Dead people don't sue! - Kartman

Please Read: Code-of-Conduct

Atmel Studio6.2/AS7, DipTrace, Quartus, MPLAB user

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

Quote:

meaning that if this is your entire code, it continuosly loops.

Yup, it's such an important point I made it FAQ#2 but I'm sure your Asm programs also do the same thing:

reset:
  call init
loop:
  call do_something
  rjmp loop

An Asm program that did:

reset:
  call init
loop:
  call do_something
;where next ?

would be very bad news ;-)

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

Quote:

would be very bad news

Yes. Worse than exiting main() in a C program linked with avrlibc, I would say. In assembler that would be a runaway train, while the C engine stands spinning indefinitively on the avrlibc turntable. :wink:

Happy 75th anniversary to one of the best movies ever made! Rick Blane [Bogart]: "Of all the gin joints, in all the towns, in all the world, she walks into mine."

 

"Some questions have no answers."[C Baird] "There comes a point where the spoon-feeding has to stop and the independent thinking has to start." [C Lawson] "There are always ways to disagree, without being disagreeable."[E Weddington] "Words represent concepts. Use the wrong words, communicate the wrong concept." [J Morin] "Persistence only goes so far if you set yourself up for failure." [Kartman]

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

I know how you feel Jim, I am also on the C Learning Curve.

bit by bit (no pun intended) it is starting to make sense.

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

Quote:
but I'm sure your Asm programs also do the same thing:

Sometimes, but isn't that why they call it "DEBUGGING"? ;)

JIm

If you want a career with a known path - become an undertaker. Dead people don't sue! - Kartman

Please Read: Code-of-Conduct

Atmel Studio6.2/AS7, DipTrace, Quartus, MPLAB user

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

Hi folks,

The external device which my Mega128 needs to control requires line feeds be sent after each command.

The initiliase command string for the device is

/1Z2R

to add the line feed should i do the following:

char char_array[]={'/','1','Z','2','R',0x0a};

i tried doing something like this but AVR Studio did not like it:

char char_array[]={"1Z2R",0x0a};

Many thanks

Ade

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

Just realised the carridge return was also required:

char char_array[]={'/','1','Z','2','R',0x0D,0x0A};

I would however much prefer to do this:

char char_array[]={"1Z2R",0x0D,0x0A};

Is there anyway this can be done?

Thanks

Ade

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0
char char_array[] = "/1Z2R\r\n"; 

Stefan Ernst

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

thanks sternst, that worked great.

it seems now that when i send the char_array to my send_string() function it gets stuck and does not return.

char init_syringe[]={"/1Z2R\r\n"};
send_string(init_syringe);

Here are the functions:

void send_char(char c)
{
	while ((UCSR1A & (1 << UDRE1)) == 0) {};
	UDR1 = c;
}


void send_string(char s[])
{
	int i =0;
	
	while (s[i] != 0x00)
	{
		send_char(s[i]);
		i++;
	}
}

now that i have the line feeds is it still acceptable to test for s[i] != 0x00 ??

The string is being sent, but the program hangs like it is not returning from the send_string() function.

hmmmm.

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

I hadnt written the ISR for USART1 RECV but yet i had the RXCIE1 bit set in UCSR1B

Thanks for your help.

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

Quote:

init_syringe

Oh dear God - this isn't a piece of medical equipment is it? Do you think you should be attempting something like that at your current level of experience?
Quote:

is it still acceptable to test for

Yes whenever you use:

char data[] = "something";

in C you are always guaranteed to have one extra byte on the end with 0x00 as the end marker in it.

BTW it doesn't matter but the more traditional way to write your send_string() is using pointer not array notation (in which case you don't need 'i'):

void send_string(char *s)
{
   while (*s != 0x00)
   {
      send_char(*s);
      s++;
   }
} 

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

Hi Clawson,

You mocked me in a previous post with regard to the medical equipment thing.

Its not hence i wont be killing anyone.

I am using a syringe drive to mix two liquids for a chemical reaction.

Thanks for the advice.

Ade.

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

'syringe' did make me CRINGE

I too hope this is not intended for medical use.
In manufacturing though a syringe is often used to inject glues

Jim

If you want a career with a known path - become an undertaker. Dead people don't sue! - Kartman

Please Read: Code-of-Conduct

Atmel Studio6.2/AS7, DipTrace, Quartus, MPLAB user

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

Quote:

You mocked me in a previous post

I never "mock" anyone. What I am concerned about is whether someone here might be doing something potentially lethal. If that were the case I'd lock the thread to prevent further discussion.

No worries if it's just chemicals (as long as you're not mixing explosives!! :lol:)

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

In terms of experince i have been writing C code for about 6 months.

I am sure many of you have 20 years plus.

It is defintely a learning curve.

I am grateful for the sound advice i get from the freaks forums.

I actually fee like i am making good progress now.

Regards

Ade.

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

i perfer using for loop :)

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

Are the chemicals being mixed nitrogen tetroxide and hydrazine?

Imagecraft compiler user