I want to make a interrupt driven uart program, to send large amounts of data at high speeds with the absolute minimal amount of cpu overhead. I combined existing code and reading of the datasheet to make this code. It compiles without errors or warnings in Atmel Studio 7 on an atmega328p (Atmega328p Xplained Mini).
The problem that I'm having is that data is erratic, sometimes it sends 'ello!' sometimes nothing for a while. The 'H' is often skipped, I don't understand this since the ISR shouldn't execute before the 'H' has been copied from UDR0 to be sent.
Any help would be greatly appreciated!
Greetings,
Bert.
#define F_CPU 16000000
#include <avr/io.h>
#include <avr/interrupt.h>
#include <util/delay.h>
#include <string.h>
volatile uint8_t transmit_index = 0;
volatile char str[] = "Hello!\n";
volatile uint8_t len = 6;
int main(void){
UCSR0A = 0b00000010;
UCSR0B = 0b00111000;
UCSR0C = 0b00000110;
//9600 baud
UBRR0L = 207;
UBRR0H = 0;
DDRD |= 0x02;
sei();
//Flash led
DDRB |= 0b00100000;
PORTB |= 0b00100000;
_delay_ms(1000);
PORTB &= ~0b00100000;
_delay_ms(1000);
while (1){
transmit_index = 1;
//Enable udre interrupt
UCSR0B |= 0b00100000; //enable interrupt
//Send first byte in main()
while (!(UCSR0A & 0b00100000)) {} //Wait for register empty
UDR0 = str[0]; //send first byte
_delay_ms(1000);
}
}
ISR(USART_UDRE_vect) {
//Buffer empty, ready for new data
if (transmit_index < (len + 1)) {
UDR0 = str[transmit_index];
transmit_index++;
} else {
UCSR0B &= ~0b00100000; //disable interrupt
}
}