LCD.ASM was adapted from Microchip application note AN587 by Norm

Cramer.  It provides interface routines to an industry standard 2

line by 20 character display module.  The code is for a PIC16C84

but should work on any PIC16CXX running at 4MHz.

 

If you find bugs, problems or want to tell the author how great

a job he has done, you can contact Norm via e-mail:

 

cramer@iamerica.net

cramer@dseg.ti.com

 

Files:

 

LCD.ASM          The routines themselves

LCD.H            Some definitions required by LCD.ASM

LCD.HEX          Hex file produced by MPASM 1.31

P16C84.INC       Microchip supplied header file for the 16C84

README.TXT       You're reading it

 

History:

 

27-Jun-96       First version

04-Jul-96       Minor changes to initialisation added

 

;*****************************************************************************************************

;

; Program: lcd.asm

;

; This program interfaces to an industry standard 2 line by 20 character display

; module. The program assembles for 4-bit data interface. LCD_DATA is the port which

; supplies the data tothe LCD, while LCD_CNTL is the port that has the control lines

; ( E, RS, R_W ).  The data is transfer on the high nibble of the port ( PORT<7:4> ).

;

; Target: PIC16C84 - But should work on any PIC16CXX running at 4Mhz

;

; Note: To change the clock speed, the delays at the end of the source file need to be changed.

;

; References:

;       Addapted from the Microchip AN587 code.

;       OPTREX data sheet.

;       Also referenced the following web pages:

;               http://www.iaehv.nl/users/pouweha/lcd.htm

;               http://www.paranoia.com/~filipg/HTML/LINK/F_LCD_tech.html

;               http://hobbes.king.ac.uk/matt/pic

;       Andrew Warren's QBasic program for calculating delays.

;

;

; History

; Author                  Date          Comments

; Microchip             05-10-94        Original Code (File name was LM032L.ASM)

;

; Norm Cramer           04-22-96        Modified to only use 4 bit interface and to not destroy the

;                                       contents of the lower portion of the output register and the

;                                       output register TRIS.  Changed the examples to include a table

;                                       definition using the "dt" compiler directive.  Added delay

;                                       subroutines for testing.  Changed Check_Busy to Wait_Busy and

;                                       added a Check_Busy that returns 0 if not busy, ff if busy. 

;                                       Modified to meet my programming standards for easy maint.

;

;

                        ERRORLEVEL      -302

                        Processor       16C84

                        Radix           HEX

                        EXPAND

 

       include <p16c84.inc>

       include <lcd.h>

;

;

 

LCD_DATA         EQU     PORTB

LCD_DATA_TRIS    EQU     TRISB

;

;

LCD_CNTL         EQU     PORTA

LCD_CNTL_TRIS    EQU     TRISA

;

;

;

; LCD Display Commands and Control Signal names.

;

E       EQU     3       ; LCD Enable control line

R_W     EQU     1       ; LCD Read/Write control line

RS      EQU     2       ; LCD Register Select control line

;

;

            cblock  0x00c

                        Temp1, Temp, Char, r1, r2, r3, r4

            endc

;

            org     _ResetVector       ; RESET vector location

RESET:

            goto    Start

;

; This is the Periperal Interrupt routine. Should NOT get here

;

            page

;

            org     _IntVector      ; Interrupt vector location

ERROR1:

            bcf     STATUS, RP0     ; Bank 0

            goto    ERROR1

;

;

;

Start:                          ; POWER_ON Reset (Beginning of program)

            clrf    STATUS          ; Do initialization (Bank 0)

            clrf    INTCON

              

            bsf     STATUS, RP0     ; Bank 1

            clrf    TRISA           ; RA5 -  0 outputs

            movlw   0xF0            ;

            movwf   TRISB           ; RB7 - 4 inputs, RB3 - 0 outputs

            bsf     OPTION_REG, NOT_RBPU  ; Disable PORTB pull-ups

            bcf     STATUS, RP0     ; Bank 0

 

            clrf    PORTA           ; ALL PORT output should output Low.

            clrf    PORTB

;

            page

;

            call    LCD_Init        ; Set up the LCD Module

           

