2
votes

I have an atmega162 chip on stk500 dev board connected to ubuntu with serial cable. On atmega, I initialize usart and write some bytes. On Ubuntu side, something comes out of the pipe, but it's definitely not what was sent...

To be more precise: For each byte sent, I get a series of about 6 or 7 bytes, each of them with either 0x00 or 0xC0 values.

Relevant snippets of my code:

compile flags:

CFLAGS = -g
CFLAGS += -mmcu=atmega162
CFLAGS += -W -Wall -Wshadow
CFLAGS += -Os
CFLAGS += -mcall-prologues
CFLAGS += -finline-limit=10
CFLAGS += -mno-interrupts
CFLAGS += -ffunction-sections
CFLAGS += -DF_CPU=7372800ULL

usart functions:

void Serial0Init(int baud)
{
        unsigned int    ubrr;

        ubrr = ((F_CPU+8*baud)/(16*baud))-1;
        // Baud rate
        UBRR0H = (unsigned char)(ubrr>>8);
        UBRR0L = (unsigned char)ubrr;
        UCSR0A &= ~(1 << U2X0); // U2X off
        // Transmission settings
        UCSR0C = (1<<URSEL0)|(3<<UCSZ00);       // 8N1
        UCSR0B = (1<<RXEN0)|(1<<TXEN0);
}

unsigned char Serial0CheckTxReady()
{
        return (UCSR0A&_BV(UDRE0));     // nonzero if transmit register is ready to receive new data.
}

void Serial0Write(unsigned char data)
{
        while (Serial0CheckTxReady()==0)        // while NOT ready to transmit
                {}
        UDR0 = data;
}

main code:

Serial0Init(9600);
Serial0Write('!');

I receive data with simple python script:

import serial
import os

port = serial.Serial('/dev/ttyS0', 9600)

print 'Reading from serial...'
while True:
  c = port.read()
  print c, ord(c)

I double checked byte size settings and baud rate calculations, and everything seems okay... Any ideas what I'm doing wrong?

1
This issue definitely looks like a baud rate problem. Are you sure that your MCU is running at 7.372 MHz? I suggest to check the fuse setting of the clock source. If the external oscillator is selected as the clock source you should check its settings too (e.g. the STK500 clock generator frequency). Also check the Atmega161 compatibility fuse. As long as you are compiling for Atmega162 the compatibility mode should be disabled to prevent possible side-effects. - Pavel Zhuravlev
Also check the expression used to calculate ubrr. With sizeof(int)==2 its calculation may result in overflow and thus incorrect result. I suggest to hard-code the UBRR0 value for test purposes. - Pavel Zhuravlev
Okay, your hints were very helpful. I found the problem. It was indeed baud rate calculation. Fixed formula looks like this: ubrr = ((F_CPU+8*(long int)baud)/(16*(long int)baud))-1; - Bob
In other words - the only problem was hidden conversion to 16-bit int, which ruined the result. - Bob

1 Answers

1
votes

As far as I can tell (and was already suspected in the comments), the baud rate calculation is wrong.
Try

UBRR = ((fOSC / (16 * BAUD)) - 1

what results in

UBRR = 47

for 9600 @ 7372800MHz.