Interfacing PIC with LCD

Thread Starter

Dritech

Joined Sep 21, 2011
869
Hi all,

I want to interface an LCD with an 18F4550 pic using assembly. This is the first time that I'm going to interface an LCD with a PIC. Do you know of any good tutorials of how to do this in assembly?

All kind of help is appreciated.

Thanks in advance.
 

thatoneguy

Joined Feb 19, 2009
6,359
This old thread has some code.

The idea, the 4 lines for data + enable and reset lines are a pretty standard setup, as well as the timing between commands being a bit critical.

That code can be ported to your project without too much of a hassle, and is the most "bare bones" version I could find in a quick search here.

You'll need to change some of the PIC18 stuff to PIC16, such as output ports writing to PORTx on PIC16, rather than LATx on PIC18.

Please limit any discussion about it to this thread only. (don't reply to the old thread)

Rich (BB code):
  LIST  p = 16F887            ;Simply sets the processor type being used
  #INCLUDE <P16F887.INC>    ;file for processor, adds predifined labels

   __CONFIG _CONFIG1,  _HS_OSC & _WDT_OFF & _PWRTE_ON & _MCLRE_ON & _CP_OFF & _LVP_OFF
                            ; Sets many parameters
  org     0x00                ; Start the code at location zero


LCD_PORT Equ PORTB 

LCD_TRIS Equ TRISB
LCD_RS Equ 0x04 ;LCD handshake lines
LCD_E Equ 0x05

  
 CBLOCK 0x20 
 count ; Counter used when switch pressed has stopped 
 count1 ; 160us Counter variable 
 counta ; variables for delay timers 
 countb ; variables for delay timers 
 LCDTemp ; 4 bit for LCD 
 ENDC ; 
  
 org 0x000 ;  
 goto Init ; 
  
HEX_Table  
 addwf PCL, f 
 retlw 0x30 
 retlw 0x31 
 retlw 0x32 
 retlw 0x33 
 retlw 0x34 
 retlw 0x35 
 retlw 0x36 
 retlw 0x37 
 retlw 0x38 
 retlw 0x39 
 retlw 0x41 
 retlw 0x42 
 retlw 0x43 
 retlw 0x44 
 retlw 0x45 
 retlw 0x46 
  
Text  
 addwf PCL, f 
 retlw 'B' 
 retlw 'E' 
 retlw 'N' 
 retlw 'S' 
 retlw 'O' 
 retlw 'N' 
 retlw ' ' 
 retlw ' ' 
 retlw ' ' 
 retlw ' ' 
 retlw ' ' 
 retlw ' ' 
 retlw 0x00 
  
Text2  
 addwf PCL, f 
 retlw 'W' 
 retlw 'A' 
 retlw 'M' 
 retlw 'B' 
 retlw 'U' 
 retlw 'L'
 retlw 'U' 
 retlw 'L' 
 retlw 'U' 
 


 retlw 0x00 
  
; Initialize the PIC and the LCD 
Init ; 
  bsf      STATUS,5            ;set memory bank 3
  bsf    STATUS,6
  clrf    ANSEL                ;cofigure pins as digital
  clrf  ANSELH

  bcf    STATUS,5            ;set memory bank 2
  bcf    CM1CON0,7            ;disable comparators
  bcf    CM2CON1,7

  bcf    STATUS,6            ;set memory bank 1
  bsf    STATUS,5
  movlw    0XC0
  movwf    TRISA                ;set port A as output except output 6 and 7
  clrf    TRISB                ;set port B as output
  clrf    TRISC                ;set port C as output
  clrf    TRISD                ;set port D as output
  bcf    STATUS,5            ;set memory bank 0

  
 call LCDInit ; Initialize the LCD Display
   
 clrf count
; Main program... 
Message  
 movf count, w ; put counter value in W    
 call Text; get a character from the text table 
 xorlw 0x00 ; is it a zero? 
 btfsc STATUS, Z 
 goto NextMessage ; display next message if finished
 call LCD_Char 
 incf count, f 
 goto Message 
  
NextMessage  
 call LCD_L2 ;move to 2nd row, first column 
 clrf count ;set counter register to zero 
  
Message2  
 movf count, w ;put counter value in W 
 call Text2 ;get a character from the text table 
 xorlw 0x00 ;is it a zero? 
 btfsc STATUS, Z 
 goto EndMessage 
 call LCD_Char 
 incf count, f 
 goto Message2 
  
EndMessage  
  
; Infinate loop  
Stop 
 goto Stop ;endless loop 
  
; LCD routines and subs 
LCDInit ; 4 Bit Initialization... 
 call Del05 ; Wait 15 msecs 
 call Del05 ; 
 call Del05 ; 
 movlw 0x03 ; Send the Reset Instruction 
 movwf LCD_PORT ; 
 call Pulse_e ; Pulse LCD_E 
 call Del05 ; Delay 5ms 
 call Pulse_e ; Pulse LCD_E 
 call D160us ; Delay of 160us 
 call Pulse_e ; Pulse LCD_E 
 call D160us ; Delay of 160us 
 movlw 0x02 ; Send the Data Length Specification 
 movwf LCD_PORT ; 
 call Pulse_e ; Pulse LCD_E 
 call D160us ; Delay of 160us 
 movlw 0x028 ; Set Interface Length 
 call LCDIns ; 
 movlw 0x010 ; Turn Off Display 
 call LCDIns ;  
 movlw 0x001 ; Clear Display RAM 
 call LCDIns ; 
 movlw 0x006 ; Set Cursor Movement 
 call LCDIns ; 
 movlw 0x00C ; Turn on Display/Cursor 
 call LCDIns ; 
 call LCD_Clr ; Clear the LCD 
 return ; 
  
LCDIns ; Send the Instruction to the LCD
 movwf LCDTemp ; Save the Value 
 swapf LCDTemp, 1
 movf LCDTemp, 0
 andlw 0x0F ; Most Significant Nibble first 
 movwf LCD_PORT ; 
 bcf LCD_PORT, LCD_RS ; 
 call Pulse_e ; 
 swapf LCDTemp, w ; Least Significant Nibble Second 
 andlw 0x0F ; 
 movwf LCD_PORT ; 
 bcf LCD_PORT, LCD_RS ; 
 call Pulse_e ; 
 call Del01 ; wait 1 ms 
 movf LCDTemp, w ; 
 andlw 0xFC ; Have to Delay 5 msecs? 
 btfsc STATUS, Z ; 
 call Del01 ; 1ms 
 return ; 
  
LCD_CharD 
 addlw 0x30 ; add 0x30 to convert to ASCII 
LCD_Char ; Send the Character to the LCD 
 movwf LCDTemp ; Save the Value 
 swapf LCDTemp, 1
 MovF LCDTemp, 0
 andlw 0x0F ; Most Significant Nibble first 
 movwf LCD_PORT ; 
 bsf LCD_PORT, LCD_RS ;  
 call Pulse_e ; 
 swapf LCDTemp, w ; Least Significant Nibble Second 
 andlw 0x0F ; 
 movwf LCD_PORT ; 
 bsf LCD_PORT, LCD_RS ; 
 call Pulse_e ; 
 call Del05 ; 
 nop ; 
 return ; 
  
  
LCD_L2: movlw 0xc0 ; move to 2nd row, first column 
 call LCDIns ; 
 retlw 0x00 ; 
  
LCD_Clr movlw 0x01 ; Clear display 
 call LCDIns ; 
 retlw 0x00 ; 
  
Pulse_e ; 
 bsf LCD_PORT, LCD_E ; LCD Enable pulse to write data from PORTB 
 nop ; into LCD module. 
 nop
 bcf LCD_PORT, LCD_E ;  
 nop ;
 nop 
 retlw 0x00 ; 
  
  
; Delay routines... 
D160us  
 clrf count1 ;  
 bsf count1, 5 ; Delay 160 usecs 
 bsf count1, 4 ; 
 decfsz count1, f ; 
 goto $ - 1 ; 
 return ; 
  
Del255 movlw 0xff ; delay 255 mS 
 goto d0 ; 
Del200 movlw d'255' ; delay 200mS 
 goto d0 ; 
Del100 movlw d'200' ; delay 100mS 
 goto d0 ; 
Del50 movlw d'100' ; delay 50mS 
 goto d0 ; 
Del20 movlw d'40' ; delay 20mS 
 goto d0 ; 
Del05 movlw 0x10 ; delay 5.000 ms (4 MHz clock) 
 goto d0 ; 
Del01 movlw 0x05 ; delay 1.000 ms (4 MHz clock) 
d0 movwf count1 ; 
d1 movlw 0xC7 ; delay 1mS 
 movwf counta ; 
 movlw 0x04 ; 
 movwf countb ; 
Del_0 decfsz counta,f ; 
 goto $+2 ; 
 decfsz countb,f ; 
 goto Del_0 ; 
 decfsz count1,f ; 
 goto d1 ; 
 retlw 0x00 ; 
  
 end
 

t06afre

Joined May 11, 2009
5,934
Also timing is VERY important. The LCD display is a slow device. So if you do not check the BUSSY flag. You must give the LCD proper time to get finished with current instruction, before accessing the LCD again.
 

Thread Starter

Dritech

Joined Sep 21, 2011
869
Hi all,

I tried to do the coding but its still not working. The LCD is remaining blank. The tutorial in using is attached below and im using the coding of experiment 8. Can someone help me with the coding please.

Thanks in advance.

Below is my coding:

Rich (BB code):
    OD EQU 60H
    OE EQU 61H
    OF EQU 62H
    O5 EQU 65H
    O6 EQU 63H
    COUNT1 EQU 66H
    COUNT2 EQU 64H
    COUNT3 EQU 67H

;LCD DISPLAY PINOUTS
;1-GROUND, 2-VDD,
;3- VO(CONTRAST CONTROL)CONNECTED TO GROUND
;4-REGISTER SELECT = RE0 LOGIC 1 IF MICRO IS TRANSFERRING DATA
                          ;LOGIC 0 IF MICRO IS TRANSFERRING A COMMAND    
;5-READ/WRITE = RE1 LOGIC 1 TO READ FROM MODULE
                      ; LOGIC 0 TO WRITE TO MODULE
;6-ENABLE LINE = RE2 DATA FROM MICRO TO MODULE IS TRANSFERRED FROM HIGH TO LOW OF THE ENABLE SIGNAL 
;                    DATA READ FROM MODULE TO MICRO IS TRANSFERRD FROM LOW TO HI OF THE ENABLE SIGNAL
;7-DATA BIT 0 = NC
;8-DATA BIT 1 = NC
;9-DATA BIT 2 = NC
;10-DATA BIT 3 = NC
;11-DATA BIT 4 = RD4
;12-DATA BIT 5 = RD5
;13-DATA BIT 6 = RD6
;14-DATA BIT 7 = RD7
;15-BACK LIGHT +VE --CAN BE CONNECTED TO ANY PIN

    ORG 0000H
    ;GOTO MAIN

    ;HIGH PRIORITY INTERRUPT VECTOR

    ORG 0008H

    ;LOW PRIORITY INTERRUPT VECTOR

    ORG 0018H

ORG 0020H


  
; INITIAIZATION

    ;MAIN PROGRAM

    ORG 0050H

    ;INITIALIZATION

    MOVLW 0FH            ; INITIALIZE ALL PORTS AS DIGITAL INPUTS
    MOVWF ADCON1

    MOVLW 07H            ;CONFIGURE COMPARATORS FOR DIGITAL INPUTS
    MOVWF CMCON    

    CLRF TRISE
    CLRF PORTE

    MOVLW B'00000000'    ;PORTD IS CONFIGURED AS OUTPUTS AND INPUTS
    MOVWF TRISD 
    CLRF LATD
    CLRF PORTD
        

MAIN

CALL LONG_DELAY
CALL LONG_DELAY

FUNCTION_SET

BCF PORTE,0        
BCF PORTE,1        

movlw    38H
movwf    PORTD
CALL PULSE_E
CALL SMALL_DELAY
CALL SMALL_DELAY

DISPLAY_ON

BCF PORTE,0        
BCF PORTE,1    
movlw    0FH
movwf    PORTD
CALL PULSE_E
CALL SMALL_DELAY
CALL SMALL_DELAY

CLRF OD

MESSAGE

MOVF OD,W
CALL TEXT
BSF PORTE,0        
BCF PORTE,1    
MOVWF PORTD
CALL PULSE_E
CALL SMALL_DELAY
CALL SMALL_DELAY
INCF OD,W
XORLW 05H
BTFSC STATUS,2
GOTO STOP
INCF OD,F
GOTO MESSAGE

STOP
GOTO STOP

TEXT
ADDWF STATUS,F
RETLW 'H'
RETLW 'E'
RETLW 'L'
RETLW 'L'
RETLW 'O'


PULSE_E
BSF PORTE,2
NOP
BCF PORTE,2
RETURN



LONG_DELAY
    movlw    D'2'
    movwf    COUNT1
    movlw    D'69'
    movwf    COUNT2
    movlw    D'169'
    movwf    COUNT3
loop        
decfsz    COUNT1
goto    loop
decfsz    COUNT2
goto    loop
decfsz    COUNT3
goto    loop
RETURN



SMALL_DELAY
    MOVLW .10
    MOVWF COUNT2
LABEL2
    CLRF COUNT1
LABEL1
    DECFSZ COUNT1
    GOTO LABEL1
    DECFSZ COUNT2
    GOTO LABEL2
    RETURN

SEND

GOTO $        ; THIS WILL STOP THE MICRO FROM STARTING TO EXECUTRE THE PROGRAME AGAIN EVEN AFTER
            ; SENDING IT TO THE END DIRECTIVE

END
 

Attachments

spinnaker

Joined Oct 29, 2009
7,835
Hi all,

I tried to do the coding but its still not working. The LCD is remaining blank. The tutorial in using is attached below and im using the coding of experiment 8. Can someone help me with the coding please.

Thanks in advance.
Have you tried stepping through your code and confirming that everything is changing on the input to the LCD as expected?

Where is your schematic?
 

MrChips

Joined Oct 2, 2009
21,393
Not connecting the contrast pin is a common mistake. I use a 1K resistor to ground. Without this the LCD will be blank.
 

Thread Starter

Dritech

Joined Sep 21, 2011
869
Hi all,

The problem was that the starting delay was too long. Now i have another problem. Instead of HELLO, it LCD is displaying HHHHH (i.e. the first letter of hello for 5 times). Does someone knows where's the mistake in the coding?

Thanks
 

spinnaker

Joined Oct 29, 2009
7,835
Hi all,

The problem was that the starting delay was too long. Now i have another problem. Instead of HELLO, it LCD is displaying HHHHH (i.e. the first letter of hello for 5 times). Does someone knows where's the mistake in the coding?

Thanks
Well I am by far no assembler expert but it seems to me you are returning H right away in the second instruction.

Not sure what you are trying to do there but it seems inefficient to me (as I said I am far from an expert). I can't give you any details on how to do it but it seems that a far more efficient way to do this is to store your text in an array then increment a pointer to that text and display it on the LCD.

This is a heck of a lot easier to do in C.
 

spinnaker

Joined Oct 29, 2009
7,835
If you don't want to use an array of characters and still want to do it this way, you might as well simplify things and just move the character to the latch on by one.

The way you are doing it really does not buy you anything except maybe making the code slightly more readable.


BTW on the 18F you should be setting latches and not ports. You read a port and set a latch. Search for "Read-modify-write operations" in your datasheet.
 

Thread Starter

Dritech

Joined Sep 21, 2011
869
Hi spinnaker thanks for you reply.

you might as well simplify things and just move the character to the latch on by one.
Can you tell me how to move the characters to the latch one by one please? im still a beginner in programming and dont know how to do that.

BTW on the 18F you should be setting latches and not ports. You read a port and set a latch. Search for "Read-modify-write operations" in your datasheet.
So where the is portD i change it to LATD ?

Thanks
 

spinnaker

Joined Oct 29, 2009
7,835
Yes change PORTD to LATD.

As I said I am no assembler expert. I don't want to send you down the wrong path.
If you wanted to do it in C then I could help.

And as I said the right way to do it is to store the text in a table. You are adding a lot of needless codes for the returns doing it this way.
 
Top