ATMEGA328P serial communication displays special characters

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

Hi guys now I'm trying serial communication stuff.  I am using the arduino uno based dev board which has 16MHz clock.  I downloaded a Realterm serial communication application and config it to 9600Baud, 1 stop bit, no parity and 8 bit.

However when I opened Realterm I can only see special characters and not the letter that I want.  What could be wrong?

 

#include <avr/io.h>
#define F_CPU 16000000UL
#include <util/delay.h>

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

void USART_init()
{
	UCSR0B=(1<<TXEN0);
	UCSR0C=(1<<UCSZ01)|(1<<UCSZ00);
	UBRR0L=BAUD_PRESCALE;
	UBRR0H=(BAUD_PRESCALE>>8);
}

void USART_Tx(unsigned char data)
{
	while(!(UCSR0A&(1<<UDRE0)));
	UDR0=data;
}


int main(void)
{
	USART_init();
	
	while (1)
	{
		USART_Tx ('A');
		_delay_ms(1000);
	}
}

 

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

Check and see if the DIV8 fuse is programmed. If it is then your internal clock is actually 2 MHZ.

Edit. Also make sure your clock is configured for external and not internal RC
Jim

I would rather attempt something great and fail, than attempt nothing and succeed - Fortune Cookie

 

"The critical shortage here is not stuff, but time." - Johan Ekdahl

 

"Step N is required before you can do step N+1!" - ka7ehk

 

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

"Why is there a "Highway to Hell" and only a "Stairway to Heaven"? A prediction of the expected traffic load?"  - Lee "theusch"

 

Speak sweetly. It makes your words easier to digest when at a later date you have to eat them ;-)  - Source Unknown

Please Read: Code-of-Conduct

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

Last Edited: Wed. Jan 15, 2020 - 04:56 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

See Tip #2 and Tip #3 (in my signature, below; may not be visible on mobile).

 

 

Top Tips:

  1. How to properly post source code - see: https://www.avrfreaks.net/comment... - also how to properly include images/pictures
  2. "Garbage" characters on a serial terminal are (almost?) invariably due to wrong baud rate - see: https://learn.sparkfun.com/tutorials/serial-communication
  3. Wrong baud rate is usually due to not running at the speed you thought; check by blinking a LED to see if you get the speed you expected
  4. Difference between a crystal, and a crystal oscillatorhttps://www.avrfreaks.net/comment...
  5. When your question is resolved, mark the solution: https://www.avrfreaks.net/comment...
  6. Beginner's "Getting Started" tips: https://www.avrfreaks.net/comment...
Last Edited: Wed. Jan 15, 2020 - 05:04 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 1

ryan2019 wrote:
I am using the arduino uno based dev board
Then I'd connect it up to the Arduino IDE and try out some Serial.begin(9600) stuff first. When that all works (proves speeds, wiring etc) then switch to non-Arduino code with many of the "unknowns" now removed.

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

ryan2019 wrote:

UCSR0C=(1<<UCSZ01)|(1<<UCSZ00);
	UBRR0L=BAUD_PRESCALE;
	UBRR0H=(BAUD_PRESCALE>>8);


Don’t mess with UCSR0C as default is 8N1

you also don’t need to split baud value, as compiler knows how to write to UBRR0 reg.

 

jim

 

 

(Possum Lodge oath) Quando omni flunkus, moritati.

"I thought growing old would take longer"

 

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

Write to UBRR0H first, then UBRR0L

 

From the Atmega328P datasheet (20.5 USART Initialization):

/*Set baud rate */
UBRR0H = (unsigned char)(ubrr>>8);
UBRR0L = (unsigned char)ubrr;

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

Thank you for all of the suggestions I will try them later. Also I have an additional question. How come ATMega 328P does not have the URSEL in UCSR0C register? I looked at the datasheet and could not find it. How is it being handled without defining this line?

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

jgmdesign wrote:
Check and see if the DIV8 fuse is programmed. If it is then your internal clock is actually 2 MHZ.

Edit. Also make sure your clock is configured for external and not internal RC
Jim

I have tried coding PWM using 16MHz as reference and so far all PWM frequencies and timings are correct as coded so I assume I am running at the right 16MHz clock. Is that right or this still does not prove the 16MHz clock?

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

ryan2019 wrote:
I assume I am running at the right 16MHz clock. Is that right or this still does not prove the 16MHz clock?

 

