Interrupt from the USART
Before to speak about the interrupts implementation of the USART, I want to say a little bit regarding the “Interrupts” and then it will follow by a description of the usage of the USART interrupts if one of the following conditions happen:
A little bit about interrupt
A microcontroller normally executes instructions sequentially as designed by a user application. However the microcontroller communicates with several external (sensor) and internal (USART, timer) devices. These devices could send events to the microcontrollers those have higher priority than the current instruction sequence. The microcontroller, generally, has the possibility to handle these unscheduled events by the so called: interrupt system.
These events may be planned, but the time when they will occur isn't know. When an interrupt event occurs, the microcontroller will normally complete the instruction that it is currently executing then it will jump to a specific routine connected to the event occurred.
These routines are called interrupt service routine (ISR). Each interrupt will normally have its own interrupt specific ISR. As soon as the ISR is complete, the microcontroller will resume to the next instruction of the interrupted instructions sequence.
When an interrupt occurs, the AVR microcontroller completes the current instruction, stores the address of the next instruction on the stack, and jumps to the instruction of the designated ISR (corresponding to the particular interrupt source). It also turns off the interrupt system to prevent further interrupts while one is in progress.
The execution of the ISR is performed by loading the beginning address of the ISR specific for that interrupt into the program counter. The execution of the ISR continues until the the instruction “return from interrupt” (reti) is executed. Program control then reverts back to the main program with interrupts enabled.
UART receive complete interrupt
When a character arrives to the USART, if the receiver is enabled RXEN0 = 1, interface from the outside world, the Receive complete flag (RXC0) is set and it indicates that there are unread data in the receive buffer. If the receive complete interrupt is enabled, by setting the RXCIE0 bit, the Atmega will execute the USART Receive Complete interrupt service routine until the RXC0 Flag is set (if global interrupts are enabled).
When interrupt-driven data reception is used, the receive complete routine must read the received data from UDR0 in order to clear the RXC0 Flag, otherwise a new interrupt will occur once the interrupt routine terminates.
In this case, during the execution of the ISR, we can read the data and put it into a data buffer, so to remove the interrupt and to gives, to an application, the possibility to take the data in future (the application doesn't need to take the data when the data has arrived and it can continue its actual job).
If it's necessary to take into account the receiver error, we need to read the three UCSR0A register before we have read the UDR0 register. In this case we can consider the three error flags the: Frame Error (FE0), Data OverRun (DOR0) and Parity Error (UPE0) and analyze them for incorrect operations.
/** global error
unsigned char gucRxError;
unsigned char ucData;
unsigned char ucReadChar;
unsigned char ucRxError;
/* read UART status register and then read the UART data register
ucReadChar = UCSR0A;
ucData = UDR0;
/* the error needs to be read before the UDR
else we lost its value !!!! we saved them in the ucReadChar
ucRxError = (ucReadChar & (_BV(FE0)|_BV(DOR0) | _BV(UPE0)) );
* Put the data into the buffer if it isn't full
* else set our Buffer overflow error
/* set the global error variable
gucRxError = ucRxError;
(to be continued…)