I'll gladly answer questions regarding software that I've written, but I cannot help with homework, class assignments, projects and unrelated AVR programming questions... especially since I'm a newbie to the AVR. Thanks.
Alphanumeric LCD displays based on the venerable Hitachi HD44780 display driver are both common and inexpensive. These displays use a common interface to access the LCD character memory - an 8 bit bus with simple addressing and clocking requirements. The HD44780 also has a 4 bit bus mode, where commands and data are sent in nibbles, rather than bytes.
What if you don't have the port bits required to access an LCD in 8 or even 4 bit mode? Peter Ouwehand has an excellent web page on how to control a HD44780-based Character LCD display. The miscellaneous examples section includes two circuits on how to control an HD44780 based LCD display using only 3 signals and an 8 bit shift register.
I thought the idea was clever and simple to implement. Stefan Heinzmann modifiedy Marc Simons' original circuit for a basic 3 line interface, simplifying it by using a 74HC164 8 bit shift register.
Stefan Heinzmann's circuit requires only a 74HC164 8 bit shift register and a 10K trimpot to adjust the LCD's contrast. His original circuit design was for the PIC, but I've adapted it (with his permission) to work with the AVR.
The AVR's hardware requirements are 3 port pins:
PORTB bit 5 (LCDE) is connected to the E Clock (E) pin on the LCD module.
PORTB bit 6 (LCDDat) is connected to the register select (RS) pin on the LCD module and to the two data inputs (A and B) of
the 74HC164 shift register.
PORTB bit 7 (LCDClk) is connected to the CLK input of the 74HC164 shift register.
Any other three output port bits could be used. It's a very simple circuit; it's a good idea to add a 0.1µf capacitor between the +5V and ground of the 74HC164.
If you can't see any characters displayed on the LCD (and you've checked that the hardware and software are working) turn the LCD Contrast pot until you can see the characters.
The code is very simple: It sets up the LCD port bits, initializes the LCD display and writes "Hello World" once, before settling down in an infinite loop.
Obviously, the important parts of the code are the data serialization and LCD setup routines.
To load an 8 bit character or LCD command into the 74HC164 shift register, the code shifts the byte out bit by bit through PORTB bit 6, (LCDDat) clocking the 74HC164 clock by toggling PORTB bit 7 (LCDClk) for each bit. The data is latched on the rising edge of the clock, so the data bit on the port should be set first. Once the byte has been loaded into the shift register (and is now appearing on the LCD Data bus pins) the code selects the LCD register (either data or command) by setting the LCDDat pin low or high. Since the LCDClk pin is not being toggled, the 74HC164 ignores this data. Once RS is set, it toggles the LCD E clock (LCDE, PORTB pin 5) and the LCD reads the data on its data bus. The LCD will ignore all data on its data bus until its E clock is pulsed high, similar to the Enable clock on many old 6800 and 6502 peripheral chips.
The AT90S2313 doesn't have a fully functional SPI bus, but some other AVR parts do. You can use the SPI port on these devices to communicate with this circuit - with the appropriate changes in code.
The HD44780 is a particularly slow device, so even though command and character bytes have to go through a serialization routine first, it's still a good thing to add a delay between bytes sent. The code assumes a 10MHZ AT90S2313 part; change the timing delays accordingly for different CPU clocks. I used Andyrate to calculate the timing values for the 8 bit timer used in the Delay routine.
You also shouldn't deviate far from the initialization sequence for the HD44780 shown in the code.
This code was developed on an Atmel STK500 board, using AVRStudio 4.
Thanks to Stefan Heinzmann for coming up with the circuit modifications and allowing me to reproduce an AVR specific circuit diagram.