# USART ISR on TXC breaking delays from <util/delay.h>?

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?

• I can just guess that the AVR makes resets, can you add toggling a PORT pin before entering main? – Andy Jan 30 at 14:49
• Btw, how have you defined __vector_USART_TXC ? – Andy Jan 30 at 14:52
• With a recent avr-libc, the ISRs should be USART_RX_vect and USART_TX_vect if you enable the interrupt but don't provide the appropriate ISR, the AVR makes a reset – Andy Jan 30 at 14:56
• @Andy I tried your first suggestion, and I didn't notice any glow on the LED, but it may be too fast to even produce a faded glow. On your second comment: I didn't define __vector_USART_TXC. I'll definitely try that.. – hat Jan 30 at 14:59
• How do you clear the TXC flag? Is it done automatically by the AVR itself? – Rohat Kılıç Jan 30 at 15:00