;************************************* ; Author : Mike Baird ; Program : How to use an LCD in 4 bit mode. ; Date : October 6th, 2009 ;************************************* List P=16F88 #include "P16F88.INC" __CONFIG _CONFIG1, _PWRTE_ON & _WDT_OFF & _INTRC_IO & _BODEN_OFF & _LVP_OFF & _CP_OFF & _MCLR_OFF __CONFIG _CONFIG2, _IESO_OFF & _FCMEN_OFF ;*** Cblock *** CBLOCK 0x20 Count1 ; For delay! CountA ; CountB ; TablePoint TempLCD ENDC ;*** Defines *** LCD_Port EQU PORTA RS EQU 0x04 RW EQU 0x06 E EQU 0x07 ;*** START OF RAM *** ORG 0x000 ; Start of program vector GOTO Start ; ORG 0x004 ; Interrupt vector ;*** ISR *** RETFIE ;*** Configuration *** Start CLRF PORTA ; PortA all low CLRF PORTB ; PortB all low BSF STATUS,RP0 ; Bank 1 MOVLW b'01100000' ; Make clock 4Mhz IORWF OSCCON ; MOVLW b'00100000' ; Bit 5 input MOVWF TRISA ; PortA all output except MCLR CLRF TRISB ; PortB all output CLRF ANSEL ; Make PORTA all digital I/O BCF STATUS,RP0 ; Bank 0 CALL Delay100 ; wait for LCD to settle CALL LCD_Init ; Initialize LCD CLRF TablePoint ;*** Main *** Main movlw 'E' call LCD_Char movlw 'x' call LCD_Char movlw 'a' call LCD_Char movlw 'm' call LCD_Char movlw 'p' call LCD_Char movlw 'l' call LCD_Char movlw 'e' call LCD_Char goto $ ;Infinite Loop to hold display GOTO Main ; ;*** LCD routines *** LCD_Init MOVLW 0x20 ; Set to 4 bit mode CALL LCD_Cmd ; MOVLW 0x28 ; Set display shift to 1 CALL LCD_Cmd ; MOVLW 0x06 ; Set display move right after character sent CALL LCD_Cmd ; MOVLW 0x0D ; Set display on, don't underline cursor but flash it CALL LCD_Cmd ; CALL LCD_Clr ; Clear display RETURN LCD_Cmd MOVWF TempLCD SWAPF TempLCD,W ; Send upper nibble ANDLW 0x0F ; Clear upper 4 bits of W (Not to interfere with RS,RW and E) MOVWF LCD_Port BCF LCD_Port,RS ; RS line to 0 BSF LCD_Port,E ; Pulse the E line high NOP BCF LCD_Port,E MOVF TempLCD,W ; Send lower nibble ANDLW 0x0F ; Clear upper 4 bits of W MOVWF LCD_Port BCF LCD_Port,RS ; RS line to 0 BSF LCD_Port,E ; Pulse the E line high NOP BCF LCD_Port,E CALL Delay5 RETURN LCD_CharD ADDLW 0x30 ; Convert W to ASCII LCD_Char MOVWF TempLCD ; SWAPF TempLCD,W ; Send upper nibble ANDLW 0x0F ; Clear upper 4 bits of W MOVWF LCD_Port ; BSF LCD_Port,RS ; RS line to 1 BSF LCD_Port,E ; Pulse the E line high NOP BCF LCD_Port,E MOVF TempLCD,W ; Send lower nibble ANDLW 0x0F ; Clear upper 4 bits of W MOVWF LCD_Port BSF LCD_Port,RS ; RS line to 1 BSF LCD_Port,E ; Pulse the E line high NOP BCF LCD_Port,E CALL Delay5 RETURN LCD_Line1 MOVLW 0x80 ; Move to 1st row, first column CALL LCD_Cmd RETURN LCD_Line2 MOVLW 0xC0 ; Move to 2nd row, first column CALL LCD_Cmd RETURN LCD_Line1W ADDLW 0x80 ; Move to 1st row, column W CALL LCD_Cmd RETURN LCD_Line2W ADDLW 0xC0 ; Move to 2nd row, column W CALL LCD_Cmd RETURN LCD_CurOn MOVLW 0x0D ; Set display on/off and cursor command CALL LCD_Cmd RETURN LCD_CurOff MOVLW 0x0C ; Set display on/off and cursor command CALL LCD_Cmd RETURN LCD_Clr MOVLW 0x01 ; Clear display CALL LCD_Cmd RETURN ;*** Table *** Table ADDWF PCL RETLW 'W' RETLW 'e' RETLW 'l' RETLW 'c' RETLW 'o' RETLW 'm' RETLW 'e' RETLW ' ' RETLW 't' RETLW 'o' RETLW '.' RETLW '.' RETLW '.' CALL LCD_Line2 RETLW ' ' RETLW 'E' RETLW 'l' RETLW 'e' RETLW 'c' RETLW 't' RETLW 'r' RETLW 'o' RETLW 'B' RETLW 'i' RETLW 'r' RETLW 'd' RETLW '!' GOTO $ ; Infinite loop ;*** Delay Routines *** Delay255 MOVLW d'255' ; Delay 255 mS GOTO d0 Delay100 MOVLW d'100' ; Delay 100mS GOTO d0 Delay50 MOVLW d'50' ; Delay 50mS GOTO d0 Delay20 MOVLW d'20' ; Delay 20mS GOTO d0 Delay5 MOVLW d'5' ; Delay 5.000 ms (4 MHz clock) d0 MOVWF Count1 d1 MOVLW 0xC7 ; Delay 1mS MOVWF CountA MOVLW 0x01 MOVWF CountB Delay_0 DECFSZ CountA,F GOTO $+2 DECFSZ CountB,F GOTO Delay_0 DECFSZ Count1,F GOTO d1 RETURN ;*** END ;********************************************************************************************* ; ; The Commands: ; ; LCD_Init Initialise LCD Module ; LCD_Cmd Sent a command to the LCD ; LCD_CharD Add 0x30 to a byte and send to the LCD (to display numbers as ASCII) ; LCD_Char Send the character in W to the LCD ; LCD_Line1 Go to start of line 1 ; LCD_Line2 Go to start of line 2 ; LCD_Line1W Go to line 1 column W ; LCD_Line2W Go to line 2 column W ; LCD_CurOn Turn block cursor on ; LCD_CurOff Turn block cursor off ; LCD_Clr Clear the display ; ; ; To use the LCD you either need 11 or 7 pins. In eight bit mode it will require 8 data lines and in 4 bit mode it will ; require 4. The remaining 3 lines are "control" lines for the LCD. ; ; Control line 1 : Enable (E) ; ; This  line allows access to the display through R/W and RS lines. When this line is low, the LCD is disabled ; and ignores signals from R/W and RS. When (E) line is high, the LCD checks the state of the two control lines ; and responds accordingly. ; ; Read/Write (R/W) ; ; This line determines the direction of data between the LCD and microcontroller. When it is low, data is written ; to the LCD. When it is high, data is read from the LCD. ; ; Register select (RS) ; ; With the help of this line, the LCD interprets the type of data on data lines. When it is low, an instruction is ; being written to the LCD. When it is high, a character is being written to the LCD. ; Logic status on control lines: ; ; E     0 Access to LCD disabled ;      1 Access to LCD enabled ; ; R/W 0 Writing data to LCD ;       1 Reading data from LCD ; ; RS    0 Instruction ;       1 Character ; ; Follow these steps to write to the LCD: ; ; (1) Set R/W bit to low  ; (2) Set RS bit to logic 0 or 1 (instruction or character) ; (3) Set data to data lines (if it is writing) ; (4) Set E line to high  ; (5) Set E line to low  ; (6) Read data from data lines (if it is reading) ; ; ; LCD Command Control Codes ; Command Binary Hex ; RS RW D7 D6 D5 D4 D3 D2 D1 D0 ; Clear Display 0 0 0 0 0 0 0 0 0 1 01 ; Display and Cursor Home 0 0 0 0 0 0 0 0 1 x 02 or 03 ; Character Entry Mode 0 0 0 0 0 0 0 1 I/D S 01 to 07 ; Display On/Off and Cursor 0 0 0 0 0 0 1 D U B 08 to 0F ; Display/Cursor Shift 0 0 0 0 0 1 D/C R/L x x 10 to 1F ; Function Set 0 0 0 0 1 8/4 2/1 10/7 x x 20 to 3F ; Set CGRAM Address 0 0 0 1 A A A A A A 40 to 7F ; Set DDRAM Address 0 0 1 A A A A A A A 80 to FF ; Write DATA to RAM 1 0 D D D D D D D D 00 to FF ; Read DATA from RAM 1 1 D D D D D D D D 00 to FF ; ; I/D: 1=Increment* 0=Decrement ; S: 1=Display Shift On 0=Display Shift off* ; D: 1=Display On 0=Display Off* ; U: 1=Cursor Underline On 0=Cursor Underline Off* ; B: 1=Cursor Blink On 0=Cursor Blink Off* ; D/C: 1=Display Shift 0=Cursor Move ; ; R/L: 1=Right Shift 0=Left Shift ; 8/4: 1=8 bit interface* 0=4 bit interface ; 2/1: 1=2 line mode 0=1 line mode* ; 10/7: 1=5x10 dot format 0=5x7 dot format* ; ; *=initialisation setting x=don't care A = Address D = Data ; ; How to create custom characters: ; produce a readout using the 8 x 80 pixels of the display. Hitachi LCD displays have a standard ASCII set ; of characters plus Japanese, Greek and mathematical symbols. ; ; ; When we want to write a string of characters, first we need to set up the starting address, and then send one character ; at a time. Characters that can be shown on the display are stored in data display (DD) RAM. The size of DDRAM is 80 bytes. ; The LCD display also possesses 64 bytes of Character-Generator (CG) RAM. This memory is used for characters defined by the ; user. Data in CG RAM is represented as an 8-bit character bit-map. Each character takes up 8 bytes of CG RAM, so the total ; number of characters, which the user can define is eight. In order to read in the character bit-map to the LCD display, ; we must first set the CG RAM address to starting point (usually 0), and then write data to the display. ; ; ; Before we access DD RAM after defining a special character, the program must set the DD RAM address. Writing and ; reading data from any LCD memory is done from the last address which was set up using set-address instruction. ; Once the address of DD RAM is set, a new written character will be displayed at the appropriate place on the screen. ; Until now we discussed the operation of writing and reading to an LCD as if it were an ordinary memory. But this is not so. ; The LCD controller needs 40 to 120 microseconds (uS) for writing and reading. Other operations can take up to 5 mS. During ; that time, the microcontroller can not access the LCD, so a program needs to know when the LCD is busy. We can solve this in ; two ways. ; ; ; That's all folks! ; ;*********************************************************************************************