XMEGA and HD44780 LCD

Character LCD are one of the easiest and cheapest way of adding output to a microcontroller system. The world of character LCDs has mainly standarized on HD44780 controller chip, which was designed to be interfaced with the rest of the system by a parallel bus, but today simple bit-banging does the job.

One of the obstacles to using HD44780 with XMEGA are different supply voltages. Displays usually require 5V, while XMEGA is 3,3V-only. The HD44780 controller will happily run from 3,3V, but the display matrix itself requires higher voltage to move crystals around. 5V displays will not have enough contrast at lower voltage to show anything. There are some HD44780 displays that run at 3,3V, but they are not available in all shapes, sizes and colors.

There are ways to run the display at 3,3V and generate bias voltage separately, but they require extra components. For one of my designs I opted for separate supply voltages for the LCD and rest of the system.

The display is centrally located in the schematic. All data lines go directly to the XMEGA. There are two separate voltage regulators (IC2, IC6) and two jumpers (solder bridges) to select a voltage for the display. To use 5V – IC6 has to be placed, J1 not soldered and J2 soldered in 2-3 position. To use 3,3V only – IC6 is not placed, J1 is soldered and J2 is soldered in 1-2 position. I had to use the first option. 3,3V signals from the MCU are correctly received by display’s 5V logic. LCD’s RW line is permanently grounded so the display can never output 5V to data lines. Without being able to read the busy flag from the display software has to use very relaxed timings, so that the display always has enough time to process the commands.


I have based my driver on this library. The main modifications are of course – different pin control macros for XMEGA, extra characters and mostly important – it is not busy waiting!. Well… it is very little busy waiting 🙂

This driver has a transmit buffer that can be loaded any time from main application context (main loop) without any delays. The transmit buffer is then being transmitted from a timer interrupt, so even though the display is a “slow” device – it does not block the whole program. The only ugly part is a small 50µs delay in interrupt handler between outputting two nibbles, but that could be easily improved by implementing a simple finite (2) state machine.


Driver – API

Driver – internals