HOw are you writing and loading your code?  Arduino IDE, or Atmel Studio and  a programmer?

 

Jim

I would rather attempt something great and fail, than attempt nothing and succeed - Fortune Cookie

 

"The critical shortage here is not stuff, but time." - Johan Ekdahl

 

"Step N is required before you can do step N+1!" - ka7ehk

 

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

"Why is there a "Highway to Hell" and only a "Stairway to Heaven"? A prediction of the expected traffic load?"  - Lee "theusch"

 

Speak sweetly. It makes your words easier to digest when at a later date you have to eat them ;-)  - Source Unknown

Please Read: Code-of-Conduct

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

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

jgmdesign wrote:

ryan2019 wrote:
I assume I am running at the right 16MHz clock. Is that right or this still does not prove the 16MHz clock?

 

HOw are you writing and loading your code?  Arduino IDE, or Atmel Studio and  a programmer?

 

Jim

I am using Atmel Studio. I have never touched the fuse bits as well. Would that still be a probability that the DIV fuse you mentioned is set to a different setting?

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

Check in the Tools>device programming>fuses>read fuses

 

Scroll through the options until you hit DIV8 and see if the checkbox is 'checked'

 

ryan2019 wrote:

UBRR0L=BAUD_PRESCALE;
	UBRR0H=(BAUD_PRESCALE>>8);

 

I have never used this approach as it bites me in the a$$.  I find out what the UBBR value should be from the datasheet or from AVRcalc and load the UBBR manually.  But thats just old, stuffy me. smiley

 

JIm

I would rather attempt something great and fail, than attempt nothing and succeed - Fortune Cookie

 

"The critical shortage here is not stuff, but time." - Johan Ekdahl

 

"Step N is required before you can do step N+1!" - ka7ehk

 

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

"Why is there a "Highway to Hell" and only a "Stairway to Heaven"? A prediction of the expected traffic load?"  - Lee "theusch"

 

Speak sweetly. It makes your words easier to digest when at a later date you have to eat them ;-)  - Source Unknown

Please Read: Code-of-Conduct

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

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

How come ATMega 328P does not have the URSEL in UCSR0C register?

 

URSEL was used in some of the old chips so that they would share UCSRC with half the BRG divider.

The newer chips have separate registers for both halves of the BRG.

 

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

ryan2019 wrote:
How come ATMega 328P does not have the URSEL in UCSR0C register?
When Atmel first made AVrs they were pretty simple. They gave them IN and OUT instructions that could be used to access the peripheral control registers in a specific area of memory. There was just room in the instructions for 6 bits to say which register to access so this catered for 64 peripheral registers. Over time they filled it up. When they got to mega16/mega32 they actually needed 65 registers so they made one register (UCSRC / UBRRH) work for 2 different things. As UBRRH would never have a value so large that the top bit was set they used bit 7 as an indicator to say whether the access was really to UBRRH or UCSRC. When bit 7 (URSEL) was set the write was to UCSRC, when not set it was to UBRRH so each of those registers is really just 7 bits with the 8th bit being an address bit to identify which of the two lots of 7 to write to.

 

This meant that all the way up to mega16/mega32 they could still make AVRs in which all the peripheral registers could still be written/read by OUT/IN.

 

But then they came up with devices that had even more peripherals and needed more than 64 registers so they finally relented and accepted that some of the more frequently used registers would still be kept in the group of 64 that could be accessed by OUT/IN but others would need to use STS/LDS for access. These AVRs then moved the base address of SRAM up from 0x0060 (just beyond the 32 CPU registers and 64 peripheral registers) to 0x100. So now the region of 0x0060..0x00FF added 160 more potential peripheral registers.

 

As such there was no longer the need for jiggery-pokery involving URSEL bits to split one 8 bit register into two 7 bit registers. So now the UART can have as many separate registers as it needs and the UCSR0C and UBRR0H registers have their own addresses.

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

clawson wrote:

ryan2019 wrote:
How come ATMega 328P does not have the URSEL in UCSR0C register?
When Atmel first made AVrs they were pretty simple. They gave them IN and OUT instructions that could be used to access the peripheral control registers in a specific area of memory. There was just room in the instructions for 6 bits to say which register to access so this catered for 64 peripheral registers. Over time they filled it up. When they got to mega16/mega32 they actually needed 65 registers so they made one register (UCSRC / UBRRH) work for 2 different things. As UBRRH would never have a value so large that the top bit was set they used bit 7 as an indicator to say whether the access was really to UBRRH or UCSRC. When bit 7 (URSEL) was set the write was to UCSRC, when not set it was to UBRRH so each of those registers is really just 7 bits with the 8th bit being an address bit to identify which of the two lots of 7 to write to.

 

