Electronic – arduino – Cannot connect Arduino Uno REV3 ATmega16u2 serial connection to outside serial connection

arduinoatmegaatmega32u4serialuart

I wanted to simply use the ATmega16u2 on my official Arduino Uno with a serial connection.

I connected my Serial Board (where I can simply connect any serial connection and read it on my PC via Putty) The Board to the Uno and the connection is reliable because it already worked with previous Projects written in the Arduino IDE.

RX -> RX and TX -> TX since the connection for the ATmega16u2 is reversed from the normal pinout as we see in https://content.arduino.cc/assets/UNO-TH_Rev3e_sch.pdf

I also saw that the pin 15/PB1 is free on the icsp and so I connected it to the Arduino pin 13 which is connected to the LED L to have some output.

Now here is my code:

/*
 * Simple_Test1.cpp
 *
 * Created: 20-May-20 17:35:10
 * Author : Paukler
 */ 

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

void init_USART(int);
void USART_Transmit( unsigned char data );
void USART_Transmit_wait( unsigned char data );
unsigned char USART_Receive( void );
unsigned char USART_Receive_wait( void );
bool USART_Receive_available( void );

int main(void)
{
    DDRB = 1<<1;//DDRC = 1<<7;
    init_USART(9600);
    PORTB &= (0xff-(1<<1));//PORTC &= (0xff-(1<<7));//led off
    while (1) 
    {
        if(USART_Receive_available()){
            unsigned char in = USART_Receive_wait();
            PORTB |= 1<<1;//PORTC |= 1<<7;//led on
            _delay_ms(1000*5);
            PORTB &= (0xff-(1<<1));//PORTC &= (0xff-(1<<7));//led off
            _delay_ms(1000*5);
            USART_Transmit_wait(in);
            PORTB |= 1<<1;//PORTC |= 1<<7;//led on
            _delay_ms(1000*5);
            PORTB &= (0xff-(1<<1));//PORTC &= (0xff-(1<<7));//led off
        }
        _delay_ms(1000);
    }
}

void init_USART(int baud){
    /* Set baud rate */
    UBRR1H = (unsigned char)(baud>>8);
    UBRR1L = (unsigned char)baud;
    /* Enable receiver and transmitter */
    UCSR1B = (1<<RXEN1)|(1<<TXEN1);
    /* Set frame format: 8data, 2stop bit */
    UCSR1C = (1<<USBS1)|(3<<UCSZ10);
}

void USART_Transmit_wait( unsigned char data )
{
    /* Wait for empty transmit buffer */
    while ( !( UCSR1A & (1<<UDRE1)) )
    ;
    /* Put data into buffer, sends the data */
    UDR1 = data;
}

bool USART_Transmit_available( void ){
    return (1<<UDRE1);
}

void USART_Transmit( unsigned char data )
{
    if ( ( UCSR1A & (1<<UDRE1)) ){
        /* Put data into buffer, sends the data */
        UDR1 = data;
    }
}

unsigned char USART_Receive_wait( void )
{
    /* Wait for data to be received */
    while ( !(UCSR1A & (1<<RXC1)) )
    ;
    /* Get and return received data from buffer */
    return UDR1;
}

bool USART_Receive_available( void ){
    return (1<<RXC1);
}

unsigned char USART_Receive( void )
{
        return UDR1;
}

When I send a '2' or '3', it seems to receive and send something as indicated by the LED, but that doesn't always work. I never however get any data on my serial PC connection.

I also tried playing around with the stop bits, the parity, the flow control, but nothing worked.

I have no idea what I am doing wrong. If somebody could help me, that would be awesome.

