;;;;;;; LCD Program ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; ; Test the LCD display. ; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; list P=PIC16C74A, F=INHX8M, C=160, N=77, ST=OFF, MM=OFF, R=DEC, X=OFF #include P16C74A.inc __config(_CP_OFF & _PWRTE_ON & _XT_OSC & _WDT_OFF & _BODEN_OFF) ;;;;;;; Equates ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; Bank0RAM equ H'20' ;Start of Bank 0 RAM area ;;;;;;; Variables ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; cblock Bank0RAM TEMP LCD_TEMP endc ;;;;;;; Macro definitions ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; MOVLF macro literal,dest movlw literal movwf dest endm ;;;;;;; Program code ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; org H'000' ;Reset vector goto Mainline ;;;;;;; LCDinit_Table subroutine ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; LCDinit_Table movf LCD_TEMP,W ;Use LCD_TEMP as offset into table addwf PCL,F retlw H'33' ;Send 3, 3, 3, 2 to obtain 4-bit interface retlw H'32' retlw H'28' ;Display has two rows retlw H'01' ;Clear display retlw H'0C' ;Turn off display of cursor retlw H'06' ;Increment cursor position automatically retlw H'00' ;End-of-table designator ;;;;;;;DisplayC_Table subroutine;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; ; This subroutine is called with LCD_TEMP containing the offset from CDS ; to the desired byte. DisplayC_Table movf LCD_TEMP,W ;Copy LCD_TEMP to W addwf PCL,F ;add adequate offset to PCL CDS _UL retlw H'80' dt "UL" retlw 0 _UR retlw H'8E' dt "UR" retlw 0 _LL retlw H'C0' dt "LL" retlw 0 _LR retlw H'CE' dt "LR" retlw 0 ;;;;;;; End of Tables ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;; Mainline program ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; Mainline call Initial ;Initialize everything movlw _UL-CDS call DisplayC movlw _UR-CDS call DisplayC movlw _LL-CDS call DisplayC movlw _LR-CDS call Display Stop goto Stop ;Stop further code execution ;;;;;;; Initial subroutine ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; ; This subroutine performs all initializations of variables and registers. Initial bsf STATUS,RP0 ;Set register access to bank MOVLF B'00000100',ADCON1 ;Enable PORTE as digital I/O MOVLF B'00001111',TRISB ;Set I/O for PORTB MOVLF B'00000100',TRISE ;Set I/O for PORTE MOVLF 249,PR2 ;Set up Timer2 for a looptime of 10 ms bcf STATUS,RP0 ;Set register access back to bank 0 MOVLF B'01001101',T2CON ;Finish set up of Timer2 (see page 62) clrf PORTB clrf PORTE call InitLCD return ;;;;;;; InitLCD subroutine ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; ; Initialize the FEMA 16x2 character LCD display. ; (Initialize PIC ports prior to calling this subroutine.) ; This subroutine uses a one-byte RAM variable called LCD_TEMP. InitLCD MOVLF 25,LCD_TEMP ;Wait 1/4 second InitLCD_1 call LoopTime ;Call LoopTime 25 times decfsz LCD_TEMP,F goto InitLCD_1 ; LCD_TEMP now equals zero bcf PORTE,0 ;RS=0 for command InitLCD_2 call LCDinit_Table ;Get next byte, pointed to by LCD_TEMP iorlw H'00' ;Set Z flag if W=0 btfsc STATUS,Z goto InitLCD_done movwf TEMP ;Save copy of byte movwf PORTB ;Send upper nibble bsf PORTE,1 ;Drive E high bcf PORTE,1 ;Drive E low so LCD will process input call LoopTime ;Wait ten milliseconds swapf TEMP,W ;Swap nibbles movwf PORTB ;Send lower nibble bsf PORTE,1 ;Drive E high bcf PORTE,1 ;Drive E low so LCD will process input call LoopTime ;Wait ten milliseconds incf LCD_TEMP,F ;Point to next byte goto InitLCD_2 ; and deal with it InitLCD_done return ;;;;;;;;DisplayC subroutine;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; ; This subroutine is called with W containing the offset from CDS to the ; beginning of the desired constant display string. It uses a one-byte LCD_TEMP ; to the next byte in the display string DisplayC movwf LCD_TEMP ;Save pointer bcf PORTE,0 ;Drive RS pin low for cursor positioning code DisplayC_1 call DisplayC_Table ;Get byte from string into W incf LCD_TEMP,F ;Point to the next byte iorlw 0 ;Set Z if end of string btfsc STATUS,Z ;if not, then go on goto DisplayC_done movwf TEMP movwf PORTB ;Write upper nibble bsf PORTE,1 ;Strobe E bcf PORTE,1 swapf TEMP,W ;Swap nibbles movwf PORTB ;Write lower nibble bsf PORTE,1 ;Strobe E bcf PORTE,1 call T40 ;Wait 40 usec bsf PORTE,0 ;Drive RS pin high for displayable characters goto DisplayC_1 DisplayC_done return ;;;;;;; T40 subroutine ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; ; Pause for 40 microseconds (assumes 4 MHz crystal). T40 movlw 12 movwf TEMP T40_1 decfsz TEMP,F goto T40_1 return ;;;;;;; LoopTime subroutine ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; ; This subroutine waits for Timer2 to complete its ten millisecond count ; sequence. LoopTime btfss PIR1,TMR2IF ;Check whether ten milliseconds are up goto LoopTime bcf PIR1,TMR2IF ;Clear flag return end