Hello guys, I am currently working on a project which requires serial communication between an Arduino Nano (ATmega328P) and my computer. Due to data transmission speed issues, I thought of performing the communication through the registers of the microcontroller. So far, I developed the following code:
unsigned char rx;
unsigned char receive() {
while (!(UCSR0A & (1 << RXC0))) {
return UDR0;
}
}
void transmit(unsigned char c) {
while (!(UCSR0A & (1 << UDRE0))) {
UDR0 = c;
}
}
int main(void) {
cli();
//---------------------------------------------------------------------------------------------
// Enable USART Receiver and Transmitter
// Set 8-bit Character Size
UCSR0B |= (1 << RXEN0) | (1 << TXEN0);
UCSR0B &= ~(1 << UCSZ02);
//---------------------------------------------------------------------------------------------
// Set USART Asynchronous Mode
// Set 8-bit Character Size
UCSR0C &= ~(1 << UMSEL01) & ~(1 << UMSEL00);
UCSR0C |= (1 << UCSZ01) | (1 << UCSZ00);
//---------------------------------------------------------------------------------------------
// Set USART Baud Rate Register to 25 to set 38400 bps Baud Rate
UBRR0 = 25;
//---------------------------------------------------------------------------------------------
sei();
//---------------------------------------------------------------------------------------------
while (1) {
if (UCSR0A & (1 << RXC0)) {
rx = receive();
}
transmit(rx);
}
}
During the code developing, I looked at the microcontroller datasheet and found that above 9600 baud, the rate with the lowest error rate was 38400 baud, because the application where the communication will be set up, a 9600 baud rate is slow. However, I have no output on the serial monitor configured at 38400 baud when sending a character.
There are no 'transmission speed issues' ... Most microcontrollers easily deal with serial ---> USB ---> PC at 115200 BAUD (or faster) assuming you are using a quality USB cable.
1. It could be that OP is doing an exercise and now he may study/practice the following Register Level codes (along with non-working codes of post #1) to exchange data between Serial Monitor and UART port of the ATmega328P MCU of the UNO Board on polling strategy.
void setup()
{
UCSR0A = 0x00; //reset; Bd factor is not doubled,
UCSR0B |= (1 << RXEN0) | (1 << TXEN0); //Serial transmitter/receiver are enabled
UCSR0C |= bit(UCSZ01)|bit(UCSZ00); //8-bit charcater size, 1-StopBit
UBRR0 = 25; //Bd = 38400
}
void loop()
{
while (bitRead(UCSR0A, RXC0) != HIGH)//check if RXC0flag HIGH indicating data ready
{
; //wait until a chacter has arrived from Serial Monitor
}
char ch = UDR0; //read the arrived data from Recievr, TXC0 flag is cleared
while(bitRead(UCSR0A, UDRE0) != HIGH)//check if transmit buffer is empty
{
; //
}
UDR0 = ch; //send the charcater back to OutputBox of Serial Monitor.
}
2. Interrupt Strategy
It is left as an exercise for OP.