I have a small project for school that requires me to load data in the EEPROM of an ATmega328P through the USART serial communication. I'm going to figure out the EEPROM read/write myself.
I have problems sending data using interrupts. Basically, I want to have the Arduino Nano loop through code and when I send something through the USART serial communication using the serial monitor of the Arduino IDE, an interruption will occur and the data that was send will be saved in a variable.
My clock is 16 MHz, with a baud rate of 9600; and as I've said I'm using the Arduino IDE.
Here is what I've tried so far:
#define USART_BAUDRATE 9600
#define MYUBRR (((F_CPU / (USART_BAUDRATE * 16UL))) - 1)
void setup() {
UCSR0B = (1 << RXEN0) | (1 << TXEN0); // Turn on the transmission and reception circuitry
UCSR0C = (1 << UCSZ00) | (1 << UCSZ01); // Use 8-bit character sizes
UBRR0H = (MYUBRR >> 8); // Load upper 8-bits of the baud rate value into the high byte of the UBRR register
UBRR0L = MYUBRR; // Load lower 8-bits of the baud rate value into the low byte of the UBRR register
UCSR0B |= (1 << RXCIE0); // Enable the USART Receive Complete interrupt (USART_RXC)
sei(); // Enable the Global Interrupt Enable flag so that interrupts can be processed
}
// Interrupt on receive
ISR (USART_RXC_vect)
{
char ReceivedByte;
ReceivedByte = UDR0; // Fetch the received byte value into the variable "ByteReceived"
UDR0 = ReceivedByte; // Echo back the received byte back to the computer
}
// Use the eeprom() function to read/write to EEPROM
void loop() {
}
I've copied and adapted the code from this site (first post).
(In the UCSR0C register, there is no URSEL bit that is mentioned in this post - the datasheet does not mention it and it gives me an error when I try to use it.)
But it seems that the interruption (as it is presented in the last part of the post) is not working for me. I've tested to see if I can read and write in the serial monitor using the following code:
while ((UCSRA & (1 << RXC)) == 0) {}; // Do nothing until data have been received and is ready to be read from UDR
ReceivedByte = UDR; // Fetch the received byte value into the variable "ByteReceived"
while ((UCSRA & (1 << UDRE)) == 0) {}; // Do nothing until UDR is ready for more data to be written to it
UDR = ReceivedByte; // Echo back the received byte back to the computer
But this makes the controller wait for a data to be sent through the serial monitor, and then it prints it in the serial monitor. I do not want this behaviour.
Here is the datasheet that I've used to check my code: ATmega328P datasheet
Did I do something wrong? Did I forget something in my implementation of USART serial communication interrupt? What is actually wrong with my implementation? why is it not working?
I think you're going wrong here:
In the above code you're basically saying UDR0 = UDR0. You need to give some time between these two lines of code in order to obtain the desired effect. If you take a look at the AVR freaks link you posted, they have this line in between: