0

I have a Arduino Uno Rev3 and I would like to use a AVR development toolchain to write a program that performs serial communication over USB.

Doing this using the Arduino IDE is fairly simple:

void setup() {
   Serial.begin(9600);
}

void loop() {
   int i;
   while(1) {
      Serial.write("hello\n");
      delay(5000);
   }
}

Then from Linux, I can simply read from /dev/ttyACM0 and every 5 seconds I get "hello\n".

I found a blog post titled Simple Serial Communications With AVR libc that explains how to perform serial communication using an AVR development toolchain. The simplified version of the above Arduino sketch is below.

#ifndef F_CPU
#define F_CPU 8000000UL
#endif

#ifndef BAUD
#define BAUD 9600
#endif

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

void uart_init() {
    // Upper and lower bytes of the calculated prescaler value for baud.
    UBRR0H = UBRRH_VALUE;
    UBRR0L = UBRRL_VALUE;

    // Configure data frame size to 8-bits.
    UCSR0C = _BV(UCSZ01) | _BV(UCSZ00);

    // Configure to enable transmitter.
    UCSR0B = _BV(TXEN0);
}

void uart_putchar(char c) {
    // Wait until the register to write to is free.
    loop_until_bit_is_set(UCSR0A, UDRE0);

    // Write the byte to the register.
    UDR0 = c;
}

void uart_putstr(char *data) {
    // Loop until end of string writing char by char.
    while(*data){
      uart_putchar(*data++);
    }
}

int main() {
    uart_init();

    while(1) {
        uart_putstr("hello\n");
        _delay_ms(5000);
    }

    return 0;
}

The problem is, this doesn't actually work. I can build and flash the ATmega328p but reads to /dev/ttyACM0 block forever. I suspect what is happening is that the serial communication is occurring on some pins and not over USB, but I am not sure.

Anyone have any idea on how I can emulate Serial.write using an AVR development toolchain and have the output be written over USB?

  • 8000000UL my Uno board has a standard 16MHz crystal on it. Besides, what program / command do you use for reading out data over dev/ttyACM0? – Maximilian Gerhardt Jul 19 '18 at 18:56
  • I tried 16000000UL as well, still didn't work. I originally switched to 8000000UL because the on-board LED did not blink correctly with 16000000UL. – Confused Programmer Jul 19 '18 at 19:05
  • As for reading /dev/ttyACM0, I've written a simple program using the following library: github.com/pkg/term. However, I imagine cat or tail -f would show the same results. – Confused Programmer Jul 19 '18 at 19:06
  • Why is this being closed as off-topic? The help centre tells that questions about other IDEs, clones/counterfeits/derivatives, and other coding languages for Arduino are OK. – Dmitry Grigoryev Aug 2 '18 at 8:37
0

Turns out the problem was with my Makefile. avr-gcc was missing the -mmcu=atmega328p flag. Once I added that and changed F_CPU to 16000000UL everything works.

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.