ࡱ>  : !"#$%&'()*+,-./0123456789<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]_`abcdefghijklmnoRoot EntryÕ֠ITEM000s7IY ֠П֠Contentsp"Ole {\rtf1\ansi\deff0{\fonttbl{\f0\fnil\fcharset0 Courier New;}} \viewkind4\uc1\pard\lang1033\f0\fs20 ;LCD Display Module Interfacing Example\par ;This example works for any LCD Module made by Optrex, Hitachi, etc.\par ;Two 4 bit nybbles are sent one after the other from the PIC16F84 to the LCD interface,\par ;as explained in Microchip Application Note AN587 (DS00587B - page 3-205)\par ;***********************************************************************\par ;LCD connections to the PIC \par ; LCD Pin LCD Sig PIC Sig\tab PIC Pin #\par ; 1\tab GND\tab\tab ---\tab\tab ---\par ; 2 Vcc\tab\tab ---\tab\tab ---\par ;\tab 3\tab Vee (Gnded for full contrast)\tab ---\par ;\tab 4\tab RS\tab\tab RA2\tab\tab P1\par ;\tab 5\tab R/W* (Gnded, since we will only write to LCD module)\par ;\tab 6\tab E\tab\tab RA1\tab\tab P18\par ;\tab 7-10 \tab DB0-DB3 (Not used)\tab\tab ---\par ;\tab 11\tab DB4\tab\tab RB4\tab\tab P10\par ;\tab 12\tab DB5\tab\tab RB5\tab\tab P11\par ;\tab 13\tab DB6\tab\tab RB6\tab\tab P12\par ;\tab 14\tab DB7\tab\tab RB7\tab\tab P13\par ;***********************************************************************\par \tab list\tab p=16F84\par \tab radix\tab decimal\par w\tab equ\tab 0\par f\tab equ\tab 1\par rp0\tab equ\tab 5\par ; Special Function Register Definitions\par status\tab equ\tab 0x03\par pcl\tab equ\tab 0x02\par porta\tab equ\tab 0x05\par portb\tab equ\tab 0x06\par ddra\tab equ\tab 0x85\par ddrb\tab equ\tab 0x86\par ; RAM (Register File) Allocations\par count1\tab equ\tab 0x0c\par count2\tab equ\tab 0x0d\par count3\tab equ\tab 0x0e\par bits\tab equ\tab 0x0f\par charptr\tab equ\tab 0x10\par ;\par \tab org\tab 0x00\par \tab goto\tab start\par \tab org\tab 0x05\par start\tab bsf\tab status,rp0\tab ;switch to bank 1\par \tab movlw\tab 0x00\tab\tab\par \tab movwf\tab ddra\par \tab movwf\tab ddrb\tab\tab ;make all PORTA and PORTB lines outputs\par \tab bcf\tab status,rp0\tab ;switch back to bank 0\par \tab movwf\tab porta\par \tab movwf\tab portb\tab\tab ;make all output lines go LOW.\par \tab call \tab initlcd\tab\tab ;initialize LCD display\par \tab movlw\tab 0\par \tab movwf\tab charptr\tab\tab ;charptr = 0\par nextchar\par \tab call\tab getnxtchar\par \tab iorlw\tab 0\tab\tab ;set Z flag if 0 returned from getmsg.\par \tab bz\tab done\tab\tab ;"BZ k" is a special "Branch on Z=1" macro.\par \tab\tab\tab\tab ;(See Assembly Language Summary Sheet)\par \tab\tab\tab\tab ;it expands into: \tab BTFSC 3,2\par \tab\tab\tab\tab ;\tab\tab \tab GOTO k\par \tab call \tab display\par \tab goto\tab nextchar\par \tab\par \tab\par done\par loophere\par \tab goto\tab loophere\par ;*********End of main program *******************\par ;\par ;*********** Subroutine "GETNXTCHAR" - Returns with the next ascii code in the message below.\par ; - returns 0 when at end of message ***************************************\par getnxtchar\par \tab movf\tab charptr,w\par \tab incf\tab charptr,f\tab ;make charptr advance to point to next char in msg.\par \tab addwf\tab pcl,f\tab\tab ;jump down to the desired entry (RETLW instruction)\par \tab\tab\tab\tab ; in the ASCII Text Message table that follows.\par \tab DT\tab "Example using DT",0\tab ;DT - "Define Table" assembler directive\par \tab\tab\tab\tab\tab ;this sets up a series of RETLW instructions:\par \tab\tab\tab\tab\tab ;RETLW 'E', RETLW 'x', RETLW 'a', etc.\par ;***************************************************************************************\par ;\par ;Subroutine Display -- Sends character in W register out to LCD display\par display\tab bsf\tab porta,2\tab\tab ;Set RS = 1, readies LCD display to receive \par \tab\tab\tab\tab ;(ASCII code) data bytes.\par \tab call\tab send\par \tab return\par ;\par ;Subroutine "initlcd" -- initializes LCD Display - in this example I have a 32 char X 2 line\par ;\par initlcd\tab call \tab delay5ms\par \tab bcf\tab porta,1\tab ;E line low\par \tab bcf\tab porta,2\tab ;RS line low, when RS = 0 => set for instruction byte\par \tab\tab\tab ;sent to the LCD display module. See instruction list.\par \tab movlw\tab 0x30\tab ;Function Set Command, Gen'l format: 0 0 1 DL N F * *\par \tab movwf\tab bits\tab ; DL = 1 => First set for 8-bit data transfer mode.\par \tab call\tab outhinybble\tab ;output 4 most sig bits -- ignore low 4 bits\par \tab call\tab pulse\par \tab call\tab outhinybble\tab ;output 4 most sig bits -- ignore low 4 bits\par \tab call\tab pulse\par \tab call\tab outhinybble\tab ;output 4 most sig bits -- ignore low 4 bits\par \tab call\tab pulse\par \tab movlw\tab 0x20\tab ; Function Set Command, Gen'l format: 0 0 1 DL N F * *\par \tab movwf\tab bits\tab ; DL = 0 => 4 bit data mode.\par \tab call\tab outhinybble\tab ; Bottom 4 bits are ignored at this time, since the four bit\par \tab\tab\tab ; mode has just been set. From now on, however, display\par \tab movwf\tab bits\tab ; will expect two successive nybbles to be sent.\par \tab call\tab outhinybble\par \tab call\tab pulse\par \tab movlw\tab 0x28\tab ;Function Set Command, Gen'l format: 0 0 1 DL N F * *\par \tab call\tab send\tab ; DL = 0 => 4 bit data mode\par \tab\tab\tab ; N=1 => 1/8 duty cycle\par \tab\tab\tab ; F=0 => 5 X 7 dot font\par \tab movlw\tab 0x0f\tab ;Display ON/OFF command, Gen'l format: 0 0 0 0 1 D C B.\par \tab\tab\tab ; D=1 => display on, \par \tab\tab\tab ; C= 1 => cursor ON, \par \tab\tab\tab ; B = 1 => Cursor blinking\par \tab call\tab send\par \tab movlw\tab 0x01\tab ;Clear Display Command, Gen'l format: 0 0 0 0 0 0 0 1\par \tab call\tab send\par \tab movlw\tab 0x06\tab ;Entry Mode Set Command, Gen'l format: 0 0 0 0 0 1 I/D* S\par \tab\tab\tab ;I/D* = 1 => Increment display addr ptr.\par \tab\tab\tab ;S = 0 => Do not shift (scroll) display\par \tab call\tab send\par \tab movlw\tab 0xC3\tab\tab ;Display Data RAM Addr Set Cmd - Gen'l Format 1 L a a a a a a\par \tab\tab\tab\tab ; L = line number (0 is top line, 1 is bottom line)\par \tab\tab\tab\tab ; aaaaaa is cursor position column number.\par \tab\tab\tab\tab ; Here, L = 1 and aaaaaa = 000011, so this starts\par \tab\tab\tab\tab ; message disply on SECOND LINE and 3rd column of display.\par \tab call\tab send\par \tab return\tab\tab\par ;\par ;\tab\par ;Subroutine delay400ms\par ;\par delay400ms\par \tab movlw\tab 80\tab ;wait 80 5ms intervals\par \tab movwf\tab count3\par delay1\tab call\tab delay5ms\par \tab decfsz\tab count3,f\par \tab goto\tab delay1\par \tab return\par ;\par ;Subroutine delay5ms - delays 5 ms\par delay5ms\par \tab movlw\tab 40\tab ;wait 40 125us intervals\par \tab movwf\tab count2\par delay\tab call\tab delay125us\par \tab decfsz\tab count2,f\par \tab goto\tab delay\par \tab return\par ;\par ;Subroutine delay125us -- delays 125 us\par delay125us\par \tab movlw\tab 104\tab ;For 10 MHz clk, Machine cycle time is 4/10MHz = 400 ns\par \tab movwf\tab count1\par repeat\tab decfsz\tab count1,f\par \tab goto\tab repeat\tab ;Inner loop takes 3 cycles, since goto takes 2 cycles.\par \tab return\tab\tab ; therefore, iteration count above = 125/3*0.4 = 104\par ;\par ;Subroutine pulse - pulses data enable (E) input line of LCD Display\par pulse\tab call\tab delay125us\par \tab bsf\tab porta,1\par \tab call\tab delay125us\par \tab bcf\tab porta,1\par \tab call\tab delay125us\par \tab return\par ;\par ;Subroutine Outhinybble -- Transfers high nybble in register "bits" to top 4 bits in PORTB\par outhinybble\tab\par \tab bcf\tab portb,4\tab ;As a "default", clear bit 4 in PORTB.\par \tab btfsc\tab bits,4\tab ;test bit 4 in "bits"\par \tab bsf\tab portb,4\tab ;If this bit was actually 1, then set bit 4 in PORTB.\par \tab bcf\tab portb,5\tab ;As a "default", clear bit 5 in PORTB.\par \tab btfsc\tab bits,5\tab ;test bit 5 in "bits"\par \tab bsf\tab portb,5\tab ;If this bit was actually 1, then set bit 5 in PORTB.\par \tab bcf\tab portb,6\tab ;As a "default", clear bit 6 in PORTB.\par \tab btfsc\tab bits,6\tab ;test bit 6 in "bits"\par \tab bsf\tab portb,6\tab ;If this bit was actually 1, then set bit 6 in PORTB.\par \tab bcf\tab portb,7\tab ;As a "default", clear bit 7 in PORTB.\par \tab btfsc\tab bits,7\tab ;test bit 7 in "bits"\par \tab bsf\tab portb,7\tab ;If this bit was actually 1, then set bit 7 in PORTB.\par \tab return\par ;\par ;Subroutine Send -- Sends ASCII code in W register out to LCD display, one \par ;\tab\tab\tab nybble (4-bit part) at a time\par send\tab movwf\tab bits\par \tab call\tab outhinybble\par \tab call\tab pulse\par \tab swapf\tab bits,f\tab ;get low nybble into high position\par \tab call\tab outhinybble\par \tab call\tab pulse\par \tab return\par \tab end\par \par \par } s7IY4VWordPad DocumentC:\PIC877a\Pic Assembly Examples\lcd4b.asm#3Rich Text FormatQCp"OlePres000DITEM000ODSITEM000FMTITEM000FMT#3 FԦ֠Ԧ֠QC !I  I  O 2 .@Courier New^ bww0- B2 ';LCD Display Module Interfacing Examplem2 D;This example works for any LCD Module made by Optrex, Hitachi, etc.2 W;Two 4 bit nybbles are sent one after the other from the PIC16F84 to the LCD interface,u2 I;as explained in Microchip Application Note AN587 (DS00587B - page 3-205)s2 @H;***********************************************************************12 ;LCD connections to the PIC ?2 ` %; LCD Pin LCD Sig PIC Sig2 ` " PIC Pin #2 ; 1 2 GNDh 2 ---h 2 ---h$2 ; 2 Vcc 2 ---h 2 "---h 2 ; 2 332  Vee (Gnded for full contrast) 2 "---h 2 ; 2 4 2  RS 2 RA2h 2 P1 2 0;1 2 051U2 0 4R/W* (Gnded, since we will only write to LCD module) 2 ;1 2 61 2  E1 2 RA1h 2 P18h 2 P;12 P7-10 "2 P DB0-DB3 (Not used) 2 P"---0 2 ;1 2 11 2  DB40 2 RB40 2 P100 2 p;1 2 p12 2 p DB50 2 pRB50 2 pP110 2 ;2 2 13 2  DB60 2 RB60 2 P120 2 ;3 2 14 2  DB70 2 RB70 2 P130s2 H;*********************************************************************** 2 list2  p=16F842 @radix2 @ decimal 2 w4 2 equi 2 04 2 `"f4 2 `"equi 2 `" 14 2 #rp0i 2 #equi 2 # 54B2 %'; Special Function Register Definitions2 'status 2 ' equi 2 '0x03 2 (pcl3 2 (equ3 2 ( 0x022 0*porta 2 0*equt 2 0* 0x052 +portb 2 +equt 2 + 0x06 2 P-ddra 2 P-equa 2 P- 0x85 2 .ddrb 2 .equb 2 . 0x8692 p0!; RAM (Register File) Allocations2 2count1 2 2 equ6 2 20x0c2 3count2 2 3 equc 2 30x0d2 5count3 2 5 equd 2 50x0e 2 6bits 2 6equs 2 6 0x0f2 @8charptr 2 @8 equf 2 @80x10 2 9;4 2 `;org0 2 `; 0x00 2 <goto2 < start 2 >orgr 2 > 0x052 @start 2 @bsfr2 @ status,rp0!2 @;switch to bank 1)2 Amovlw 2 A 0x002 A2 0Cmovwf 2 0C ddra2 Dmovwf 2 D ddrbB2 D';make all PORTA and PORTB lines outputs 2 PFbcfb2 PF status,rp0(2 PF;switch back to bank 02 Gmovwf2 G porta2 pImovwf2 pI portb42 pI;make all output lines go LOW. 2 K 42 Kcall 2 K initlcd*2 K;initialize LCD display2 Lmovlw 2 L 042 Nmovwf2 N charptr2 N ;charptr = 02 Onextchar 2 @Qcall2 @Q getnxtchar2 Riorlw 2 R 04@2 R&;set Z flag if 0 returned from getmsg. 2 `Tbz 2 `T doneH2 `T+;"BZ k" is a special "Branch on Z=1" macro.@2 U&;(See Assembly Language Summary Sheet)"2 W;it expands into: 2 W' BTFSC 3,2r 2 Y;z 2 Y z2 Y"GOTO k2 Zcall 2 Z display 2 0\goto2 0\ nextchar2 ]2 P_ 2 `done2 pbloophere 2 dgoto2 d loophereQ2 e1;*********End of main program ******************* 2 g;z2 h];*********** Subroutine "GETNXTCHAR" - Returns with the next ascii code in the message below.2 @jW; - returns 0 when at end of message ***************************************2 k getnxtchar 2 `mmovf2 `m charptr,wr 2 nincf2 n charptr,frT2 n3;make charptr advance to point to next char in msg.)2 paddwf2 p pcl,fT2 p3;jump down to the desired entry (RETLW instruction))N2 r/; in the ASCII Text Message table that follows.t 2 sDT%2 s "Example using DT",0C2 s(;DT - "Define Table" assembler directiveK2 0u-;this sets up a series of RETLW instructions:@2 v&;RETLW 'E', RETLW 'x', RETLW 'a', etc.2 PxX;*************************************************************************************** 2 y;Tr2 p{G;Subroutine Display -- Sends character in W register out to LCD display*2 }displaye 2 } bsf,2 }porta,2eI2 },;Set RS = 1, readies LCD display to receive -2 ~;(ASCII code) data bytes. 2 call 2 send2 return 2 @;T2 Є\;Subroutine "initlcd" -- initializes LCD Display - in this example I have a 32 char X 2 line 2 `;T2 initlcd2 call 2 delay5ms 2 bcfl2 porta,1s2  ;E line low0 2 bcfl2  porta,2sW2 5;RS line low, when RS = 0 => set for instruction byteZ2 7;sent to the LCD display module. See instruction list.2 0movlw 2 0 0x30W2 05;Function Set Command, Gen'l format: 0 0 1 DL N F * *2 movwf 2 bitsT2 3; DL = 1 => First set for 8-bit data transfer mode. 2 Pcall2 P outhinybble0I2 P,;output 4 most sig bits -- ignore low 4 bits 2 call2 pulse 2 pcall2 p outhinybble0I2 p,;output 4 most sig bits -- ignore low 4 bits 2 call2 pulse 2 call2 outhinybble0I2 ,;output 4 most sig bits -- ignore low 4 bits 2 call2 pulse2 movlw 2 0x20X2 6; Function Set Command, Gen'l format: 0 0 1 DL N F * *2 @movwf 2 @ bits12 @; DL = 0 => 4 bit data mode. 2 Нcall2 Н outhinybble0a2 Н<; Bottom 4 bits are ignored at this time, since the four bit[2 `8; mode has just been set. From now on, however, display2 movwf 2 bitsO2 0; will expect two successive nybbles to be sent. 2 call2 outhinybble0 2 call2  pulse2 movlw 2 0x28W2 5;Function Set Command, Gen'l format: 0 0 1 DL N F * * 2 0call 2 0 send02 0; DL = 0 => 4 bit data mode.*2 ; N=1 => 1/8 duty cycle*2 P; F=0 => 5 X 7 dot font2 movlw 2 0x0fZ2 7;Display ON/OFF command, Gen'l format: 0 0 0 0 1 D C B.y'2 p; D=1 => display on, '2 ; C= 1 => cursor ON, .2 ; B = 1 => Cursor blinking 2 call 2 send2 movlw 2 0x01W2 5;Clear Display Command, Gen'l format: 0 0 0 0 0 0 0 1 2 @call 2 @ send2 жmovlw 2 ж 0x06]2 ж9;Entry Mode Set Command, Gen'l format: 0 0 0 0 0 1 I/D* SC2 `(;I/D* = 1 => Increment display addr ptr.B2 ';S = 0 => Do not shift (scroll) display. 2 call 2 send2 movlw 2  0xC3c2 =;Display Data RAM Addr Set Cmd - Gen'l Format 1 L a a a a a aT2 3; L = line number (0 is top line, 1 is bottom line) F2 0*; aaaaaa is cursor position column number.Q2 1; Here, L = 1 and aaaaaa = 000011, so this starts^2 P:; message disply on SECOND LINE and 3rd column of display. 2 call 2 send2 preturn2 p 2 ;T 2 ;T2 (2 ;Subroutine delay400ms 2 ;T2 @ delay400ms2 movlw 2 80(2 ;wait 80 5ms intervals2 `movwf2 ` count32 delay1 2 call2 delay5ms2 decfsz2 count3,f 2 goto2  delay12 return 2 0;0:2 ";Subroutine delay5ms - delays 5 ms2 Pdelay5ms2 movlw 2 40+2 ;wait 40 125us intervals2 pmovwf2 p count2NANIOle  OlePres000;DITEM000FMTRich Text Format8^t"QC !I  I  O 2 .@Courier New^ bww0- B2 ';LCD Display Module Interfacing Examplem2 D;This example works for any LCD Module made by Optrex, Hitachi, etc.2 W;Two 4 bit nybbles are sent one after the other from the PIC16F84 to the LCD interface,u2 I;as explained in Microchip Application Note AN587 (DS00587B - page 3-205)s2 @H;***********************************************************************12 ;LCD connections to the PIC ?2 ` %; LCD Pin LCD Sig PIC Sig2 ` " PIC Pin #2 ; 1 2 GNDh 2 ---h 2 ---h$2 ; 2 Vcc 2 ---h 2 "---h 2 ; 2 332  Vee (Gnded for full contrast) 2 "---h 2 ; 2 4 2  RS 2 RA2h 2 P1 2 0;1 2 051U2 0 4R/W* (Gnded, since we will only write to LCD module) 2 ;1 2 61 2  E1 2 RA1h 2 P18h 2 P;12 P7-10 "2 P DB0-DB3 (Not used) 2 P"---0 2 ;1 2 11 2  DB40 2 RB40 2 P100 2 p;1 2 p12 2 p DB50 2 pRB50 2 pP110 2 ;2 2 13 2  DB60 2 RB60 2 P120 2 ;3 2 14 2  DB70 2 RB70 2 P130s2 H;*********************************************************************** 2 list2  p=16F842 @radix2 @ decimal 2 w4 2 equi 2 04 2 `"f4 2 `"equi 2 `" 14 2 #rp0i 2 #equi 2 # 54B2 %'; Special Function Register Definitions2 'status 2 ' equi 2 '0x03 2 (pcl3 2 (equ3 2 ( 0x022 0*porta 2 0*equt 2 0* 0x052 +portb 2 +equt 2 + 0x06 2 P-ddra 2 P-equa 2 P- 0x85 2 .ddrb 2 .equb 2 . 0x8692 p0!; RAM (Register File) Allocations2 2count1 2 2 equ6 2 20x0c2 3count2 2 3 equc 2 30x0d2 5count3 2 5 equd 2 50x0e 2 6bits 2 6equs 2 6 0x0f2 @8charptr 2 @8 equf 2 @80x10 2 9;4 2 `;org0 2 `; 0x00 2 <goto2 < start 2 >orgr 2 > 0x052 @start 2 @bsfr2 @ status,rp0!2 @;switch to bank 1)2 Amovlw 2 A 0x002 A2 0Cmovwf 2 0C ddra2 Dmovwf 2 D ddrbB2 D';make all PORTA and PORTB lines outputs 2 PFbcfb2 PF status,rp0(2 PF;switch back to bank 02 Gmovwf2 G porta2 pImovwf2 pI portb42 pI;make all output lines go LOW. 2 K 42 Kcall 2 K initlcd*2 K;initialize LCD display2 Lmovlw 2 L 042 Nmovwf2 N charptr2 N ;charptr = 02 Onextchar 2 @Qcall2 @Q getnxtchar2 Riorlw 2 R 04@2 R&;set Z flag if 0 returned from getmsg. 2 `Tbz 2 `T doneH2 `T+;"BZ k" is a special "Branch on Z=1" macro.@2 U&;(See Assembly Language Summary Sheet)"2 W;it expands into: 2 W' BTFSC 3,2r 2 Y;z 2 Y z2 Y"GOTO k2 Zcall 2 Z display 2 0\goto2 0\ nextchar2 ]2 P_ 2 `done2 pbloophere 2 dgoto2 d loophereQ2 e1;*********End of main program ******************* 2 g;z2 h];*********** Subroutine "GETNXTCHAR" - Returns with the next ascii code in the message below.2 @jW; - returns 0 when at end of message ***************************************2 k getnxtchar 2 `mmovf2 `m charptr,wr 2 nincf2 n charptr,frT2 n3;make charptr advance to point to next char in msg.)2 paddwf2 p pcl,fT2 p3;jump down to the desired entry (RETLW instruction))N2 r/; in the ASCII Text Message table that follows.t 2 sDT%2 s "Example using DT",0C2 s(;DT - "Define Table" assembler directiveK2 0u-;this sets up a series of RETLW instructions:@2 v&;RETLW 'E', RETLW 'x', RETLW 'a', etc.2 PxX;*************************************************************************************** 2 y;Tr2 p{G;Subroutine Display -- Sends character in W register out to LCD display*2 }displaye 2 } bsf,2 }porta,2eI2 },;Set RS = 1, readies LCD display to receive -2 ~;(ASCII code) data bytes. 2 call 2 send2 return 2 @;T2 Є\;Subroutine "initlcd" -- initializes LCD Display - in this example I have a 32 char X 2 line 2 `;T2 initlcd2 call 2 delay5ms 2 bcfl2 porta,1s2  ;E line low0 2 bcfl2  porta,2sW2 5;RS line low, when RS = 0 => set for instruction byteZ2 7;sent to the LCD display module. See instruction list.2 0movlw 2 0 0x30W2 05;Function Set Command, Gen'l format: 0 0 1 DL N F * *2 movwf 2 bitsT2 3; DL = 1 => First set for 8-bit data transfer mode. 2 Pcall2 P outhinybble0I2 P,;output 4 most sig bits -- ignore low 4 bits 2 call2 pulse 2 pcall2 p outhinybble0I2 p,;output 4 most sig bits -- ignore low 4 bits 2 call2 pulse 2 call2 outhinybble0I2 ,;output 4 most sig bits -- ignore low 4 bits 2 call2 pulse2 movlw 2 0x20X2 6; Function Set Command, Gen'l format: 0 0 1 DL N F * *2 @movwf 2 @ bits12 @; DL = 0 => 4 bit data mode. 2 Нcall2 Н outhinybble0a2 Н<; Bottom 4 bits are ignored at this time, since the four bit[2 `8; mode has just been set. From now on, however, display2 movwf 2 bitsO2 0; will expect two successive nybbles to be sent. 2 call2 outhinybble0 2 call2  pulse2 movlw 2 0x28W2 5;Function Set Command, Gen'l format: 0 0 1 DL N F * * 2 0call 2 0 send02 0; DL = 0 => 4 bit data mode.*2 ; N=1 => 1/8 duty cycle*2 P; F=0 => 5 X 7 dot font2 movlw 2 0x0fZ2 7;Display ON/OFF command, Gen'l format: 0 0 0 0 1 D C B.y'2 p; D=1 => display on, '2 ; C= 1 => cursor ON, .2 ; B = 1 => Cursor blinking 2 call 2 send2 movlw 2 0x01W2 5;Clear Display Command, Gen'l format: 0 0 0 0 0 0 0 1 2 @call 2 @ send2 жmovlw 2 ж 0x06]2 ж9;Entry Mode Set Command, Gen'l format: 0 0 0 0 0 1 I/D* SC2 `(;I/D* = 1 => Increment display addr ptr.B2 ';S = 0 => Do not shift (scroll) display. 2 call 2 send2 movlw 2  0xC3c2 =;Display Data RAM Addr Set Cmd - Gen'l Format 1 L a a a a a aT2 3; L = line number (0 is top line, 1 is bottom line) F2 0*; aaaaaa is cursor position column number.Q2 1; Here, L = 1 and aaaaaa = 000011, so this starts^2 P:; message disply on SECOND LINE and 3rd column of display. 2 call 2 send2 preturn2 p 2 ;T 2 ;T2 (2 ;Subroutine delay400ms 2 ;T2 @ delay400ms2 movlw 2 80(2 ;wait 80 5ms intervals2 `movwf2 ` count32 delay1 2 call2 delay5ms2 decfsz2 count3,f 2 goto2  delay12 return 2 0;0:2 ";Subroutine delay5ms - delays 5 ms2 Pdelay5ms2 movlw 2 40+2 ;wait 40 125us intervals2 pmovwf2 p count2NANIp"{\rtf1\ansi\deff0{\fonttbl{\f0\fnil\fcharset0 Courier New;}} \viewkind4\uc1\pard\lang1033\f0\fs20 ;LCD Display Module Interfacing Example\par ;This example works for any LCD Module made by Optrex, Hitachi, etc.\par ;Two 4 bit nybbles are sent one after the other from the PIC16F84 to the LCD interface,\par ;as explained in Microchip Application Note AN587 (DS00587B - page 3-205)\par ;***********************************************************************\par ;LCD connections to the PIC \par ; LCD Pin LCD Sig PIC Sig\tab PIC Pin #\par ; 1\tab GND\tab\tab ---\tab\tab ---\par ; 2 Vcc\tab\tab ---\tab\tab ---\par ;\tab 3\tab Vee (Gnded for full contrast)\tab ---\par ;\tab 4\tab RS\tab\tab RA2\tab\tab P1\par ;\tab 5\tab R/W* (Gnded, since we will only write to LCD module)\par ;\tab 6\tab E\tab\tab RA1\tab\tab P18\par ;\tab 7-10 \tab DB0-DB3 (Not used)\tab\tab ---\par ;\tab 11\tab DB4\tab\tab RB4\tab\tab P10\par ;\tab 12\tab DB5\tab\tab RB5\tab\tab P11\par ;\tab 13\tab DB6\tab\tab RB6\tab\tab P12\par ;\tab 14\tab DB7\tab\tab RB7\tab\tab P13\par ;***********************************************************************\par \tab list\tab p=16F84\par \tab radix\tab decimal\par w\tab equ\tab 0\par f\tab equ\tab 1\par rp0\tab equ\tab 5\par ; Special Function Register Definitions\par status\tab equ\tab 0x03\par pcl\tab equ\tab 0x02\par porta\tab equ\tab 0x05\par portb\tab equ\tab 0x06\par ddra\tab equ\tab 0x85\par ddrb\tab equ\tab 0x86\par ; RAM (Register File) Allocations\par count1\tab equ\tab 0x0c\par count2\tab equ\tab 0x0d\par count3\tab equ\tab 0x0e\par bits\tab equ\tab 0x0f\par charptr\tab equ\tab 0x10\par ;\par \tab org\tab 0x00\par \tab goto\tab start\par \tab org\tab 0x05\par start\tab bsf\tab status,rp0\tab ;switch to bank 1\par \tab movlw\tab 0x00\tab\tab\par \tab movwf\tab ddra\par \tab movwf\tab ddrb\tab\tab ;make all PORTA and PORTB lines outputs\par \tab bcf\tab status,rp0\tab ;switch back to bank 0\par \tab movwf\tab porta\par \tab movwf\tab portb\tab\tab ;make all output lines go LOW.\par \tab call \tab initlcd\tab\tab ;initialize LCD display\par \tab movlw\tab 0\par \tab movwf\tab charptr\tab\tab ;charptr = 0\par nextchar\par \tab call\tab getnxtchar\par \tab iorlw\tab 0\tab\tab ;set Z flag if 0 returned from getmsg.\par \tab bz\tab done\tab\tab ;"BZ k" is a special "Branch on Z=1" macro.\par \tab\tab\tab\tab ;(See Assembly Language Summary Sheet)\par \tab\tab\tab\tab ;it expands into: \tab BTFSC 3,2\par \tab\tab\tab\tab ;\tab\tab \tab GOTO k\par \tab call \tab display\par \tab goto\tab nextchar\par \tab\par \tab\par done\par loophere\par \tab goto\tab loophere\par ;*********End of main program *******************\par ;\par ;*********** Subroutine "GETNXTCHAR" - Returns with the next ascii code in the message below.\par ; - returns 0 when at end of message ***************************************\par getnxtchar\par \tab movf\tab charptr,w\par \tab incf\tab charptr,f\tab ;make charptr advance to point to next char in msg.\par \tab addwf\tab pcl,f\tab\tab ;jump down to the desired entry (RETLW instruction)\par \tab\tab\tab\tab ; in the ASCII Text Message table that follows.\par \tab DT\tab "Example using DT",0\tab ;DT - "Define Table" assembler directive\par \tab\tab\tab\tab\tab ;this sets up a series of RETLW instructions:\par \tab\tab\tab\tab\tab ;RETLW 'E', RETLW 'x', RETLW 'a', etc.\par ;***************************************************************************************\par ;\par ;Subroutine Display -- Sends character in W register out to LCD display\par display\tab bsf\tab porta,2\tab\tab ;Set RS = 1, readies LCD display to receive \par \tab\tab\tab\tab ;(ASCII code) data bytes.\par \tab call\tab send\par \tab return\par ;\par ;Subroutine "initlcd" -- initializes LCD Display - in this example I have a 32 char X 2 line\par ;\par initlcd\tab call \tab delay5ms\par \tab bcf\tab porta,1\tab ;E line low\par \tab bcf\tab porta,2\tab ;RS line low, when RS = 0 => set for instruction byte\par \tab\tab\tab ;sent to the LCD display module. See instruction list.\par \tab movlw\tab 0x30\tab ;Function Set Command, Gen'l format: 0 0 1 DL N F * *\par \tab movwf\tab bits\tab ; DL = 1 => First set for 8-bit data transfer mode.\par \tab call\tab outhinybble\tab ;output 4 most sig bits -- ignore low 4 bits\par \tab call\tab pulse\par \tab call\tab outhinybble\tab ;output 4 most sig bits -- ignore low 4 bits\par \tab call\tab pulse\par \tab call\tab outhinybble\tab ;output 4 most sig bits -- ignore low 4 bits\par \tab call\tab pulse\par \tab movlw\tab 0x20\tab ; Function Set Command, Gen'l format: 0 0 1 DL N F * *\par \tab movwf\tab bits\tab ; DL = 0 => 4 bit data mode.\par \tab call\tab outhinybble\tab ; Bottom 4 bits are ignored at this time, since the four bit\par \tab\tab\tab ; mode has just been set. From now on, however, display\par \tab movwf\tab bits\tab ; will expect two successive nybbles to be sent.\par \tab call\tab outhinybble\par \tab call\tab pulse\par \tab movlw\tab 0x28\tab ;Function Set Command, Gen'l format: 0 0 1 DL N F * *\par \tab call\tab send\tab ; DL = 0 => 4 bit data mode\par \tab\tab\tab ; N=1 => 1/8 duty cycle\par \tab\tab\tab ; F=0 => 5 X 7 dot font\par \tab movlw\tab 0x0f\tab ;Display ON/OFF command, Gen'l format: 0 0 0 0 1 D C B.\par \tab\tab\tab ; D=1 => display on, \par \tab\tab\tab ; C= 1 => cursor ON, \par \tab\tab\tab ; B = 1 => Cursor blinking\par \tab call\tab send\par \tab movlw\tab 0x01\tab ;Clear Display Command, Gen'l format: 0 0 0 0 0 0 0 1\par \tab call\tab send\par \tab movlw\tab 0x06\tab ;Entry Mode Set Command, Gen'l format: 0 0 0 0 0 1 I/D* S\par \tab\tab\tab ;I/D* = 1 => Increment display addr ptr.\par \tab\tab\tab ;S = 0 => Do not shift (scroll) display\par \tab call\tab send\par \tab movlw\tab 0xC3\tab\tab ;Display Data RAM Addr Set Cmd - Gen'l Format 1 L a a a a a a\par \tab\tab\tab\tab ; L = line number (0 is top line, 1 is bottom line)\par \tab\tab\tab\tab ; aaaaaa is cursor position column number.\par \tab\tab\tab\tab ; Here, L = 1 and aaaaaa = 000011, so this starts\par \tab\tab\tab\tab ; message disply on SECOND LINE and 3rd column of display.\par \tab call\tab send\par \tab return\tab\tab\par ;\par ;\tab\par ;Subroutine delay400ms\par ;\par delay400ms\par \tab movlw\tab 80\tab ;wait 80 5ms intervals\par \tab movwf\tab count3\par delay1\tab call\tab delay5ms\par \tab decfsz\tab count3,f\par \tab goto\tab delay1\par \tab return\par ;\par ;Subroutine delay5ms - delays 5 ms\par delay5ms\par \tab movlw\tab 40\tab ;wait 40 125us intervals\par \tab movwf\tab count2\par delay\tab call\tab delay125us\par \tab decfsz\tab count2,f\par \tab goto\tab delay\par \tab return\par ;\par ;Subroutine delay125us -- delays 125 us\par delay125us\par \tab movlw\tab 104\tab ;For 10 MHz clk, Machine cycle time is 4/10MHz = 400 ns\par \tab movwf\tab count1\par repeat\tab decfsz\tab count1,f\par \tab goto\tab repeat\tab ;Inner loop takes 3 cycles, since goto takes 2 cycles.\par \tab return\tab\tab ; therefore, iteration count above = 125/3*0.4 = 104\par ;\par ;Subroutine pulse - pulses data enable (E) input line of LCD Display\par pulse\tab call\tab delay125us\par \tab bsf\tab porta,1\par \tab call\tab delay125us\par \tab bcf\tab porta,1\par \tab call\tab delay125us\par \tab return\par ;\par ;Subroutine Outhinybble -- Transfers high nybble in register "bits" to top 4 bits in PORTB\par outhinybble\tab\par \tab bcf\tab portb,4\tab ;As a "default", clear bit 4 in PORTB.\par \tab btfsc\tab bits,4\tab ;test bit 4 in "bits"\par \tab bsf\tab portb,4\tab ;If this bit was actually 1, then set bit 4 in PORTB.\par \tab bcf\tab portb,5\tab ;As a "default", clear bit 5 in PORTB.\par \tab btfsc\tab bits,5\tab ;test bit 5 in "bits"\par \tab bsf\tab portb,5\tab ;If this bit was actually 1, then set bit 5 in PORTB.\par \tab bcf\tab portb,6\tab ;As a "default", clear bit 6 in PORTB.\par \tab btfsc\tab bits,6\tab ;test bit 6 in "bits"\par \tab bsf\tab portb,6\tab ;If this bit was actually 1, then set bit 6 in PORTB.\par \tab bcf\tab portb,7\tab ;As a "default", clear bit 7 in PORTB.\par \tab btfsc\tab bits,7\tab ;test bit 7 in "bits"\par \tab bsf\tab portb,7\tab ;If this bit was actually 1, then set bit 7 in PORTB.\par \tab return\par ;\par ;Subroutine Send -- Sends ASCII code in W register out to LCD display, one \par ;\tab\tab\tab nybble (4-bit part) at a time\par send\tab movwf\tab bits\par \tab call\tab outhinybble\par \tab call\tab pulse\par \tab swapf\tab bits,f\tab ;get low nybble into high position\par \tab call\tab outhinybble\par \tab call\tab pulse\par \tab return\par \tab end\par \par \par }