This meant that all the way up to mega16/mega32 they could still make AVRs in which all the peripheral registers could still be written/read by OUT/IN.

 

But then they came up with devices that had even more peripherals and needed more than 64 registers so they finally relented and accepted that some of the more frequently used registers would still be kept in the group of 64 that could be accessed by OUT/IN but others would need to use STS/LDS for access. These AVRs then moved the base address of SRAM up from 0x0060 (just beyond the 32 CPU registers and 64 peripheral registers) to 0x100. So now the region of 0x0060..0x00FF added 160 more potential peripheral registers.

 

As such there was no longer the need for jiggery-pokery involving URSEL bits to split one 8 bit register into two 7 bit registers. So now the UART can have as many separate registers as it needs and the UCSR0C and UBRR0H registers have their own addresses.

 

Thank you Sir for the detailed explanation :)

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

jgmdesign wrote:

Check in the Tools>device programming>fuses>read fuses

 

Scroll through the options until you hit DIV8 and see if the checkbox is 'checked'

 

ryan2019 wrote:

UBRR0L=BAUD_PRESCALE;
	UBRR0H=(BAUD_PRESCALE>>8);

 

I have never used this approach as it bites me in the a$$.  I find out what the UBBR value should be from the datasheet or from AVRcalc and load the UBBR manually.  But thats just old, stuffy me. smiley

 

JIm

 

Not sure why I could not find this.  The dialog box is empty.  Thank you for your support.  I will try to reorder the codes or look for answers online :)

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

Ok, assuming that your clock is indeed 16Mhz heres a little test program you can try:

 

#define F_CPU 16000000UL
#include <avr/io.h>
#include <util/delay.h>


void AVR_init(void)
{
// USART initialization
// Communication Parameters: 8 Data, 1 Stop, No Parity
// USART Receiver: Off
// USART Transmitter: On
// USART Mode: Asynchronous
// USART Baud Rate: 9600
UCSR0A=(0<<RXC0) | (0<<TXC0) | (0<<UDRE0) | (0<<FE0) | (0<<DOR0) | (0<<UPE0) | (0<<U2X0) | (0<<MPCM0);
UCSR0B=(0<<RXCIE0) | (0<<TXCIE0) | (0<<UDRIE0) | (0<<RXEN0) | (1<<TXEN0) | (0<<UCSZ02) | (0<<RXB80) | (0<<TXB80);
UCSR0C=(0<<UMSEL01) | (0<<UMSEL00) | (0<<UPM01) | (0<<UPM00) | (0<<USBS0) | (1<<UCSZ01) | (1<<UCSZ00) | (0<<UCPOL0);
UBRR0H=0x00;
UBRR0L=0x67;

}


void main(void)
{
    AVR_init();
    
    while(1)
    {
        USART_Tx('A');
        _delay_ms(250);
    }
}

Untested, but I am pretty confident it will output the letter A every 250 milliseconds.

 

JIm

I would rather attempt something great and fail, than attempt nothing and succeed - Fortune Cookie

 

"The critical shortage here is not stuff, but time." - Johan Ekdahl

 

"Step N is required before you can do step N+1!" - ka7ehk

 

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

"Why is there a "Highway to Hell" and only a "Stairway to Heaven"? A prediction of the expected traffic load?"  - Lee "theusch"

 

Speak sweetly. It makes your words easier to digest when at a later date you have to eat them ;-)  - Source Unknown

Please Read: Code-of-Conduct

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

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

jgmdesign wrote:

Ok, assuming that your clock is indeed 16Mhz heres a little test program you can try:

 

#define F_CPU 16000000UL
#include <avr/io.h>
#include <util/delay.h>