;Send a message the hard way

            movlw   'M'

            call    Send_Char

            movlw   'i'

            call    Send_Char

            movlw   'c'

            call    Send_Char

            movlw   'r'

            call    Send_Char

            movlw   'o'

            call    Send_Char

            movlw   'c'

            call    Send_Char

            movlw   'h'

            call    Send_Char

            movlw   'i'

            call    Send_Char

            movlw   'p'

            call    Send_Char

 

            movlw   LINE2           ; Address DDRam first character, second line

            call    Send_Cmd

           

;Demonstration of the use of a table to output a message

 

            movlw   0               ; Table address of start of message

dispmsg:

            movwf   Temp1           ; Temp1 holds start of message address

            call    Table

            andlw   0FFh           

            btfsc   STATUS,Z        ; Check if at end of message (zero returned at end)

            goto    out            

            call    Send_Char       ; Display character

            movf    Temp1,w         ; Point to next character

            addlw   1

            goto    dispmsg

out:

 

loop:

            goto    loop            ; Stay here forever

 

;

            page

;

Table:

            addwf   PCL,f           ; Jump to character

            dt      "This is a test line!" ; 20 Character string terminated with a 0

Table_End:

            retlw   0

;

; Check to ensure table doesn't cross a page boundary.

            if ( (Table & 0x0FF) >= (Table_End & 0x0FF) )

       MESSG   "Warning - User Definded: Table crosses page boundry in computed jump"

    endif

;

 

 

 

;*******************************************************************

;* The LCD Module Subroutines                                      *

;*******************************************************************

;

;*******************************************************************

;*SendChar - Sends character to LCD                                *

;*This routine splits the character into the upper and lower       *

;*nibbles and sends them to the LCD, upper nibble first.           *

;*******************************************************************

;

Send_Char

            movwf   Char            ; Character to be sent is in W

            call    Wait_Busy       ; Wait for LCD to be ready

            movlw   0x0f

            andwf   LCD_DATA,F      ; Clear the upper nibble

            movf    Char,w         

            andlw   0xF0            ; Get upper nibble

            iorwf   LCD_DATA,F      ; Send data to LCD

            bcf     LCD_CNTL, R_W   ; Set LCD to write

            bsf     LCD_CNTL, RS    ; Set LCD to data mode

            bsf     LCD_CNTL, E     ; toggle E for LCD

            bcf     LCD_CNTL, E

            movlw   0x0f

            andwf   LCD_DATA,F      ; Clear the upper nibble

            swapf   Char,W

            andlw   0xF0            ; Get lower nibble

            iorwf   LCD_DATA,F      ; Send data to LCD

            bsf     LCD_CNTL, E     ; toggle E for LCD

            bcf     LCD_CNTL, E

            return

;

            page

;

 

;*******************************************************************

;* Send_Cmd - Sends command to LCD                                 *

;* This routine splits the command into the upper and lower        *

;* nibbles and sends them to the LCD, upper nibble first.          *

;*******************************************************************

 

Send_Cmd

            movwf   Char            ; Character to be sent is in W

            call    Wait_Busy       ; Wait for LCD to be ready

            movlw   0x0f

            andwf   LCD_DATA,F      ; Clear the upper nibble

            movf    Char,w         

            andlw   0xF0            ; Get upper nibble

            iorwf   LCD_DATA,F      ; Send data to LCD

            bcf     LCD_CNTL,R_W    ; Set LCD to write

            bcf     LCD_CNTL,RS     ; Set LCD to command mode

            bsf     LCD_CNTL,E      ; toggle E for LCD

            bcf     LCD_CNTL,E

            movlw   0x0f

            andwf   LCD_DATA,F      ; Clear the upper nibble

            swapf   Char,W

            andlw   0xF0            ; Get lower nibble

            iorwf   LCD_DATA,F      ; Send data to LCD

            bsf     LCD_CNTL,E      ; toggle E for LCD

            bcf     LCD_CNTL,E

            return

;

            page

;

;*******************************************************************

;* This routine checks the busy flag, returns when not busy        *

;*  Affects:                                                       *

;*      Temp - Returned with busy/address                          *

;*******************************************************************

;

