--Message-Boundary-3544 Content-type: text/plain; charset=US-ASCII Content-transfer-encoding: 7BIT Content-description: Mail message body Giles Honeycutt wrote: > I am reviewing a lot of example LCD code, some very old, some with > some good and bad features. Any recommendations for a good > reference that incorporates: 4 bit mode Uses the busy flag as > apposed to delays ASM, my target is 16F876A and a 2X16 LCD > (actually VFD that emulates LCD) Giles: Here's some code stripped out of an old project. It's neither been tested nor even assembled in this form. As written, it assumes that the LCD's 4 data lines are wired to the upper half of Port D (MSB on RD7, LSB on RD4). You'll have to define LCDRS, LCDRW, and LCDE to match your pinout. Call LCDINIT to initialize the display, then just use the six macros to make it do stuff... And don't listen to people who say that the Busy flag is "unreliable"; it isn't. -Andy === Andrew Warren -- aiw@cypress.com === Principal Design Engineer === Cypress Semiconductor Corporation === === Opinions expressed above do not === necessarily represent those of === Cypress Semiconductor Corporation -- http://www.piclist.com#nomail Going offline? Don't AutoReply us! email listserv@mitvma.mit.edu with SET PICList DIGEST in the body --Message-Boundary-3544 Content-type: text/plain; charset=US-ASCII Content-transfer-encoding: 7BIT Content-description: Text from file 'LCD.TXT' PAGE0 MACRO BCF STATUS,RP0 ;SWITCH TO DATA SEGMENT 0. BCF STATUS,RP1 ; ENDM PAGE1 MACRO BSF STATUS,RP0 ;SWITCH TO DATA SEGMENT 1. BCF STATUS,RP1 ; ENDM ; LCD MACROS. HOME MACRO MOVLW HOMELCD ;HOME THE CURSOR. CALL LCDCMD ; ENDM CLS MACRO MOVLW CLRLCD ;CLEAR THE LCD. CALL LCDCMD ; ENDM LOCATE MACRO ROW,COLUMN LOCAL X IF ( ((ROW)<0) || ((ROW)>1) || ((COLUMN)<0) || ((COLUMN)>15) ) ERROR "LOCATE USAGE: LOCATE ROW,COLUMN" ERROR "ROW MUST BE IN [0,1]; COLUMN IN [0-15]" ELSE X = 64 * (ROW) + (COLUMN) MOVLW SETDDA | X ;MOVE THE CURSOR TO [ROW (0-1), COLUMN (0-15)]. CALL LCDCMD ; ENDIF ENDM PUTLIT MACRO LITERAL MOVLW (LITERAL) ;DISPLAY "LITERAL" ON THE LCD. PUTW ; ENDM PUTREG MACRO REG MOVF (REG),W ;DISPLAY CONTENTS OF "REG" ON THE LCD. PUTW ; ENDM PUTW MACRO CALL LCDDATA ;DISPLAY CONTENTS OF W-REG ON THE LCD. ENDM ; HD44780A LCD DRIVER INSTRUCTIONS. CLRLCD EQU 00000001B ;CLEAR THE LCD. HOMELCD EQU 00000010B ;HOME THE CURSOR. LCDMODE EQU 00000110B ;INCREMENT DISPLAY POSITION, NO SHIFT. DISPON EQU 00001100B ;DISPLAY ON, NO CURSOR, NO BLINK. BLINK EQU 00001101B ;DISPLAY ON, NO CURSOR, BLINK. CURSOR EQU 00001110B ;DISPLAY ON, CURSOR, NO BLINK. LCDFUNC EQU 00101000B ;4-BIT INTERFACE, 2 LINES, 5X7 FONT. SETCGA EQU 01000000B ;SET CG RAM ADDRESS (ADDRESS IN BITS 0-5). SETDDA EQU 10000000B ;SET DD RAM ADDRESS (ADDRESS IN BITS 0-6). ; PORTD SETUP SETPDO EQU 0000xxxxB ;PORTD I/O STRUCTURE FOR WRITING TO LCD. SETPDI EQU 1111xxxxB ;PORTD I/O STRUCTURE FOR READING FROM LCD. ; ; INITIALIZE THE LCD DISPLAY. ENTER WITH TRISD SET TO "SETPDO", SO ; THE LCD DATA BUS IS ALL OUTPUTS. ; LCDINIT: BCF LCDRS ;CLEAR THE LCD CONTROL LINES. BCF LCDRW ; BCF LCDE ; MOVLW 00001111B ;CLEAR THE LCD DATA BUS. ANDWF PORTD ; BSF LCDPOWR ;TURN ON THE LCD POWER. MOVLW 20 ;WAIT 20 MILLISECONDS. CALL WAITMS ; MOVLW LCDFUNC ;SWITCH THE LCD TO 4-BIT MODE. CALL LCDCMD ; MOVLW LCDMODE ;SETUP OUR ENTRY MODE. CALL LCDCMD ; MOVLW DISPON ;MAKE SURE THE DISPLAY IS ON. CALL LCDCMD ; LOCATE 0,0 ;SET DD RAM ADDRESS TO 00. RETURN ;RETURN. ; ; SEND A COMMAND TO THE LCD. ; LCDCMD: MOVWF LCDTMP ;STORE THE COMMAND TEMPORARILY. CALL LCDREADY ;WAIT FOR THE "BUSY" FLAG TO CLEAR. MOVF LCDTMP,W ;HI-NIBBLE OF W = HI NIBBLE OF COMMAND. ANDLW 11110000B ; IORWF PORTD ;SEND IT TO THE LCD. ; BCF LCDRS ; BCF LCDRW ; BSF LCDE ;CLOCK IT IN. NOP ; BCF LCDE ; MOVLW 00001111B ;CLEAR THE DATA BUS. ANDWF PORTD ; SWAPF LCDTMP,W ;HI-NIBBLE OF W = LO-NIBBLE OF COMMAND. ANDLW 11110000B ; IORWF PORTD ;SEND IT TO THE LCD. BSF LCDE ;CLOCK IT IN. NOP ; BCF LCDE ; MOVLW 00001111B ;CLEAR THE DATA BUS. ANDWF PORTD ; RETURN ;RETURN. ; ; SEND DATA TO THE LCD. ENTER WITH DATA IN W. EXITS WITH W UNCHANGED. ; LCDDATA: MOVWF LCDTMP ;STORE THE DATA TEMPORARILY. CALL LCDREADY ;WAIT FOR THE "BUSY" FLAG TO CLEAR. MOVF LCDTMP,W ;HI-NIBBLE OF W = HI NIBBLE OF DATA. ANDLW 11110000B ; IORWF PORTD ;SEND IT TO THE LCD. ; BSF LCDRS ; BCF LCDRW ; BSF LCDE ;CLOCK IT IN. NOP ; BCF LCDE ; MOVLW 00001111B ;CLEAR THE DATA BUS. ANDWF PORTD ; SWAPF LCDTMP,W ;HI-NIBBLE OF W = LO-NIBBLE OF DATA. ANDLW 11110000B ; IORWF PORTD ;SEND IT TO THE LCD. BSF LCDE ;CLOCK IT IN. NOP ; BCF LCDE ; MOVLW 00001111B ;CLEAR THE DATA BUS. ANDWF PORTD ; MOVF LCDTMP,W ;RESTORE THE W-REG. RETURN ;RETURN. ; ; WAIT FOR THE LCD'S "BUSY" FLAG TO CLEAR. ; LCDREADY: PAGE1 ;SWITCH TO DATA-SEGMENT 1. -------------------- ; MOVLW SETPDI ;MAKE THE LCD DATA BUS ALL INPUTS. ; MOVWF TRISD ^ 080H ; ; ; PAGE0 ;SWITCH BACK TO DATA-SEGMENT 0. --------------- LCDWTLP: BCF LCDRS ;SETUP TO READ THE BUSY FLAG. BSF LCDRW ; BSF LCDE ;CLOCK THE DATA IN. NOP ; MOVF PORTD,W ;GRAB THE HI-NIBBLE OF DATA (BIT 7 = BUSY). BCF LCDE ;FINISH CLOCKING. NOP ;WAIT A CYCLE. BSF LCDE ;CLOCK THE LO-NIBBLE OUT (AND IGNORE IT). NOP ; BCF LCDE ; ANDLW 10000000B ;MASK OFF ALL BUT THE BUSY FLAG. BNZ LCDWTLP ;IF THE LCD'S STILL BUSY, LOOP BACK AND TRY ;AGAIN. MOVLW 00001111B ;OTHERWISE, CLEAR THE DATA BUS. ANDWF PORTD PAGE1 ;SWITCH TO DATA-SEGMENT 1. -------------------- ; MOVLW SETPDO ;MAKE THE LCD DATA BUS ALL OUTPUTS. ; MOVWF TRISD ^ 080H ; ; ; PAGE0 ;SWITCH BACK TO DATA-SEGMENT 0. --------------- RETURN ;RETURN. ; ; WAIT SOME NUMBER OF MILLISECONDS. ENTER WITH NUMBER OF MILLISECONDS IN W ; (0 = 256). ; WAITMS: MOVWF MSTIMR ;STORE THE NUMBER OF MILLISECONDS. WAITMS1: MOVLW 250 ;1-SETUP TO WAIT A MILLISECOND. DECW ;999-WASTE 999 MICROSECONDS. SKPZ ; GOTO $-2 ; DECFSZ MSTIMR ;HAVE WE WAITED ENOUGH? GOTO WAITMS1 ;IF NOT, LOOP BACK AND WAIT ANOTHER ;MILLISECOND. RETURN ;OTHERWISE, RETURN. -- http://www.piclist.com#nomail Going offline? Don't AutoReply us! email listserv@mitvma.mit.edu with SET PICList DIGEST in the body --Message-Boundary-3544--