Interfacing PIC with LCD

Discussion in 'Programmer's Corner' started by Dritech, Jan 31, 2012.

  1. Dritech

    Thread Starter Well-Known Member

    Sep 21, 2011
    756
    5
    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.
     
  2. thatoneguy

    AAC Fanatic!

    Feb 19, 2009
    6,357
    718
    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)

    Code ( (Unknown Language)):
    1.  
    2.   LIST  p = 16F887            ;Simply sets the processor type being used
    3.   #INCLUDE <P16F887.INC>    ;file for processor, adds predifined labels
    4.  
    5.    __CONFIG _CONFIG1,  _HS_OSC & _WDT_OFF & _PWRTE_ON & _MCLRE_ON & _CP_OFF & _LVP_OFF
    6.                             ; Sets many parameters
    7.   org     0x00                ; Start the code at location zero
    8.  
    9.  
    10. LCD_PORT Equ PORTB
    11.  
    12. LCD_TRIS Equ TRISB
    13. LCD_RS Equ 0x04 ;LCD handshake lines
    14. LCD_E Equ 0x05
    15.  
    16.  
    17.  CBLOCK 0x20
    18.  count ; Counter used when switch pressed has stopped
    19.  count1 ; 160us Counter variable
    20.  counta ; variables for delay timers
    21.  countb ; variables for delay timers
    22.  LCDTemp ; 4 bit for LCD
    23.  ENDC ;
    24.  
    25.  org 0x000 ;  
    26.  goto Init ;
    27.  
    28. HEX_Table  
    29.  addwf PCL, f
    30.  retlw 0x30
    31.  retlw 0x31
    32.  retlw 0x32
    33.  retlw 0x33
    34.  retlw 0x34
    35.  retlw 0x35
    36.  retlw 0x36
    37.  retlw 0x37
    38.  retlw 0x38
    39.  retlw 0x39
    40.  retlw 0x41
    41.  retlw 0x42
    42.  retlw 0x43
    43.  retlw 0x44
    44.  retlw 0x45
    45.  retlw 0x46
    46.  
    47. Text  
    48.  addwf PCL, f
    49.  retlw 'B'
    50.  retlw 'E'
    51.  retlw 'N'
    52.  retlw 'S'
    53.  retlw 'O'
    54.  retlw 'N'
    55.  retlw ' '
    56.  retlw ' '
    57.  retlw ' '
    58.  retlw ' '
    59.  retlw ' '
    60.  retlw ' '
    61.  retlw 0x00
    62.  
    63. Text2  
    64.  addwf PCL, f
    65.  retlw 'W'
    66.  retlw 'A'
    67.  retlw 'M'
    68.  retlw 'B'
    69.  retlw 'U'
    70.  retlw 'L'
    71.  retlw 'U'
    72.  retlw 'L'
    73.  retlw 'U'
    74.  
    75.  
    76.  
    77.  retlw 0x00
    78.  
    79. ; Initialize the PIC and the LCD
    80. Init ;
    81.   bsf      STATUS,5            ;set memory bank 3
    82.   bsf    STATUS,6
    83.   clrf    ANSEL                ;cofigure pins as digital
    84.   clrf  ANSELH
    85.  
    86.   bcf    STATUS,5            ;set memory bank 2
    87.   bcf    CM1CON0,7            ;disable comparators
    88.   bcf    CM2CON1,7
    89.  
    90.   bcf    STATUS,6            ;set memory bank 1
    91.   bsf    STATUS,5
    92.   movlw    0XC0
    93.   movwf    TRISA                ;set port A as output except output 6 and 7
    94.   clrf    TRISB                ;set port B as output
    95.   clrf    TRISC                ;set port C as output
    96.   clrf    TRISD                ;set port D as output
    97.   bcf    STATUS,5            ;set memory bank 0
    98.  
    99.  
    100.  call LCDInit ; Initialize the LCD Display
    101.    
    102.  clrf count
    103. ; Main program...
    104. Message  
    105.  movf count, w ; put counter value in W    
    106.  call Text; get a character from the text table
    107.  xorlw 0x00 ; is it a zero?
    108.  btfsc STATUS, Z
    109.  goto NextMessage ; display next message if finished
    110.  call LCD_Char
    111.  incf count, f
    112.  goto Message
    113.  
    114. NextMessage  
    115.  call LCD_L2 ;move to 2nd row, first column
    116.  clrf count ;set counter register to zero
    117.  
    118. Message2  
    119.  movf count, w ;put counter value in W
    120.  call Text2 ;get a character from the text table
    121.  xorlw 0x00 ;is it a zero?
    122.  btfsc STATUS, Z
    123.  goto EndMessage
    124.  call LCD_Char
    125.  incf count, f
    126.  goto Message2
    127.  
    128. EndMessage  
    129.  
    130. ; Infinate loop  
    131. Stop
    132.  goto Stop ;endless loop
    133.  
    134. ; LCD routines and subs
    135. LCDInit ; 4 Bit Initialization...
    136.  call Del05 ; Wait 15 msecs
    137.  call Del05 ;
    138.  call Del05 ;
    139.  movlw 0x03 ; Send the Reset Instruction
    140.  movwf LCD_PORT ;
    141.  call Pulse_e ; Pulse LCD_E
    142.  call Del05 ; Delay 5ms
    143.  call Pulse_e ; Pulse LCD_E
    144.  call D160us ; Delay of 160us
    145.  call Pulse_e ; Pulse LCD_E
    146.  call D160us ; Delay of 160us
    147.  movlw 0x02 ; Send the Data Length Specification
    148.  movwf LCD_PORT ;
    149.  call Pulse_e ; Pulse LCD_E
    150.  call D160us ; Delay of 160us
    151.  movlw 0x028 ; Set Interface Length
    152.  call LCDIns ;
    153.  movlw 0x010 ; Turn Off Display
    154.  call LCDIns ;  
    155.  movlw 0x001 ; Clear Display RAM
    156.  call LCDIns ;
    157.  movlw 0x006 ; Set Cursor Movement
    158.  call LCDIns ;
    159.  movlw 0x00C ; Turn on Display/Cursor
    160.  call LCDIns ;
    161.  call LCD_Clr ; Clear the LCD
    162.  return ;
    163.  
    164. LCDIns ; Send the Instruction to the LCD
    165.  movwf LCDTemp ; Save the Value
    166.  swapf LCDTemp, 1
    167.  movf LCDTemp, 0
    168.  andlw 0x0F ; Most Significant Nibble first
    169.  movwf LCD_PORT ;
    170.  bcf LCD_PORT, LCD_RS ;
    171.  call Pulse_e ;
    172.  swapf LCDTemp, w ; Least Significant Nibble Second
    173.  andlw 0x0F ;
    174.  movwf LCD_PORT ;
    175.  bcf LCD_PORT, LCD_RS ;
    176.  call Pulse_e ;
    177.  call Del01 ; wait 1 ms
    178.  movf LCDTemp, w ;
    179.  andlw 0xFC ; Have to Delay 5 msecs?
    180.  btfsc STATUS, Z ;
    181.  call Del01 ; 1ms
    182.  return ;
    183.  
    184. LCD_CharD
    185.  addlw 0x30 ; add 0x30 to convert to ASCII
    186. LCD_Char ; Send the Character to the LCD
    187.  movwf LCDTemp ; Save the Value
    188.  swapf LCDTemp, 1
    189.  MovF LCDTemp, 0
    190.  andlw 0x0F ; Most Significant Nibble first
    191.  movwf LCD_PORT ;
    192.  bsf LCD_PORT, LCD_RS ;  
    193.  call Pulse_e ;
    194.  swapf LCDTemp, w ; Least Significant Nibble Second
    195.  andlw 0x0F ;
    196.  movwf LCD_PORT ;
    197.  bsf LCD_PORT, LCD_RS ;
    198.  call Pulse_e ;
    199.  call Del05 ;
    200.  nop ;
    201.  return ;
    202.  
    203.  
    204. LCD_L2: movlw 0xc0 ; move to 2nd row, first column
    205.  call LCDIns ;
    206.  retlw 0x00 ;
    207.  
    208. LCD_Clr movlw 0x01 ; Clear display
    209.  call LCDIns ;
    210.  retlw 0x00 ;
    211.  
    212. Pulse_e ;
    213.  bsf LCD_PORT, LCD_E ; LCD Enable pulse to write data from PORTB
    214.  nop ; into LCD module.
    215.  nop
    216.  bcf LCD_PORT, LCD_E ;  
    217.  nop ;
    218.  nop
    219.  retlw 0x00 ;
    220.  
    221.  
    222. ; Delay routines...
    223. D160us  
    224.  clrf count1 ;  
    225.  bsf count1, 5 ; Delay 160 usecs
    226.  bsf count1, 4 ;
    227.  decfsz count1, f ;
    228.  goto $ - 1 ;
    229.  return ;
    230.  
    231. Del255 movlw 0xff ; delay 255 mS
    232.  goto d0 ;
    233. Del200 movlw d'255' ; delay 200mS
    234.  goto d0 ;
    235. Del100 movlw d'200' ; delay 100mS
    236.  goto d0 ;
    237. Del50 movlw d'100' ; delay 50mS
    238.  goto d0 ;
    239. Del20 movlw d'40' ; delay 20mS
    240.  goto d0 ;
    241. Del05 movlw 0x10 ; delay 5.000 ms (4 MHz clock)
    242.  goto d0 ;
    243. Del01 movlw 0x05 ; delay 1.000 ms (4 MHz clock)
    244. d0 movwf count1 ;
    245. d1 movlw 0xC7 ; delay 1mS
    246.  movwf counta ;
    247.  movlw 0x04 ;
    248.  movwf countb ;
    249. Del_0 decfsz counta,f ;
    250.  goto $+2 ;
    251.  decfsz countb,f ;
    252.  goto Del_0 ;
    253.  decfsz count1,f ;
    254.  goto d1 ;
    255.  retlw 0x00 ;
    256.  
    257.  end
    258.  
     
  3. t06afre

    AAC Fanatic!

    May 11, 2009
    5,939
    1,222
  4. ErnieM

    AAC Fanatic!

    Apr 24, 2011
    7,386
    1,605
    If you were doing this in C then Microchip provides example code to do just this. I've used their code, it works (though I'm a fussy bastich and I made several changes) and may serve as a working example for you.

    However, I spent several years reading C and writing Pentium assembler so I'm familiar with the process.
     
  5. t06afre

    AAC Fanatic!

    May 11, 2009
    5,939
    1,222
    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.
    [​IMG]
     
  6. Dritech

    Thread Starter Well-Known Member

    Sep 21, 2011
    756
    5
    Hi,
    Thanks all for your help. I will read the codings you gave me and see if i manage to do my own.
     
  7. Dritech

    Thread Starter Well-Known Member

    Sep 21, 2011
    756
    5
    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:

    Code ( (Unknown Language)):
    1.     OD EQU 60H
    2.     OE EQU 61H
    3.     OF EQU 62H
    4.     O5 EQU 65H
    5.     O6 EQU 63H
    6.     COUNT1 EQU 66H
    7.     COUNT2 EQU 64H
    8.     COUNT3 EQU 67H
    9.  
    10. ;LCD DISPLAY PINOUTS
    11. ;1-GROUND, 2-VDD,
    12. ;3- VO(CONTRAST CONTROL)CONNECTED TO GROUND
    13. ;4-REGISTER SELECT = RE0 LOGIC 1 IF MICRO IS TRANSFERRING DATA
    14.                           ;LOGIC 0 IF MICRO IS TRANSFERRING A COMMAND    
    15. ;5-READ/WRITE = RE1 LOGIC 1 TO READ FROM MODULE
    16.                       ; LOGIC 0 TO WRITE TO MODULE
    17. ;6-ENABLE LINE = RE2 DATA FROM MICRO TO MODULE IS TRANSFERRED FROM HIGH TO LOW OF THE ENABLE SIGNAL
    18. ;                    DATA READ FROM MODULE TO MICRO IS TRANSFERRD FROM LOW TO HI OF THE ENABLE SIGNAL
    19. ;7-DATA BIT 0 = NC
    20. ;8-DATA BIT 1 = NC
    21. ;9-DATA BIT 2 = NC
    22. ;10-DATA BIT 3 = NC
    23. ;11-DATA BIT 4 = RD4
    24. ;12-DATA BIT 5 = RD5
    25. ;13-DATA BIT 6 = RD6
    26. ;14-DATA BIT 7 = RD7
    27. ;15-BACK LIGHT +VE --CAN BE CONNECTED TO ANY PIN
    28.  
    29.     ORG 0000H
    30.     ;GOTO MAIN
    31.  
    32.     ;HIGH PRIORITY INTERRUPT VECTOR
    33.  
    34.     ORG 0008H
    35.  
    36.     ;LOW PRIORITY INTERRUPT VECTOR
    37.  
    38.     ORG 0018H
    39.  
    40. ORG 0020H
    41.  
    42.  
    43.  
    44. ; INITIAIZATION
    45.  
    46.     ;MAIN PROGRAM
    47.  
    48.     ORG 0050H
    49.  
    50.     ;INITIALIZATION
    51.  
    52.     MOVLW 0FH            ; INITIALIZE ALL PORTS AS DIGITAL INPUTS
    53.     MOVWF ADCON1
    54.  
    55.     MOVLW 07H            ;CONFIGURE COMPARATORS FOR DIGITAL INPUTS
    56.     MOVWF CMCON    
    57.  
    58.     CLRF TRISE
    59.     CLRF PORTE
    60.  
    61.     MOVLW B'00000000'    ;PORTD IS CONFIGURED AS OUTPUTS AND INPUTS
    62.     MOVWF TRISD
    63.     CLRF LATD
    64.     CLRF PORTD
    65.        
    66.  
    67. MAIN
    68.  
    69. CALL LONG_DELAY
    70. CALL LONG_DELAY
    71.  
    72. FUNCTION_SET
    73.  
    74. BCF PORTE,0        
    75. BCF PORTE,1        
    76.  
    77. movlw    38H
    78. movwf    PORTD
    79. CALL PULSE_E
    80. CALL SMALL_DELAY
    81. CALL SMALL_DELAY
    82.  
    83. DISPLAY_ON
    84.  
    85. BCF PORTE,0        
    86. BCF PORTE,1    
    87. movlw    0FH
    88. movwf    PORTD
    89. CALL PULSE_E
    90. CALL SMALL_DELAY
    91. CALL SMALL_DELAY
    92.  
    93. CLRF OD
    94.  
    95. MESSAGE
    96.  
    97. MOVF OD,W
    98. CALL TEXT
    99. BSF PORTE,0        
    100. BCF PORTE,1    
    101. MOVWF PORTD
    102. CALL PULSE_E
    103. CALL SMALL_DELAY
    104. CALL SMALL_DELAY
    105. INCF OD,W
    106. XORLW 05H
    107. BTFSC STATUS,2
    108. GOTO STOP
    109. INCF OD,F
    110. GOTO MESSAGE
    111.  
    112. STOP
    113. GOTO STOP
    114.  
    115. TEXT
    116. ADDWF STATUS,F
    117. RETLW 'H'
    118. RETLW 'E'
    119. RETLW 'L'
    120. RETLW 'L'
    121. RETLW 'O'
    122.  
    123.  
    124. PULSE_E
    125. BSF PORTE,2
    126. NOP
    127. BCF PORTE,2
    128. RETURN
    129.  
    130.  
    131.  
    132. LONG_DELAY
    133.     movlw    D'2'
    134.     movwf    COUNT1
    135.     movlw    D'69'
    136.     movwf    COUNT2
    137.     movlw    D'169'
    138.     movwf    COUNT3
    139. loop        
    140. decfsz    COUNT1
    141. goto    loop
    142. decfsz    COUNT2
    143. goto    loop
    144. decfsz    COUNT3
    145. goto    loop
    146. RETURN
    147.  
    148.  
    149.  
    150. SMALL_DELAY
    151.     MOVLW .10
    152.     MOVWF COUNT2
    153. LABEL2
    154.     CLRF COUNT1
    155. LABEL1
    156.     DECFSZ COUNT1
    157.     GOTO LABEL1
    158.     DECFSZ COUNT2
    159.     GOTO LABEL2
    160.     RETURN
    161.  
    162. SEND
    163.  
    164. GOTO $        ; THIS WILL STOP THE MICRO FROM STARTING TO EXECUTRE THE PROGRAME AGAIN EVEN AFTER
    165.             ; SENDING IT TO THE END DIRECTIVE
    166.  
    167. END
     
    • lcd2.pdf
      File size:
      121.5 KB
      Views:
      39
  8. spinnaker

    AAC Fanatic!

    Oct 29, 2009
    4,884
    1,000
    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?
     
  9. MrChips

    Moderator

    Oct 2, 2009
    12,439
    3,360
    How is the contrast pin connected?
     
  10. spinnaker

    AAC Fanatic!

    Oct 29, 2009
    4,884
    1,000

    That is why I asked for a schematic. :)
     
  11. MrChips

    Moderator

    Oct 2, 2009
    12,439
    3,360
    Not connecting the contrast pin is a common mistake. I use a 1K resistor to ground. Without this the LCD will be blank.
     
  12. Dritech

    Thread Starter Well-Known Member

    Sep 21, 2011
    756
    5
    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
     
  13. spinnaker

    AAC Fanatic!

    Oct 29, 2009
    4,884
    1,000
    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.
     
  14. spinnaker

    AAC Fanatic!

    Oct 29, 2009
    4,884
    1,000
    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.
     
    Dritech likes this.
  15. Dritech

    Thread Starter Well-Known Member

    Sep 21, 2011
    756
    5
    Hi spinnaker thanks for you reply.

    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.

    So where the is portD i change it to LATD ?

    Thanks
     
  16. spinnaker

    AAC Fanatic!

    Oct 29, 2009
    4,884
    1,000
    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.
     
Loading...