​Hi,
​I'm having a problem with the USART_RX_vect interrupt of the ATMega 328p. The receiving works fine and I'm able to evaluate the sent bits (so it's not due to the baudrate) but everytime I send a bit, the ISR gets executed 4 times.​
So a ISR like this:
ISR(USART_RX_vect) {
uart_transmit('t');
uart_flush();
}
Will transmit {'t', 't', 't', 't'}
​
I have no clue why this is happening, and I hope you can help me.
My main
is a empty loop (of course I execute uart_setup
). My ISR is like above. I'm using avr-gcc on linux.
This is my UART Setup:
void uart_setup() {
UBRR0H = (BAUDRATE >> 8);
UBRR0L = BAUDRATE;
// Set 8-Bit mode
setBit(UCSR0C, UCSZ01);
setBit(UCSR0C, UCSZ00);
setBit(UCSR0B, RXEN0); // Receiver enable
setBit(UCSR0B, TXEN0); // Transmitter enable
setBit(UCSR0B, RXCIE0); // Enable RX Interrupt
sei(); // Enable global interrupts
}
void uart_transmit(unsigned char data)
{
while (!( UCSR0A & (1<<UDRE0))); // wait while register is free
UDR0 = data; // load data in the register
}
void uart_flush( void ) {
unsigned char dummy;
while ( UCSR0A & (1<<RXC0) ) dummy = UDR0;
}
Best Answer
It appears that the design of your code is such that when a byte is received in the UART, you wish to dispose of that byte and respond by transmitting a "t".
The UART shares a common receive/transmit buffer register. Since your UART receive routine is interrupt driven, you should immediately read the received character before putting the response in the buffer otherwise you will retrigger the receive interrupt when you exit.
There is also no reason to have the 'while' code in the uart_flush routine since you know there is a character in the buffer based on the fact that an interrupt brought you to this point. Just read the buffer register.
Here is a simplified version of a corrected ISR without the functions: