Help with custom UART initialization

Hello,

I am trying to write my own UART initialize function without using Serial.begin(), and I don’t think the baud rate is setting correctly.

This is the code that I have:

#include <avr/io.h>
#include <arduino/Arduino.h>

#define FOSC 8000000UL
#define BAUD 115200UL
#define MYUBRR FOSC/16/BAUD-1

void UART_init(uint16_t ubrr)
{
	UBRR0H = (uint8_t) (ubrr >> 8);	// set baud rate registers
	UBRR0L = (uint8_t) (ubrr);
	
	UCSR0B = (1 << RXEN0) | (1 << TXEN0);	// enable RX(bit 4) and TX(bit 3)
	
	UCSR0C = (1 << UCSZ00) | (1 << UCSZ01);	// 8 data bits, 1 stop bit
	
}

void print_char(char c)
{
	while( !( UCSR0A  & (1 << UDRE0) ) );
	
	UDR0 = c;
	
}

int main(void)
{
	startup();
	
    while (1) 
    {
		PORTC |= B00010000;	// DEBUG led on

		print_char('0');
		
		PORTC &= B11101111;	// DEBUG led off
    }
}

I think the division of the clock and baud rate are what is messing it up, but I need 115200 baud. How can I achieve this?

I should also note that this code is going to be placed in a bootloader so it has to compile to be under 1024 bytes

Have you looked at how the baud rate is set in the code for Serial.begin() ?

...R

I have and it has been of no help

	UBRR0H = (uint8_t) (ubrr >> 8);	// set baud rate registers
	UBRR0L = (uint8_t) (ubrr);

...splitting the assigment is pointless. The compiler is capable of doing the right thing...

	UBRR0 = ubrr;

I did this and it still doesn't work lol. I still get jibberish spitting out of the serial port

aalvarado028:
I still get jibberish spitting out of the serial port

Probably a result of the previous program you uploaded. The code you presented does not compile so you obviously are not using that.

What board are ypu using that makes FOSC 8MHz and not 16?

DKWatson:
What board are ypu using that makes FOSC 8MHz and not 16?

I am using the Atmega328p as a standalone microcontroller

Well then change the frequency to 16000000UL.

Sorry, are you using the internal oscillator?

The USART is driven by its own internal clock dividers. With the wide range of frequencies available for the processor clock, you can imagine that some will divide more evenly than others. Unfortunately, for your first kick at this particular cat, you chose poorly. 115,200 and 230,400 are perhaps the two worst freqs in terms of error (followed by 57,600) for a 16MHz clock. They'd be perfect if your clock was 14.7456MHz or 18.432MHz, but such is not the case.

Your best all-round choice at any freq is 38,400. At 16MHz, 76,800 is also good. Surprisingly, the best performer at what we would consider to be conventional freqs (8, 16 and 20MHz) is 250,000. Bear in mind that when the speed increases, the margin for error narrows. If the on-board oscillator is not functioning within spec you can throw all your calculations out the window.

All is not necessarily lost though. Auto baud detecting functions actually time the incoming signals and adjust themselves accordingly. When you do your UBRR calculation, you are in fact creating an output compare register value for the USART timer/counter. The calculation for 38,400 works out to be 51 (which is actually 52 when you count from zero) which you'll note is simply the period, in microseconds. Without doing the UBRR calculation, you can assign values directly to UBRR0 (49, 50, 51, 52, ...) thereby tweaking the baud rate until you find a match. Better though, that you stick to the low error rates if your design allows for it.

aalvarado028:
I have and it has been of no help

That does not provide much useful information from which to help YOU.

...R

DKWatson:
Well then change the frequency to 16000000UL.

I use all my breadboard Atmega328s with the internal 8MHz oscillator and I have never had a problem.

...R

It does not appear to be a problem with the clock speed, it is a problem with the BAUD rate. I downloaded OP's code, made the obligatory changes to correct the syntax and got the same garbage (s)he complained of. Changing away from 115K (and 230) got rid of the problem.

The Atmega 328 is not good at dealing with 115200 and 230400 baud. And, yes, according to the datasheet it is worse at 8Mhz.

…R

DKWatson:
It does not appear to be a problem with the clock speed, it is a problem with the BAUD rate. I downloaded OP's code, made the obligatory changes to correct the syntax and got the same garbage (s)he complained of. Changing away from 115K (and 230) got rid of the problem.

What baud rate did you use and what was the corresponding UBRR value? Did you change any of the UCSR0A/B/C registers from what I originally had?

BAUD rate, frequency only. As for what I changed them to… Really?

My 8MHz and 16MHz Arduinos work very nicely with 500,000 baud.

...R