![]() NEW! 416028 |
This is my first decent bit of code for the PICmicro. It's a display control library that was distributed to a few members of the PICList for testing. I have used the serial control library (lcd_ser.inc) extensively - LCDs make great debugging tools. Examine the examples carefully - almost all you need to know is contained in them.
A small bug in the 4-bit driver code was fixed on 26 May 2003. This bug meant that some display panels (such as the Optrex DMC16106C) would miss characters sent to the display.
LIST
; PIC16-series PAGE-switching macros
; By P. Pemberton, Jr.
; WWW: http://www.philpem.me.uk/
; Email: piclist@philpem.me.uk
; This software is distributed under the BSD License. You are free to do whatever
; you want with this code, but I would appreciate an email first. I would also
; appreciate copies of any modifications you make.
;
; Provides:
; BANK0 Switch to RAM BANK 0
; BANK1 Switch to RAM BANK 1
; BANK2 Switch to RAM BANK 2
; BANK3 Switch to RAM BANK 3
NOLIST
#ifndef __BANKS_INCLUDED
#define __BANKS_INCLUDED
BANK0 MACRO ; Macro to select data RAM BANK 0
BCF STATUS,RP0
BCF STATUS,RP1
ENDM
BANK1 MACRO ; Macro to select data RAM BANK 1
BSF STATUS,RP0
BCF STATUS,RP1
ENDM
BANK2 MACRO ; Macro to select data RAM BANK 2
BCF STATUS,RP0
BSF STATUS,RP1
ENDM
BANK3 MACRO ; Macro to select data RAM BANK 3
BSF STATUS,RP0
BSF STATUS,RP1
ENDM
#endif
LIST
; Universal PIC LCD Interface Module ; HD44780 main handler/common functions (LCD_CMN.INC) ; NOTE: DO NOT #INCLUDE THIS FILE - #INCLUDE ONE OF THE BACKENDS INSTEAD! ; By P. Pemberton, Jr. ; WWW: http://www.philpem.me.uk/ ; Email: piclist@philpem.me.uk ; This software is distributed under the BSD License. You are free to do whatever ; you want with this code, but I would appreciate an email first. I would also ; appreciate copies of any modifications you make. CBLOCK __LCD_DOCBUFF ; Display Control settings ENDC ; Initialize LCD LCD_INIT: MOVLW B'00000100' ; Init DOCBUFF MOVWF __LCD_DOCBUFF CALL __LCD_INIT ; Init the LCD RETURN ; Return ; Display Clear LCD_CLRSCR: MOVLW B'00000001' ; Clear the LCD display CALL LCD_SENDINS RETURN ; Display On/Off - If W=0 then display off else display on LCD_ONOFF: BSF __LCD_DOCBUFF, 2 ; Assume W != 0 IORLW 0 ; Update flags BTFSC STATUS, Z ; Zero? BCF __LCD_DOCBUFF, 2 ; W=0; turn off the display MOVF __LCD_DOCBUFF, W ; Move control byte into W IORLW .8 ; Set command bit CALL LCD_SENDINS ; Send the instruction RETURN ; Cursor On/Off - If W=0 then cursor off else cursor on LCD_CURSOR: BSF __LCD_DOCBUFF, 1 ; Assume W != 0 IORLW 0 ; Update flags BTFSC STATUS, Z ; Zero? BCF __LCD_DOCBUFF, 1 ; W=0; turn off the cursor MOVF __LCD_DOCBUFF, W ; Move control byte into W IORLW .8 ; Set command bit CALL LCD_SENDINS ; Send the instruction RETURN ; Blinking Cursor On/Off - If W=0 then blinking cursor on else off LCD_CURSBLINK: BSF __LCD_DOCBUFF, 0 ; Assume W != 0 IORLW 0 ; Update flags BTFSC STATUS, Z ; Zero? BCF __LCD_DOCBUFF, 0 ; W=0; turn off the block cursor MOVF __LCD_DOCBUFF, W ; Move control byte into W IORLW .8 ; Set command bit CALL LCD_SENDINS ; Send the instruction RETURN ; Move cursor - W=offset LCD_MOVECURS: IORLW B'10000000' ; Set command bit CALL LCD_SENDINS ; Send the instruction RETURN ; Move cursor to Line 1 LCD_LINE1: MOVLW 0x00 ; Move cursor to 0x00 CALL LCD_MOVECURS RETURN ; Move cursor to Line 2 LCD_LINE2: MOVLW 0x40 ; Move cursor to 0x40 CALL LCD_MOVECURS RETURN
; Universal PIC LCD Interface Module
; HD44780 4-bit mode transport layer/backend (LCD_4BIT.INC)
; By P. Pemberton, Jr.
; WWW: http://www.philpem.me.uk/
; Email: piclist@philpem.me.uk
; This software is distributed under the BSD License. You are free to do whatever
; you want with this code, but I would appreciate an email first. I would also
; appreciate copies of any modifications you make.
;
; Pindefs required:
; LCD_D7 The PIC pin connected to the LCD's D7 pin (ex: PORTB,3)
; LCD_D6 The PIC pin connected to the LCD's D6 pin (ex: PORTB,2)
; LCD_D5 The PIC pin connected to the LCD's D5 pin (ex: PORTB,1)
; LCD_D4 The PIC pin connected to the LCD's D4 pin (ex: PORTB,0)
; LCD_E The PIC pin connected to the LCD's E pin (ex: PORTB,5)
; LCD_RS The PIC pin connected to the LCD's RS pin (ex: PORTB,4)
CBLOCK
__LCD_TEMP0
__LCD_TEMP1
ENDC
; Send a byte to the LCD, assumes RS already set
__LCD_SEND:
MOVWF __LCD_TEMP0 ; Store byte in Temp 0
BCF LCD_D7 ; Clear data bits
BCF LCD_D6
BCF LCD_D5
BCF LCD_D4
BTFSC __LCD_TEMP0, 7 ; Load high nibble
BSF LCD_D7
BTFSC __LCD_TEMP0, 6
BSF LCD_D6
BTFSC __LCD_TEMP0, 5
BSF LCD_D5
BTFSC __LCD_TEMP0, 4
BSF LCD_D4
BSF LCD_E ; Strobe E
GOTO $+1
BCF LCD_E
BCF LCD_D7 ; Clear data bits
BCF LCD_D6
BCF LCD_D5
BCF LCD_D4
BTFSC __LCD_TEMP0, 3 ; Load low nibble
BSF LCD_D7
BTFSC __LCD_TEMP0, 2
BSF LCD_D6
BTFSC __LCD_TEMP0, 1
BSF LCD_D5
BTFSC __LCD_TEMP0, 0
BSF LCD_D4
BSF LCD_E ; Strobe E
GOTO $+1
BCF LCD_E
RETURN
; Send an instruction byte to the LCD
LCD_SENDINS:
BCF LCD_RS ; RS low=instruction
CALL __LCD_SEND ; Send the instruction byte
CALL __LCD_SHORTDELAY ; Short delay for instruction
RETURN
; Send a character to the LCD
LCD_PUTCH:
BSF LCD_RS ; RS high=character
CALL __LCD_SEND ; Send the character
CALL __LCD_SHORTDELAY ; Short delay for data
RETURN
; Initialize the LCD
__LCD_INIT:
CALL __LCD_LONGDELAY ; Long init delay
MOVLW B'00110011' ; 2x 8bit resets
CALL LCD_SENDINS
MOVLW B'00110011' ; 2x 8bit resets
CALL LCD_SENDINS
MOVLW B'00110010' ; 8bit reset then 4bit reset
CALL LCD_SENDINS
MOVLW B'00101100' ; Function Set - 4bit, 2 lines
CALL LCD_SENDINS
MOVLW B'00000110' ; Mode Set - incr. w/crsr shift
CALL LCD_SENDINS
MOVLW B'00001100' ; Display on, cursor & blink off
CALL LCD_SENDINS
MOVLW B'00000001' ; Display Clear
CALL LCD_SENDINS
MOVLW B'00000010' ; Cursor Home
CALL LCD_SENDINS
CALL __LCD_LONGDELAY ; Long post-init delay
RETURN
; Long delay for init
__LCD_LONGDELAY:
CLRF __LCD_TEMP0
__LCD_LONGDEL:
CLRF __LCD_TEMP1
__LCD_SHORTDEL:
DECFSZ __LCD_TEMP1, F
GOTO __LCD_SHORTDEL
DECFSZ __LCD_TEMP0, F
GOTO __LCD_LONGDEL
RETURN
; Short delay between commands
__LCD_SHORTDELAY:
MOVLW 0x14
MOVWF __LCD_TEMP1
__LCD_SHORTLOOP:
DECFSZ __LCD_TEMP1, F
GOTO __LCD_SHORTLOOP
RETURN
; Include the Common LCD Functions
INCLUDE "lcd_cmn.inc"
; Universal PIC LCD Interface Module
; HD44780 serial mode transport layer/backend (LCD_SER.INC)
; By P. Pemberton, Jr.
; WWW: http://www.philpem.me.uk/
; Email: piclist@philpem.me.uk
; This software is distributed under the BSD License. You are free to do whatever
; you want with this code, but I would appreciate an email first. I would also
; appreciate copies of any modifications you make.
;
; Pindefs required:
; LCD_DATA The PIC pin connected to the A and B pins on the
; 74LS164 (ex: PORTB,5)
; LCD_CLOCK The PIC pin connected to the LS164's CLOCK pin
; (ex: PORTB,4)
INCLUDE "banks.inc"
; File register Usage
CBLOCK
__LCD_DLAY ; Delay variable
__LCD_NOTEMP ; Temporary variable for nibble output
__LCD_TEMP ; Temporary variable
__LCD_CNTR ; Counter
ENDC
__LCD_INIT:
CALL __LCD_DLAY5 ; Wait 20 msecs before Reset
CALL __LCD_DLAY5
CALL __LCD_DLAY5
CALL __LCD_DLAY5
BCF STATUS, C ; RS=0 (instruction)
MOVLW 0x30 ; RESET
CALL __LCD_NIBBLE ; Send the nibble
CALL __LCD_DLAY5 ; Wait 5mS before resending
BSF LCD_DATA ; Send again.
BCF LCD_DATA
CALL __LCD_DLAY160 ; Wait 160uS before resending
BSF LCD_DATA
BCF LCD_DATA
CALL __LCD_DLAY160 ; Wait 160uS before sending
BCF STATUS, C ; RS=0 (instruction)
MOVLW 0x20 ; Set 4-bit (nibble) mode
CALL __LCD_NIBBLE ; Send the nibble
CALL __LCD_DLAY160 ; Wait 160uS before sending
MOVLW 0x28 ; Two line mode, 4-bit
CALL LCD_SENDINS
CALL __LCD_DLAY160
MOVLW 0x08 ; Turn off the display
CALL LCD_SENDINS
MOVLW 0x01 ; Clear the DDRAM
CALL LCD_SENDINS
CALL __LCD_DLAY5 ; Can take up to 5uS
MOVLW 0x06 ; Set cursor direction
CALL LCD_SENDINS
MOVLW 0x0C ; Display on
CALL LCD_SENDINS
CALL __LCD_DLAY160
RETURN
LCD_PUTCH: ; Send a character to the LCD
MOVWF __LCD_DLAY ; Temporary store.
BSF STATUS, C ; RS=1 (data)
CALL __LCD_NIBBLE ; Send the high nibble
SWAPF __LCD_DLAY, W ; Low nibble -> W
BSF STATUS, C ; RS=1 (data)
CALL __LCD_NIBBLE ; Send the low nibble
RETURN
LCD_SENDINS: ; Send an instruction to the LCD
MOVWF __LCD_DLAY ; Temporary store
BCF STATUS, C ; RS=0 (instruction)
CALL __LCD_NIBBLE ; Send the high nibble
SWAPF __LCD_DLAY, W ; Low nibble -> W
BCF STATUS, C ; RS=0 (instruction)
CALL __LCD_NIBBLE ; Send the low nibble
RETURN
__LCD_NIBBLE: ; Sends a nibble (4 bits) to the LCD
MOVWF __LCD_NOTEMP ; Temporarily store the nibble
RRF __LCD_NOTEMP, F ; Save the RS bit
BSF STATUS, C ; Carry high
RRF __LCD_NOTEMP, F ; Save the gate bit
MOVLW .0 ; Clear the shift register
CALL __LCD_SEND
MOVF __LCD_NOTEMP, W ; Send the nibble to the LCD
CALL __LCD_SEND
BSF LCD_DATA ; Clock in the data
BCF LCD_DATA
RETURN
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; Send the byte in W to the 74HCT164
__LCD_SEND:
MOVWF __LCD_TEMP ; Store byte
MOVLW .8 ; Eight data bits
MOVWF __LCD_CNTR ; Store in counter
__LCD_SENDLOOP:
MOVLW 0
RLF __LCD_TEMP, F ; Rotate left into carry
BCF LCD_DATA ; Assume carry low
BTFSC STATUS, C ; Carry high?
BSF LCD_DATA ; Yes. Set port bit
; GOTO $+1 ; Wait for the data line to settle
BSF LCD_CLOCK ; Clock high
; GOTO $+1 ; Make sure the HC164 sees the transition
BCF LCD_CLOCK ; Clock low
DECFSZ __LCD_CNTR, F ; Decrement counter
GOTO __LCD_SENDLOOP ; Not zero yet; keep going
RETURN ; Counter=0; return.
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
__LCD_DLAY160: ; 160uS delay
MOVLW .256-(160/4) ; Loop until carry set
ADDLW .1
BTFSS STATUS, C
GOTO $-2
RETURN
__LCD_DLAY5: ; 5mS delay
MOVLW .4 ; Set up the Delay
MOVWF __LCD_DLAY
MOVLW .256 - 0x0E8 ; Inner loop
ADDLW 1
BTFSC STATUS, Z
DECFSZ __LCD_DLAY, F ; Outer loop
GOTO $-3
RETURN
; Include the Common LCD Functions
INCLUDE "lcd_cmn.inc"
; Universal PIC LCD Interface Module ; 74LS164-to-LCD test program ; By P. Pemberton, Jr. ; WWW: http://www.philpem.me.uk/ ; Email: piclist@philpem.me.uk ; This software is distributed under the BSD License. You are free to do whatever ; you want with this code, but I would appreciate an email first. I would also ; appreciate copies of any modifications you make. ; ; Connections: ; PIC 74LS164 LCD ; RB7 1 and 2 via 10k resistor to "E" ; RB6 8 ; 5 D4 ; 6 D5 ; 10 D6 ; 11 D7 ; 12 RS ; 13 to 1N4148 cathode ; Vcc 9 and 14 Vcc ; Vss 7 Vss ; E to 1N4148 anode ; ; ; The contrast pin on the LCD should be connected as shown in the LCD module's ; datasheet. ; ; The above circuit is based on one included in an article written by ; Myke Predko for www.rentron.com ;; PIC setup and toplevel includes LIST P=16F874 INCLUDE <p16f874.inc> INCLUDE "banks.inc" ; Pindefs #DEFINE LCD_DATA PORTB, 7 #DEFINE LCD_CLOCK PORTB, 6 ; Variables CBLOCK 0x20 ENDC ; Reset vector ORG 0 GOTO START ; Interrupt vector ORG 4 GOTO START ; Start of code ORG 5 START: CLRF PORTB ; Clear PORTB PAGE1 ; Bank 1 BCF LCD_DATA ; Data, clock=outputs BCF LCD_CLOCK PAGE0 ; Bank 0 CALL LCD_INIT ; Init the LCD CLRF FSR ; Message loop MSGLOOP: MOVF FSR, W INCF FSR, F CALL MESSAGE IORLW .0 BTFSC STATUS, Z GOTO MSGDONE CALL LCD_PUTCH GOTO MSGLOOP MSGDONE: MOVLW .1 ; Block Cursor on CALL LCD_CURSBLINK CALL LCD_LINE2 MOVLW "2" CALL LCD_PUTCH MOVLW "0" CALL LCD_PUTCH MOVLW "." CALL LCD_PUTCH MOVLW "0" CALL LCD_PUTCH MOVLW 0x1A CALL LCD_PUTCH GOTO $ MESSAGE: ADDWF PCL, F DT "Hello.",0 ;; Final post-code includes INCLUDE "lcd_ser.inc" END
; Universal PIC LCD Interface Module ; 4-bit LCD test program ; By P. Pemberton, Jr. ; WWW: http://www.philpem.me.uk/ ; Email: piclist@philpem.me.uk ; This software is distributed under the BSD License. You are free to do whatever ; you want with this code, but I would appreciate an email first. I would also ; appreciate copies of any modifications you make. ; ; Connections: ; PIC LCD ; RB5 E ; RB4 RS ; RB3 D7 ; RB2 D6 ; RB1 D5 ; RB0 D4 ; ; The contrast pin on the LCD should be connected as shown in the LCD module's ; datasheet. ;; PIC setup and toplevel includes LIST P=16F874 INCLUDE <p16f874.inc> INCLUDE "banks.inc" ; Pindefs #DEFINE LCD_D7 PORTB, 3 #DEFINE LCD_D6 PORTB, 2 #DEFINE LCD_D5 PORTB, 1 #DEFINE LCD_D4 PORTB, 0 #DEFINE LCD_E PORTB, 5 #DEFINE LCD_RS PORTB, 4 ; Variables CBLOCK 0x20 ENDC ; Reset vector ORG 0 GOTO START ; Interrupt vector ORG 4 GOTO START ; Start of code ORG 5 START: CLRF PORTB ; Clear PORTB PAGE1 ; Bank 1 BCF LCD_D7 ; Databits=outputs BCF LCD_D6 BCF LCD_D5 BCF LCD_D4 BCF LCD_RS ; RS, E=outputs BCF LCD_E PAGE0 ; Bank 0 CALL LCD_INIT ; Init the LCD CLRF FSR ; Message loop MSGLOOP: MOVF FSR, W INCF FSR, F CALL MESSAGE IORLW .0 BTFSC STATUS, Z GOTO MSGDONE CALL LCD_PUTCH GOTO MSGLOOP MSGDONE: MOVLW .1 ; Blinking Cursor on CALL LCD_CURSBLINK CALL LCD_LINE2 MOVLW "2" CALL LCD_PUTCH MOVLW "0" CALL LCD_PUTCH MOVLW "." CALL LCD_PUTCH MOVLW "0" CALL LCD_PUTCH MOVLW 0x1A CALL LCD_PUTCH GOTO $ MESSAGE: ADDWF PCL, F DT "Hello.",0 ;; Final post-code includes INCLUDE "lcd_4bit.inc" END
Comments: