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.
debug.h - USB debugging stubs used in the implementation. They are disabled by default.
Enabling them requires some additional code you can get here.
lcd_hello.c - demo program for the lib; shows example usage with some animated scrolling and
character generator animation. See the video below for the output.
Makefile - makefile for the lib. If you have the AVR development software for the Teensy++ 2.0
already installed, this should produce the .hex binary for the demo program when you type 'make'.
lcd_chardata.c - character generator data for the demo program.
Demo Program Output
Things I learned from this project:
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.
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.
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.
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.