Two ATmega's serial communication problem

Hi,

I have a 3pi robot and ATmega 1284P and I would like to make a serial connection between them. In order to do so, I connected: VCC → VCC, GND → GND, PD0 → PD1, PD1 → PD0 of 3pi and 1284P respectively. However, serial link doesn’t work. I used a very simple code to check functionality:

// Code for ATmega 1284P
// Sends letter 'a' every second

int main()
{
	char text[] = "a";
	serial_set_baud_rate(UART0, 9600);
	while (1) {
		serial_send_blocking(UART0, text, 1);
		delay_ms(1000);
	}
	return 0;
}

// Code for 3pi (ATmega328P)
// Uses polling to receive data form ATmega1284P. Prints out number of bytes
// caught and ASCII code of the character.

char receive_buffer[100];
int receive_buffer_position = 0;

void init_serial() {
	serial_set_baud_rate(9600);
	serial_set_mode(SERIAL_CHECK);
	serial_receive_ring(receive_buffer, 100);
}

char serial_read_byte() {
	char result;
	
	while (serial_get_received_bytes() == receive_buffer_position) {
		serial_check();
	}
	
	result = receive_buffer[receive_buffer_position];
	receive_buffer_position++;
	if (receive_buffer_position >= 100)
		receive_buffer_position = 0;
	
	return result;
}

int main()
{	
	unsigned short number = 0;
	
	init_serial();
	while (1) {
		char byte = serial_read_byte();
		number++;
		clear();
		print_long(number);
		lcd_goto_xy(4, 0);
		print_long(byte);
	}
	return 0;
}

The expected result would be an increasing number every second together with 97 (ASCII for ‘a’). Unfortunately, all I get is a number incresing by 3 (!) every 20 seconds (!!) with a 0 ASCII code (!!!).

I spent several hours to debug it, but without success. However, I found out that when I use delay_ms() on ATmega1284P it actually takes x20 more time. I replaced it with _delay_ms() like this:

#define F_CPU 20000000UL  // 20 MHz
#include <util/delay.h>

int main()
{
	char text[] = "a";
	serial_set_baud_rate(UART0, 9600);
	while (1) {
		serial_send_blocking(UART0, text, 1);
		_delay_ms(1000);
	}
	return 0;
}

And got exactly the same result. Only changing F_CPU to 1000000 (20x slower) gave me correct timing. However, serial still doesn’t work.

Here is what I tried already:

  • using interrupt versions of USART receiver functions
  • different baud rates (19200, 115200)
  • checked my soldering

I would appreciate help!

Hello.

As it seems like you’ve already discovered, it looks like your ATmega1284 is running at 1 MHz (these are the default fuse settings for an AVR: run off the internal 8 MHz oscillator and divide the clock frequency by 8). If your program is assuming 20 MHz operation, the behavior you describe makes sense:

What is the behavior when you change FCPU to 1000000? What happens if you change the baud rate to 1200?

- Ben

Thanks for a fast answer. I looked up how clock is configured in ATmega1284P and ATmega328P (3pi) and prescaled both to 8 MHz. In case of 3pi changing fuse bits was needed. Now everything works fine. Thanks!