void AVR_init(void)
{
// USART initialization
// Communication Parameters: 8 Data, 1 Stop, No Parity
// USART Receiver: Off
// USART Transmitter: On
// USART Mode: Asynchronous
// USART Baud Rate: 9600
UCSR0A=(0<<RXC0) | (0<<TXC0) | (0<<UDRE0) | (0<<FE0) | (0<<DOR0) | (0<<UPE0) | (0<<U2X0) | (0<<MPCM0);
UCSR0B=(0<<RXCIE0) | (0<<TXCIE0) | (0<<UDRIE0) | (0<<RXEN0) | (1<<TXEN0) | (0<<UCSZ02) | (0<<RXB80) | (0<<TXB80);
UCSR0C=(0<<UMSEL01) | (0<<UMSEL00) | (0<<UPM01) | (0<<UPM00) | (0<<USBS0) | (1<<UCSZ01) | (1<<UCSZ00) | (0<<UCPOL0);
UBRR0H=0x00;
UBRR0L=0x67;

}


void main(void)
{
    AVR_init();
    
    while(1)
    {
        USART_Tx('A');
        _delay_ms(250);
    }
}

Untested, but I am pretty confident it will output the letter A every 250 milliseconds.

 

JIm

Thank you sir. Still strange that I am getting special characters. Let me do futher check.

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

ryan2019 wrote:
Still strange that I am getting special characters.

Do you have an oscilloscope or logic analyser to see what is actually happening on the wire?

 

Did you see Tip #3 ? (it's also FAQ #3 in clawson's sig)

Top Tips:

  1. How to properly post source code - see: https://www.avrfreaks.net/comment... - also how to properly include images/pictures
  2. "Garbage" characters on a serial terminal are (almost?) invariably due to wrong baud rate - see: https://learn.sparkfun.com/tutorials/serial-communication
  3. Wrong baud rate is usually due to not running at the speed you thought; check by blinking a LED to see if you get the speed you expected
  4. Difference between a crystal, and a crystal oscillatorhttps://www.avrfreaks.net/comment...
  5. When your question is resolved, mark the solution: https://www.avrfreaks.net/comment...
  6. Beginner's "Getting Started" tips: https://www.avrfreaks.net/comment...
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

awneil wrote:

ryan2019 wrote:
Still strange that I am getting special characters.

Do you have an oscilloscope or logic analyser to see what is actually happening on the wire?

 

Did you see Tip #3 ? (it's also FAQ #3 in clawson's sig)

 

Thank you sir for the advices.  I do not want to waste too much time debugging so I decided to connect 2 MCUs (328P and 2560) and they can exchange UART data pretty well.  I will try another USB to serial converter and see if the problem is there.  Thankyou very much.

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

ryan2019 wrote:
I decided to connect 2 MCUs (328P and 2560) and they can exchange UART data pretty well. 

The critical thing is that both ends of the link are at the same baud rate; it's not the numerical value that's important - just that they are both the same.

 

So, if you connect 2 microcontrollers which both have the same error from the "nominal" rate (eg, because they are both running the same code) - they will work fine together, despite the baud rate being "wrong".

 

So an incorrect baud rate remains a possibility.

 

Other possibilities include:

  • Wrong voltage levels between the micro & the USB converter;
  • Poor or broken/missing ground connection between the micro & the USB converter

Top Tips:

  1. How to properly post source code - see: https://www.avrfreaks.net/comment... - also how to properly include images/pictures
  2. "Garbage" characters on a serial terminal are (almost?) invariably due to wrong baud rate - see: https://learn.sparkfun.com/tutorials/serial-communication
  3. Wrong baud rate is usually due to not running at the speed you thought; check by blinking a LED to see if you get the speed you expected
  4. Difference between a crystal, and a crystal oscillatorhttps://www.avrfreaks.net/comment...
  5. When your question is resolved, mark the solution: https://www.avrfreaks.net/comment...
  6. Beginner's "Getting Started" tips: https://www.avrfreaks.net/comment...
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

awneil wrote:

ryan2019 wrote:
I decided to connect 2 MCUs (328P and 2560) and they can exchange UART data pretty well. 

The critical thing is that both ends of the link are at the same baud rate; it's not the numerical value that's important - just that they are both the same.

 

So, if you connect 2 microcontrollers which both have the same error from the "nominal" rate (eg, because they are both running the same code) - they will work fine together, despite the baud rate being "wrong".

 

So an incorrect baud rate remains a possibility.

 

Other possibilities include:

  • Wrong voltage levels between the micro & the USB converter;
  • Poor or broken/missing ground connection between the micro & the USB converter

