uart in megax8 family?

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

I was trying to compile the stdiodemo example code that comes with the avr-libc documentation with the mega88 as the target. I merely changed one line in the makefile:

# MCU name
MCU = atmega88
#MCU = atmega8
#MCU = atmega169
#MCU = atmega128

I get the following errors in my make output:

uart.c: In function ‘uart_init’:
uart.c:33: error: ‘UBRRL’ undeclared (first use in this function)
uart.c:33: error: (Each undeclared identifier is reported only once
uart.c:33: error: for each function it appears in.)
uart.c:35: error: ‘UCSRB’ undeclared (first use in this function)
uart.c:35: error: ‘TXEN’ undeclared (first use in this function)
uart.c:35: error: ‘RXEN’ undeclared (first use in this function)
uart.c: In function ‘uart_putchar’:
uart.c:54: error: ‘UCSRA’ undeclared (first use in this function)
uart.c:54: error: ‘UDRE’ undeclared (first use in this function)
uart.c:55: error: ‘UDR’ undeclared (first use in this function)
uart.c: In function ‘uart_getchar’:
uart.c:104: error: ‘UCSRA’ undeclared (first use in this function)
uart.c:104: error: ‘RXC’ undeclared (first use in this function)
uart.c:105: error: ‘FE’ undeclared (first use in this function)
uart.c:107: error: ‘DOR’ undeclared (first use in this function)
uart.c:109: error: ‘UDR’ undeclared (first use in this function)
make: *** [uart.o] Error 1

When I try the 169 or 8 targets, everything is fine, but the 128 and 88 targets fail. Are these just not implemented on the megax8s?

PS - I am using 1.4.4 of the avr-libc

Last Edited: Mon. Apr 2, 2007 - 11:40 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Of course the megax8s have a UART... or in this case a USART. If you look at the datasheet you will find that the registers have different names because the USART is called USART0.

UDR becomes UDR0, UCSRA becomes UCSR0A, etc.

Martin.

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

Ok, I was under the impression that those were the deprecated names? For example I've also been tinkering with an AVR butterfly and got the very cool book +kit from smileymicros. All the code in his book was written for the 1.0 version of the avr-lib (he has the old versions of the compiler on his site). However, before I started work on my own project I wanted to upgrade to 1.4. In the process of porting some of smiley's code to 1.4, I did the exact opposite of what you just said (i.e. changed UCSR0A to UCSRA, etc), so are you sure about this?

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

The register and bit names in the io???.h files (in \winavr\avr\include\avr) will be the same as in the datasheet for the chip you chooose to use.

As Martin says the iom8.h for the Mega8 therefore contains:

/* USART */
#define UBRRL	_SFR_IO8(0x09)
#define UCSRB	_SFR_IO8(0x0A)
#define UCSRA	_SFR_IO8(0x0B)
#define UDR	_SFR_IO8(0x0C)

/* UCSRA */
#define RXC	7
#define TXC	6
#define UDRE	5
#define FE	4
#define DOR	3
#define PE	2
#define U2X	1
#define MPCM	0

/* UCSRB */
#define RXCIE	7
#define TXCIE	6
#define UDRIE	5
#define RXEN	4
#define	TXEN	3
#define UCSZ2	2
#define RXB8	1
#define TXB8	0

and iomx8.h (which is included by iom88.h) contains:

#define UCSR0A  _SFR_MEM8 (0xC0)
/* UCSR0A */
#define RXC0    7
#define TXC0    6
#define UDRE0   5
#define FE0     4
#define DOR0    3
#define UPE0    2
#define U2X0    1
#define MPCM0   0

#define UCSR0B  _SFR_MEM8 (0xC1)
/* UCSR0B */
#define RXCIE0  7
#define TXCIE0  6
#define UDRIE0  5
#define RXEN0   4
#define TXEN0   3
#define UCSZ02  2
#define RXB80   1
#define TXB80   0

#define UCSR0C  _SFR_MEM8 (0xC2)
/* UCSR0C */
#define UMSEL01  7
#define UMSEL00  6
#define UPM01    5
#define UPM00    4
#define USBS0    3
#define UCSZ01   2
#define UDORD0   2
#define UCSZ00   1
#define UCPHA0   1
#define UCPOL0   0

#define UBRR0   _SFR_MEM16 (0xC4)
#define UBRR0L  _SFR_MEM8 (0xC4)
#define UBRR0H  _SFR_MEM8 (0xC5)
#define UDR0    _SFR_MEM8 (0xC6)

I think the confusing thing here is that Atmel, in the Mega48/88/168 datasheet, chose to number all the UART registers/bits with an additional '0' as if there might have been a second UART with '1' in those positions - but this is not the case in 48/88/168 - they have just the one UART like the Mega8

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

Ya it's confusing all right. So what would be the proper behavior to solve this? Using find&replace in the editor of your choice (i.e. :% s/UCSRA/UCSR0A/g in vi):

1. edit uart.c and make the changes here

2. write a header file with some defines

3. change iomx8.h to be consistent with the rest

Personally I like the last solution the best, but I am sure that someone will yell at me, telling me that's a horrible solution. But it seems to me when you get example code with your library you'd want it to compile without you having to edit it, am I crazy? And wouldn't this increase the code portability across the avr's, or is there some reason you would'nt want code that works on all these procs at the same time?

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

Don't ever think of (3) !

What you do in your own uart.c or whatever is:

#if defined (__AVR_ATmega8__)
   UBRRL = baudrate;
#elif defined(__AVR_ATmega88__)
   UBRR0L = baudrate;
#endif

and so on if you want the same file to be able to work with different architectures. Or you just port the code once and for all from the AVR it was written for to the one you want to use and be done with it (the "undeclared symbol" errors from the compiler will actually assist you in this process!)

If you wanted to go the "own header file" route you could do:

#if defined (__AVR_ATmega8__)
   #define MY_UBRR UBRRL
#elif defined(__AVR_ATmega88__)
   #define MY_UBRR UBRR0L
#endif

then access MY_UBRR in your .c code

Cliff

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

Thank you guys for such detailed and professional responses. I'll shoot for the if elif structures when writing a new project, but just to get this example code working I've been doing something like this for each of the undefined errors:

echo '#define UCSZ1 UCSZ01'>>m88xx.h

and just adding an include line on files with errors:

#include "m88xx.h"

It might be a little lazy, but it sure is fast when you're using bash and just want to see example code run.

Hello World!

cheers!

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

Just wanted you to know I've bookmarked this page and now use that elif structure repeatedly to keep my programs cross-compatible. Thanks for the heads up, and greatly detailed answers!