# Atmega 328 uart program: compiler error on undeclared variable on register name ending with "n"

I'm trying to get the atmega328 to communicate over serial port with my pc. I'm using hyperterminal to echo back the keyboard character entries. I'm using the max3232 chip to do the communicated with the computer.

When I try to compile it gives and error and says that the variables in this function are undeclared, but they aren't variables but data register assignments.

If I replace the 'n' char in the register assignments to a number it will compile and program but no info is displayed in hyperterminal.

What should the 'n' be set too?

My RX is on pin 2 and TX is on pin 3, if that helps. It is being programmed because I've done the blinky light programs.

unsigned char USARTReadChar( void )
{
//Wait untill a data is available

while(!(UCSRnA & (1<<RXCn)))
{
//Do nothing
}

//Now USART has got data from host
//and is available is buffer

return UDRn;
}


THE ENTIRE SOURCE CODE

#define FOSC 1843200 // Clock Speed
#define BAUD 9600
#define MYUBRR FOSC/16/BAUD-1

//This function is used to initialize the USART
//at a given UBRR value
void USARTInit(unsigned int ubrr)
{

//Set Baud rate

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

UCSR0B = (1<<RXEN0)|(1<<TXEN0);
// Set fram format: 8data 2stopBit
UCSR0C = (1<<USBS0)|(3<<UCSZ00);

}

//This function is used to read the available data
//from USART. This function will wait untill data is
//available.
{
//Wait untill a data is available

while(!(UCSR0A & (1<<RXC0)))
{
//Do nothing
}

//Now USART has got data from host
//and is available is buffer

return UDR0;
}

//This fuction writes the given "data" to
//the USART which then transmit it via TX line
void USARTWriteChar(unsigned char data)
{
//Wait untill the transmitter is ready

while(!(UCSR0A & (1<<UDRE0)))
{
//Do nothing
PORTD ^= 1 << PINB2;

}

//Now write the data to USART buffer

UDR0 = data;
}

int main(void)
{
DDRB |= 1 << PINB2;

//Varriable Declaration
char data;

USARTInit(MYUBRR);

//Loop forever

while(1)
{

/* Now send the same data but but surround it in
square bracket. For example if user sent 'a' our
system will echo back '[a]'.

*/

USARTWriteChar('[');
USARTWriteChar(data);
USARTWriteChar(']');

}
}


The 'n' is meant to be a placeholder for the actual UART peripheral that you want to use when discussing the set of registers associated with the UARTs.

So if you had two UARTs, you could read the status register from the first UART by replacing it with a '0' or the second UART with a '1' like: UCSR0A or UCSR1A - note that these two are #define'd for you in a register definition file. Since we only use the UCSRnA convention for when we refer to these registers in discussion, it will not be #define'd to a register and thus using it in code will throw an error. You can follow your #include statements to find where they are defined. The register definition file and datasheet are usually two things that I have handy when working.

The ATmega328 only has one UART peripheral, but follows the same naming convention. So you would replace it with a 0. Regarding being able to read/write to a serial port - assuming that you have hooked up your MAX232 correctly, have you set your baud rate correctly on both the ATmega and the PC? Post the rest of your UART initialization code if you want further help debugging that.

1. Check your clock frequency and make sure it's correct when calculating the baud register value
2. Ensure that both uC and PC have same UART settings (baud, parity, stop bits)
3. Try not to use random code samples that may or may not be valid for your hardware configuration.
• @Cjueden, can I ask how you determined your clock frequency: #define FOSC 1843200 ? Also, have you tried to test USARTWriteChar() independently first? Jul 3 '12 at 18:46
• @Cjueden, that value may not correspond to what frequency you are running your chip at. Are you using an external oscillator? Internal oscillator? Are you using a board that you bought or your own design on a breadboard...? Also, what I meant by asking if you tested USARTWriteChar() independently is if you tried just looping and writing known, hard-coded characters out to the serial port and got them in-tact on the PC side without doing any reads. Probably irrelevant if your clock frequency in code is not correct. Jul 3 '12 at 18:58
• @Cjueden, if you are using the default internal oscillator setting, then try: #define FOSC 1000000 (1 MHz). See section 9.2.1 of the datasheet regarding "Default Clock Source" for an explanation Jul 3 '12 at 19:06
• @Cjueden // Set frame format: 8data 2stopBit - did you set this to be the same on the PC as well? Typical settings use 1 stop bit, either set your PC to 2 stop bits or change the uC to 1 stop bit. But be sure to verify that they are both set the same way. Jul 3 '12 at 20:23
• @Cjueden, as a side note, I would avoid using random code samples. Try to understand and set your registers according to what you want and how your hardware is configured. Jul 3 '12 at 20:27

When I see the "variables in this function are undeclared" message, it often means that I haven't included or linked some library I'm trying to use -- in this case, I perhaps the library that defines TXEN0, RXEN0, UCSR0A, UBRR0H, etc.

There seem to be two popular ways to implement serial communication with the ATmega328: "Low-level control" using the gcc compiler, which generally requires the line a b c d

#include <avr/io.h>


somewhere in your code that implements the "send" and "recieve" functions out of individual register reads and writes.

"High-level control" (also using the gcc compiler) involves using libraries pre-written by someone else that implements the "send" and "receive" functions out of individual register reads and writes, such as the Arduino "Serial" library a b. (Its implementation a b already has "#include <avr/io.h>" so people who use it don't have to write that line again.)