LCD Interface

Based on HD44780 LCD controller. (See Hitachi LCD Documentation)

  • Block Diagram
    • E – enable
      • Located at lcdPORT0 on SunRom LCD panel.
    • R/W – read/write (1 – read, 0 – write)
      • Located at lcdPORT1 on SunRom LCD panel.
    • RS – register select
      • Located at lcdPORT2 on SunRom LCD panel.
    • Data – 8 data bits
      • The data bits are bidirectional, but rarely is there a need to read from it.
      • On SunRom LCD panel D[7..4] connected to lcdPORT[7..4] and D[3..0] connected to ground.
  • There are two types of information that can be written to the data pins:
    • Data (RS should be set (high)).
    • Command (RS should be cleared (low)).
    • A few useful commands:
      • clear – clears the display.
      • home – move cursor to home (first) position.
      • blink – cursor blinks.
      • auto-increment cursor position.

LCD Commands

Table 6 from the HD44780 datasheet lists the set of available instructions:

A number of instructions have parameters specified by one to three letters.

  • Function Set
    • DL – specifies the interface data length
      • 0 – 4-bit mode.
      • 1 – 8-bit mode.
    • N – specifies the number of lines for the display
      • 0 – 1-line display.
      • 1 – 2-line display.
    • F – specifies the font used
      • 0 – 5 x 8 dot character font
      • 1 – 5 x 10 dot character font
  • Display On/Off Control
    • D – display on/off flag
      • 0 – display off.
      • 1 – display on.
    • C – cursor on/off flag
      • 0 – cursor off.
      • 1 – cursor on.
    • B – blinking on/off flag
      • 0 – blinking off.
      • 1 – blinking on.
  • Entry Mode Set
    • I/D – Increment/Decrement cursor by 1 on data read/write flag
      • 0 – moves cursor position to right by one character after reading/writing character from/to current position.
      • 1 – moves cursor position to left by one character after reading/writing character from/to current position.
    • S – display shift
      • 0 – disabled.
      • 1 – enables shifting of data so that current data moves right and new data takes the home position.

Writing Commands to the LCD

  • The LCD has both a 4-bit and 8-bit mode.
  • Since D[3..0] are connected to ground on the SunRom LCD panel, we must use the 4-bit communication mode.
  • However, the LCD defaults to 8-bit mode.
  • Therefore, the first command must be sent in 8-bit mode, and that command should instruct the LCD to operate in 4-bit mode.

Generic Command Write Process in 4-bit Mode

  1. Output upper nibble of command to lcdPORT
  2. Set E
  3. Delay for four cycles
  4. Clear E
  5. Delay for 2ms
  6. Output lower nibble of command to lcdPORT
  7. Set E
  8. Delay for four cycles
  9. Clear E
  10. Delay for 2ms
  11. Set RS
  12. Set R/W
  13. Delay for 2ms

We can write 4 bits to the LCD as follows:

; lcd_cmd_write_nibble PRELIMINARY VERSION
; Purpose: write 4-bits of a command to the LCD display
; Parameters:
;   r24 -- upper nibble contains the 4 bits to be written to the LCD display
; Assumes .equ directive has set lcdPORT to the appropriate I/O port
; Dependencies: delay2ms (found in delay.asm)... you'll need to write this.
lcd_cmd_write_nibble:
      push    r24              ; store register values

      andi    r24, 0xF0        ; strip off lower 4 bits

      out     lcdPORT, r24     ; write nibble to LCD display
      sbi     lcdPORT, 0       ; set E (enable LCD)

      nop                      ; delay 4 cycles
      nop
      nop
      nop

      cbi     lcdPORT, 0       ; clear E (latch cmd/data being written to LCD display)
      rcall   delay2ms         ; found in delay.asm

      pop     r24              ; restore register values
      ret
; end lcd_cmd_write_nibble
  • Provided we load R24 with the appropriate values, the lcd_write_nibble1 subroutine does steps 1-5 and 5-10.
  • We can perform the entire generic command write process in 4-bit mode by making use of lcd_write_nibble1 and the subroutine below:
