Pic16f690 LCD initialisation

Discussion in 'Embedded Systems and Microcontrollers' started by Egberts, Jun 15, 2014.

  1. Egberts

    Thread Starter New Member

    Jun 7, 2014
    13
    0
    Hello guys!
    I have a small problem again and it is driving me nuts. I am trying to interface a pic16f690 with a LCD (Hitachi 44780). But I only get black boxes on my screen. I have been searching the whole internet but didn't find any results.

    I used this tutorial (http://www.pyroelectro.com/tutorials/pic_lcd/schematic.html) as a basic start and used his code(see below). I have connected RS to RC7, RW to RC6 and E to RC5 and port D4 tot D7 to PORTB of the pic for 4 bit communication.

    I don't think it is a contrast problem, since i have connected a 10k pot between the VCC en VO pin. When i turn down the pot the black boxes only get less visible. I checked all the connection a hundred times, so that wont be the problem also.

    I really hope someone can help me!
    Thanks!

    Code ( (Unknown Language)):
    1. #include <htc.h>
    2. #include <pic.h>
    3. #include <pic16f690.h>
    4.  
    5.  
    6.  
    7. #define RS_PIN   PORTCbits.RC7   /* PORT for RS */
    8. #define RW_PIN   PORTCbits.RC6   /* PORT for RW */
    9. #define E_PIN    PORTCbits.RC5   /* PORT for E  */
    10.  
    11.  
    12.  
    13.     unsigned char counter=0;//Overflow counter
    14.            int count=0;
    15.  
    16.     char output[] = " Hello";
    17.     char output2[] = "World";
    18.  
    19. void prnt(unsigned int);
    20. void commd(unsigned int);
    21. void lcd_init(void);
    22.  
    23.  
    24.     void main()
    25.     {
    26.  
    27.        ANSEL = 0;
    28.       ANSELH=0;
    29.  
    30.       TRISC=0;     // PORTC = output
    31.       PORTC=0;     // PORTC reset      
    32.  
    33.  
    34.  
    35.     TRISC=0x00;
    36.     TRISB=0x00;
    37.  
    38.     PORTB=0x00;
    39.     PORTC=0x00;
    40.  
    41.         __delay_ms(100);
    42.  
    43.     lcd_init();
    44.  
    45.     while(output[count] != '\0')
    46.     {
    47.     prnt(output[count]);
    48.     count++;
    49.     }
    50.  
    51.     commd(0b11000000);  //Move 2nd Next Line
    52.  
    53.     count = 0;
    54.     while(output2[count] != '\0')
    55.     {
    56.     prnt(output2[count]);
    57.     count++;
    58.     }
    59.  
    60.     commd(0b10000000);
    61.  
    62.       while(1)
    63.       {
    64.  
    65.       };
    66.     }
    67.  
    68.  
    69.  
    70. void lcd_init(void)
    71. {
    72. E_PIN = 0;
    73. RS_PIN = 0;
    74. RW_PIN = 0;
    75.  
    76. commd(0b00000010);
    77.  
    78. commd(0b00101000);
    79.  
    80. commd(0b00001100);
    81.  
    82. commd(0b00000001);
    83.  
    84. commd(0b00000010);
    85.  
    86. }
    87.  
    88.  
    89. //4-bit print interface
    90.  
    91. void prnt(unsigned int character)
    92. {
    93.  
    94. PORTB=character >> 4;
    95.  
    96. RS_PIN = 1;
    97. E_PIN = 1;
    98. __delay_ms(200);
    99. E_PIN = 0;
    100. RS_PIN = 0;
    101.  
    102. PORTB=character & 0x0f;
    103.  
    104. RS_PIN = 1;
    105. E_PIN = 1;
    106. __delay_ms(200);
    107. E_PIN = 0;
    108. RS_PIN = 0;
    109.  
    110.  
    111.  
    112. }
    113.  
    114.  
    115. //4-bit instruction interface
    116.  
    117. void commd(unsigned int commd)
    118. {
    119.  
    120. PORTB=commd >> 4;
    121. E_PIN = 1;
    122. E_PIN = 0;
    123.  
    124. PORTB=commd &0x0f;
    125. E_PIN = 1;
    126. E_PIN = 0;
    127.  
    128. __delay_ms(200);
    129.  
    130. }
    131.  
    132.  
     
  2. shteii01

    AAC Fanatic!

    Feb 19, 2010
    3,377
    494
    It looks like you modified their code badly.

    This should be inside main():
    unsigned char counter=0;//Overflow counter
    int count=0;
    char output[] = " Hello";
    char output2[] = "World";
     
  3. Egberts

    Thread Starter New Member

    Jun 7, 2014
    13
    0
    Thanks for the answer, that was a small mistake indeed.
    I changed is but still nothing happens..
    Maybe it is something with my delay? I am using the standard delay from the pic.h header. MPLAB X keeps saying that he is unable to resolve identifier __delay_ms. But when I compile my project, there are no errors or warnings.
    I already tried building my own delay but that didn't work either.

    Thanks in advance!
     
  4. ErnieM

    AAC Fanatic!

    Apr 24, 2011
    7,386
    1,605
    MPLAB X throws false warning all the time. If it compiles despite the warning then you can very safely ignore it.

    While there are several areas for improvement nothing jumps out as bad in the code. Once it works you can run thru and pull out some of the incredibly long delays (you should be able to print more then 2 characters/sec).

    Do you have a schematic to check? Did you put in that contrast pot?
     
  5. Egberts

    Thread Starter New Member

    Jun 7, 2014
    13
    0
    Allright thanks that is good to know!
    Yeah i just used the schematic as mentioned in the tutorial, I only changed some ports to fit my solution(see first post for specific ports). And i added a 10k pot between VCC and VO, and that gives blackboxes when on 10K and nothing when he has a value of 0.
    I even tried to short VO to ground, which also gave me black boxes..
    Also the backlight is connected with a 100ohm resistor to VCC, but on my LCD the VCC and ground are switched in comparison with the schematic in the tutorial
     
  6. jjw

    Member

    Dec 24, 2013
    173
    31
    Why you have unsigned int as argument in prnt function, when you are displaying unsigned characters?
     
  7. MrChips

    Moderator

    Oct 2, 2009
    12,415
    3,354
    Why are you changing the state of RS_PIN unnecessarily in prnt( ) ?

    Why are you ANDing with 0x0f ?

    What is your delay between PORTB output, E_PIN = 1 and E_PIN = 0 ?

    Why not test by sending the same character such as 0x41 (which is 'A') ?
     
  8. Egberts

    Thread Starter New Member

    Jun 7, 2014
    13
    0
    Thanks for answers guys!
    I changed the code like you said, but still nothing happens.. This is my new code, I hope you can help me one more time!

    Thanks!

    Code ( (Unknown Language)):
    1. #include <htc.h>
    2. #include <pic.h>
    3. #include <pic16f690.h>
    4.  
    5. #define RS_PIN   PORTCbits.RC7   /* PORT for RS */
    6. #define RW_PIN   PORTCbits.RC6   /* PORT for RW */
    7. #define E_PIN    PORTCbits.RC5   /* PORT for E  */
    8.  
    9. void prnt(unsigned char);
    10. void commd(unsigned char);
    11. void lcd_init(void);
    12.  
    13.     void main()
    14.     {
    15.         unsigned char counter=0;//Overflow counter
    16.         int count=0;
    17.  
    18.     char output[] = " PyroElectro.com";
    19.     char output2[] = "Is Where Its At!";
    20.        
    21.        initTMR0();  //TMR0 init
    22.        ANSEL = 0;
    23.        ANSELH=0;
    24.        TRISC=0;     // PORTC = output
    25.        PORTC=0;     // PORTC reset
    26.  
    27.        TRISC=0x00;
    28.        TRISB=0x00;
    29.  
    30.     PORTB=0x00;
    31.     PORTC=0x00;
    32.  
    33.         __delay_ms(100);
    34.  
    35.     lcd_init();
    36.  
    37.     while(output[count] != '\0')
    38.     {
    39.     prnt(output[count]);
    40.     count++;
    41.     }
    42.  
    43.     commd(0b11000000);  //Move 2nd Next Line
    44.  
    45.     count = 0;
    46.     while(output2[count] != '\0')
    47.     {
    48.     prnt(output2[count]);
    49.     count++;
    50.     }
    51.  
    52.     commd(0b10000000);
    53.  
    54.       while(1)
    55.       {
    56.  
    57.       };
    58.     }
    59.  
    60. void lcd_init(void)
    61. {
    62. E_PIN = 0;
    63. RS_PIN = 0;
    64. RW_PIN = 0;
    65.  
    66. commd(0b00000010);
    67.  
    68. commd(0b00101000);
    69.  
    70. commd(0b00001100);
    71.  
    72. commd(0b00000001);
    73.  
    74. commd(0b00000010);
    75.  
    76. }
    77.  
    78. //4-bit print interface
    79. void prnt(unsigned char character)
    80. {
    81. PORTB=character >> 4;
    82.  
    83. //RS_PIN = 1;
    84. E_PIN = 1;
    85. __delay_ms(200);
    86. E_PIN = 0;
    87. //RS_PIN = 0;
    88.  
    89. PORTB=character >> 4;
    90.  
    91. //RS_PIN = 1;
    92. E_PIN = 1;
    93. __delay_ms(200);
    94. E_PIN = 0;
    95. //RS_PIN = 0;
    96.  
    97. }
    98.  
    99. //4-bit instruction interface
    100. void commd(unsigned char commd)
    101. {
    102. PORTB=commd >> 4;
    103. E_PIN = 1;
    104. __delay_ms(200);
    105. E_PIN = 0;
    106.  
    107. PORTB=commd >> 4;
    108. E_PIN = 1;
    109. __delay_ms(200);
    110. E_PIN = 0;
    111.  
    112. __delay_ms(10);
    113.  
    114. }
     
  9. deme

    New Member

    Mar 24, 2014
    11
    1
    Is the 100ms delay important? If it is, then it's possible your code does not provide enough delay because 100 may be too large for the __delay_ms() (as the MPLABX warning states). :confused:
     
  10. ErnieM

    AAC Fanatic!

    Apr 24, 2011
    7,386
    1,605
    Not quite... MPLAB is barking up the wrong tree here saying it is "unable to resolve identifier". It this compiles then the compiler can find that identifier (the function name). That is different from passing too large an argument. Reading the help file (otherwise known as the MPLAB® XC8 C Compiler User’s Guide) shows no max number for any of the delay macros.

    HOWEVER... it does state the following:
    That would look something like
    Code ( (Unknown Language)):
    1.     #define [FONT=Courier New][SIZE=2][FONT=Courier New][SIZE=2]_XTAL_FREQ  8000000 // for an 8MHz crystal
    2. [/SIZE][/FONT][/SIZE][/FONT]
    I don't see this symbol defined in your code. Try that and see.

    I would hope the XC8 library would throw an error without this importaint symbol being defined... but one never knows, does one?
     
  11. ErnieM

    AAC Fanatic!

    Apr 24, 2011
    7,386
    1,605
    HAH! And I just also noticed you don't have the configuration bits set in the code. If you can do this elsewhere again check they are correct.

    Final hint is make sure your PIC is basically working with a simple test program. This can be as simple as making one pin change every second: put a LED there and you can tell with a wrist watch if the code is working and the delays are proper.

    Do you have an in circuit debugger? The pic16f690 can be checked using either PICkit 2 or 3, if the programming pins are free when nornmally running. I design all my boards so these are free just for this purpose.
     
  12. Egberts

    Thread Starter New Member

    Jun 7, 2014
    13
    0
    Yea you are right, to use the __delay_ms() function you have to set the XTAL frequency. I defined mine as a macro inside the compiler properties. Same goes for the configuration bits, I defined them in configuration_bits.c in the source folder. But nothing changes when i import them to my main file. These are my config bits by the way:

    Code ( (Unknown Language)):
    1. #pragma config FOSC = INTRCCLK  // Oscillator Selection bits (INTOSC oscillator: CLKOUT function on RA4/OSC2/CLKOUT pin, I/O function on RA5/OSC1/CLKIN)
    2. #pragma config WDTE = OFF       // Watchdog Timer Enable bit (WDT disabled and can be enabled by SWDTEN bit of the WDTCON register)
    3. #pragma config PWRTE = OFF      // Power-up Timer Enable bit (PWRT disabled)
    4. #pragma config MCLRE = ON       // MCLR Pin Function Select bit (MCLR pin function is MCLR)
    5. #pragma config CP = OFF         // Code Protection bit (Program memory code protection is disabled)
    6. #pragma config CPD = OFF        // Data Code Protection bit (Data memory code protection is disabled)
    7. #pragma config BOREN = ON       // Brown-out Reset Selection bits (BOR enabled)
    8. #pragma config IESO = ON        // Internal External Switchover bit (Internal External Switchover mode is enabled)
    9. #pragma config FCMEN = ON       // Fail-Safe Clock Monitor Enabled bit (Fail-Safe Clock Monitor is enabled)
    I also tried your advice to test the delay function with a blinking LED, and this works on every port of the PIC. I am really tired of being stuck on this problem. Do you guys have any tips or example codes i could use?

    Thanks!
     
  13. MMcLaren

    Well-Known Member

    Feb 14, 2010
    759
    116
    Would you confirm that you have LCD D4-D7 pins connected to RB0..RB3 pins on the 16F690, please?
     
  14. Egberts

    Thread Starter New Member

    Jun 7, 2014
    13
    0
    Well, I connected pin D4-D7 to port RB4-RB7 since the PIC16f690 only has these PORTB connections. I assumed that would be no problem?
     
  15. MMcLaren

    Well-Known Member

    Feb 14, 2010
    759
    116
    Oops, that's a problem... You'll need to change your low-level routines...

    Code ( (Unknown Language)):
    1. void prnt(unsigned int character)
    2. {
    3.   RW_PIN = 0;                // write op
    4.   RS_PIN = 1;                // RS = 1, Data
    5.   PORTB = character & 0xF0;  // send hi nibble
    6.   E_PIN = 1;                 // write LCD
    7.   E_PIN = 0;                 //  "
    8.   PORTB = character << 4;    // send lo nibble
    9.   E_PIN = 1;                 // write LCD
    10.   E_PIN = 0;                 //  "
    11.   __delay_us(50);            // inter-write delay
    12. }
    13.  
    14. void commd(unsigned int commd)
    15. {
    16.   RW_PIN = 0;                // write op
    17.   RS_PIN = 0;                // RS = 0, Command
    18.   PORTB = commd & 0xF0;      // send hi nibble
    19.   E_PIN = 1;                 // write LCD
    20.   E_PIN = 0;                 //  "
    21.   PORTB = commd << 4;        // send lo nibble
    22.   E_PIN = 1;                 // write LCD
    23.   E_PIN = 0;                 //  "
    24.   __delay_us(50);            // inter-write delay
    25. }
    26.  
    27.  
    The LCD_INIT() routine doesn't look quite right. You should be allowing 50-100 msecs for the LCD to finish its power up initialization before writing to it. Also, the "clear screen" (0b00000001) and "home" (0b00000010) commands both require a ~1500-usec delay. You don't need both commands. Just send the "clear screen" command, which leaves the cursor in the 'home' position, followed by a ~1500-usec delay.

    The very first command should probably be followed by a 5 or 10 msec delay because it's being sent incorrectly, or, it should really be sent as a single 4-bit nibble (the hi nibble of 0x20) because the LCD powers up in 8-bit interface mode by default.

    Good luck with your project.

    Cheerful regards, Mike
     
    Last edited: Jun 17, 2014
  16. Egberts

    Thread Starter New Member

    Jun 7, 2014
    13
    0
    Wow i am sorry for the late reaction, i have been very busy!
    But thanks for your help, it worked!:D

    I only have a small question, can you explain me why you do this?
    PORTB = character & 0xF0
    PORTB = character << 4;

    And what if i wanted to use my RC4-RC7 ports for this purpose?
    Because when I just change PORTB to PORTC i get the black boxes again..

    Thanks again!
     
  17. MMcLaren

    Well-Known Member

    Feb 14, 2010
    759
    116
    Those instructions put the high nibble, bits 7..4, and the low nibble, bits 3..0, onto PORTB pins 7..4 which are wired to LCD pins D7..D4.

    You've got LCD control pins on RC7, RC6, and RC5, so you can't use those same pins for the LCD D4..D7 lines...
     
  18. Egberts

    Thread Starter New Member

    Jun 7, 2014
    13
    0
    Oh yes that seems kinda logical haha, thanks!.
    Yes that's right, but if i change the RS,RW and E wires to, say PORTB.
    Because now, it is not possible to use serial communications since part of PORTB is rx/tx..
     
  19. MMcLaren

    Well-Known Member

    Feb 14, 2010
    759
    116
    Why not leave the LCD control pins where they are and just move the D4..D7 data pins onto RC0..RC3? Modify the driver code match. Perhaps something like this;

    Good luck on you project.

    Cheerful regards, Mike

    Code ( (Unknown Language)):
    1. void prnt(unsigned int character)
    2. {
    3.   PORTC = character >> 4;    // send hi nibble
    4.   RS_PIN = 1;                // RS = 1, Data
    5.   E_PIN = 1;                 // write LCD
    6.   E_PIN = 0;                 //  "
    7.   PORTC = character & 0x0F;  // send lo nibble
    8.   RS_PIN = 1;                // RS = 1, Data
    9.   E_PIN = 1;                 // write LCD
    10.   E_PIN = 0;                 //  "
    11.   __delay_us(50);            // inter-write delay
    12. }
    13.  
    14. void commd(unsigned int commd)
    15. {
    16.   PORTC = commd >> 4;        // send hi nibble
    17.   E_PIN = 1;                 // write LCD
    18.   E_PIN = 0;                 //  "
    19.   PORTC = commd & 0x0F;      // send lo nibble
    20.   E_PIN = 1;                 // write LCD
    21.   E_PIN = 0;                 //  "
    22.   __delay_us(50);            // inter-write delay
    23. }
    24.  
     
    Last edited: Jun 27, 2014
Loading...