Getting wrong data via UART

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

Hello,

 

I am working on a project in which microcontroller communicate with mobile phone using bluetooth module. I am using UART communication with 11.0592 Mhz external crystal and 9600 baud rate. But I am getting wrong data in the microcontroller. Table below shows mapping between data what I sent from mobile and what I received in micro-controller:

 

 

I have checked the bluetooth module and mobile app code using HyperTerminal and thats part working fine. And if send data from PC using HyperTerminal, I am getting the same result. I have also replace micro-controller, crystal and capacitor; still the same result.

 

Please help me i solving this issue.

 

Thanks in advance. 

This topic has a solution.

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

How have you set your clock fuses?

How have you initialised your USART?

'This forum helps those who help themselves.'

 

pragmatic  adjective dealing with things sensibly and realistically in a way that is based on practical rather than theoretical consideration.

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

Hello Brian Fairchild,

 

Yes I have set the fuse bits and here is the UART initialization code (I am using Atmega32A uC):

 

 

void InitializeUART(int baud, char AsyncDoubleSpeed, char DataSizeInBits, char ParityEVENorODD, char StopBits, char USARTInterruptEnable)
{
uint16_t UBBRValue = lrint(( F_CPU / (16L * baud) ) - 1);

//setting the U2X bit to 1 for double speed asynchronous
if (AsyncDoubleSpeed == 1) UCSRA = (1 << U2X); 

//Put the upper part of the baud number here (bits 8 to 11)
UBRRH = (unsigned char) (UBBRValue >> 8);

//Put the remaining part of the baud number here
UBRRL = (unsigned char) UBBRValue;

//Enable the receiver and transmitter
UCSRB = (1 << RXEN) | (1 << TXEN);

//Enable Interrupt
if (USARTInterruptEnable) UCSRB |= ( 1 << RXCIE);

//Set 2 stop bits
if (StopBits == 2) UCSRC = (1 << USBS);

if (ParityEVENorODD == EVEN) UCSRC |= (1 << UPM1); //Sets parity to EVEN
if (ParityEVENorODD == ODD) UCSRC |= (3 << UPM0); //Alternative way to set parity to ODD

if (DataSizeInBits == 6) UCSRC |= (1 << UCSZ0); //6-bit data length
if (DataSizeInBits == 7) UCSRC |= (2 << UCSZ0); //7-bit data length 
if (DataSizeInBits == 8) UCSRC |= (3 << UCSZ0); //8-bit data length 
if (DataSizeInBits == 9) UCSRC |= (7 << UCSZ0); //9-bit data length
}

 

Thanks 

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

Good test is to send UUUU. This is hex 55, so it should look like a 4800 Hz square wave. Got a scope or a meter that freads freq?

Imagecraft compiler user

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

pranshu.aggarwal91 wrote:

Yes I have set the fuse bits...

 

But HOW have you set them? Or, asked another way, how do you know that your CPU is really running at F_CPU?

'This forum helps those who help themselves.'

 

pragmatic  adjective dealing with things sensibly and realistically in a way that is based on practical rather than theoretical consideration.

This reply has been marked as the solution. 
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0
//Set 2 stop bits
if (StopBits == 2) UCSRC = (1 << USBS);

if (ParityEVENorODD == EVEN) UCSRC |= (1 << UPM1); //Sets parity to EVEN
if (ParityEVENorODD == ODD) UCSRC |= (3 << UPM0); //Alternative way to set parity to ODD

if (DataSizeInBits == 6) UCSRC |= (1 << UCSZ0); //6-bit data length
if (DataSizeInBits == 7) UCSRC |= (2 << UCSZ0); //7-bit data length 
if (DataSizeInBits == 8) UCSRC |= (3 << UCSZ0); //8-bit data length 
if (DataSizeInBits == 9) UCSRC |= (7 << UCSZ0); //9-bit data length

(I am using Atmega32A uC)

The ATmega32 has got UBRRH and UCSRC sharing the same address.     So you must use the URSEL bit to distinguish between them.

As a side-effect,   using the |= operation is rather tricky.

 

Of course,    if you have not chosen any of the UCSRC features,   it looks as if UCSRC is never accessed.

 

The trick in life is to use the Compiler Libraries and headers whenever possible.      e.g.  <util/setbaud.h>

However,   it looks as if GCC does not have a system provided <util/setusart.h>

 

So you will have to write your own.    Incidentally,   your current example would be a fine starting point.    Just build the UCSRC 'bits' into a local variable.

When you have assembled them all,  OR the value with (1<<URSEL) and write this to UCSRC.

 

David.

 

p.s. if my guess is correct,   what you are seeing is UBRRH being initialised to some non-zero value.    e.g. a really SLOW baud rate.

p.p.s.  if the others' guesses are correct,   you don't have the fuse values that you thought you had.

Last Edited: Sun. Nov 16, 2014 - 09:31 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hello Devid,

 

Yes you are right. Problem is that I didn't distinguish between UBRRH and UCSRC and as per your suggestion, I writed 1<<URSEL to UCSRC before writing anything on UCSRC. Now everything is work like a charm. 

 

And thanks for your suggestion on using Compiler Libraries. As GCC doesn't provide these Libraries, I have created one for the usart operation.

 

And regarding your comment of using "|=" operator, Yes I agree, it is tricky to use this operator because sometime I forget to include "|" that create a problem. So I am just thinking of creating a Libraries that contain function like setPin(port_name, pin_number) and resetPin(port_name, pin_number).

 

Thanks

Pranshu

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

Well,   writing to DDRx or PORTx is just the occasion when you probably want to write to individual pins.

 

However,   setting up TCCR1B or ADCSRA at the beginning of your program is better done with =

 

In other words,   use = or |= or &= at the appropriate time.     It may take a little while to get used to these operators.     But it will be easier to avoid mistakes when you have neat code that can be read on one screen.   e.g. use spaces around operators and a sensible amount of comments,   blank lines.

 

Incidentally,    UCSRC defaults to 8-N-1 at reset.     So most people never need to assign UCSRC for most apps.

 

David.