Kaguei Nakueka
Kaguei Nakueka

Reputation: 1128

USART with ATMEGA168A -

I am trying to make a very simple USART program which send the received character back to the transmitter and represent the equivalent binary number by flashing 8 leds in my breadboard.

Here is the code:

#define F_CPU 1000000UL                    // set the CPU clock
#define BAUD 9600                           // define baud
#define BAUDRATE ((F_CPU)/(BAUD*16UL)-1)    // set baudrate value for UBRR

#include <avr/io.h>
#include <util/delay.h>
#include <stdlib.h>
#include <inttypes.h>
#include "led.h"

// function to initialize UART
void uart_init (void)
{
    UBRRH=(BAUDRATE>>8);
    UBRRL=BAUDRATE;                         //set baud rate
    UCSRB|=(1<<TXEN)|(1<<RXEN);             //enable receiver and transmitter
    UCSRC|=(1<<URSEL)|(1<<UCSZ0)|(1<<UCSZ1);// 8bit data format
}

// function to send data
void uart_transmit (unsigned char data)
{
    while (!( UCSRA & (1<<UDRE)));            // wait while register is free
    UDR = data;                             // load data in the register
}

// function to receive data
unsigned char uart_receive (void)
{
    while(!(UCSRA) & (1<<RXC));           // wait while data is being received
    return UDR;                             // return 8-bit data
}

// main function: entry point of program
int main (void)
{
    unsigned char a = 0;
    char buffer[10] = 0;
    DDRB = 0xFF;

    uart_init();                            // initialize UART

    while(1)
    {
        a=uart_receive();                   // save the received data in a variable
        uart_transmit(a);                   // send it back
        blink(a - 0);                       // print in the led
        _delay_ms(100);                     // wait before next attempt
    }

    return 0;
}

The problem I am facing is that none of the registers related to the USART seem to be recognized by the compiler. See an example of the compilation error I am getting:

'UBRRH' undeclared (first use in this function)

Am I missing an include here?

Screeshot

Upvotes: 2

Views: 1630

Answers (1)

Gabriel Ilharco
Gabriel Ilharco

Reputation: 1679

It seems that code you have is not for ATMEGA168, the errors you are getting are due to some registers that doesnt exist in ATMEGA168. In ATMEGA168, there is more than one UART, so the register names are numbered. You can use UBRR0H instead of UBRRH, for example.

Try this:

#ifdef UDR0
#define UBRRH UBRR0H
#define UBRRL UBRR0L
#define UDR UDR0

#define UCSRA UCSR0A
#define UDRE UDRE0
#define RXC RXC0

#define UCSRB UCSR0B
#define RXEN RXEN0
#define TXEN TXEN0
#define RXCIE RXCIE0

#define UCSRC UCSR0C
#define URSEL 
#define UCSZ0 UCSZ00
#define UCSZ1 UCSZ01
#define UCSRC_SELECT 0
#else
#define UCSRC_SELECT (1 << URSEL)
#endif

#define BAUD 9600UL
#define UBRRVAL (F_CPU/(BAUD*16)-1)
#define USE_SLEEP 1

void uart_init() {
    /* set baud rate */
    UBRRH = UBRRVAL >> 8;
    UBRRL = UBRRVAL & 0xff;
    /* set frame format: 8 bit, no parity, 1 bit */
    UCSRC = UCSRC_SELECT | (1 << UCSZ1) | (1 << UCSZ0);
    /* enable serial receiver and transmitter */
    #if !USE_SLEEP
        UCSRB = (1 << RXEN) | (1 << TXEN);
    #else
        UCSRB = (1 << RXEN) | (1 << TXEN) | (1 << RXCIE);
    #endif
}

void uart_putc(uint8_t c) {
    if(c == '\n')
        uart_putc('\r');

    /* wait until transmit buffer is empty */
    while(!(UCSRA & (1 << UDRE)));

    /* send next byte */
    UDR = c;
}

uint8_t uart_getc()
{
    /* wait until receive buffer is full */
    #if USE_SLEEP
        uint8_t sreg = SREG;
        sei();

        while(!(UCSRA & (1 << RXC)))
            sleep_mode();

        SREG = sreg;
    #else
        while(!(UCSRA & (1 << RXC)));
    #endif

    uint8_t b = UDR;
    if(b == '\r')
        b = '\n';

    return b;
}

int main(){
    DDRB   = 0xff;

    uint8_t data = 0;
    uart_init();

    while(1){
      data = uart_getc();
      uart_putc(data);
      blink(a - 0);
      _delay_ms(100);
    }

    return 0;
}

Upvotes: 3

Related Questions