I tried to activate 4 outputs of the Atmega2560 by 4 input pins on the Atmega328p through the UART serial communication. I set the baud rate to 9600 and then I noticed some intermittent activation on one of the Atmega2560 output. I changed the baud rate to 4800 and it was gone. Are there any rules or considerations that I need to consider when defining the baud rate?

Last Edited: Sun. Jan 19, 2020 - 10:54 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

ryan2019 wrote:
I tried to activate 4 outputs of the Atmega2560 by 4 input pins on the Atmega328p through the UART serial communication. I set the baud rate to 9600 and then I noticed some intermittent activation on one of the Atmega2560 output. I changed the baud rate to 4800 and it was gone. Are there any rules or considerations that I need to consider when defining the baud rate?

 

Too little information to make a determination. You've introduced a mega2560 into the mix - is this an Arduino mega board? How are you sending the data? There could be a million different issues to cause your problem - without seeing some code and a better description, we can only guess.

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

Kartman wrote:

ryan2019 wrote:
I tried to activate 4 outputs of the Atmega2560 by 4 input pins on the Atmega328p through the UART serial communication. I set the baud rate to 9600 and then I noticed some intermittent activation on one of the Atmega2560 output. I changed the baud rate to 4800 and it was gone. Are there any rules or considerations that I need to consider when defining the baud rate?

 

Too little information to make a determination. You've introduced a mega2560 into the mix - is this an Arduino mega board? How are you sending the data? There could be a million different issues to cause your problem - without seeing some code and a better description, we can only guess.

 

Sorry sir :)

I started another topic for this.  Refer to the link below:

https://www.avrfreaks.net/node/add/forum/591

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

ryan2019 wrote:
Refer to the link below:
Not a valid link ?!?

 

EDIT: presumably you really meant:  https://www.avrfreaks.net/forum/serial-communication-between-atmega328p-and-atmega-2560-glitch ?

Last Edited: Mon. Jan 20, 2020 - 10:15 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

clawson wrote:

ryan2019 wrote:
Refer to the link below:
Not a valid link ?!?

 

EDIT: presumably you really meant:  https://www.avrfreaks.net/forum/serial-communication-between-atmega328p-and-atmega-2560-glitch ?

 

Yes that's the right link sir :)

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

Do you get the same results when using another and different PC terminal program besides RealTerm?   As I recall, Realterm has a strange user interface, and is likely in a different mode than you think it is.   A crystal or resonator-based AVR should have no problems sending and receiving at 9600  baud.

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

Simonetta wrote:

Do you get the same results when using another and different PC terminal program besides RealTerm?   As I recall, Realterm has a strange user interface, and is likely in a different mode than you think it is.   A crystal or resonator-based AVR should have no problems sending and receiving at 9600  baud.

 

Yes I also tried Putty and it's the same.  I am waiting for another USB to Serial converter so I can test it.

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

I just had a thought....>>UH OH<<

 

Your OP says that they are using an UNO board.    Did you cit the lines that connect the on board USB interface to the Mega328 USART pins?  That could be altering your signal levels causing ht odd characters.

 

 

Jim

I would rather attempt something great and fail, than attempt nothing and succeed - Fortune Cookie

 

"The critical shortage here is not stuff, but time." - Johan Ekdahl

 

"Step N is required before you can do step N+1!" - ka7ehk

 

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

"Why is there a "Highway to Hell" and only a "Stairway to Heaven"? A prediction of the expected traffic load?"  - Lee "theusch"

 

Speak sweetly. It makes your words easier to digest when at a later date you have to eat them ;-)  - Source Unknown

Please Read: Code-of-Conduct

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

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

ryan2019 wrote:
I will try another USB to serial converter and see if the problem is there.  Thankyou very much.

 

Are you using an actual USB to TTL serial adapter or USB to RS-232 serial adapter?  You CANNOT use USB/RS232.  YOu will break something on teh UNO for sure.

 

JIm

I would rather attempt something great and fail, than attempt nothing and succeed - Fortune Cookie

 

"The critical shortage here is not stuff, but time." - Johan Ekdahl

 

"Step N is required before you can do step N+1!" - ka7ehk

 

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

"Why is there a "Highway to Hell" and only a "Stairway to Heaven"? A prediction of the expected traffic load?"  - Lee "theusch"

 

Speak sweetly. It makes your words easier to digest when at a later date you have to eat them ;-)  - Source Unknown

Please Read: Code-of-Conduct

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