title "Animate - Draw the 'Walking Man' on an LCD" ; ; This Code Uses the two wire LCD interface to draw a ; walking man using User Defined Characters. ; ; ; Hardware Notes: ; Reset is tied directly to Vcc and PWRT is Enabled. ; The PIC is a 16C84 Running at 4 MHz. ; PortA.0 is the Data Bit ; PortA.1 is the Clock Bit ; ; Shift Data: ; Bit 1 - Always High (Gate for "E") ; Bit 2 - RS Bit ; Bit 3 - LCD D4 ; Bit 4 - LCD D5 ; Bit 5 - LCD D6 ; Bit 6 - LCD D7 ; ; Myke Predko ; 99.04.28 ; LIST P=16C84, R=DEC ; 16C84 Runs at 4 MHz errorlevel 0,-305 INCLUDE "p16c84.inc" ; Register Usage CBLOCK 0x00C ; Start Registers at End of the Values Dlay ; 8 Bit Delay Variable Temp ; Temporary Value Used When Sending Out Data NOTemp ; Temporary Value to "NybbleOutput" Count ; Character Counter for Output ENDC ; Define Inforation #DEFINE Data PORTA,0 #DEFINE Clock PORTA, 1 ; Macros ClockStrobe MACRO ; Strobe the Data Bit bsf Clock bcf Clock ENDM EStrobe MACRO ; Strobe the "E" Bit bsf Data bcf Data ENDM PAGE __CONFIG _CP_OFF & _XT_OSC & _PWRTE_ON & _WDT_OFF ; Note that the WatchDog Timer is OFF ; Demo Code, Loop Forever Toggling PA0 (Flashing the LED) org 0 clrf PORTA movlw 0x01C ; Enable PA0 & PA1 for Output bsf STATUS, RP0 movwf TRISA ^ 0x080 bcf STATUS, RP0 call Dlay5 ; Wait 20 msecs before Reset call Dlay5 call Dlay5 call Dlay5 bcf STATUS, C ; Clear Carry (Instruction Out) movlw 0x03 ; Reset Command call NybbleOut2 ; Send the Nybble call Dlay5 ; Wait 5 msecs before Sending Again EStrobe call Dlay160 ; Wait 160 usecs before Sending the Third Time EStrobe call Dlay160 ; Wait 160 usecs before Sending the Third Time bcf STATUS, C movlw 0x02 ; Set 4 Bit Mode call NybbleOut2 call Dlay160 movlw 0x028 ; Note that it is a 2 Line Display call SendINS movlw 0x008 ; Turn off the Display call SendINS movlw 0x001 ; Clear the Display RAM call SendINS call Dlay5 ; Note, Can take up to 4.1 msecs movlw 0x006 ; Enable Cursor Move Direction call SendINS movlw 0x00C ; Turn the LCD Back On call SendINS movlw 0x040 ; Put the Cursor to the Start of CGRAM call SendINS movlw 0x030 ; Send 6 Characters of 8 Bytes movwf Count ; Output the User Characters clrf FSR CharLoop movf FSR, w ; Get the Offset to Output incf FSR call ManChar call SendCHAR ; Output the ASCII Character decfsz Count ; Do 48x goto CharLoop movlw 0x080 ; Move the Cursor Back into LCD Memory Space call SendINS movlw 0 ; Display the Man call SendCHAR movlw 'A' ; Put in "A" for Comparison call SendCHAR Loop ; Loop Forever when Done call LongDlay ; Delay Between Movements movlw 0x080 ; Send Char "1" call SendINS movlw 1 call SendCHAR call LongDlay movlw 0x080 ; Send Char "2" call SendINS movlw 2 call SendCHAR call LongDlay movlw 0x080 ; Send Char "3" call SendINS movlw 3 call SendCHAR call LongDlay movlw 0x080 ; Send Char "4" call SendINS movlw 4 call SendCHAR call LongDlay movlw 0x080 ; Send Char "5" call SendINS movlw 5 call SendCHAR goto Loop ; Subroutines ManChar ; User Characters to Display addwf PCL ; Output the Characters retlw 0x00E ; Character 0 - Byte 0 retlw 0x00E retlw 0x004 retlw 0x004 retlw 0x004 retlw 0x004 retlw 0x00C retlw 0x000 retlw 0x00E ; Character 1 - Byte 0 retlw 0x00E retlw 0x004 retlw 0x004 retlw 0x00C retlw 0x004 retlw 0x00C retlw 0x000 retlw 0x00E ; Character 2 - Byte 0 retlw 0x00E retlw 0x004 retlw 0x004 retlw 0x00A retlw 0x01A retlw 0x006 retlw 0x000 retlw 0x00E ; Character 3 - Byte 0 retlw 0x00E retlw 0x004 retlw 0x004 retlw 0x006 retlw 0x009 retlw 0x019 retlw 0x000 retlw 0x00E ; Character 4 - Byte 0 retlw 0x00E retlw 0x004 retlw 0x004 retlw 0x007 retlw 0x009 retlw 0x018 retlw 0x000 retlw 0x00E ; Character 5 - Byte 0 retlw 0x00E retlw 0x004 retlw 0x004 retlw 0x00C retlw 0x006 retlw 0x00C retlw 0x000 ; Bottom Character retlw 0x01F ; #### - Note Full Line for Bottom Character ; #### - To Show, Comment out the Previous Line SendCHAR ; Send the Character to the LCD movwf Temp ; Save the Temporary Value swapf Temp, w ; Send the High Nybble bsf STATUS, C ; RS = 1 call NybbleOut2 movf Temp, w ; Send the Low Nybble bsf STATUS, C call NybbleOut2 return SendINS ; Send the Instruction to the LCD movwf Temp ; Save the Temporary Value swapf Temp, w ; Send the High Nybble bcf STATUS, C ; RS = 0 call NybbleOut2 movf Temp, w ; Send the Low Nybble bcf STATUS, C call NybbleOut2 return NybbleOut2 ; Send a Nybble to the LCD movwf NOTemp ; Save the Nybble to Shift Out swapf NOTemp ; Setup to Output to the High Part of the Byte movlw 6 ; Clear the Shift Register movwf Dlay NO2Loop1 ClockStrobe decfsz Dlay goto NO2Loop1 movlw 5 ; Now, Shift out the Data with the "RS" Bit movwf Dlay bsf Data ; Put out the Gate Bit ClockStrobe NO2Loop2 bcf Data ; Clear the Data Bit (which is the Clock) btfsc STATUS, C ; If the Bit to be output is a "1", Shift it Out bsf Data ClockStrobe rlf NOTemp ; Shift the Next Bit into the Carry Flag decfsz Dlay goto NO2Loop2 EStrobe ; Strobe out the LCD Data return LongDlay ; Delay 200 msecs movlw 40 movwf Count LDLoop call Dlay5 decfsz Count goto LDLoop return Dlay160 ; Delay 160 usecs movlw 256 - ( 160 / 4 ) ; Loop Until Carry Set addlw 1 btfss STATUS, C goto $-2 return Dlay5 ; Delay 5 msecs movlw 4 ; Set up the Delay movwf Dlay movlw 256 - 0x0E8 addlw 1 btfsc STATUS, Z decfsz Dlay goto $-3 return end