Search code examples
avruartatmega

How can a UART signal from a ATMEGA8535 be 200x slower than that from a Arduino with a ATMEGA328?


So I've been trying to get UART to work on a ATMEGA8535, but am encountering some issues. The setting is as follows: I need UART working when the ATMEGA is on a custom pcb. This wasn't working so went back to a bare breadboard with the ATMEGA hooked up to just GND and 5V. The TX pin is connected to a oscilloscope to monitor it's output. This is the code on the chip:

#define F_CPU 1000000UL //CPU frequency

#include <xc.h>
#include <avr/io.h>
#include <avr/interrupt.h>
#include <util/delay.h>

#define BAUD 19200 // baud
#define BRC ((F_CPU/16/BAUD) - 1)

int main(void) {
    
    /* Set baud rate */
    UBRRH = (BRC >> 8);
    UBRRL =  BRC;
    
    /* Enable receiver and transmitter */
    UCSRB = (1<<RXEN)|(1<<TXEN);
    /* Set frame format: 8data*/
    UCSRC = (1<<UCSZ1)|(1<<UCSZ0);
    
    while(1){
        UDR = 'b';
        
        _delay_ms(2000);
    }
}

Although the oscilloscope show the correct signal is sent, it is way to slow: the entire signal takes well over 200ms. For comparison, for a Arduino set to the same baud-rate it takes a little under 1ms. I checked whether the chip was faulty, but five different ATMEGA8535's give the same output. When looking through the datasheet, I don't see anything that could cause this large of a error in clock generation. Any thoughts on the origins and solution to this problem?


Solution

  • You don't have correct setup UCSRC register. For this MCU type this register has same address as UBRRH. If you want write to UCSRC register you must set eighth bit to one. So, your code save not UCSRC but UBRRH. That means UBRRH value is overwritten.

    Look at DS

    Bit 7 – URSEL: Register Select This bit selects between accessing the UCSRC or the UBRRH Register. It is read as one when reading UCSRC. The URSEL must be one when writing the UCSRC.

    datasheet

    Correct write to UCSRC is:

    /* Set frame format: 8data*/
    UCSRC = (1<<UCSZ1)|(1<<UCSZ0)|(1<<URSEL);
    

    It is disccused on page 163 How to write UCSRC