; lcd_cmd_write1 PRELIMINARY VERSION
; Purpose: Sends command to the LCD display
; Parameter:
;   r24 -- cmd/data to be written to the LCD display
; Assumes .equ directive has set lcdPORT to the appropriate I/O port
; Dependencies: lcd_write_nibble1
lcd_cmd_write1:
      push    r24              ; store register value

      rcall   lcd_cmd_write_nibble; write upper nibble to lcd
      swap    r24              ; swap upper and lower nibbles
      rcall   lcd_cmd_write_nibble; write what was originally the lower nibble to lcd
      sbi     lcdPORT, 2       ; set RS (data mode)
      sbi     lcdPORT, 1       ; set R/W (read mode)

      pop     r24              ; restore register value
      ret
; end lcd_cmd_write1

Initializing LCD to 4-bit Mode

Figure 24 from the HD44780 datasheet describes the procedure for initializing the LCD to use the 4-bit interface:

We can approximate the datasheet instructions by calling lcd_cmd_write1 with the following:

  1. 0×33 – Function set to 8-bit mode.
  2. insert additional 2ms delay after first command write.
  3. 0×32 – Function set to 8-bit mode again.
  4. 0×28 – Set function to 4-bit mode, indicate LCD has two lines.
  5. 0x0F – Turn display on, cursor on and blink cursor.
  6. 0×01 – Clear display.
  7. 0×06 – Sets Entry Mode to auto-increment cursor and disable shift mode.
  8. 0×02 – send the cursor to the home position.

Writing Data to the LCD

  • The process of writing data to the LCD is identical to writing commands except that the RS flag must be set instead of cleared.
  • As a result:
    • The lcd_data_write1 subroutine would be identical to lcd_cmd_write1 except we would call lcd_data_write_nibble instead of lcd_cmd_write_nibble.
    • The lcd_data_write_nibble would be identical to lcd_cmd_write_nibble except that we would insert ORI r24, 0×04 after the line with the ANDI instruction in order to set the RS flag.
  • Since this would be duplicating a significant portion of code, I've chosen to use a register to indicate whether the byte should be written as a command or as data.
; CE-2800 lcdlib.asm
; Purpose: This file contains a collection of utility subroutines
;          used for controlling the LCD display.
;
; Author: t a y l o r@msoe.edu, 01-10-2008
;
; Usage: It is intended that this file be included at the end of
;        the .asm file that makes use of the subroutines found in
;        this file.
;        In addition to including lcdlib.asm, two .equ directives
;        must be added to specify the PORT to which the LCD is
;        connected.  For example, if the LCD panel is connected
;        to PORTB, the following lines should be included:
;
;        .equ lcdPORT = PORTB
;        .equ lcdDDR = DDRB
;        .include "lcdlib.asm"
;
; Subroutines Provided:
;   lcd_port_config -- Initializes the ATmega32 port used by the LCD display
;
;   lcd_init -- Initializes the LCD display
;
;   lcd_cmd_write -- Sends a command to the LCD display
;       Parameter: r24 -- data to be written to the LCD display
;
;   lcd_data_write -- Sends a byte of data to the LCD display
;       Parameter: r24 -- data to be written to the LCD display
;
;   lcd_clear -- Clear the LCD display and home cursor
;
;   lcd_string_write -- Display a message on the LCD screen
;       Parameter: Z -- byte address of beginning of message
;
; Dependencies: Requires "delay.asm"

.cseg
; lcd_port_config
; Purpose: Initializes the ATmega32 port used by the LCD display
lcd_port_config:
    ;
    ; Left as an exercise for the diligent student
    ;
; end lcd_port_config


; lcd_init
; Purpose: Initialize the LCD display
; Dependencies: lcd_cmd_write
lcd_init:
    ;
    ; Left as an exercise for the diligent student
    ;
; end lcd_init


; lcd_cmd_write
; Purpose: Sends a command to the LCD display
; Parameter:
;   r24 -- command to be written to the LCD display
; Dependencies: lcd_write
; Author: t a y l o r@msoe.edu, 01-10-2008
lcd_cmd_write:
      push    r22              ; store register value
      
      clr     r22              ; clear r22 to tell lcd_write to use command mode
      rcall   lcd_write
      
      pop     r22              ; restore register value
      ret
