Teensy++ Interface Library for HD44780-Based LCDs

(Project completed: 2015-05)

Some of my planned electronics projects require microcontrollers and LCD displays, and I've found the Teensy breakout boards for AVR microcontrollers to be very useful for rapid prototyping.

To that end I've created a code library to help with the interfacing. I chose to target LCD displays using the HD44780 controller chip because they are extremely common and versatile; I have nearly a dozen of them in my salvage bins already from past scrapping.

Yes, I do know there are several similar libraries floating around out there already, but this seemed like a good project to tackle myself to help get dust off my interfacing skills. Also, I wanted to make use of the LCD controller's 4-bit transfer mode to save on I/O pins; this way only 7 pins are needed to control the LCD instead of 11 (8 data + 3 control).

I'm releasing this code under the Creative Commons CC-BY-SA 4.0 license in case it might be useful to other hobbyists. No warranty, no support and all that, but let me know if you find a definite bug.

Here's the code. The zip contains these files:


Demo Program Output

Things I learned from this project:

  1. Read the data sheet patiently and don't hesitate to reread it. There are a number of gotchas with the HD44780 that are easy to miss in a casual reading of the data sheet.
  2. For example, the HD44780 defaults to 8-bit transfer mode and is switched to 4-bit mode with the first command sent, which is elegantly constructed so that it works even though you've only connected four data lines. The surprise is that you have to send the command again as a 4-bit command in order to complete the initialization of the controller; it considers the first command a complete 8-bit command and may put itself into an undesired mode as a result of the unused data lines.
  3. The LCD controller's internal processing is much slower than a typical microcontroller, so some delays are necessary between control signal state changes. One place this tripped me up was when trying to read out the contents of the custom character generator RAM. I initially failed to realize that read operations trip the HD44780's busy flag, which indicates it is doing internal processing. By not waiting for the busy flag to clear, I was trying to read out the RAM contents too fast and was getting garbage as a result.
  4. Don't trust the debugger! In this case I was using the USB debugging code I mentioned above to do debugging-via-printf over USB, and when I had the debugging code enabled at some point the LCD interface code stopped working. By backing out changes incrementally I discovered the debugging hooks were the problem, and it turned out the time spent transmitting the USB data was interfering with the LCD interface timing too much. I removed all debug statements from the time-critical sections and that fixed it.

Revision History