HD44780 Display does not work at 16MHZ

Discussion in 'Embedded Systems and Microcontrollers' started by spinnaker, Jan 23, 2011.

  1. spinnaker

    Thread Starter AAC Fanatic!

    Oct 29, 2009
    4,866
    988
    I bought several 16x2 LCD displays on eBay. They are HD44780 compatible. My pic is has an internal IRC OSC capable of 31KHz, 250Khz, 500khz, 1Mhz, 4mhz, 8mhz and 16mhz.


    I have tested the displays with 250khz to 16mhz. And it works fine on all frequencies except 16mhz.

    At 16MHZ, it sort of works but displays either all or some garbage characters.

    I am guessing the problem is a timing issue. Could it be the internal IRC is just unstable at 16MHZ? I do not have a 16MHZ crystal on hand.

    Here is my code for my delay at 16MHZ. It appears to be accurate.

    Code ( (Unknown Language)):
    1.  
    2. extern unsigned char macro_delay;
    3.            
    4.  
    5. #define delay_us(a) _asm movlw a\
    6.                       movwf macro_delay,1\
    7.               loop:      nop\
    8.                       decfsz macro_delay,1,1\
    9.                       bra loop\
    10.                  _endasm
    11.  
    12.  
    13. void delay_ms(unsigned int x);
    14.  
    15.    
    16. unsigned char macro_delay;
    17.  
    18. void delay_ms(unsigned int x)
    19.  {unsigned int i;
    20.     for(i=0; i<x;i++)    
    21.     {
    22.    
    23.         delay_us(200);
    24.         delay_us(200);
    25.         delay_us(200);
    26.         delay_us(200);
    27.         delay_us(200);
    28.     }
    29. }
    30.  
    31.  
     
  2. thatoneguy

    AAC Fanatic!

    Feb 19, 2009
    6,357
    718
    20 milliseconds from power on to first command to LCD
    5 milliseconds between commands
    200 microseconds between characters

    If you are getting garbage between characters, try increasing the inter-character delay by double or so.

    I can write to LCD using the internal RC at 20Mhz, so I doubt that is the issue.
     
    spinnaker likes this.
  3. spinnaker

    Thread Starter AAC Fanatic!

    Oct 29, 2009
    4,866
    988

    But why would it work at 8mhz? Same code and hopefully same delay if I am calcualting my delay correctly. But I will give it a try.


    Got any code you want to share?

    What I like about the code I have is I can pick each pin as opposed to having to use a PORT like the XLCD microchip code appears to be.


    What is strange is if I power off the pic and lcd and turn it back on, it works for the first line or two. Then it starts to get all messed up.
     
  4. spinnaker

    Thread Starter AAC Fanatic!

    Oct 29, 2009
    4,866
    988
    Thanks looks like it was the delays. The original code had no delays between characters and short delays between commands. I just spent the whole day trying to figure that one out :(. :)
     
  5. thatoneguy

    AAC Fanatic!

    Feb 19, 2009
    6,357
    718
    I use the compiler delay_ms(xx) and delay_us(xx) functions, rather than the assembly call. The compiler gets it correct with various delays. Example, went for a 25 Hz blinking LED, measured it at 25.001 Hz, toggling to 25 Hz. That was it's only task, but it's still impressive using only the delay function.

    Here is this one from Myke Predko - cLCD.c Works in BoostC when I change the variables, only raw LCD one I had handy (others require a lot of surgery to get just the LCD routines from).

    For BoostC, it's just a matter of changing PORTC.RC2 to portc.2 or whichever defines. That and the config word to match sourceboost's definitions. Works on 16F877A.
    Code ( (Unknown Language)):
    1.  
    2. #include
    3. /*  cLCD.c - Write a String to a 4 Bit Hitachi 44780 LCD I/F
    4.  
    5. This Program Initializes Hitachi 44780 Based LCD in 4 Bit Mode
    6.   and then writes a simple string to it.  The simulator was used
    7.   to time delay values.  
    8.  
    9. LCD Write Information can be found at http://www.myke.com
    10.  
    11. RC3:RC0 - LCD I/O D7:D4 (Pins 14:11)
    12. RC4     - LCD 6 Clocking Pin
    13. RC5     - LCD 4 Pin
    14.  
    15. myke predko
    16. 04.11.08
    17. */
    18.  
    19. __CONFIG(INTIO & WDTDIS & PWRTEN & MCLRDIS & UNPROTECT \
    20.   & UNPROTECT & BORDIS & IESODIS & FCMDIS);
    21.  
    22. int i, j, k, n;                 //  Use Global Variables for Debug
    23.  
    24. //                         1234567890123456
    25. const char TopMessage[] = "    PIC MCU     ";
    26. const char BotMessage[] = "  Evil Genius   ";
    27.  
    28. #define E  RC4                  //  Define the LCD Control Pins
    29. #define RS RC5
    30.  
    31. const int Twentyms = 1250;      //  Declare a Constant for 20 ms Delay
    32. const int Fivems = 300;
    33. const int TwoHundredus = 10;
    34.  
    35. LCDWrite(int LCDData, int RSValue)
    36. {
    37.  
    38.     PORTC = (LCDData >> 4) & 0x0F;  //  Get High 4 Bits for Output
    39.     RS = RSValue;
    40.     E = 1;  E = 0;              //  Toggle the High 4 Bits Out
    41.  
    42.     PORTC = LCDData & 0x0F;     //  Get Low 4 Bits for Output
    43.     RS = RSValue;
    44.     E = 1;  E = 0;              //  Toggle the Low 4 Bits Out
    45.  
    46.     if ((0 == (LCDData & 0xFC)) && (0 == RSValue))
    47.         n = Fivems;             //  Set Delay Interval
    48.     else
    49.         n = TwoHundredus;
    50.  
    51.     for (k = 0; k < n; k++);    //  Delay for Character
    52.  
    53. }  //  End LCDWrite
    54.  
    55. main()
    56. {
    57.  
    58.     PORTC = 0;                  //  Start with Everything Low
    59.     CMCON0 = 7;                 //  Turn off Comparators
    60.     ANSEL = 0;                  //  Turn off ADC
    61.     TRISC = 0;                  //  All of PORTC are Outputs
    62.  
    63. //  Initialize LCD according to the Web Page
    64.     j = Twentyms;
    65.     for (i = 0; i < j; i++);    //  Wait for LCD to Power Up
    66.  
    67.     PORTC = 3;                  //  Start Initialization Process
    68.     E = 1;  E = 0;              //  Send Reset Command
    69.     j = Fivems;
    70.     for (i = 0; i < j; i++);
    71.  
    72.     E = 1;  E = 0;              //  Repeat Reset Command
    73.     j = TwoHundredus;
    74.     for (i = 0; i < j; i++);
    75.  
    76.     E = 1;  E = 0;              //  Repeat Reset Command Third Time
    77.     j = TwoHundredus;
    78.     for (i = 0; i < j; i++);
    79.  
    80.     PORTC = 2;                  //  Initialize LCD 4 Bit Mode
    81.     E = 1;  E = 0;
    82.     j = TwoHundredus;
    83.     for (i = 0; i < j; i++);
    84.  
    85.     LCDWrite(0b00101000, 0);    //  LCD is 4 Bit I/F, 2 Line
    86.  
    87.     LCDWrite(0b00000001, 0);    //  Clear LCD
    88.  
    89.     LCDWrite(0b00000110, 0);    //  Move Cursor After Each Character
    90.  
    91.     LCDWrite(0b00001110, 0);    //  Turn On LCD and Enable Cursor
    92.  
    93.     for (i = 0; TopMessage[i] != 0; i++)
    94.         LCDWrite(TopMessage[i], 1);
    95.  
    96.     LCDWrite(0b11000000, 0);    //  Move Cursor to the Second Line
    97.  
    98.     for (i = 0; BotMessage[i] != 0; i++)
    99.         LCDWrite(BotMessage[i], 1);
    100.  
    101.     while(1 == 1);              //  Finished
    102.  
    103. }  //  End cLCD
    104.  
    105. [/i][/i][/i][/i]
     
  6. thatoneguy

    AAC Fanatic!

    Feb 19, 2009
    6,357
    718
    Glad you got it working!

    LCDs are picky sometimes. At the same time, I've found the RC oscillator remarkably stable for a given temperature.

    Do you have the code that you wrote the the LCD with? 4 bit or 8 bit mode? I almost always use 4, unless it is GLCD.
     
  7. spinnaker

    Thread Starter AAC Fanatic!

    Oct 29, 2009
    4,866
    988
    Let me clean it up and make it more user friendly. I will then post it.

    I am guessing that under 16MHZ the LCD was tolerant of delays under 16MHZ,
     
  8. blueroomelectronics

    AAC Fanatic!

    Jul 22, 2007
    1,758
    98
    Which PIC are you using?
     
  9. spinnaker

    Thread Starter AAC Fanatic!

    Oct 29, 2009
    4,866
    988
    I got it working. Thanks. It was the delays(bad code I picked up somewhere and failed to review. I am in the process of fixing it now). But I am using a 18f14k22.
     
  10. ELECTRONERD

    Senior Member

    May 26, 2009
    1,146
    16
    I had this same experience as well, and it would appear that your PIC is going too fast for the LCD to understand. Thus, as it picks up information, it might catch one or two but then rush into the next data information, some characters will be lost.
     
Loading...