; Example of writing to the LCD ; ; The Raven board interfaces to the LCD LIST P=16F877, R=DEC INCLUDE "P16F877.inc" ; Definitions ; __CONFIG _CP_OFF & _DEBUG_OFF & _WRT_ENABLE_OFF & _CPD_OFF & _LVP_OFF & _BODEN_OFF & _PWRTE_ON & _WDT_OFF & _HS_OSC #define CMD_RS 0 ; Setting or RS bit for commands or data #define DATA_RS 1 ; Define start of vars ScratchPad EQU 0x20 Temp EQU ScratchPad+0 LCD_Data EQU ScratchPad+1 Count EQU ScratchPad+2 Nchar EQU ScratchPad+3 rs EQU ScratchPad+4 ; Start of the Program ORG 3 goto Start ORG 0x50 ; Return the proper lookup codes for the standard LCD DD RAM tables. ; W cntains the character ; ; No attempt here to do the whole table, just the ASCII codes, hence the way ; the jump is handled. LCD_Table addlw 32 addwf PCL,F retlw b'00110000' ; 0 retlw b'00110001' ; 1 retlw b'00110010' ; 2 retlw b'00110011' ; 3 retlw b'00110100' ; 4 retlw b'00110101' ; 5 retlw b'00110110' ; 6 retlw b'00110111' ; 7 retlw b'00111000' ; 8 retlw b'00111001' ; 9 retlw b'00111010' ; : retlw b'00111011' ; ; retlw b'00111100' ; < retlw b'00111101' ; = retlw b'00111110' ; > retlw b'00111111' ; ? retlw b'01000000' ; @ retlw b'01000001' ; A retlw b'01000010' ; B retlw b'01000011' ; C retlw b'01000100' ; D retlw b'01000101' ; E retlw b'01000110' ; F retlw b'01000111' ; G retlw b'01001000' ; H retlw b'01001001' ; I retlw b'01001010' ; J retlw b'01001011' ; K retlw b'01001100' ; L retlw b'01001101' ; M retlw b'01001110' ; N retlw b'01001111' ; O retlw b'01010000' ; P retlw b'01010001' ; Q retlw b'01010010' ; R retlw b'01010011' ; S retlw b'01010100' ; T retlw b'01010101' ; U retlw b'01010110' ; V retlw b'01010111' ; W retlw b'01011000' ; X retlw b'01011001' ; Y retlw b'01011010' ; Z Msg addwf PCL,F DT "TESTING, 1:2:3" ; String to output Start ; Set A for output and D for output bsf STATUS, RP0 clrf TRISA clrf PORTD bcf STATUS, RP0 call LCDInit ; Now output something to it movlw 14 movwf Count movwf Nchar outloop movf Count,W subwf Nchar,W call Msg call LCDWriteData decfsz Count,F goto outloop done ; Ok that was fun, now do some scrolling movlw 50 movwf Temp sleft1 call LCDScrollLeft movlw 200 call Delay_ms decfsz Temp,F goto sleft1 movlw 20 movwf Temp sright1 call LCDScrollRight movlw 100 call Delay_ms decfsz Temp,F goto sright1 movlw 10 movwf Temp sleft2 call LCDScrollLeft movlw 200 call Delay_ms decfsz Temp,F goto sleft2 ; Finally, lets end it all call LCDClear movlw 40 call LCDSetAddress movlw b'01000010' call LCDWriteData movlw b'01011001' call LCDWriteData movlw b'01000101' call LCDWriteData call Forever ; Initialize the LCD LCDInit ; Start with a delay to insure that the LCD is ready to accept commands. This has to ; be at least 15 ms. movlw 20 call Delay_ms ; Now, execute a series of commands that set up the LCD movlw b'00110011' ; indicate that initialization will follow call LCDWriteCmd movlw b'00110010' ; Second part of init call LCDWriteCmd movlw b'00101000' ; Set DDRAM address call LCDWriteCmd movlw b'00000001' ; Clear display call LCDWriteCmd movlw b'000000110' ; increment address by 1 on each write and shift cursor call LCDWriteCmd movlw b'00001100' ; turn the display on, no cursor, no blink call LCDWriteCmd return ; Write to the LCD LCDWriteData movwf LCD_Data ; swap the nybbles and send the high nybble first movlw DATA_RS movwf rs swapf LCD_Data, W andlw b'00001111' call LCDToggle ; send high nybble movlw 20 call Delay_ms ; now handle the low order nybble movf LCD_Data, w andlw b'00001111' call LCDToggle ; send low nybble movlw 20 call Delay_ms return LCDWriteCmd movwf LCD_Data movlw CMD_RS movwf rs ; swap the nybbles and send the high nybble first swapf LCD_Data, W andlw b'00001111' call LCDToggle ; send high nybble movlw 20 call Delay_ms ; now handle the low order nybble movf LCD_Data, w andlw b'00001111' call LCDToggle ; send low nybble movlw 20 call Delay_ms return ; Scroll the LCD left LCDScrollLeft movlw b'00011000' call LCDWriteCmd return ; Scroll the LCD right LCDScrollRight movlw b'00011100' call LCDWriteCmd return ; Clear LCD and home cursor LCDClear movlw b'00000001' ; Clear and home call LCDWriteCmd return ; Shift cursor left LCDCursorLeft movlw b'00010000' call LCDWriteCmd return ; Shift cursor left LCDCursorRight movlw b'00010100' call LCDWriteCmd return ; Set the write address location (e.g. the cursor location) ; The address is 0-39 for the first line and 40-79 for the second line. LCDSetAddress iorlw b'10000000' call LCDWriteCmd return ; Toggle the Enable line of the LCD, which is connected to output Y11 of the multiplexor. ; At the same time, set the value of the R/S input, which is connected to RD7. 0 means ; that a command is being sent and 1 means that data is being sent. LCDToggle movwf PORTD bcf PORTD,7 btfsc rs,0 bsf PORTD,7 movlw 0x1B ;LATCH + LCD_Enable movwf PORTA movlw 150 call Delay_us movlw 0x10 ; LATCH + NO_CONN movwf PORTA return ; ======================================================================================= ; Wait forever Forever waitforever nop goto waitforever return ; ======================================================================================== ; Delay routines for a 20 Mhz clock, which is a 5Mhz instruction rate ; These are designed to be separated and placed in a separate file ; ;============================================================================= ; Variables ; We need some variables for the delay routines, but they could ; overlap variables in the main program. Use bank4 and users of these ; routines should be careful. VarBase EQU 0x20 ; in bank 4 DTemp1 EQU VarBase+0 DTemp2 EQU VarBase+1 ; ms delay. 250 x 20 x 1/5 M = 1 ms, approximately Delay_ms bsf STATUS,RP0 bsf STATUS,RP1 movwf DTemp1 dloop_0 ; number of ms to delay movlw 250 movwf DTemp2 dloop_1 ; 1 ms delay (approximately) fill (nop), 17 decfsz DTemp2,F goto dloop_1 decfsz DTemp1,F goto dloop_0 bcf STATUS,RP1 bcf STATUS,RP0 return ; usec delay 5 instructions x 1/5 M = 1 usec (approximately) Delay_us bsf STATUS,RP0 bsf STATUS,RP1 movwf DTemp1 dloop_2 ; number of us to delay ; 1 us delay (approximately 5 instructions) fill (nop), 2 decfsz DTemp1,F goto dloop_2 bcf STATUS,RP1 bcf STATUS,RP0 return END