Electronic – UART on the atmega328. Dataregister on the USART (UCSR0A) status never set on

avruart

I'm experiencing a little troubleshooting trying to send and receiving data into the UART of my atmega. I don't know if it's because the clock cycle is misconfigured or if I made wrong assumption of what the code should be, but I took it from an example book.

I'm expecting to write data into the usart then simply read it back.
I 'm just trying to output a LED for the moment, but it never glows, so that i'm assuming my code never goes out of usartReadChar().

I'm working with an atmega328p and the pin / register macro are from iom328p. The clock speed is configured at 1Mh.

The only difference from the book is that he uses an atmega168.

What I don't understand is that I'm not blocked for sending data to the usart (the Usart Data Register Empty (UDRE0) is actually always empty). But
the receive complete bit (RCX0) into the statut register (UCSR0A) is never set either.
As if the status bit are never working at all.

I have tried to change the CPU clock speed without any luck.
By the way i'm not sure how to compute the baudRate of my usart and I'm not sure if it has really an impact on my code, since I'm only sending data from the AVR locally. So does I need to synchronize it with my CPU?

I tried lot of variant of usartInit() setup, but they never work.

here is my code:

#include <avr/io.h>
#include <util/delay.h>


  void initUSART(void) {

  UBRR0H = UBRRH_VALUE;                        /* defined in setbaud.h */
  UBRR0L = UBRRL_VALUE;
#if USE_2X
  UCSR0A |= (1 << U2X0);
#else
  UCSR0A &= ~(1 << U2X0);
#endif
                                  /* Enable USART transmitter/receiver */
  UCSR0B = (1 << TXEN0) | (1 << RXEN0);
  UCSR0C = (1 << UCSZ01) | (1 << UCSZ00);   /* 8 data bits, 1 stop bit */
}

char usartReadChar(){
    while(! (UCSR0A & (1 << RXC0))){}

    return UDR0;
}

void usartWriteChar(char data){
    while(! (UCSR0A & (1 << UDRE0))){}

    UDR0 = data;
}

int main(){
    DDRB   = 0xff;

    char data;
    initUSART();
    usartWriteChar('a');

    while(1){
      data = usartReadChar();
// actually, never reach

      PORTB  = (1 << 0);
    }

    return 0;
}

When I compile it with a Baud rate of 9600, I don't get any warning error about baud rate.
But if I choose wrong Baud, of course I've got this kind of warning.

/avr/include/util/setbaud.h:227:4: warning: #warning "Baud rate
achieved is lower than allowed" [-Wcpp] # warning "Baud rate
achieved is lower than allowed"

So i'm assuming my baud rate is correct. What could be wrong then?
Your help will be greatly appreciated. Thanks.

* edit *

I gave up trying to output something localy into my avr. So in order to debug i have connected my FT232R chip to the rx and tx pin of my atmega, to see if something could output from the UCSR0A status register, and it worked.

What is strange is that actually the debug function to send data into the transmiter register was not working at all, even if the UCSR0A say it is busy to transmit data.

According to the book, the data sended from the arduino program must work, but it was totally not working with me. But from my FT232 the program is nicely working, as if the USART was not actually initialized when i called the instruction to send data to the us art. But since it is all synchrone I know this is not that.

I found lot of topics about configuring USART on avr, but no one tells to test a debug program like in my book. So i'm wondering if it is actually an atmega168 specific feature. Actually i don't understand why this is not woking like the book tells.

Best Answer

I don't see where you put the correct F_CPU definition, which is mandatory for setbaud.h.

You also have to define the BAUD macro to use UBRR(L|H)_VALUE, like this:

#define F_CPU 1e6       // 1Mhz clock
#include <avr/io.h>
#include <util/delay.h>

void initUSART(void) {
 #define BAUD 9600
 #include <util/setbaud.h> 
 UBRR0H = UBRRH_VALUE;
 UBRR0L = UBRRL_VALUE;
// ...
}

You can also calculate the UBRRnx values with this site. The values depend on your clock speed and the prescaler setting. At the default configuration it is simply one, so it is not used.

And don't forget the pull-up resistors (about 10K ohm) at the TX/RX lines.

I hope this helps.