USART configuration for ATMEGA88

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

I'm having problems getting the USART to work on an ATMEGA88. I've got a project working on at ATMEGA16, but I want to change architecture.

Here's a compare of the USART setup in the two cases (master branch on the right is atmega16):

https://github.com/joakimgk/trafikklys/compare/atmega88..master?diff=split

 

I've looked through the datasheet, and also compared my code (on the left side of the diff) to various forum posts, but all I get is unprintable bytes in my terminal program.

The communications I'm expecting (and have configured the terminal software for) is:

 

Baud: 115200

Parity: None

Data bits: 8

Stop bits: 1

 

The line of code where I attempt a transmission over serial, is:  https://github.com/joakimgk/trafikklys/compare/atmega88..master?diff=split#diff-6d620a7d0a627b58cee5e409284a2ed8L441

 

I assume I've got some registers messed up in the USART_Init function?

 

 

Joakim

This topic has a solution.
Last Edited: Sun. Dec 29, 2019 - 10:23 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Is your crystal rock solid & working properly?  Due to rise & fall times, timing is much more stringent at these higher rates (compared to the likes of 9600 baud).

So first, make sure your clocking source is right on the money.

 

Also, make sure your 8x clock divider fuse is not in effect 

 

I'm having problems getting the USART to work on an ATMEGA88

What problems?  Finding the power switch? Plugging in the cable?

When in the dark remember-the future looks brighter than ever.   I look forward to being able to predict the future!

Last Edited: Sun. Dec 8, 2019 - 11:19 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

 

Thanks for replying!

I'm using the internal oscillator, configured at 8MHz: Int. RC Osc. 8 MHz; Start-up time PWRDWN/RESET: 6 CK/14CK + 65ms INTRCOSC_8MHZ_6CK_14CK_65MS

The LOW.CKDIV8 fuse was indeed set -- perhaps this is default? Clearing it, and the communications look a lot better, but still not perfect.

Where the ATMEGA16 would "achieve" perfect comms at 115200 baud, I'm currently receiving something like this (if I re-run/reset the avr):

 

USART_SendString("HEI VELKOMMEN VERDEN");

HEI VELKOMMEN VERDEN

HEI VELKOMMEN VERDEN

HEI VELKOMMEN VERDEN

HEI VELKOMMEN VERDEN
HEI VELKOMMEN VERDEN

HEI VELKOMMEN VERDEN

HEI VELKOMMEN VERDEN

HEI VELKOMMEN VERDEN
HEI VELKOMMEN VERDEN

HEI VELKOMMEN VERDEN

ÈÅI ÖÅÌËÏÍMÅÎ ÖEÒÄÅN

HEI VELKOMMEN VERÄEN
HEI VELKOMMEN VERDEN

HEI VELKOMMEN VÃ…RDEN

Is there reason to expect different "performance" of the internal clock of an ATMEGA88 than that of an ATMEGA16? 

I guess I should use an external crystal, but I'd hope to understand more of this problem while I'm at it.

 

Here are the fuses as set:

 

 

Joakim

 

 

 

Last Edited: Sun. Dec 8, 2019 - 11:46 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 1

It is NOT that it is different in Mega88 compared to Mega16. The ISSUE is that it is different from one chip to the next of the same kind, even.

 

The problem is the tolerance of the frequency for the internal oscillator (for all but XMega and newer XTiny and Mega-0 chips). Clocks have to be within a few percent difference at the two ends of the serial link. Tolerance on Mega88 (and 168 and 328 and many others) is about 50% bigger than what is allowed for reliable asynchronous serial. Thus, even for a specific model, SOME will work and some will not. 

 

The standard solution is to use an external crystal. Alternatively, you can use a 32.768KHz crystal to calibrate the internal oscillator on the fly. 

 

Jim

 

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

 

 

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

You could fiddle about with OSCCAL:

uint8_t n;

n = OSCCAL - 10;

for (uint8_t i = 0; i < 20; i++) {
    OSCAL = n++;
    USART_SendString("HEI VELKOMMEN VERDEN");
}

