Log a quick overview of the latest changes, for your convinience
Projects finished projects, both hard and software
Ideas / How-tos Short articles about technologies, unfinished ideas and other information not related to a specific project
Tidbits Small things, no programming or electronic knowledge required
About about me and this website
2.3.2014

A simple simplex UART for debugging AVRs

If you don’t have any way to output information, debugging projects can get annoying very quickly. Often you can help yourself by blinking LEDs but one of the most popular method still is “printf-debugging”.

Since I tend to slim down my projects as much as possible, I often end up with microcontrollers without built-in serial communications. There are a few software UART libraries around, but those are normally fully featured implementations and need timers or interrupts.

My needs are far simpler, I just need a way to output debug information, while I’m still on the workbench. The serial communication doesn’t need to be robust for all environments and I don’t even need to be able to receive anything. On the other hand, I want to be able to drop the library into any project, assign it any open output pin and have it work.

To help me with this task I wrote a very small simplex UART implementation for AVR. The basic implementation takes up a whole 60 lines of code.

The header is:

UART.h
C
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#ifndef __UART_H
#define __UART_H
#include <stdint.h>
#include <avr/io.h>
 
// Baud rate
#define UART_BPS 9800
#define UART_TX_DDR  DDRB
#define UART_TX_PORT PORTB
#define UART_TX_PIN  PB0
 
extern uint8_t uart_setup(void);
extern void uart_putc(char c);
extern void uart_puts(char* s);
 
#endif

And the actual code is:

UART.c
C
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
#include <stdint.h>
#include <avr/io.h>
#include <util/delay.h>
#include "uart.h"
 
#define UART_SET_BIT(port,bit)   (port |=  (1 << bit))
#define UART_CLEAR_BIT(port,bit) (port &= ~(1 << bit))
 
#define UART_BIT_WAIT()  _delay_us(1000000.0 / (float) UART_BPS)
#define UART_SEND_HIGH() {UART_CLEAR_BIT(UART_TX_PORT, UART_TX_PIN); UART_BIT_WAIT();}
#define UART_SEND_LOW()  {UART_SET_BIT(UART_TX_PORT, UART_TX_PIN); UART_BIT_WAIT();}
 
uint8_t uart_setup(void){
  UART_SET_BIT(UART_TX_DDR, UART_TX_PIN);
  UART_SET_BIT(UART_TX_PORT, UART_TX_PIN);
  return 0;
}
 
void uart_putc(char c){
  uint8_t i = 8;
  // start bit
  UART_SEND_HIGH();
  while(i){
    if(c & 1){
      UART_SEND_LOW();
    } else {
      UART_SEND_HIGH();
    }
    c = c >> 1;
    i--;
  }
  // stop bits
  UART_SEND_LOW();
}
 
void uart_puts(char* s){
  while (*s) {
    uart_putc(*s);
    s++;
  }
}

This will work as an 8-bit UART with one stop and no parity bit. This mode should be compatible with the majority of serial consoles, but if necessary, the code can be adjusted for other bit-lengths and parity and additional stop bits can be added.

It doesn’t have many bells and whistles, and the timing will be a bit off, but the main goal was to have a simple and easy to use debug interface, not a fully featured software UART. If you need a full UART, there are already better solutions available.

All content of this site is licensed under the CC BY-NC-SA 3.0 license unless otherwise specified.
powered by wordpress