The exact same behavior on my Leonardo (where it's only one chip and no reversing etc.) with slightly modified code:

/*
 * Simple_Test1.cpp
 *
 * Created: 20-May-20 17:35:10
 * Author : Paukler
 */ 

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

void init_USART(int);
void USART_Transmit( unsigned char data );
void USART_Transmit_wait( unsigned char data );
unsigned char USART_Receive( void );
unsigned char USART_Receive_wait( void );
bool USART_Receive_available( void );

int main(void)
{
    DDRC = 1<<7;//DDRB = 1<<1;
    init_USART(9600);
    PORTC &= (0xff-(1<<7));//led off//PORTB &= (0xff-(1<<1));
    while (1) 
    {
        if(USART_Receive_available()){
            unsigned char in = USART_Receive_wait();
            PORTC |= 1<<7;//PORTB |= 1<<1;//led on
            _delay_ms(1000*5);
            PORTC &= (0xff-(1<<7));//PORTB &= (0xff-(1<<1))//led off
            _delay_ms(1000*5);
            USART_Transmit_wait(in);
            PORTC |= 1<<7;//PORTB |= 1<<1;//led on
            _delay_ms(1000*5);
            PORTC &= (0xff-(1<<7));//PORTB &= (0xff-(1<<1))//led off
        }
        /*PORTC |= 1<<7;//PORTB |= 1<<1;//led on
        _delay_ms(1000);
        PORTC &= (0xff-(1<<7));//led off//PORTB &= (0xff-(1<<1));
        _delay_ms(1000);*/
    }
}

void init_USART(int baud){
    /* Set baud rate */
    UBRR1H = (unsigned char)(baud>>8);
    UBRR1L = (unsigned char)baud;
    /* Enable receiver and transmitter */
    UCSR1B = (1<<RXEN1)|(1<<TXEN1);
    /* Set frame format: 8data, 2stop bit */
    UCSR1C = (1<<USBS1)|(3<<UCSZ10);
}

void USART_Transmit_wait( unsigned char data )
{
    /* Wait for empty transmit buffer */
    while ( !( UCSR1A & (1<<UDRE1)) )
    ;
    /* Put data into buffer, sends the data */
    UDR1 = data;
}

bool USART_Transmit_available( void ){
    return (1<<UDRE1);
}

void USART_Transmit( unsigned char data )
{
    if ( ( UCSR1A & (1<<UDRE1)) ){
        /* Put data into buffer, sends the data */
        UDR1 = data;
    }
}

unsigned char USART_Receive_wait( void )
{
    /* Wait for data to be received */
    while ( !(UCSR1A & (1<<RXC1)) )
    ;
    /* Get and return received data from buffer */
    return UDR1;
}

bool USART_Receive_available( void ){
    return (1<<RXC1);
}

unsigned char USART_Receive( void )
{
        return UDR1;
}

Is my code wrong or am I missing something? It's not urgent since this is just as a hobby, but I would appreciate any help.


@Justme was correct and here is my final code. It works now.

/*
 * Simple_Test1.cpp
 *
 * Created: 20-May-20 17:35:10
 * Author : Paukler
 */ 

#include <avr/io.h>

#ifndef F_CPU
#define F_CPU 16000000L
#endif

#include <util/delay.h>

#define BAUD 9600
#define UBRR_VAL ((( F_CPU / ( BAUD * 16UL))) - 1) // 103 for 16M=F_CPU and BAUD=9600

void init_USART(int);
void USART_Transmit( unsigned char data );
void USART_Transmit_wait( unsigned char data );
unsigned char USART_Receive( void );
unsigned char USART_Receive_wait( void );
bool USART_Receive_available( void );

int main(void)
{
    DDRC = 1<<7;//DDRB = 1<<1;
    init_USART(UBRR_VAL);
    PORTC &= (0xff-(1<<7));//led off//PORTB &= (0xff-(1<<1));
    while (1) 
    {
        if(USART_Receive_available()){
            unsigned char in = USART_Receive_wait();
            PORTC |= 1<<7;//PORTB |= 1<<1;//led on
            _delay_ms(1000);
            PORTC &= (0xff-(1<<7));//PORTB &= (0xff-(1<<1))//led off
            _delay_ms(1000);
            USART_Transmit_wait(in);
            PORTC |= 1<<7;//PORTB |= 1<<1;//led on
            _delay_ms(1000);
            PORTC &= (0xff-(1<<7));//PORTB &= (0xff-(1<<1))//led off
        }
        /*PORTC |= 1<<7;//PORTB |= 1<<1;//led on
        _delay_ms(1000);
        PORTC &= (0xff-(1<<7));//led off//PORTB &= (0xff-(1<<1));
        _delay_ms(1000);*/
    }
}

void init_USART(int baud){
    /* Set baud rate */
    UBRR1H = (unsigned char)(baud>>8);
    UBRR1L = (unsigned char)baud;
    /* Enable receiver and transmitter */
    UCSR1B = (1<<RXEN1)|(1<<TXEN1);
    /* Set frame format: 8data, 2stop bit */
    UCSR1C = (1<<USBS1)|(3<<UCSZ10);
}

void USART_Transmit_wait( unsigned char data )
{
    /* Wait for empty transmit buffer */
    while ( !( UCSR1A & (1<<UDRE1)) )
    ;
    /* Put data into buffer, sends the data */
    UDR1 = data;
}

bool USART_Transmit_available( void ){
    return (1<<UDRE1);
}

void USART_Transmit( unsigned char data )
{
    if ( ( UCSR1A & (1<<UDRE1)) ){
        /* Put data into buffer, sends the data */
        UDR1 = data;
    }
}

unsigned char USART_Receive_wait( void )
{
    /* Wait for data to be received */
    while ( !(UCSR1A & (1<<RXC1)) )
    ;
    /* Get and return received data from buffer */
    return UDR1;
}

bool USART_Receive_available( void ){
    return (1<<RXC1);
}

unsigned char USART_Receive( void )
{
        return UDR1;
}
```

Best Answer

The baud rate is incorrect.

Your code writes the baud rate value directly to the register, that is not how it works.

The AVR runs at some clock frequency, which must be divided by some divisor, to achieve the baud rate. It's the divisor that must be written to the register.