Serial Communications Possessed!

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

I've read the UART datasheet a million times but this one has me stumped. It seems that at the end of my serial communication the data gets distorted for some reason.

I'm using UART 0 of the ATmega128. Configured for 9600 baud / 8 data bits/ no parity.

When I set UMSEL0 to high in UCSR0C I get no serial output on the comm port.

When UMSEL0 is low I get the below result using the following code:

for( index= 0; index < 10 ; index++)
{
_delay_loop_2(999999999);
_delay_loop_2(999999999);
_delay_loop_2(999999999);

USART_Transmit0(0xAA);

}

for( index= 0; index < 10 ; index++)
{
_delay_loop_2(999999999);
_delay_loop_2(999999999);
_delay_loop_2(999999999);

USART_Transmit0(0xBB);

}

USART_Transmit0(0xCC);
....
USART_Transmit0(0xDD);
....
USART_Transmit0(0xEE);
...

Output:

AA AA AA AA AA AA AA AA AA AA BB BB BB BB BB BB BB BB BB BB CC CC CC CC CC CC CC EC EC EC ED ED ED ED ED ED EF EF EE EE 77 CF CF CF CF CF CF CF CF EF FF

What!? The output starts off good but then turns bad at the end! Parts of the CC's, the D'ss and EE's are screwed up!

// init the UART
void InitUART0(unsigned char baud)
{	
  /* Set baud rate */
  UBRR0H = (unsigned char)(baud>>8);
  UBRR0L = (unsigned char)baud;
  /* Enable receiver and transmitter */
  UCSR0B = (1<<RXEN)|(1<<TXEN);

  /* Set frame format: 8data, 1 stop bit */
  
// This will allow for some of my data to be valid.
  UCSR0C = (3<<UCSZ0);

// If I do the below I see no data at all.
// UCSR0C = (3<<UCSZ0)| (1<< UMSEL0);

	
}

I'm using the internal RC oscillator and initialzing my uart with:

InitUART0(51);

UCSR0A = 0x20
UCSR0B = 0x98
UCSR0C = 0x86

Anyone have any ideas on this one?

-Henk

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

Using a fixed delay to wait for the USART to complete isn't good practice. You should learn how to read the status.

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

I'd like to see uart transmit. Waiting for the txc bit? I's also like to see delay-2.... You really need to wait for 3 billion counts between chars? What clock frequency are you using? A coupla jiggahurtz?

Imagecraft compiler user

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

It looks like if I put all of my transmissions in for loops with he delay statements I don't have a problem. The problem is when I send things out consecutively. But it should not matter because I am polling UDRE to see if data is ready to be sent out before I move to UDR0!

void USART_Transmit0( unsigned char data )
{
	// Take this while loop out. 
	while ( !( UCSR0A & (1<<UDRE0)) )
	   	;

	 UDR0 = data;	
}

Something I am missing?

-Henk

Last Edited: Mon. Apr 12, 2004 - 09:30 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Does your code work differently without the delays? It seems to me that either your delays aren't being executed (optimized out) or this program will take years to run.

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

You are supposed to wait when the data register is full..... so when it goes empty, you can stuff in another char. Are you waiting while its empty?

Imagecraft compiler user

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

Bob, yes sir! I am waiting!

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

Bob,

Initially, it took me a while to figure this out:

while ( !( UCSR0A & (1<<UDRE0)) )  ; 

Will execute the empty statement for as long as UDRE0 is low.
-Mike

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

Mike, Right. That is exactly what I have in my code. Same problem.

-Henk

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

Setting UMSEL0 will use synchronous mode, which why you won't see any output. Stick with Asynchronous.

The fact that you're using the internal oscillator may be the root of your problem. If you look at the baudrate charts starting on page 192, you'll see you have a 7% error using the 1mhz clock. The more consecutive data you send, the worse the error will get. For best results you need to use an external crystal/resonator with a frequency that will give you 0% error with standard baudrates, such as 3.6864 or 7.3728. If you can't use an external clock then set U2X0 to reduce the error rate to .2%, set UBRR to 12, but your noise rejection will go down.

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

I don't see what possibly could be wrong. Double checking my register settings again I get:

UCSRA
--------
Set at 0xA0:
1010 0000

UCSRB
--------
Set at 0x98
1001 1000

UCSRC
--------
Set at 0x86
1000 0110

Mike,

My code works perfectly with the delays. When I do the transmissions back-to-back that is where I am running into problems! My transmsit should be able to do this correctly with the above while loop! Still having the same issue.

-Henk

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

1) UMSEL0 is synchronous mode, which (I assume) you don't want in
any case.
2) The delays look to be about 25ms each (9...9 truncated to 16 bits),
which isn't an eon but, as mentioned, shouldn't be needed.
Are you saying that the transmission is perfect as long as the delays
are present? (I'm losing track.)
3) The pattern of the failure is reminiscent of a gradual clock drift -- it
starts out in sync and continues to look right until it drifts "over the
edge".

I have no experience with the internal oscillator, but I think I've
read here that it's not terribly accurate. Can someone who knows
more about this say whether this is a plausible symptom?

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

dksmall!!

I initally changed the internal oscillator to 8 Mhz with AVR studio then set U2X =1, UBRR = 103, at a baud rate of 9600 giving me an error of 0.2%. Using this configuration I still saw errors.

Then when I read you post I put the oscillator back to 1 Mhz, U2X=1, UBRR=12 with a baud rate of 9600. There error for this is also 0.2% but works fine!

The percentage for both configurations are the same! Why am I getting such a huge difference than?

-Henk

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

If your USART code is correct, it should work without delays.

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

Baud rate needs to be within that few tenths of a percent..... try it at 1200 or 2400.... will probably work great....

