![]() NEW! 416028 |
Simple routines for controlling a HD44780 display. Useful if you are adding a display to an old project. The data bus and control lines can use any pin. It works just fine on pic 16f677 and 16f877.
Code:
;**********************************************************************
; Simple routines for controlling a HD44780 display *
; Useful if you are adding a display to an old project. *
; The data bus and control lines can use any pin. *
; If the pin is open collector you need a pull up resistor *
; *
;**********************************************************************
; *
; Filename: lcd.asm *
; Date: 20080204 *
; File Version: 1.1 *
; *
; Author: Stefan Johansson *
; tessier at telia dot com *
; *
;**********************************************************************
; *
; Usage: #include <lcd.asm> *
; call LCDINIT ; Initialize LCD *
; *
; movlw 0x05 *
; call LCDADD ; Goto lcd adress 0x05*
; *
; movlw 'A' *
; call LCDSEND ; Write character A *
;**********************************************************************
; *
; Variables: D0 *
; D1 *
; D2 *
; LCDTmp *
; *
;**********************************************************************
; *
; Notes: This was written and compiled for PIC 16f677. *
; Modification might be needed for other models. *
; Any comments, questions or improvements... mail me *
; *
;**********************************************************************
; LCD control lines
; Modify to match your project
#define LCD_D4 PORTB, 3
#define LCD_D5 PORTB, 2 ; 4 data lines
#define LCD_D6 PORTB, 1
#define LCD_D7 PORTB, 0
#define LCD_RS PORTB, 5 ; 0 = Command, 1 = Data
#define LCD_E PORTB, 4 ; 1 to send data
;*************************************************************
; Initialize LCD functions
;*************************************************************
LCDINIT
; Set correct TRIS values for LCD ports
bsf STATUS, RP0 ;Bank 1
bcf LCD_RS
bcf LCD_E
bcf LCD_D4
bcf LCD_D5
bcf LCD_D6
bcf LCD_D7
bcf STATUS, RP0 ;Bank 0
movlw 0x40 ; Initial delay, probably not needed...
call delay
; Forced LCD initialization
bcf LCD_RS ; Set command mode
bcf LCD_E
bsf LCD_D4
bsf LCD_D5
bcf LCD_D6
bcf LCD_D7
call PULSE
movlw 0x04
call delay
call PULSE
call short_dly
call short_dly
call PULSE
; Send the command to select 4-bit mode first
bcf LCD_D4
call PULSE
; Function set
; Format: xxxDNFxx D: 1= 8-bit, 0= 4-bit (use 4-bit!)
movlw b'00101000' ; N: 1= 2 lines, 0= 1 line
call LCDSEND ; F: 1= 5x10 font, 0= 5x8 font
; Display control
; Format: xxxxxDCB D: Display on(1)/0ff(0)
movlw b'00001100' ; C: Cursor on(1)/0ff(0)
call LCDSEND ; B: Blink on(1)/0ff(0)
; Entry mode set
; Format: xxxxxxIS I: 1= Increment counter, 0= Decrement counter
movlw b'00000110' ; S: 1= "Accompanies display shift"
call LCDSEND
; Cursor or display shift
; Format: xxxxSRxx S: 1= Display shift, 0= Cursor move
movlw b'00010000' ; R: 1= Shift right, 0= Shift left
call LCDSEND
movlw b'00000001' ; Clear screen
call LCDSEND
bsf LCD_RS ; Set data mode
RETURN
;*************************************************************
; Moves "cursor"
;*************************************************************
LCDADD
bcf LCD_RS ; Command mode
iorlw 0x80 ; Goto DDRAM adress
call LCDSEND
bsf LCD_RS ; Data mode
call delay_1ms ; Takes a couple of ms
RETURN
;*************************************************************
; Sends contens of W to display
;*************************************************************
LCDSEND ; Sends character in W to lcd. Does not alter RS line!
movwf LCDTmp
bcf LCD_D4
bcf LCD_D5
bcf LCD_D6
bcf LCD_D7
btfsc LCDTmp, 7
bsf LCD_D7
btfsc LCDTmp, 6
bsf LCD_D6
btfsc LCDTmp, 5
bsf LCD_D5
btfsc LCDTmp, 4
bsf LCD_D4
call PULSE
bcf LCD_D4
bcf LCD_D5
bcf LCD_D6
bcf LCD_D7
btfsc LCDTmp, 3
bsf LCD_D7
btfsc LCDTmp, 2
bsf LCD_D6
btfsc LCDTmp, 1
bsf LCD_D5
btfsc LCDTmp, 0
bsf LCD_D4
call PULSE
return
;*************************************************************
; Pulse enable line
;*************************************************************
PULSE ; Pulse Enable.
bsf LCD_E
nop ; Increase the delay here if you get
nop ; problems with high clock speed
nop ; Probably not needed since
nop ; 1 instruction @10MHz = 400ns
bcf LCD_E
call delay_1ms
call delay_1ms
return
;*************************************************************
; Clears display
;*************************************************************
LCDCLR ; clears the entire display
bcf LCD_RS ; Set command mode
movlw b'00000001' ; Clear screen
call LCDSEND
bsf LCD_RS ; Set data mode
return
;*************************************************************
; Calls the delay_1ms W times
;*************************************************************
delay
movwf d0
dly_loop
call delay_1ms
decfsz d0, F
goto dly_loop
return
;*************************************************************
; 1ms delay.
; Modify this to match your processor speed.
; http://www.piclist.com/techref/piclist/codegen/delay.htm
;*************************************************************
delay_1ms
movlw 0xF3 ;2498 cycles
movwf d1
movlw 0x02
movwf d2
Delay_0
decfsz d1, f
goto $+2
decfsz d2, f
goto Delay_0
goto $+1 ;2 cycles
return ;4 cycles (including call)
;*************************************************************
; 40us delay.
; Modify this to match your processor speed.
; http://www.piclist.com/techref/piclist/codegen/delay.htm
;*************************************************************
short_dly
movlw 0x1F ;94 cycles
movwf d1
short_dly_0
decfsz d1, f
goto short_dly_0
goto $+1 ;2 cycles
return ;4 cycles (including call)
Comments:
#include <yourpic.pic>
call LCDINIT ; Initialize LCD
movlw 0x05
call LCDADD
movlw 'A'
call LCDSEND ; Write character A *
; Variables:
d0 equ 0x20
d1 equ 0x21
d2 equ 0x22
LCDTmp equ 0x23
AND IT WORKS, thanks to the author.
Stefan Johansson replies: But it works for me... Anyone else?