Wait_Busy

            bsf     STATUS, RP0     ; Select Register page 1

            movlw   0xf0            ; Set port to input

            iorwf   LCD_DATA_TRIS,W ; Only set upper half of port

            movwf   LCD_DATA_TRIS

            bcf     STATUS, RP0     ; Select Register page 0

            bcf     LCD_CNTL, RS    ; Set LCD for Command mode

            bsf     LCD_CNTL, R_W   ; Setup to read busy flag

            bsf     LCD_CNTL, E     ; Set E high

            bcf     LCD_CNTL, E     ; Set E low

            movf    LCD_DATA, W     ; Read upper nibble busy flag, DDRam address

            andlw   0xF0            ; Mask out lower nibble

            movwf   Temp

            bsf     LCD_CNTL, E     ; Toggle E to get lower nibble

            bcf     LCD_CNTL, E

            swapf   LCD_DATA, w     ; Read lower nibble busy flag, DDRam address

            andlw   0x0F            ; Mask out upper nibble

            iorwf   Temp,W          ; Combine nibbles

            btfsc   Temp, 7         ; Check busy flag, high = busy

            goto    Wait_Busy       ; If busy, check again

            bcf     LCD_CNTL, R_W       

            bsf     STATUS, RP0     ; Select Register page 1

            movlw   0x0F

            andwf   LCD_DATA_TRIS,W

            movwf   LCD_DATA_TRIS   ; Set Port for output

            bcf     STATUS, RP0     ; Select Register page 0

            return

;

            page

;

;*******************************************************************

;* This routine checks the busy flag, returns ff if busy 00 if not *

;* busy.  Temp will contain the current address.                   *

;*                                                                 *

;*  Affects:                                                       *

;*      Temp - Returned with busy/address                          *

;*******************************************************************

;

Check_Busy

            bsf     STATUS, RP0     ; Select Register page 1

            movlw   0xf0            ; Set port to input

            iorwf   LCD_DATA_TRIS,W ; Only set upper half of port

            movwf   LCD_DATA_TRIS

            bcf     STATUS, RP0     ; Select Register page 0

            bcf     LCD_CNTL, RS    ; Set LCD for Command mode

            bsf     LCD_CNTL, R_W   ; Setup to read busy flag

            bsf     LCD_CNTL, E     ; Set E high

            bcf     LCD_CNTL, E     ; Set E low

            movf    LCD_DATA, W     ; Read upper nibble busy flag, DDRam address

            andlw   0xF0            ; Mask out lower nibble

            movwf   Temp

            bsf     LCD_CNTL, E     ; Toggle E to get lower nibble

            bcf     LCD_CNTL, E

            swapf   LCD_DATA, w     ; Read lower nibble busy flag, DDRam address

            andlw   0x0F            ; Mask out upper nibble

            iorwf   Temp,W          ; Combine nibbles

            btfsc   Temp, 7         ; Check busy flag, high = busy

            goto    Busy_Exit       ; If busy exit with busy flag set

 

            bcf     LCD_CNTL, R_W       

            bsf     STATUS, RP0     ; Select Register page 1

            movlw   0x0F

            andwf   LCD_DATA_TRIS,W

            movwf   LCD_DATA_TRIS   ; Set Port for output

            bcf     STATUS, RP0     ; Select Register page 0

            retlw   0x00

 

Busy_Exit:

            bcf     LCD_CNTL, R_W       

            bsf     STATUS, RP0     ; Select Register page 1

            movlw   0x0F

            andwf   LCD_DATA_TRIS,W

            movwf   LCD_DATA_TRIS   ; Set Port for output

            bcf     STATUS, RP0     ; Select Register page 0

            retlw   0xff

;

            page

;

; Initilize the LCD Display Module

;