; end lcd_cmd_write


; lcd_data_write
; Purpose: Sends a byte of data to the LCD display
; Parameter:
;   r24 -- data to be written to the LCD display
; Dependencies: lcd_write
; Author: t a y l o r@msoe.edu, 01-10-2008
lcd_data_write:
      push    r22              ; store register value
      
      ser     r22              ; sets r22 to tell lcd_write to use data mode
      rcall   lcd_write
      
      pop     r22              ; restore register value
      ret
; end lcd_data_write


; lcd_write
; Purpose: Sends cmd/data to the LCD display
; Parameter:
;   r24 -- cmd/data to be written to the LCD display
;   r22 -- 0b-------0 for command mode, 0b-------1 for data mode (- means don't care)
; Dependencies: lcd_write_nibble
; Author: t a y l o r@msoe.edu, 01-10-2008
; Note: Not documented at top of file since this is a helper subroutinue
lcd_write:
      push    r24              ; store register value

      rcall   lcd_write_nibble ; write upper nibble to lcd
      swap    r24              ; swap upper and lower nibbles
      rcall   lcd_write_nibble ; write what was originally the lower nibble to lcd
      sbi     lcdPORT, 2       ; set RS (data mode)
      sbi     lcdPORT, 1       ; set R/W (read mode)

      pop     r24              ; restore register value
      ret
; end lcd_write


; lcd_write_nibble
; Purpose: write 4-bits to the LCD display (either command or data)
; Parameters:
;   r24 -- upper nibble contains the 4 bits to be written to the LCD display
;   r22 -- 0b-------0 for command mode, 0b-------1 for data mode (- means don't care)
; Dependencies: delay2ms (found in delay.asm)
; Author: t a y l o r@msoe.edu, 01-10-2008
; Note: Not documented at top of file since this is a helper subroutinue
lcd_write_nibble:
      ; store register values
      push    r24
      push    r22

      andi    r24, 0xF0        ; strip off lower 4 bits

      ; Set RS=1 if in data mode, otherwise leave RS=0
      sbrc    r22, 0           ; skip next line if in CMD mode (r22=0b-------0)
      ori     r24, 0x04        ; set RS (in data mode)

      out     lcdPORT, r24     ; write nibble to LCD display
      sbi     lcdPORT, 0       ; set E (enable LCD)

      nop                      ; delay 4 cycles
      nop
      nop
      nop

      cbi     lcdPORT, 0       ; clear E (latch cmd/data being written to LCD display)
      rcall   delay2ms

      ; restore register values
      pop     r22
      pop     r24
      ret
; end lcd_write_nibble

; lcd_clear
; Purpose: Clear the LCD display and home cursor
; Dependencies: lcd_cmd_write
lcd_clear:
    ;
    ; Left as an exercise for the diligent student
    ;
; end lcd_clear


; lcd_string_write
; Purpose: Display a message on the LCD screen
; Parameter: 
;   Z -- byte address of beginning of message
; Dependencies: lcd_data_write
lcd_string_write:
    ;
    ; Left as an exercise for the diligent student
    ;
; end lcd_string_write

.include "delay.asm"

Missing Pieces

You should be able to write subroutines for:

  • delay2ms – delay for two milliseconds and store that subroutine in a file called delay.asm
  • lcd_init – sends a sequence of initialization commands to LCD.
  • lcd_port_init – configures ports used by LCD.
  • lcd_string_write – write the null terminated string stored in program memory (indicated by the Z pointer) to the LCD.
  • lcd_clear – clears the LCD screen.
ce2800/lcddisplay.txt · Last modified: 2009/06/03 11:22 (external edit)
 

This website is not owned or managed by the Milwaukee School of Engineering.

© 2003-2010 Dr. Christopher C. Taylor, et. al. • Office: L-343 • Phone: 277-7339 • npǝ˙ǝosɯ@ɹolʎɐʇ • -> RSS <-