that would try printing the string from the power on value in OSCAL - 10 in steps up to OSCAL + 10. The likely output may be something like:

...
ÈÅI ÖÅÌËÏÍMÅÎ ÖEÒÄÅN
ÈÅI ÖÅÌËÏÍMÅÎ ÖEÒÄÅN
HEI VELKOMMEN VERÄEN
HEI VELKOMMEN VERDEN
HEI VELKOMMEN VÃ…RDEN
HEI VELKOMMEN VERDEN
HEI VELKOMMEN VERDEN
HEI VELKOMMEN VERDEN
HEI VELKOMMEN VERDEN
HEI VELKOMMEN VERDEN
HEI VELKOMMEN VERDEN
HEI VELKOMMEN VERDEN
HEI VELKOMMEN VERDEN
HEI VELKOMMEN VÃ…RDEN
HEI VELKOMMEN VERDEN
HEI VELKOMMEN VERÄEN
ÈÅI ÖÅÌËÏÍMÅÎ ÖEÒÄÅN
ÈÅI ÖÅÌËÏÍMÅÎ ÖEÒÄÅN
...

That is there will be some "good ones" in the middle with noisy ones around the outside. Work out what n was at the middle of the good ones and from then on always pre-load that value into OSCCAL when you start.

 

However this calibration may vary over varying temperature and Vcc level.

 

A far better idea is to use a crystal.

 

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


joakimk wrote:

The communications I'm expecting (and have configured the terminal software for) is:

 

Baud: 115200

Parity: None

Data bits: 8

Stop bits: 1

joakimk wrote:
I'm using the internal oscillator, configured at 8MHz: Int. RC Osc. 8 MHz; Start-up time PWRDWN/RESET: 6 CK/14CK + 65ms INTRCOSC_8MHZ_6CK_14CK_65MS
joakimk wrote:
Where the ATMEGA16 would "achieve" perfect comms at 115200 baud,

