I am trying to work out USART ISR's on the ATmega 328P. So far I have got the USART rx and tx working. I have come across a strange issue when it comes to the UART ISR's, though. The ISR seems to override the delays, causing the code in my main loop to run without a pause.
Consider the following code (which is complete and functioning for easy troubleshooting):
#include <avr/io.h>
#include <util/delay.h>
#include <avr/interrupt.h>
#define FOSC 16000000
#define BAUD 9600
#define BAUD_GEN_VAL (((FOSC/BAUD)/16)-1)
void uart_tx( unsigned char data );
unsigned char uart_rx( void );
void main(void)
{
sei(); //enable interrupts globally
UBRR0H = (BAUD_GEN_VAL>>8);
UBRR0L = BAUD_GEN_VAL; //set baud rate
UCSR0B |= (1<<TXEN0) | (1<<RXEN0); //enable transmitter and receiver
//UCSR0B |= (1<<TXCIE0); //Enable interrupt on TX (serial)
UCSR0C |= (1<<UCSZ00) | (1<<UCSZ01); //8 bit data
while (1)
{
uart_tx('A');
_delay_ms(2500);
}
}
ISR(__vector_USART_TXC)
{
//blink an led here or something similar
}
void uart_tx( unsigned char data )
{
while ( !( UCSR0A & (1<<UDRE0)) ); //Wait for empty transmit buffer
UDR0 = data; //Put data into buffer, sends the data
}
This code works perfectly, printing "A" to a serial monitor every 2.5 seconds. However, if I un-comment the line UCSR0B |= (1<<TXCIE0);
— which enables the interrupt on transmission completion — the microcontroller spews "A"s out so fast that the serial monitor can't even keep up.
I can't understand how this is happening, however. It is as if the ISR did nothing but override the delay! Can anyone shed light on this?
USART_RX_vect
andUSART_TX_vect
if you enable the interrupt but don't provide the appropriate ISR, the AVR makes a reset \$\endgroup\$