PIC16f690 interfacing with LCD 16x2

Discussion in 'Embedded Systems and Microcontrollers' started by andyv, Apr 6, 2010.

  1. andyv

    andyv Thread Starter New Member

    Joined:
    Apr 6, 2010
    Messages:
    5
    Hi all,

    I'm just starting out in the world of microcontrollers, and the microchip pic was recommended to me, along with 'PIC in practice' book by D W Smith.

    I have pretty much covered everything in the book, at times with difficulty due to my minute budget. I have been using the PICkit 2 that comes with a PIC16F690, and many will confirm has hidden problebs, such as recognising switch inputs.

    My latest issue is interfacing with an 16x2 LCD alfanumeric display. I have come up with the following .asm code from sources off the internet and also the PIC in practice book.

    I am using a Displaytech display from RS- 532-6442
    Code:
     
     
    ;*********************************************************
    ; EQUATES SECTION
     #include <p16F690.inc>
     DELAY1  EQU 21h
     DELAY2  EQU 22h  
     DISPLAY  EQU 23h
     COUNT  EQU 34h
     
    ;**********************************************************************
    ; Configuration Bits
        __config (_INTRC_OSC_NOCLKOUT & _WDT_OFF & _PWRTE_OFF & _MCLRE_OFF & _CP_OFF & _BOR_OFF & _IESO_OFF & _FCMEN_OFF)
    org 0
    ;*********************************************************
    ;CONFIGURATION SECTION
    Start:
      bsf  STATUS,RP0    ;select Register Page 1
      clrf TRISC             ;make make port C outputs
      CLRF TRISA
      bcf  STATUS,RP0    ;back to Register Page 0
      bsf  STATUS,RP1    ;page 2
      clrf ANSEL             ;turn off ADC
      bcf  STATUS,RP1    ;back to page 0
      CLRF PORTA
      CLRF PORTC
     
    ;Display Configuration
      MOVLW 03h
      MOVWF PORTC  ;8 BIT DATA
      CALL  CLOCK
      CALL  DELAY
      MOVLW 02h
      MOVWF PORTC  ;CHANGE TO 4BIT
      CALL CLOCK
      CALL DELAY
      MOVLW 0h
      MOVWF PORTC  ;REPAET COMMAND
      CALL DELAY
      MOVLW 08h
      MOVWF PORTC  ;2 LINE DISPLAY
      CALL DELAY
      MOVLW 0h
      MOVWF PORTC  ;DISPLAY ON CURSOR OFF
      CALL CLOCK
      MOVLW 0Ch
      MOVWF PORTC
      CALL CLOCK
      CALL DELAY
      MOVLW 0h
      MOVWF PORTC  ;INCREMENT CURSOR
      CALL CLOCK
      MOVLW 6h
      MOVWF PORTC
      CALL CLOCK
    
      MOVLW .8
      MOVWF DISPLAY
    ;*********************************************************
    ;Program starts now.
    
    HELLO_WORLD
      CALL CLRDISP
      CLRF PORTA
      MOVLW 8h   ;CURSOR AT TOP LEFT,80h
      MOVWF PORTC
      CALL CLOCK
      MOVLW 0h
      MOVWF PORTC
      CALL  CLOCK
      BSF  PORTA,0
      CALL  H
      CALL DELAY
      CALL E
      CALL DELAY 
      CALL  L
      CALL DELAY
      CALL L
      CALL DELAY 
      CALL  O
      CALL DELAY
      CALL GAP
      CALL DELAY 
      CALL  W
      CALL DELAY
      CALL O
      CALL DELAY 
      CALL  R
      CALL DELAY
      CALL L
      CALL DELAY 
      CALL  D
      CALL DELAY
      CALL DELAY3S
      GOTO  HELLO_WORLD 
    
    ;*********************************************************
    ;SUBROUTINE SECTION.
    ;1MS DELAY
    
    DELAY
         DECFSZ    DELAY1,f             ; Waste time.  
         GOTO      DELAY        ; The Inner loop takes 3 instructions per loop * 
                                      256 loopss = 768 instructions
         DECFSZ    DELAY2,f             ; The outer loop takes and additional 3 
                                                  instructions per lap * 256 loops
         GOTO      DELAY          ; (768+3) * 256 = 197376 instructions / 1M 
                                           instructions per second = 0.197 sec.
                                          ; call it a two-tenths of a second.
         RETLW  0
     
    DELAY1S
      MOVLW .10
      MOVWF COUNT
    LOOP 
      CALL DELAY
      DECFSZ COUNT
      GOTO LOOP
      RETLW 0
    
    DELAY3S
      MOVLW .30
      MOVWF COUNT
    LOOP1 
      CALL DELAY
      DECFSZ COUNT
      GOTO LOOP1
      RETLW 0
     
    CLOCK 
      BSF  PORTA,2
      NOP
      BCF  PORTA,2
      NOP
      RETLW 0
     
    ;***********************************************************************
    ;
    ;HELLO WORLD
      
    A  MOVLW .1  ;Enables Display
      MOVWF PORTA
      MOVLW 3h  ;First part of byte (31h)
      MOVWF PORTC
      CALL CLOCK
      MOVLW 1h
      MOVWF PORTC
      CALL CLOCK
      RETLW 0
     
    H  MOVLW .1  ;Enables Display
      MOVWF PORTA
      MOVLW 3h  ;First part of byte (38h)
      MOVWF PORTC
      CALL CLOCK
      MOVLW 8h
      MOVWF PORTC
      CALL CLOCK
      RETLW 0
      
    E  MOVLW .1  ;Enables Display
      MOVWF PORTA
      MOVLW 3h  ;First part of byte (35h)
      MOVWF PORTC
      CALL CLOCK
      MOVLW 5h
      MOVWF PORTC
      CALL CLOCK
      RETLW 0
     
    L  MOVLW .1  ;Enables Display
      MOVWF PORTA
      MOVLW 3h  ;First part of byte (3Ch)
      MOVWF PORTC
      CALL CLOCK
      MOVLW 0Ch
      MOVWF PORTC
      CALL CLOCK
      RETLW 0
     
    O  MOVLW .1  ;Enables Display
      MOVWF PORTA
      MOVLW 3h  ;First part of byte (3Fh)
      MOVWF PORTC
      CALL CLOCK
      MOVLW 0Fh
      MOVWF PORTC
      CALL CLOCK
      RETLW 0
     
    WW  MOVLW .1  ;Enables Display
      MOVWF PORTA
      MOVLW 4h  ;First part of byte (47h)
      MOVWF PORTC
      CALL CLOCK
      MOVLW 7h
      MOVWF PORTC
      CALL CLOCK
      RETLW 0
     
    RR  MOVLW .1  ;Enables Display
      MOVWF PORTA
      MOVLW 4h  ;First part of byte (42h)
      MOVWF PORTC
      CALL CLOCK
      MOVLW 2h
      MOVWF PORTC
      CALL CLOCK
      RETLW 0
     
    DD  MOVLW .1  ;Enables Display
      MOVWF PORTA
      MOVLW 3h  ;First part of byte (32h)
      MOVWF PORTC
      CALL CLOCK
      MOVLW 4h
      MOVWF PORTC
      CALL CLOCK
      RETLW 0
     
    GAP  MOVLW .1  ;Enables Display
      MOVWF PORTA
      MOVLW 1h  ;First part of byte (10h)
      MOVWF PORTC
      CALL CLOCK
      MOVLW 0h
      MOVWF PORTC
      CALL CLOCK
      RETLW 0
     
    CLRDISP CLRF PORTA
      MOVLW .1  ;Enables Display
      MOVWF PORTA
      MOVLW 0h  ;First part of byte (01h)
      MOVWF PORTC
      CALL CLOCK
      MOVLW 1h
      MOVWF PORTC
      CALL CLOCK
      RETLW 0
    
       END
    
    
    If you could either go through my code, or possibly suggest code for me that I can then play with, and learn from, that would be a great help

    Thanks all,

    AndyV
    Last edited: Apr 6, 2010
  2. t06afre

    t06afre AAC Fanatic!

    Joined:
    May 11, 2009
    Messages:
    5,939
    Welcome to the forum I am sure we can help you. What is problem;) Can you write a few words about that also. And perhaps post a schematic that show us how the LCD is connected. It would be very helpful for us.
    By the way. Then you post code it is more convenient to use the code option explained here http://forum.allaboutcircuits.com/misc.php?do=bbcode#code You can edit your first posting to see the difference
  3. andyv

    andyv Thread Starter New Member

    Joined:
    Apr 6, 2010
    Messages:
    5
    Cheers t06afre,

    I'm not getting anything displayed on my screen, just all white squares surrounded by black lines (if that makes sense I'll be amazed!)

    I have connect the PIC to the LCD by RA0-RS RA2-E and RC0-RC7 - DB0-DB7 for the command lines.

    I have grounded R/W as I don't need to read back the values.

    When i check the o/p of the pic with an LED there is definatly a supply to the screen on the command lines, RS, and E. So There must be something wrong in the initialising, but i can't figure out what it is.

    Thanks again,

    Andy.
  4. MMcLaren

    MMcLaren Active Member

    Joined:
    Feb 14, 2010
    Messages:
    657
    Location:
    Michigan, USA
    Hi Andy,

    You may be running into a few problems;

    (1) You need to clear the ANSEL and ANSELH registers in bank 2 to disable the ADC and enable the I/O pins for "digital" I/O. <added> Please excuse me -- I just saw that you cleared ANSEL.

    (2) You've connected the LCD using an 8-bit data interface but the software you posted is for 4-bit interface mode. If you want to use 4-bit mode then you should ground the LCD D3 through D0 pins.

    (3) There's a reasonably precise procedure for initializing '44780 displays in either 8-bit or 4-bit interface mode. Both procedures are outlined pretty well here; Brief overview about Hitachi HD44780 LCD controller

    I attached an example program that I just threw together and tested on a 16F690 using 4-MHz INTOSC with LCD D4..D7 on RC0..RC3, LCD RS on RC4, and LCD E on RC7. Please note in the LCD init' procedure where you need to send single 4-bit nybbles instead of bytes during the first part of the procedure until the controller is switched into 4-bit mode. After that you can start sending 8-bit bytes as two nybbles.

    Best luck. Regards, Mike

    Attached Files:

    Last edited: Apr 7, 2010
  5. andyv

    andyv Thread Starter New Member

    Joined:
    Apr 6, 2010
    Messages:
    5
    Thanks guys, you've helped loads.

    Theres some language in your example Mike that I've never seen before! Theres still a long road ahead, and look forward to going down it.

    Cheers again, Andy.
  6. MMcLaren

    MMcLaren Active Member

    Joined:
    Feb 14, 2010
    Messages:
    657
    Location:
    Michigan, USA
    Hi Andy,

    You're probably talking about those assembler pseudo opcodes; skpc (skip if carry), skpnc (skip no carry), etc. They're described in the MPLAB "MPASM Assembler" help file. I use them because they're more intuitive (to me) then the 'btfss' (bit test file skip if set) or 'btfsc' (bit test file skip if clear) instructions they replace. I apologize for any confusion they may have caused you Sir.

    Good luck on your project.
  7. andyv

    andyv Thread Starter New Member

    Joined:
    Apr 6, 2010
    Messages:
    5
    No, not at all, i kinda got the hang of it once I had read it through a few times. Its nice to see more language used to open my eyes, and hopefully applications.

    Thanks.
  8. MMcLaren

    MMcLaren Active Member

    Joined:
    Feb 14, 2010
    Messages:
    657
    Location:
    Michigan, USA
    Hi Andy,

    Did you get your LCD working yet or would you like an example program setup for your 8-bit interface using RC7..RC0 (D7..D0) + RA2 (E) + RA0 (RS)?

    Mike
  9. andyv

    andyv Thread Starter New Member

    Joined:
    Apr 6, 2010
    Messages:
    5
    Sorry to resurrect this, but I think I may have found the reason why I'm being unsuccessful with the interfacing.

    I have run the program that you've suggested Mike, and it still didn't run, so I went back to basics, read through the links you've suggested, and still didn't run, so I ran the MPLAB SIM and watched the registers, it writes the info for an 8 bit interface, but only seems to write the lower 4 bits.

    Is there something obvious I'm missing?!?!

    Cheers again, Andy.
  10. MMcLaren

    MMcLaren Active Member

    Joined:
    Feb 14, 2010
    Messages:
    657
    Location:
    Michigan, USA
    Hi Andy,

    The "working" example program I posted is for 4-bit interface mode and is wired like this;

    [​IMG]

    Attached Files:

  11. halestorm

    halestorm New Member

    Joined:
    Apr 7, 2012
    Messages:
    4
    I think there's a bug in the program, in the init routine where it sends 0x03 three times followed by 0x02 once, these should be 0x30 and 0x20.

    --Dave
  12. MMcLaren

    MMcLaren Active Member

    Joined:
    Feb 14, 2010
    Messages:
    657
    Location:
    Michigan, USA
    Hi Dave,

    That's not a bug. In that portion of the LCD init sequence you need to place the upper four bits of the 0x30 and the 0x20 commands onto the D7 through D4 LCD lines. Please notice that the D7..D4 lines are connected to the RC3..RC0 pins and take a closer look at the driver (and the Hitachi HD44780 Datasheet).

    Regards, Mike
  13. t06afre

    t06afre AAC Fanatic!

    Joined:
    May 11, 2009
    Messages:
    5,939
    This thread is quite old. The Op has not posted in about two years. I would assume his problem are solved by now
  14. halestorm

    halestorm New Member

    Joined:
    Apr 7, 2012
    Messages:
    4
    Well, I tried running the code in a 16f690 and it didn't work unless I changed the 0x03 -> 0x30 and 0x02 -> 0x20.

    I wasn't pointing this out for the OP, but for future people like myself that may search these archives.
  15. MMcLaren

    MMcLaren Active Member

    Joined:
    Feb 14, 2010
    Messages:
    657
    Location:
    Michigan, USA
    Did you change the LCD init routine? The code relies on the Carry flag being clear on return from the DelayCy() routine calls.

    Then why not be more helpful to future people by posting your schematic and code?
  16. halestorm

    halestorm New Member

    Joined:
    Apr 7, 2012
    Messages:
    4
    I used the code as downloaded and the schematic as shown in the earlier post -- no changes. It didn't work. But when I changed the 0x03s and 0x02s to 0x30s and 0x20s, it worked (no other changes).
  17. MMcLaren

    MMcLaren Active Member

    Joined:
    Feb 14, 2010
    Messages:
    657
    Location:
    Michigan, USA
    Dave,

    I just tested the circuit and code and it works fine. It's difficult to say why you had a problem. If you use the simulator you'll see that using three 0x30 values and one 0x20 value results in sending four '0000' nibbles to the LCD.

    Regards, Mike
    Last edited: Apr 14, 2012
  18. t06afre

    t06afre AAC Fanatic!

    Joined:
    May 11, 2009
    Messages:
    5,939
    After power on of the LCD and during the first four writings to the LCD data bus. The lower nibble is "dont care" In the example by MMcLaren. He has connected the lower nibble of PORTC to the high nibble of the LCD databus. Hence it is correct to send 0x03 three times followed by 0x02 once. It will all depend on which nibble you use on the PIC PORTx. I have done LCD designs on the 16f690 and found using PORTB was the most practical for LCD data
  19. MMcLaren

    MMcLaren Active Member

    Joined:
    Feb 14, 2010
    Messages:
    657
    Location:
    Michigan, USA
    If Dave has the LCD D0-D3 lines grounded then the LCD is actually seeing four 8-bit 0x00 commands. I believe 0x00 ('00000000') is undefined in the HD44780 command set so I wonder if his LCD isn't just doing the normal power-up initialization into 8-bit mode and then catching the first half of the two nibble 0x28 instruction to switch into 4-bit mode? If that's the case, he could use 0x00 byte parameters for those first four instructions and get the same results. Perhaps the 30-msec time delay before the first instruction in the init sequence isn't long enough if he's using a power supply with large electrolytic capacitors which would effect Vcc/Vdd rise-time. Anyway, lots of possibilities but I don't think the 0x03 and 0x02 operands used in the HD44780 "initialize by instruction" sequence in that example program are the problem.
  20. halestorm

    halestorm New Member

    Joined:
    Apr 7, 2012
    Messages:
    4
    hi,

    OK, I need to correct a mistake in what I said but first let me start with the easy part, which is stating what remains unchanged. I also want to say, since you don't know me, I'm not trying to be a jerk, but was really trying to be helpful to future searchers. I believe you when you say it works for you. So now I'm trying to understand the problem and discrepancy. Anyway, here's what I can say with certainty:

    • I have checked and re-checked, and confirmed that my wiring is exactly as shown in Mike's schematic
    • When I run Mike's original code as downloaded, it does not work.

    There was some comment about the power supply. I have tried powering from the PICKit2 itself, from a bench ps (which has big caps), and from a 9V battery (the latter two use a 5V regulator, of course). I get the same results for all three power supplies.

    Now, here's where I was wrong. It turns out that I did change more than just 0x03 to 0x30 and 0x02 to 0x20 but forgot it when I typed my easlier post and frankly, I didn't realize the significance of it. Also, you are correct, for the wiring and the code, the values should be 0x03 and 0x02. Incidentally, once I found (what I believe to be) the actual problem, I went back and tried 0x03, 0x30, 0x20, 0x02, and even 0x00 -- and it didn't matter -- they all worked. I think what that means is that my controller is doing the internal power-up reset properly on its own, as Mike most recently suggested.

    So there is ONE difference that I have to make to the original code in order to make it work here, and that is to insert a small delay just before the command which turns the display on, which I've colored in red in the following snippet of the init routine,

    Code:
    ;
    ;  now we're in 4-bit mode and can handle 8-bit transactions
    ;
            movlw   b'00101000'     ; 4-bit, 2-lines, 5x7 font        |B0
            call    PutCMD          ; send "function set" command     |B0
            movlw   b'00001000'     ; display, cursor, blink all off  |B0
            call    PutCMD          ; send "display on/off" command   |B0
            movlw   b'00000001'     ; clear display (1.53-msecs)      |B0
            call    PutCMD          ; send "entry mode set" command   |B0
            DelayCy(1500*usecs)     ; required 1.53-msec delay        |B0
            movlw   b'00000110'     ; cursor inc, shift off           |B0
            call    PutCMD          ; send "entry mode set" command   |B0
            DelayCy(1500*usecs)
            movlw   b'00001100'     ; display on, leave cursor off    |B0
            call    PutCMD          ; send "display on/off" command   |B0
    
    I didn't pick the length of this delay for any particular reason, I just copied and pasted the one above; it could be shorter, perhaps. What I think it probably happening here is that my HD44780 is busy and doesn't accept the last command which turns the display on. (As a check to that, I also tried replacing the display-off command in the second line shown above, with a display-on command, omitting the red delay and this also works.) Probably the correct solution here would be to check the busy flag before proceeding with each write.

    Sound reasonable?

    best,

    --Dave
Similar Threads
Forum Title Date
Embedded Systems and Microcontrollers Pic16f690 LCD initialisation Jun 15, 2014
Embedded Systems and Microcontrollers PIC16F690 Potentiometers Shorting Out May 23, 2014
Embedded Systems and Microcontrollers project using pic16F690 and 2 x 16 LCD Oct 26, 2013
Embedded Systems and Microcontrollers pic16f690 migration to other pic Jul 14, 2013
Embedded Systems and Microcontrollers DS18B20 and PIC16F690 Mar 20, 2013

Share This Page