0
votes

I try to transmit data from my Atmega168A-PU to my computer using the USART. To do so I have written the following code:

#include <avr/io.h>
#include <stdlib.h>

#define F_CPU 8000000UL
#define USART_BAUD 9600
#define UBRR_VALUE (F_CPU/16/USART_BAUD - 1)

void
usart_init(void)
{
    UBRR0H = (unsigned char)(UBRR_VALUE >> 8);
    UBRR0L = (unsigned char)UBRR_VALUE;
    UCSR0B = _BV(TXEN0) | _BV(UDRIE0);
    UCSR0C = _BV(USBS0) | _BV(UCSZ00) | _BV(UCSZ01);
    //UCSR0C = _BV(UCSZ00) | _BV(UCSZ01);
}


ISR(USART0_UDRE_vect)
{
    UDR0 = '0';
    UCSR0A |= _BV(TXC0);
}

int main(void)
{
    usart_init();
    while(!(UCSR0A & _BV(UDRE0)));
    UDR0 = '0';
    while(1);
    return 0;
}

I have attached the Arduino USB2SERIAL converter to read the values on my computer, however the converter says that he does not receive data and my computer does not receive data either.

Note: My lfuse is 0xe2 (CLKDIV8 disabled), so I have 8MHz F_CPU.
Note: I tried without the UCSR0A |= _BV(TXC0);, too.
Note: I have a capacitor between AVcc and AGnd.
Note: Fuses: (E:F9, H:DF, L:E2)

1
Maybe you are going to miss that one byte sent in the main. The UDRE ISR should be firing as fast as it can send that byte, but it the global ISR flag have to be actually enabled. - KIIV

1 Answers

0
votes

Well the problem was pretty easy. I forgot the sei(); as @KIIV pointed out (also u/odokemono pointed that out). Thanks.

Also it is better to use the USART_TX_vect instead of USART0_UDRE_vect because my receiver is disabled. Here is the corrected code:

#include <avr/io.h>
#include <stdlib.h>
#include <avr/interrupt.h>

#define F_CPU 8000000UL
#define USART_BAUD 9600
#define UBRR_VALUE (F_CPU/16/USART_BAUD - 1)

void
usart_init(void)
{
    UBRR0H = (unsigned char)(UBRR_VALUE >> 8);
    UBRR0L = (unsigned char)UBRR_VALUE;
    UCSR0B = _BV(TXEN0) | _BV(TXCIE0);
    UCSR0C = _BV(UCSZ00) | _BV(UCSZ01);
    //UCSR0C = _BV(UCSZ00) | _BV(UCSZ01);
    sei();
}


ISR(USART_TX_vect)
{
    UDR0 = '0';
    UCSR0A |= _BV(TXC0);
}

int main(void)
{
    usart_init();
    while(!(UCSR0A & _BV(UDRE0)));
    UDR0 = '0';
    while(1);
    return 0;
}

By the way: I disabled the second stop bit as u/odokemono pointed out because my USB2SERIAL seems to work better without the second stop bit.