Imagecraft compiler user

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

Thanks for your help guys! :lol:

-Henkie

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

Looking at page 195 of the ATmega128 datasheet the error shown running at 1 Mhz with a baud rate of 9600 is 0.2%. (U2X = 1)

http://www.atmel.com/dyn/resourc...

Then on page 197 the error running at 8 Mhz with a baud rate of 9600 is also 0.2%. (U2X = 1)

Both of the error values are the same! But when I actually implement this my results vary!


                 /* 9600 bps - 1 Mhz -- asyncronous */
	// U2X = 1
	// this works with no errors.
	InitUART0(12);
	
	/* 9600 bps - 8 Mhz -- asyncronous */
	// U2X = 1
	// Bluetooth  / serial connection.
                // Get invalid data when I do this.
	InitUART0(103);

Any idea why I have seeing such a differfent?

Thanks.

-Henk

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

Your processor crystal/oscillator may be off.

For example, your crystal may not be designed to work with the caps you actually have.

You may have more capacitance than you expect on one or more pins due to wiring, protoboard, etc. By the way, protoboards have a LOT of capacitance at each socket pin.

Most processor crystals are spec'd somewhere in the range of 50-100ppm (with the expected load capacitance). 100ppm is one part in 1E-4 or 0.01%, so that should not be an issue, again with expected load capacitance.

Excess capacitance should result in the oscillator being LOW in frequency. This would manefest itself in requiring a smaller divide number for correct operation.

Jim

 

Until Black Lives Matter, we do not have "All Lives Matter"!

 

 

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

I am using the internal RC oscillator of the AVR!

-Henk

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

henkvisser wrote:
I am using the internal RC oscillator of the AVR!

-Henk

But your speed may still be off!

The internal oscillator is nominal!

Did you check what speed the oscillator is ACTUALLY running at?

Are you aware that even with the OSCCAL byte loaded the internal oscillator will vary with temperature and supply voltage?

Lee

You can put lipstick on a pig, but it is still a pig.

I've never met a pig I didn't like, as long as you have some salt and pepper.

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

Lee,

Any error related to temperature or supply voltage should effect both frequencies! This includes the 1 Mhz and also the 8 Mhz settings! But invalid data is only seen with the 8 Mhz configuratoin!

If temperture and supply voltage were playing a role I would expect errors with *BOTH* frequencies!

This doesn't make sense!

-Henk!

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

Study the graphs in the back of the datasheet -- at 8MHz, the oscillator is
clearly more sensitive (even %) than at 1MHz. The two graphs even use
different scales.

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

So,

Quote:
Did you check what speed the oscillator is ACTUALLY running at?

Lee

You can put lipstick on a pig, but it is still a pig.

I've never met a pig I didn't like, as long as you have some salt and pepper.

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

Hello every body,
I went through the first query and was agast to see a huge number being passed to the _delay_loop_2 function. A little bit of reading of the function proto type clearly shows that it can take only an unsigned int, meaning the value must not exceed 65535 (0xffff). If a larger value is passed the actual number that will be loaded will be less 65535. As an eaxmple if you pass 65538, the actual number loaded will be 2! and hence your delay will not be as expected.

Now here is the sample code for serial communication which should work.
I am using an Atmega128 and serial port 0

code for initialisation of the port

[/code]
void usart0_init (void)
{
UBRR0H = 00;
UBRR0L = 23; // this is as per page 180 .pdf file of atmega128. I am using a 6.39 Mhz crystal. You may change this to suit your crystal/clock

UCSR0B = 0x18; // enable receive and transmit
UCSR0C = 0x06; // no parity and that stuff
}

to send a NULL terminated string

void usart0_transmit (unsigned char *cptr)
{
while (*cptr)
{
UDR0 = *cptr++;
while (!(UCSR0A & 0x40)); // wait here for transmit complete signal
UCSR0A = 0x40; // clear the bit for next char
}
}

This will go at full speed (9600) till the end of the string.

}[code]

Well I hope this helps.
Regards

Parthasaradhi Nayani

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

Quote:

Did you check what speed the oscillator is ACTUALLY running at?

Lee,

What would be the best^D^D^D^Deasiest way to verify the actual speed of the oscillator? Toggle a pin and look for the transition on my scope?

Your point is that the oscillator is probably not runing at exactly 8 Mhz so I can't make that 0.2% error comparison?

-Henk

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

Hi Henk,

I had a quick question. What happens if you change the order of the bytes you are sending - i.e. start with EE, then DD, to AA.

The timing should restart for each byte that is sent out. You shouldn't see cumulative errors over byte sequences. The errors should only accumulate over the bits of a single byte. That's true for every transmitter and receiver I've ever seen. Each byte stands alone.

I'm curious how you have the actual electrical connections made. Are you driving real RS-232 through a driver chip/circuit or are you driving something directly.

Reason I ask is I'm wondering if there are hardware issues of some kind afoot here. Once you start sending, maybe something starts heating up, or a cap drains down, etc.

Just some thoughts...

Please note - this post may not present all information available on a subject.

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

Hi Henk, me again.

After looking over the posts and questions/responses, I'm thinking this just might be hardware related. The reason is that each byte stands alone. You should not see cumulative errors on a byte to byte basis. You say if you put delays between each byte, it works but if you send them out fast it doesn't.

How about some details on how you are making the actual connections outside the chip?

The more I look at this the more I think you have something discharging, or heating up, or something along those lines and that is why you see the errors after a sequence of bytes goes out. And, are you reading these results that you posted in the first post with another UART - i.e. a terminal program on a PC or something or is it a homebrew method that might have the cumulative timing errors?

Maybe I'm off in left field too... :roll:

Please note - this post may not present all information available on a subject.