RS232 routines for Orangutan/ATmega168

Now that the Orangutan is being shipped with the ATmega168 and standard clock speed of 8 MHz, much code written for the older ATmega8 processor won’t work correctly, and in some cases won’t compile without modification. For example, the register and bit names for the UART are different and now include an extra 0 (zero) – this is to discriminate between multiple uarts on the newer MPUs. See the data sheets for details.

I’ve put together some example RS232 routines that work on the new Orangutan and tested them fairly thoroughly with the Pololu USB-serial adapter and Hyperterm on a Windoze PC.

If you use this USB adapter, connect PD0 (RX) on the Orangutan to TX on the USB adapter, likewise for PD1 (TX) and RX on the USB adapter. You will probably need to have a series resistor between PD0 and TX (I used 10K ohms). Otherwise, the USB adapter, which is continuously powered by the PC, will cause reset problems with the Orangutan and you may have difficulty with the programmer.

One of several simple examples is pasted in below. The routines are available as a zip file at
uoxray.uoregon.edu/orangutan … 8_uart.zip
and include two different examples in which the uart is defined as stdio, so that you can use printf and scanf, etc. to get input from the PC.

If any problems surface with the code (other than development system issues – I only know about WinAVR and AVRISP, and not much at that), please let me know by email.

sjames_remington at yahoo dot com.

/*
Simple RS232 input/output example routines, including print string and print hex value
For Orangutan with ATmega168 processor. 8 MHz CPU clock assumed
Produces about 800 bytes of loaded code with -O3
A startup delay may be required with some Pcs for serial port input synchronization
*/

#include <avr/io.h>

//define CPU clock speed and desired baud rate

#define F_CPU 8000000UL
#define baud 9600
#include <util/delay.h>

//function prototypes

void init_uart(void);
void uart_putchar(char c);
unsigned char uart_getchar(void);
void uart_string (const unsigned char* string);
void uart_hex_nibble (unsigned char c);
void uart_hex(unsigned char c);

//initialize the UART hardware on an ATmega168.
void init_uart(void)
{
UBRR0H = ((F_CPU / (16UL * baud) - 1)>>8); //0 for 8 MHz
UBRR0L = ((F_CPU / (16UL * baud) - 1)&0xFF); //51 for 8 MHz
UCSR0B = (1<<RXEN0) | (1<<TXEN0); //enable transmitter and receiver
UCSR0C = (3<<UCSZ00); // 8 bits, 1 stop bit, no parity
}

// put a character to the UART

void uart_putchar(char c)
{
loop_until_bit_is_set(UCSR0A,UDRE0);
UDR0 = c;
if(c == ‘\n’) uart_putchar(’\r’); // newline -> CRLF
}

//get a character

unsigned char uart_getchar(void)
{
char c;
loop_until_bit_is_set(UCSR0A,RXC0);
c = UDR0;
return c;
}

void uart_string( const unsigned char *string )
{
while (*string != 0) { //zero terminated string
uart_putchar( *string++ );
}
}

//print hexadecimal nibble

void uart_hex_nibble( unsigned char c )
{
c &= 0x0F; //mask off low nibble and convert to hex
if ( c > 9 ) c += (‘A’ - ‘9’ - 1);
uart_putchar( c + ‘0’ ); //make ascii and output
}

//print hexadecimal character

void uart_hex( unsigned char c )
{
uart_hex_nibble( c >> 4 );
uart_hex_nibble( c );
}

int main (void)
{
char c;

init_uart();

// _delay_ms(1); //may be needed with some PCs for synchronize

uart_string(“Hello, world!\n”);

while (1) //echo characters until “escape” key hit
{
c=uart_getchar();
if(c==0x1B) break; //check for escape character
if( (c<’ ') || (c>0x7E) ) //check for control char or extended ascii
{
uart_string("\nunprintable character input, hex value = “);
uart_hex©;
uart_string (”\n");
}
else uart_putchar©;
}
uart_string(“Goodbye!\n”);
return 0;
}