1
\$\begingroup\$

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;
}
```
\$\endgroup\$
8
  • \$\begingroup\$ Are you trying to connect TTL level (5 V) signals to an RS232 serial port on your PC without using an RS232 level converter? \$\endgroup\$ – Transistor May 21 '20 at 18:33
  • \$\begingroup\$ i am using an "Silicon Labs CP210x USB to UART Bridge" wich has built in TX and RX that should work right? \$\endgroup\$ – Paukler May 21 '20 at 18:36
  • \$\begingroup\$ I already had some connections to arduino where i send Chars to the arduino and change uppercase to lowercase and the other way around but that was written with the arduino ide. I wanted to start with the atmel studio though and now i can't even start a connection. \$\endgroup\$ – Paukler May 21 '20 at 18:38
  • \$\begingroup\$ I have no idea what a Silicon Labs CP210x USB to UART Bridge is. If it's relevant then it should be included in the question and hyperlinked to the datasheet. "I already had some connections" is rather vague. A schematic would be so much better. \$\endgroup\$ – Transistor May 21 '20 at 18:41
  • \$\begingroup\$ DEBO USB2UART 2 Entwicklerboards - USB Typ-A auf UART, CP210 Wiki \$\endgroup\$ – Paukler May 21 '20 at 18:42
1
\$\begingroup\$

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.

\$\endgroup\$
3
  • \$\begingroup\$ ahh yeah i missed that thank you for pointing that out i'll try it and see if it workes \$\endgroup\$ – Paukler May 21 '20 at 22:36
  • \$\begingroup\$ ok that helped a lot but i still have a problem i added this now #ifndef F_CPU #define F_CPU 16000000 #endif #include <util/delay.h> #define BAUD 9600 #define UBRR_VAL 103//((F_CPU+BAUD*8)/(BAUD*16)-1) and when i hardcode the 103 it works but not with the equasion \$\endgroup\$ – Paukler May 21 '20 at 23:09
  • \$\begingroup\$ thank you i edited the question with my final code and set your answer as the correct one you helped me a lot :D \$\endgroup\$ – Paukler May 21 '20 at 23:19

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.