I find this a bit hard to believe (the "good" performance on the Mega16 with implied 8MHz internal oscillator, as

and

If indeed you are getting good results with these conditions, then I'd speculate that the Mega16 clock just happens to be off of nominal a useful amount.

 

Why not end the speculation and >>measure<< the clock on both setups?

 

 

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: 1

theusch wrote:
Why not end the speculation and >>measure<< the clock on both setups?

Or better, invest a $0.10 in  a baud rate friendly xtal and all is taken care of and you can move on to solving the real problem!

 

Jim

 

 

(Possum Lodge oath) Quando omni flunkus, moritati.

"I thought growing old would take longer"

 

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

Typically if you are more than about 1% off (perhaps 2%, but that's getting big), you should take some action to reduce it....since you don't know how far off the other end is & there will be temperature variations, etc.

If you use a uart freq xtal, you are at 0.000% ...so why not take the easy route?

Look at all the time you already wasted over a 15 cent part!

 

95.383% of uart comm problems are due to an improper frequency---let's work together to lower that to 28.694%!

When in the dark remember-the future looks brighter than ever.   I look forward to being able to predict the future!

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

avrcandies wrote:
95.383% of uart comm problems are due to an improper frequency
Not everyone agrees with that...

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

Thanks for all the helpful responses! I will obviously go for an external crystal. I must have been very lucky with the random atmega16 I pulled out to do the initial toying around with the esp8266 (which is pre-configured to 115200 baud). Being a hobby project, it didn't occur to me to use a crystal as long as this was working fine with the internal oscillator. Also, this is a hobby project, and very much in the proto/proof of concept stage, running in the STK500 and a protoboard.

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

joakimk wrote:
running in the STK500 and a protoboard.

 

Why not configure the on board oscillator the STK500 has to a baud rate friendly value and use that to drive your Mega88?  Its super easy to do.  3.686MHz should do the trick

 

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

95.383% of uart comm problems are due to an improper frequency

Not everyone agrees with that...

I bet >73.684% of the time when someone writes in saying "I just set up my Mega9876's  serial comm PC interface & trying to communicate with it....my terminal seems to be erratically unresponsive or emits strange characters...the rest of my program is running fine on the same setup"  we ask "what is your clock source" & they say the internal osc.  If it doesn't comm at all, then its their reversed connections (TXD to TXD instead of proper TXD to RXD) (6.83%)  or improper register settings (17.12%)

When in the dark remember-the future looks brighter than ever.   I look forward to being able to predict the future!

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

Are you sure that the Rx/Tx swap is not 6.87%?

 

Jim

 

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

 

 

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

Yes, that is precisely the plan :)

Looking into this, I learn that choosing the right crystal is a matter of checking that the crystal frequency is divisible by 16 times the baud rate. Since 115.200*16 % 3.686.400 = 0, that crystal is perfect.

If I have understood that properly, then how can the comms be working so stable on the ATMEGA16 when it's running at 8MHz? I mean, 115.200*16 is not divisible by 8.000.000.

 

 

Finally, when I change the frequency (to 3.686MHz external crystal) I'll have to set the proper fuse, connect the crystal (with caps, when I move out of the STK), and update the calculation of the baud prescaler:

https://github.com/joakimgk/traf...

 

#define F_CPU 3686400UL 


#ifdef DOUBLE_SPEED_MODE
	#define BAUD_PRESCALE (int)round(((((double)F_CPU / ((double)BAUDRATE * 8.0))) - 1.0))	/* Define prescale value */
#else
	#define BAUD_PRESCALE (int)round(((((double)F_CPU / ((double)BAUDRATE * 16.0))) - 1.0))	/* Define prescale value */
#endif

 

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


jgmdesign wrote:
why not use the on board oscillator the STK500 has

Currently, I have the on board oscillator set to 3.686MHz, with the STK jumpers mounted to default settings:

 

 

Does this mean the ATMEGA88 (and the ATMEGA16, for that matter) is clocked at 3.686MHz, and not to the 8MHz I'm trying to configure in the software?

 

I'm still struggling to port my code from ATMEGA16 to AMTEGA88. Adapting the code (as described earlier/above) proves to be complicated, especially so when I can never be sure if the serial comms is not working due to improper clocking. I have tried to compare the datasheets to get the UART setup (registers) correct --- mostly, the register names are the same but with an extra "0" appended to them:

 

Meanwhile, I have ordered some crystals from Digikey, and now have a bag of 3.6864 MHz (and 9.2160MHz), but then I'm facing problems understanding how to hook up an external crystal in the STK500 properly. Reading the STK manual, it seems I should simply plug the crystal in the socket, and change the OSCSEL and XTAL1 jumpers, but then I also need to change a fuse in the ATMEGA88 (the LOW.SUT_CKSEL fuse), which is currently set to "Int. RC Osc. 8 MHz)? As in my previous question, are the prescaler calculations the same as for 8MHz?

 

 

 

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


Regarding changing the fuse for external crystal, Atmel Studio gives the following warning

 

 

When I tried going forward with this, it seems that particular ATMEGA88 chip just broke down and had to be replaced...

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


Here's what happens when I try to change the fuse to some external crystal setting. Programming (setting) the fuse seems to go OK (the yellow ! icon on LOW.SUT_CKSEL in the above screenshot turns into a green check) but after that the chips is toast.

It does not run, and I'm unable to re-program the fuses using Atmel Studio:

 

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

When you select External Oscillator, it requires a stand-alone powered oscillator. If you only have a crystal, it is pretty much toast. There are numerous threads and tutorials about "unbricking an MCU" on this forum. One of those will give you details about how to fix your chip.

 

Jim

 

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

 

 

Last Edited: Sat. Dec 28, 2019 - 11:32 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

But the fuse setting was "Ext. Low-Freq. Crystal"...

 

The crystal I'm using is 3.6864MHz -- I have no idea if this is low or high frequency?

 

I did, however, manage to set the fuses correctly (it didn't brick, at least) by using an online fuse calculator: http://www.engbedded.com/fusecalc

By guessing "Ext. Full-swing crystal" (again, crystal), and un-checking CKDIV8, it output: 

 

Low: 0xC6

High: 0xDF

Extended: 0xF9

 

Entering these hex values in the Fuses dialog of Atmel Studio, I was able to program (a new) ATMEGA88-20PU. Yet, I'm in no way confident these are correct settings?

It's been a long thread, so I hope a brief repetition is OK: I want to set up the ATMEGA88's UART for 115200 baud, 8n1.

The terminal program now only displays "junk bytes"...

 

Are these baud prescaler calculations still proper?

 

#define F_CPU 3686400UL					/* Define CPU clock Frequency */
#include <avr/io.h>							/* Include AVR std. library file */
#include <math.h>

//#define DOUBLE_SPEED_MODE

#ifdef DOUBLE_SPEED_MODE
	#define BAUD_PRESCALE (int)round(((((double)F_CPU / ((double)BAUDRATE * 8UL))) - 1UL))	/* Define prescale value */
#else
	#define BAUD_PRESCALE (int)round(((((double)F_CPU / ((double)BAUDRATE * 16UL))) - 1UL))	/* Define prescale value */
#endif

 

and here is my registers setup for the UART:

 

void USART_Init(unsigned long BAUDRATE)				/* USART initialize function */
{
#ifdef DOUBLE_SPEED_MODE
	UCSR0A |=(1 << U2X0);
#endif
	UCSR0B |= (1 << RXEN0) | (1 << TXEN0);	/* Enable USART transmitter and receiver */
	UCSR0C |= (1<<USBS0)| (1 << UCSZ00 ) | (1 << UCSZ01 );	/* Write USCRC for 8 bit data and 1 stop bit */ 
	UBRR0L = BAUD_PRESCALE;							/* Load UBRRL with lower 8 bit of prescale value */
	UBRR0H = (BAUD_PRESCALE >> 8);					/* Load UBRRH with upper 8 bit of prescale value */
	UCSR0B |= (1 << RXCIE0 );
}

 

Last Edited: Sat. Dec 28, 2019 - 11:57 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

 

I'm learning "high frequency" starts at 8MHz, which means I should go for low freq. (with the longest startup time):

 

 

Thanks for the tip on un-bricking the megas... Thankfully, until then, I have a whole tube of them to experiment with :-/

 

Update: And, yeah, this broke this ATMEGA, too :-( Am I making any obvious errors with the fuse settings?

 

Last Edited: Sun. Dec 29, 2019 - 12:16 AM
This reply has been marked as the solution. 
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

If the AVR is configured for high speed crystal, your 3.686MHZ crystal will work.  Did you put 18pf capacitors on the crystal legs to ground?

 

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

Well, the AVR is running inside the STK500, with a 3.6864MHz crystal in the CRYSTAL socket. As far as I understand, that's all there is to setting up a crystal in the STK500. I guess caps are Integrated into the stk itself? I hadn't planned on moving the AVR onto a breadboard just yet. This should be possible (and even very easy), as I gather from docs?

And, just to emphasize: The AVR dies promptly, as soon as I've succeeded writing the high speed crystal fuses. Apparently, writing low speed crystal fuse values does not kill it, for some reason, but then I couldn't get the comms to resolve to anything meaningful. Maybe low speed is the right choice, but then how do I reconfigure the UART (which was previously configured for 8MHz internal oscillator)?

Last Edited: Sun. Dec 29, 2019 - 03:32 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0


OK, finally, this seems to have converged to something stable :D

Setting high-freq crystal, as below, does not brick the AVR and the program seems to run as intended!

Furthermore, the UART is now communicating reliably with the ESP8266 -- just like the ATMEGA16 did.

So it seems I'm back on track, having ported from ATMEGA16 to ATMEGA88. Thanks for all the help and guidance, everyone!

 

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

Great to read that your project is moving ahead!
When you move to a breadboard, remember to add the caps to the XTAL pins.

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