LCD_Init:

 

            bcf     LCD_CNTL, E     ; Clear all controll lines

            bcf     LCD_CNTL, RS

            bcf     LCD_CNTL, R_W

 

            call    Delay15000      ; Wait for 15ms for LCD to get powered up

 

            movlw   0x0f

            andwf   LCD_DATA,F      ; Clear the upper nibble

            movlw   0x030           ; Command for 4-bit interface high nibble

            iorwf   LCD_DATA,F      ; Send data to LCD     

 

            bsf     STATUS, RP0     ; Select Register page 1

            movlw   0x0F

            andwf   LCD_DATA_TRIS,W

            movwf   LCD_DATA_TRIS   ; Set Port for output

            BCF     STATUS, RP0     ; Select Register page 0

 

            bsf     LCD_CNTL, E     ; Clock the initalize command to LCD module

            bcf     LCD_CNTL, E

 

            call    Delay4100       ; Delay for at least 4.1ms before continuing

 

            bsf     LCD_CNTL, E     ; Clock the initalize command to LCD module

            bcf     LCD_CNTL, E

           

             

            call    Delay100        ; delay for at least 100usec before continuing

 

            bsf     LCD_CNTL, E     ; Clock the initalize command to LCD module

            bcf     LCD_CNTL, E

 

            call    Wait_Busy       ; From here on, the Busy Bit will be valid.

 

            movlw   0x0f

            andwf   LCD_DATA,F      ; Clear the upper nibble

            movlw   0x020           ; Command for 4-bit interface high nibble (Really an 8bit command but

                                               ;   lower 4 bits are don't care at this point)

            iorwf   LCD_DATA,F      ; Send data to LCD     

 

            bsf     LCD_CNTL, E     ; Clock the initalize command to LCD module

            bcf     LCD_CNTL, E

 

            movlw   FUNCTION_SET    ; Send the function set command 4-bit I/F, Font, Number of lines

            call    Send_Cmd        ; Can now use the Send_Cmd routine since Busy Bit Valid and in 4bit mode.

            movlw   DISP_OFF

            call    Send_Cmd

            movlw   DISP_ON

            call    Send_Cmd

            movlw   ENTRY_INC

            call    Send_Cmd

 

; LCD Module is now initalized

            return

 

;

; Delay routines.  These routines need to be modified to work with the particular PIC configuration

; used.  For test purposes, they are instruction count delays based on 4Mhz PIC.  The delays are a

; little longer than advertised but close enough for testing.

;

 

Delay4100:

            movlw   d'252'

            movwf   r1

            movlw   4

            movwf   r2

            movlw   1

            movwf   r3

            movlw   1

            movwf   r4

 

delay_loop:

            nop            

            decfsz  r1,f

            goto    delay_loop

            decfsz  r2,f

            goto    delay_loop

            decfsz  r3,f

            goto    delay_loop

            decfsz  r4,f

            goto    delay_loop

            return

 

Delay100:

            movlw   d'22'

            movwf   r1

            movlw   1

            movwf   r2

            movlw   1

            movwf   r3

            movlw   1

            movwf   r4

            goto    delay_loop

 

Delay15000:

            movlw   d'156'

            movwf   r1

            movlw   15

            movwf   r2

            movlw   1

            movwf   r3

            movlw   1

            movwf   r4

            goto    delay_loop

           

            end

;*****************************************************************************************************

;

; Program: lcd.asm

;

; This program interfaces to an industry standard 2 line by 20 character display

; module. The program assembles for 4-bit data interface. LCD_DATA is the port which

; supplies the data tothe LCD, while LCD_CNTL is the port that has the control lines

; ( E, RS, R_W ).  The data is transfer on the high nibble of the port ( PORT<7:4> ).

;

; Target: PIC16C84 - But should work on any PIC16CXX running at 4Mhz

;

; Note: To change the clock speed, the delays at the end of the source file need to be changed.

;

; References:

;       Addapted from the Microchip AN587 code.

;       OPTREX data sheet.

;       Also referenced the following web pages:

;               http://www.iaehv.nl/users/pouweha/lcd.htm

;               http://www.paranoia.com/~filipg/HTML/LINK/F_LCD_tech.html

;               http://hobbes.king.ac.uk/matt/pic

;       Andrew Warren's QBasic program for calculating delays.

;

;

; History

; Author                  Date          Comments

; Microchip             05-10-94        Original Code (File name was LM032L.ASM)

;

; Norm Cramer           04-22-96        Modified to only use 4 bit interface and to not destroy the

;                                       contents of the lower portion of the output register and the

;                                       output register TRIS.  Changed the examples to include a table

;                                       definition using the "dt" compiler directive.  Added delay

;                                       subroutines for testing.  Changed Check_Busy to Wait_Busy and

;                                       added a Check_Busy that returns 0 if not busy, ff if busy. 

;                                       Modified to meet my programming standards for easy maint.

;

;

                        ERRORLEVEL      -302

                        Processor       16C84

                        Radix           HEX

                        EXPAND

 

       include <p16c84.inc>

       include <lcd.h>

;

;

 

LCD_DATA         EQU     PORTB

LCD_DATA_TRIS    EQU     TRISB

;

;

LCD_CNTL         EQU     PORTA

LCD_CNTL_TRIS    EQU     TRISA

;

;

;

; LCD Display Commands and Control Signal names.

;

E       EQU     3       ; LCD Enable control line

R_W     EQU     1       ; LCD Read/Write control line

RS      EQU     2       ; LCD Register Select control line

;

;

            cblock  0x00c

                        Temp1, Temp, Char, r1, r2, r3, r4

            endc

;

            org     _ResetVector       ; RESET vector location

RESET:

            goto    Start

;

; This is the Periperal Interrupt routine. Should NOT get here

;

            page

;

            org     _IntVector      ; Interrupt vector location

ERROR1:

            bcf     STATUS, RP0     ; Bank 0

            goto    ERROR1

;

;

;

Start:                          ; POWER_ON Reset (Beginning of program)

            clrf    STATUS          ; Do initialization (Bank 0)

            clrf    INTCON

              

            bsf     STATUS, RP0     ; Bank 1

            clrf    TRISA           ; RA5 -  0 outputs

            movlw   0xF0            ;

            movwf   TRISB           ; RB7 - 4 inputs, RB3 - 0 outputs

            bsf     OPTION_REG, NOT_RBPU  ; Disable PORTB pull-ups

            bcf     STATUS, RP0     ; Bank 0

 

            clrf    PORTA           ; ALL PORT output should output Low.

            clrf    PORTB

;

            page

;

            call    LCD_Init        ; Set up the LCD Module

           

;Send a message the hard way

            movlw   'M'

            call    Send_Char

            movlw   'i'

            call    Send_Char

            movlw   'c'

            call    Send_Char

            movlw   'r'

            call    Send_Char

            movlw   'o'

            call    Send_Char

            movlw   'c'

            call    Send_Char

            movlw   'h'

            call    Send_Char

            movlw   'i'

            call    Send_Char

            movlw   'p'

            call    Send_Char

 

            movlw   LINE2           ; Address DDRam first character, second line

            call    Send_Cmd

           

;Demonstration of the use of a table to output a message

 

            movlw   0               ; Table address of start of message

dispmsg:

            movwf   Temp1           ; Temp1 holds start of message address

            call    Table

            andlw   0FFh           

            btfsc   STATUS,Z        ; Check if at end of message (zero returned at end)

            goto    out            

            call    Send_Char       ; Display character

            movf    Temp1,w         ; Point to next character

            addlw   1

            goto    dispmsg

out:

 

loop:

            goto    loop            ; Stay here forever

 

;

            page

;

Table:

            addwf   PCL,f           ; Jump to character

            dt      "This is a test line!" ; 20 Character string terminated with a 0

Table_End:

            retlw   0

;

; Check to ensure table doesn't cross a page boundary.

            if ( (Table & 0x0FF) >= (Table_End & 0x0FF) )

       MESSG   "Warning - User Definded: Table crosses page boundry in computed jump"

    endif

;

 

 

 

;*******************************************************************

;* The LCD Module Subroutines                                      *

;*******************************************************************

;

;*******************************************************************

;*SendChar - Sends character to LCD                                *

;*This routine splits the character into the upper and lower       *

;*nibbles and sends them to the LCD, upper nibble first.           *

;*******************************************************************

;

Send_Char

            movwf   Char            ; Character to be sent is in W

            call    Wait_Busy       ; Wait for LCD to be ready

            movlw   0x0f

            andwf   LCD_DATA,F      ; Clear the upper nibble

            movf    Char,w         

            andlw   0xF0            ; Get upper nibble

            iorwf   LCD_DATA,F      ; Send data to LCD

            bcf     LCD_CNTL, R_W   ; Set LCD to write

            bsf     LCD_CNTL, RS    ; Set LCD to data mode

            bsf     LCD_CNTL, E     ; toggle E for LCD

            bcf     LCD_CNTL, E

            movlw   0x0f

            andwf   LCD_DATA,F      ; Clear the upper nibble

            swapf   Char,W

            andlw   0xF0            ; Get lower nibble

            iorwf   LCD_DATA,F      ; Send data to LCD

            bsf     LCD_CNTL, E     ; toggle E for LCD

            bcf     LCD_CNTL, E

            return

;

            page

;

 

;*******************************************************************

;* Send_Cmd - Sends command to LCD                                 *

;* This routine splits the command into the upper and lower        *

;* nibbles and sends them to the LCD, upper nibble first.          *

;*******************************************************************

 

Send_Cmd

            movwf   Char            ; Character to be sent is in W

            call    Wait_Busy       ; Wait for LCD to be ready

            movlw   0x0f

            andwf   LCD_DATA,F      ; Clear the upper nibble

            movf    Char,w         

            andlw   0xF0            ; Get upper nibble

            iorwf   LCD_DATA,F      ; Send data to LCD

            bcf     LCD_CNTL,R_W    ; Set LCD to write

            bcf     LCD_CNTL,RS     ; Set LCD to command mode

            bsf     LCD_CNTL,E      ; toggle E for LCD

            bcf     LCD_CNTL,E

            movlw   0x0f

            andwf   LCD_DATA,F      ; Clear the upper nibble

            swapf   Char,W

            andlw   0xF0            ; Get lower nibble

            iorwf   LCD_DATA,F      ; Send data to LCD

            bsf     LCD_CNTL,E      ; toggle E for LCD

            bcf     LCD_CNTL,E

            return

;

            page

;

;*******************************************************************

;* This routine checks the busy flag, returns when not busy        *

;*  Affects:                                                       *

;*      Temp - Returned with busy/address                          *

;*******************************************************************

;

Wait_Busy

            bsf     STATUS, RP0     ; Select Register page 1

            movlw   0xf0            ; Set port to input

            iorwf   LCD_DATA_TRIS,W ; Only set upper half of port

            movwf   LCD_DATA_TRIS

            bcf     STATUS, RP0     ; Select Register page 0

            bcf     LCD_CNTL, RS    ; Set LCD for Command mode

            bsf     LCD_CNTL, R_W   ; Setup to read busy flag

            bsf     LCD_CNTL, E     ; Set E high

            bcf     LCD_CNTL, E     ; Set E low

            movf    LCD_DATA, W     ; Read upper nibble busy flag, DDRam address

            andlw   0xF0            ; Mask out lower nibble

            movwf   Temp

            bsf     LCD_CNTL, E     ; Toggle E to get lower nibble

            bcf     LCD_CNTL, E

            swapf   LCD_DATA, w     ; Read lower nibble busy flag, DDRam address

            andlw   0x0F            ; Mask out upper nibble

            iorwf   Temp,W          ; Combine nibbles

            btfsc   Temp, 7         ; Check busy flag, high = busy

            goto    Wait_Busy       ; If busy, check again

            bcf     LCD_CNTL, R_W       

            bsf     STATUS, RP0     ; Select Register page 1

            movlw   0x0F

            andwf   LCD_DATA_TRIS,W

            movwf   LCD_DATA_TRIS   ; Set Port for output

            bcf     STATUS, RP0     ; Select Register page 0

            return

;

            page

;

;*******************************************************************

;* This routine checks the busy flag, returns ff if busy 00 if not *

;* busy.  Temp will contain the current address.                   *

;*                                                                 *

;*  Affects:                                                       *

;*      Temp - Returned with busy/address                          *

;*******************************************************************

;

Check_Busy

            bsf     STATUS, RP0     ; Select Register page 1

            movlw   0xf0            ; Set port to input

            iorwf   LCD_DATA_TRIS,W ; Only set upper half of port

            movwf   LCD_DATA_TRIS

            bcf     STATUS, RP0     ; Select Register page 0

            bcf     LCD_CNTL, RS    ; Set LCD for Command mode

            bsf     LCD_CNTL, R_W   ; Setup to read busy flag

            bsf     LCD_CNTL, E     ; Set E high

            bcf     LCD_CNTL, E     ; Set E low

            movf    LCD_DATA, W     ; Read upper nibble busy flag, DDRam address

            andlw   0xF0            ; Mask out lower nibble

            movwf   Temp

            bsf     LCD_CNTL, E     ; Toggle E to get lower nibble

            bcf     LCD_CNTL, E

            swapf   LCD_DATA, w     ; Read lower nibble busy flag, DDRam address

            andlw   0x0F            ; Mask out upper nibble

            iorwf   Temp,W          ; Combine nibbles

            btfsc   Temp, 7         ; Check busy flag, high = busy

            goto    Busy_Exit       ; If busy exit with busy flag set

 

            bcf     LCD_CNTL, R_W       

            bsf     STATUS, RP0     ; Select Register page 1

            movlw   0x0F

            andwf   LCD_DATA_TRIS,W

            movwf   LCD_DATA_TRIS   ; Set Port for output

            bcf     STATUS, RP0     ; Select Register page 0

            retlw   0x00

 

Busy_Exit:

            bcf     LCD_CNTL, R_W       

            bsf     STATUS, RP0     ; Select Register page 1

            movlw   0x0F

            andwf   LCD_DATA_TRIS,W

            movwf   LCD_DATA_TRIS   ; Set Port for output

            bcf     STATUS, RP0     ; Select Register page 0

            retlw   0xff

;

            page

;

; Initilize the LCD Display Module

;

LCD_Init:

 

            bcf     LCD_CNTL, E     ; Clear all controll lines

            bcf     LCD_CNTL, RS

            bcf     LCD_CNTL, R_W

 

            call    Delay15000      ; Wait for 15ms for LCD to get powered up

 

            movlw   0x0f

            andwf   LCD_DATA,F      ; Clear the upper nibble

            movlw   0x030           ; Command for 4-bit interface high nibble

            iorwf   LCD_DATA,F      ; Send data to LCD     

 

            bsf     STATUS, RP0     ; Select Register page 1

            movlw   0x0F

            andwf   LCD_DATA_TRIS,W

            movwf   LCD_DATA_TRIS   ; Set Port for output

            BCF     STATUS, RP0     ; Select Register page 0

 

            bsf     LCD_CNTL, E     ; Clock the initalize command to LCD module

            bcf     LCD_CNTL, E

 

            call    Delay4100       ; Delay for at least 4.1ms before continuing

 

            bsf     LCD_CNTL, E     ; Clock the initalize command to LCD module

            bcf     LCD_CNTL, E

           

             

            call    Delay100        ; delay for at least 100usec before continuing

 

            bsf     LCD_CNTL, E     ; Clock the initalize command to LCD module

            bcf     LCD_CNTL, E

 

            call    Wait_Busy       ; From here on, the Busy Bit will be valid.

 

            movlw   0x0f

            andwf   LCD_DATA,F      ; Clear the upper nibble

            movlw   0x020           ; Command for 4-bit interface high nibble (Really an 8bit command but

                                               ;   lower 4 bits are don't care at this point)

            iorwf   LCD_DATA,F      ; Send data to LCD     

 

            bsf     LCD_CNTL, E     ; Clock the initalize command to LCD module

            bcf     LCD_CNTL, E

 

            movlw   FUNCTION_SET    ; Send the function set command 4-bit I/F, Font, Number of lines

            call    Send_Cmd        ; Can now use the Send_Cmd routine since Busy Bit Valid and in 4bit mode.

            movlw   DISP_OFF

            call    Send_Cmd

            movlw   DISP_ON

            call    Send_Cmd

            movlw   ENTRY_INC

            call    Send_Cmd

 

; LCD Module is now initalized

            return

 

;

; Delay routines.  These routines need to be modified to work with the particular PIC configuration

; used.  For test purposes, they are instruction count delays based on 4Mhz PIC.  The delays are a

; little longer than advertised but close enough for testing.

;

 

Delay4100:

            movlw   d'252'

            movwf   r1

            movlw   4

            movwf   r2

            movlw   1

            movwf   r3

            movlw   1

            movwf   r4

 

delay_loop:

            nop            

            decfsz  r1,f

            goto    delay_loop

            decfsz  r2,f

            goto    delay_loop

            decfsz  r3,f

            goto    delay_loop

            decfsz  r4,f

            goto    delay_loop

            return

 

Delay100:

            movlw   d'22'

            movwf   r1

            movlw   1

            movwf   r2

            movlw   1

            movwf   r3

            movlw   1

            movwf   r4

            goto    delay_loop

 

Delay15000:

            movlw   d'156'

            movwf   r1

            movlw   15

            movwf   r2

            movlw   1

            movwf   r3

            movlw   1

            movwf   r4

            goto    delay_loop

           

            end

Ïåðåéòè: /Ãëàâíàÿ/ CBuild/ JavaScript 1.2-5.6/ Delphi6/ I2C êîíòðîëëåðû/ AVR êîíòðîëëåðû/ ÏËÈÑ/ AHDL/ VHDL/
LPT EPP/ LPT ECP/ PCI/ COM port/ I2C/ RS-232/
Ðåéòèíã@Mail.ru Rambler's Top100 Rambler's Top100 Rambler's Top100    
И�пользуют�� технологии uCoz