Interface LCD to PIC (Details inside!)

Discussion in 'Embedded Systems and Microcontrollers' started by jegues, Feb 10, 2012.

  1. jegues

    Thread Starter Well-Known Member

    Sep 13, 2010
    735
    43
    The PIC being used is: PIC16F877A

    LCD beind used is:
    NHD‐0216XZ‐FSW‐GBW

    The objective is to get the LCD to display the following message,

    "Bananas $0.49/lb" - for 5 seconds, followed by,

    "WOW!" - which is centered on the display and blinking at a rate of once per second for 3 seconds (i.e. 500ms on 500ms off).

    I'm having trouble finding information on the correct procedure to use the LCD, and a large portion of the code used in my program has been provided by our instructor.

    I have a feeling that before I attempt to, writeString("Hello World!"), to the LCD I must first set the display line and place the cursor accordingly which I don't know how to do. We have been given an incomplete function called setDisplayLine(), but I'm not entirely sure in what sense it is incomplete, nor what the codes being passed to the command function represent.

    Then again, I'm not even sure if that is the correct procedure to follow.

    Does anyone know?

    I've been looking for a data sheet, but all I've been able to find is pinouts which I already have.

    See below for my code. (I appologize as the indentation is ruined when I paste it into the forum)

    Thanks for the help!

    Code ( (Unknown Language)):
    1.  
    2. #include <htc.h>
    3. #include <string.h>
    4. #include "ProcessorConfiguration.h"
    5. #include "FunctionPrototypes.h"
    6. #include "Definitions.h"
    7. void main(void){
    8.  portInit();
    9.  LCDInit();
    10.  writeString("Hello World!");
    11.  
    12. }
    13. static void interrupt isr(void){
    14. }
    15. //May be moved to its own .c file later
    16. void LCDInit(void){
    17.  E = 0;
    18.  delay(15); //Wait >15 msec after power is applied
    19.  initCommand(0x30); //command 0x30 = Wake up
    20.  delay(5); //must wait 5ms, busy flag not available
    21.  initCommand(0x30); //command 0x30 = Wake up #2
    22.  delay(160); //must wait 160us, busy flag not available
    23.  initCommand(0x30); //command 0x30 = Wake up #3
    24.  delay(160); //must wait 160us, busy flag not available
    25.  command(0x38); //Function set: 8-bit/2-line
    26.  command(0x10); //Cursor shift mode, S/C to the Left
    27.  command(0x0C); //1DCB: Display ON; Cursor OFF; Blink OFF
    28.  command(0x06); //Entry mode: Inc cursor and display shift off
    29.  clearDisplay();
    30.  returnHome();
    31. }
    32. void initCommand(char theCommand){ //Cannot Utilize BF
    33.  LCDCOMMAND = theCommand; //put command on PORTD
    34.  RS = RS_COMMAND; // Select Command Register
    35.  RWn = WRITE; // Write Mode
    36.  E = 1;
    37.  E = 0; //Clock enable: falling edge
    38. }
    39. void command(char theCommand) {
    40.  waitForNotBusy();
    41.  LCDCOMMAND = theCommand; //put command on PORTD
    42.  RS = RS_COMMAND; // Select Command Register
    43.  RWn = WRITE; // Write Mode
    44.  E = 1;
    45.  E = 0; //Clock enable: falling edge
    46. }
    47. void clearDisplay(void) {
    48.  waitForNotBusy();
    49.  command(0x01); //Clear Display
    50. }
    51. void returnHome(void) {
    52.  waitForNotBusy();
    53.  command(0x02); //Return Home
    54. }
    55. void waitForNotBusy(void) {
    56.  unsigned char BF;
    57.  RS = RS_COMMAND; // Select Command Register
    58.  RWn = READ; // Read Mode
    59.  BF = 0b10000000;
    60.  TRISD = 0b11111111;
    61.  delay(1); // Wait at least 80 μs before reading BF
    62.  while(BF==0b10000000){
    63.   E = 1;
    64.   BF = LCDDATA & 0b10000000;
    65.   E = 0; //Clock enable: falling edge
    66.  }
    67.  TRISD = 0b00000000;
    68. }
    69. void delay(unsigned char loops) {
    70.  unsigned char i;
    71.  for(i=0; i<loops;i++){}
    72. }
    73. //End of block pasted from LCDInitialization.c
    74. void setDisplayLine(unsigned char line, unsigned char position) { //This function is incomplete.
    75.  switch(line) {
    76.   case 1:command(0b01000000);
    77.   break;
    78.   case 2:command(0b11000000);
    79.   break;
    80.  }
    81. }
    82. void writeChar(char theData) {
    83.  waitForNotBusy();
    84.  LCDDATA = theData; //put data on PORTD
    85.  RS = RS_DATA; // Select Data Register
    86.  RWn = WRITE; // Write Mode
    87.  E = 1; //enable pulse width >= 300ns
    88.  E = 0; //Clock enable: falling edge
    89. }
    90. void writeString(char *theString) {
    91.  unsigned char i;
    92.  for(i = 0; i < strlen(theString); i++) {
    93.   waitForNotBusy();
    94.   LCDDATA = theString[i]; // Put data on PORTD
    95.   RS = RS_DATA; // Select Data Register
    96.   RWn = WRITE; // Write Mode
    97.   E = 1; // Enable pulse width >= 300ns
    98.   E = 0; // Clock enable: falling edge
    99.  }
    100. }
    101. [/i]


    And the code for portInit(),

    Code ( (Unknown Language)):
    1.  
    2. #include <htc.h>
    3. void portInit(void){
    4. //Configure for Digital IO
    5. PCFG3 = 0;
    6. PCFG2 = 1;
    7. PCFG1 = 1;
    8. TRISE0 = 0;
    9. TRISE1 = 0;
    10. TRISE2 = 0;
    11. TRISD = 0b00000000; //Configure PORTD for output
    12. INTCON = 0; //Disable interrupts.
    13. }
    14.  
     
    Last edited: Feb 10, 2012
  2. spinnaker

    AAC Fanatic!

    Oct 29, 2009
    4,887
    1,014
    Sounds to me like someone wants us to do his / her homework for him or her. :)


    Do a search on HD44780. You will find datasheets and plenty of code samples . But you should really work from the datasheet just like your instructor wants you to. :)
     
  3. jegues

    Thread Starter Well-Known Member

    Sep 13, 2010
    735
    43
    Where in my original post did I ever ask anyone to do my homework for me?

    As the description of this section of the forum reads,

    "Discussion forum for projects and working with embedded systems and microcontrollers (FPGAs, PICs, AVRs). Get help with hardware issues and embedded programming."

    I would like to get some help, not have someone do my homework for me. Just thought I would clarify that for you.

    Anyways, I've already looked up the data sheet online,

    http://www.newhavendisplay.com/specs/NHD-0216XZ-FSW-GBW.pdf

    I feel like I understand the majority of the information being presented, aside from the font table on page 6.

    What is CGRAM?

    It also shows example intialization programs, but not how to actually display anything on the LCD? Can anyone point me in the right direction?

    Thanks again!
     
  4. spinnaker

    AAC Fanatic!

    Oct 29, 2009
    4,887
    1,014

    Page 6 is just a really complicated looking ASCII table.

    http://www.asciitable.com/

    CG RAM = Character Generator RAM
    DD RAM = Display Data RAM

    You are probably going to want to use 4 bit display. It is more complicated but uses less pins. Check page 8. It shows how to display a character using 4 bit.


    You will still need to know how to display it on the line you want but that is next.

    Remember timing is fairly critical for these displays. It does not need to be exact but you need to pay attention to the delays they recommend.
     
  5. jegues

    Thread Starter Well-Known Member

    Sep 13, 2010
    735
    43
    This is what I would like to figure out how to do.

    4 bit is not an option as we are required to use 8 bits.
     
  6. spinnaker

    AAC Fanatic!

    Oct 29, 2009
    4,887
    1,014
    OK then page 7 has the code to output a character for 8 bit.
     
  7. jegues

    Thread Starter Well-Known Member

    Sep 13, 2010
    735
    43
    I already have a similiar code within a function called writeChar.

    See the code below,

    Code ( (Unknown Language)):
    1.  
    2. void writeChar(char theData) {
    3.  waitForNotBusy();
    4.  LCDDATA = theData; //put data on PORTD
    5.  RS = RS_DATA; // Select Data Register
    6.  RWn = WRITE; // Write Mode
    7.  E = 1; //enable pulse width >= 300ns
    8.  E = 0; //Clock enable: falling edge
    9. }
    10.  
    However, when I call the function in main like so,

    writeChar("p");

    I don't see any display on the LCD.

    Do I have to set the display first somehow?
     
  8. spinnaker

    AAC Fanatic!

    Oct 29, 2009
    4,887
    1,014
    Did you run the initialization code?

    Post your schematic of how you have the LCD wired.


    Do you have a scope, logic probe pr even a multimeter?

    Step through your code. When you out put a byte to the port, verify it is appearing at the LCD how you expect it to be. This includes your enable, r/w and select bits.

    Sometimes it is easier just to write a little test program to toggle the bits on your LCD and forget about the LCD code till you confirm all of your connections.
     
  9. t06afre

    AAC Fanatic!

    May 11, 2009
    5,939
    1,222
    You do know what Hi-Tech C is shipped with examples. And that also include a LCD demo. Look in the the "C:\Program Files\HI-TECH Software\PICC\9.83\samples" folder. It is a four bit LCD demo. But it can with ease be modified to 8 bit. Your code is somewhat untidy. Like Hi-Tech are shipped with good functions for delays. They are named "__delay_ms()" and "__delay_us()" In order to work they need a
    Code ( (Unknown Language)):
    1.  
    2. #define _XTAL_FREQ 4000000
    3.  
    In the example the system clock is 4 MHz. I also noticed that as far as I can see you do not set the configurations word.
    Why not use the HI-Tech C example as your work horse. And take it from there. As a hint make a copy of the example. So you do not overwrite it
     
  10. John P

    AAC Fanatic!

    Oct 14, 2008
    1,634
    224
    What the???

    Code ( (Unknown Language)):
    1.  
    2. void LCDInit(void){
    3.  E = 0;
    4.  delay(15); //Wait >15 msec after power is applied
    5.  initCommand(0x30); //command 0x30 = Wake up
    6.  delay(5); //must wait 5ms, busy flag not available
    7.  initCommand(0x30); //command 0x30 = Wake up #2
    8.  delay(160); //must wait 160us, busy flag not available
    9.  
    How come delay(5) counts 5 milliseconds but delay(160) counts 160 microseconds?
     
  11. spinnaker

    AAC Fanatic!

    Oct 29, 2009
    4,887
    1,014
    Not sure. Check your documentation for delay. Where is it from BTW? Which compiler?

    It could be that delay has a maximum count it can handle. Try stringing a bunch together. Say 3 50s and a 10.
     
  12. jegues

    Thread Starter Well-Known Member

    Sep 13, 2010
    735
    43
    That is a typo, its actually 160ms which is larger than 160us so it is sufficient.

    HI-TECH C compiler.
     
    Last edited: Feb 11, 2012
  13. jegues

    Thread Starter Well-Known Member

    Sep 13, 2010
    735
    43
    Here is the wiring diagram for the setup I'm currently running,

    [​IMG]

    What is this and how do I set it?
     
  14. spinnaker

    AAC Fanatic!

    Oct 29, 2009
    4,887
    1,014
    Check your datasheet. Is there an on-board current limiting resistor for the back light? If not you should add one.

    What is the value of that trim pot?
     
  15. jegues

    Thread Starter Well-Known Member

    Sep 13, 2010
    735
    43
    I'm not sure of its exact value, but isn't that just for adjusting the intensity of the backlight?
     
  16. spinnaker

    AAC Fanatic!

    Oct 29, 2009
    4,887
    1,014
  17. t06afre

    AAC Fanatic!

    May 11, 2009
    5,939
    1,222
    @jegues
    You are using HI-Tech C correct? And which version are you using. Any deatils on that. The configuration word(s) are described in the section SPECIAL FEATURES OF THE CPU in the datasheet. I may give you some pointers if I know which version you are using of the C compiler. The configuration word can be set from MPLAB. But it is highly recommended that you put this information in the code.
     
  18. jegues

    Thread Starter Well-Known Member

    Sep 13, 2010
    735
    43
    Yes I am using HI-TECH C. The version listed in the readme file is,

    "HI-TECH C Compiler for PIC10/12/16 MCUs Version 9.83 ".
     
  19. t06afre

    AAC Fanatic!

    May 11, 2009
    5,939
    1,222
    At the top of your PIC header file located in "......\HI-TECH Software\PICC\9.83\include" you will find this section
    Code ( (Unknown Language)):
    1.  
    2. // Configuration mask definitions
    3. //
    4.  
    5. // Config Register: CONFIG
    6. #define CONFIG               0x2007
    7. // Oscillator Selection bits
    8. // RC oscillator
    9. #define FOSC_EXTRC           0xFFFF
    10. // HS oscillator
    11. #define FOSC_HS              0xFFFE
    12. // XT oscillator
    13. #define FOSC_XT              0xFFFD
    14. // LP oscillator
    15. #define FOSC_LP              0xFFFC
    16. // Watchdog Timer Enable bit
    17. // WDT enabled
    18. #define WDTE_ON              0xFFFF
    19. // WDT disabled
    20. #define WDTE_OFF             0xFFFB
    21. // Power-up Timer Enable bit
    22. // PWRT disabled
    23. #define PWRTE_OFF            0xFFFF
    24. // PWRT enabled
    25. #define PWRTE_ON             0xFFF7
    26. // Brown-out Reset Enable bit
    27. // BOR enabled
    28. #define BOREN_ON             0xFFFF
    29. // BOR disabled
    30. #define BOREN_OFF            0xFFBF
    31. // Low-Voltage (Single-Supply) In-Circuit Serial Programming Enable bit
    32. // RB3/PGM pin has PGM function; low-voltage programming enabled
    33. #define LVP_ON               0xFFFF
    34. // RB3 is digital I/O, HV on MCLR must be used for programming
    35. #define LVP_OFF              0xFF7F
    36. // Data EEPROM Memory Code Protection bit
    37. // Data EEPROM code protection off
    38. #define CPD_OFF              0xFFFF
    39. // Data EEPROM code-protected
    40. #define CPD_ON               0xFEFF
    41. // Flash Program Memory Write Enable bits
    42. // Write protection off; all program memory may be written to by EECON control
    43. #define WRT_OFF              0xFFFF
    44. // 0000h to 00FFh write-protected; 0100h to 1FFFh may be written to by EECON control
    45. #define WRT_256              0xFDFF
    46. // 0000h to 07FFh write-protected; 0800h to 1FFFh may be written to by EECON control
    47. #define WRT_1FOURTH          0xFBFF
    48. // 0000h to 0FFFh write-protected; 1000h to 1FFFh may be written to by EECON control
    49. #define WRT_HALF             0xF9FF
    50. // In-Circuit Debugger Mode bit
    51. // In-Circuit Debugger disabled, RB6 and RB7 are general purpose I/O pins
    52. #define DEBUG_OFF            0xFFFF
    53. // In-Circuit Debugger enabled, RB6 and RB7 are dedicated to the debugger
    54. #define DEBUG_ON             0xF7FF
    55. // Flash Program Memory Code Protection bit
    56. // Code protection off
    57. #define CP_OFF               0xFFFF
    58. // All program memory code-protected
    59. #define CP_ON                0xDFFF
    60.  
    61.  
    Then match these options to the figure named "REGISTER 14-1: CONFIGURATION WORD (ADDRESS 2007h)" in the PIC datasheet
    At the top of your program after the include section. You add the __CONFIG() macro. You will be using RC OSC, and watchdog timer can be turned off. So to get you started the two first parameters in your __config macro will be like this. You can do the rest. The order of the macro names is unconcerned. For more info see the HI-Tech C manual section 3.3.4 Configuration Bit Access in the docs folder.
    Code ( (Unknown Language)):
    1.  
    2. __config(FOSC_EXTRC & WDTE_OFF........)            
    3.  
    As you see the macro names are bitwise ANDed together to form the configuration value. To avoid any confusion or problems set every options up to the last CP_OFF/CP_ON option. (CP_OFF in your case)
     
    Last edited: Feb 12, 2012
  20. ErnieM

    AAC Fanatic!

    Apr 24, 2011
    7,392
    1,605
    On the display Pins 15 and 16 are the backlight LED and absolutely need a limit resistor. If you powered on like that you probably killed the LED but the unit should still work in a bright room. The pot connecting to Pin 3 should typically be 10K. If misadjusted nothing will show on the display. Turn it one end to the other to find where it wants to be.

    The config word needs to be set. The following may work with your hardware:

    Code ( (Unknown Language)):
    1.  
    2. // Oscillator Selection bits: RC oscillator
    3. // Watchdog Timer Enable bit: WDT disabled
    4. // Power-up Timer Enable bit: PWRT disabled
    5. // Brown-out Reset Enable bit: BOR disabled
    6. // Low-Voltage (Single-Supply) ICSP Enable bit: RB3 is I/O, HV on MCLR for programming
    7. // Data EEPROM Memory Code Protection bit: Data EEPROM code protection off
    8. // Flash Program Memory Write Enable bits: Write protection off; all program memory may be written to by EECON control
    9. // In-Circuit Debugger Mode bit: In-Circuit Debugger enabled, RB6 and RB7 are dedicated to the debugger
    10. // Flash Program Memory Code Protection bit: Code protection off
    11.  
    12. __CONFIG(FOSC_EXTRC & WDTE_OFF & PWRTE_OFF & BOREN_OFF & LVP_OFF & CPD_OFF & WRT_OFF & DEBUG_ON & CP_OFF);
    13.  
     
Loading...