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, the code 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 (which is no longer available)
to calculate the timing values for the 8 bit timer used in the Delay routine.
Kevin Rosenberg has
AVRCalc, which can be used instead to generate the timer values.
You also shouldn't deviate far from the initialization sequence for the HD44780 shown in the code.