LCD PIC16F877A Troubles

Discussion in 'Embedded Systems and Microcontrollers' started by ActivePower, Oct 2, 2012.

  1. ActivePower

    Thread Starter Member

    Mar 15, 2012
    155
    23
    Hi all,

    I have been stuck lately with classes, course projects and assignments so I couldn't make much progress on the personal projects front. I recently bought a PICKit 2 clone USB ICSP programmer and have been trying to get an LCD working on my breadboard. Here's the code

    Code ( (Unknown Language)):
    1. //main.c
    2. //Driver software for LCD
    3.  
    4.  
    5. #include<htc.h>
    6. #define _XTAL_FREQ 20000000
    7.  
    8. __CONFIG(FOSC_HS & LVP_OFF & CP_OFF & CP_OFF & BOREN_OFF & DEBUG_OFF & WDTE_OFF & PWRTE_OFF);
    9.                    
    10. #define DATA PORTC              //data bus
    11. #define BUSY RC7                //busy flag
    12. #define ENABLE RD0              //enable signal
    13. #define RW RD1          //read/write signal (R=1/W=0)
    14. #define RS RD2              //register select (Text=1, Instructions=0)
    15.  
    16. #define SETBIT(x) x=x||1
    17. #define CLRBIT(x) x=x&&0
    18.  
    19. void Push()         //push data into the LCD
    20. {
    21.     SETBIT(ENABLE);
    22.     CLRBIT(ENABLE);
    23. }
    24.  
    25. void LCD_Busy()
    26. {
    27.     TRISC7=1;       //RC7 as input
    28.     CLRBIT(ENABLE);
    29.     SETBIT(RW);         //read mode
    30.     CLRBIT(RS);         //instructions
    31.     while(1)            //code execution halted until LCD is busy
    32.     {
    33.         SETBIT(ENABLE);
    34.         if(!BUSY)
    35.             break;
    36.         CLRBIT(ENABLE);
    37.     }
    38.     CLRBIT(ENABLE);
    39.     CLRBIT(RW);         //write mode
    40.     TRISC7=0;
    41. }
    42.  
    43. void Init()
    44. {
    45.     TRISC=0x00;         //PORTC as output
    46.     TRISD0=0;
    47.     TRISD1=0;
    48.     TRISD2=0;           //control signals
    49. }
    50.  
    51.  
    52.  
    53. void LCD_Init()
    54. {
    55.     CLRBIT(ENABLE);     //deactivate LCD
    56.     SETBIT(RW);         //write mode
    57.     CLRBIT(RS);         //write instructions
    58.    
    59.     //start sending instructions to the LCD    
    60.  
    61.     DATA=0x38;          //initialize two row display
    62.     Push();             //push data onto LCD
    63.     LCD_Busy();     //wait until LCD processes it
    64.     DATA=0x1;           //clear LCD
    65.     Push();
    66.     LCD_Busy();
    67.     DATA=0xE;           //turn cursor ON
    68.     Push();
    69.     LCD_Busy();
    70.     DATA=0x6;           //move cursor right automatically
    71.     Push();
    72.     LCD_Busy();
    73. }
    74.  
    75. void LCD_Write(unsigned char ch)
    76. {
    77.     CLRBIT(ENABLE);
    78.     SETBIT(RW);         //write mode
    79.     SETBIT(RS);         //write text
    80.     DATA=ch;
    81.     Push();
    82.     LCD_Busy();
    83. }
    84.  
    85. void LCD_Clear()
    86. {
    87.     CLRBIT(ENABLE);     //deactivate LCD
    88.     SETBIT(RW);         //write mode
    89.     CLRBIT(RS);         //write instructions
    90.     DATA=0x1;           //clear LCD
    91.     Push();
    92.     LCD_Busy();
    93. }
    94.  
    95. void main()
    96. {
    97.     Init();
    98.     LCD_Init();
    99.     LCD_Write('H');
    100.    
    101.     LCD_Write('E');
    102.     LCD_Write('L');
    103.     LCD_Write('L');
    104.     LCD_Write('O');
    105.     LCD_Write('!');
    106. }
    107.  
    I have single-stepped through the code in hardware with no results. I have been programming 8051 chips for my microcontroller course recently and seem to have forgotten some PIC basics so kindly excuse any apparent stupid mistake. I did consider that there might be something wrong with the hardware setup as well as the LCD but I just wanted to be sure of the firmware first.

    Thanks!
     
  2. t06afre

    AAC Fanatic!

    May 11, 2009
    5,939
    1,222
    It is an example for using LCD display in the HI-Tech C samples folder. Contains both 4 and 8 bit data bus. You should also know that the busy pin on the LCD do not work in the early stages then setting up the LCD. Here you have to use some kind of timing in the software
     
  3. ActivePower

    Thread Starter Member

    Mar 15, 2012
    155
    23
    Tried replacing the polling routine with delays and didn't achieve any significantly different results.

    I am beginning to think this is more of a hardware problem than a firmware one. I might have to solder my LCD to the header after all, I suppose.

    Could it be a buggy breadboard issue? I just wanted to confirm that the code is alright so I can proceed further with the troubleshooting.
     
  4. t06afre

    AAC Fanatic!

    May 11, 2009
    5,939
    1,222
    To me it looks like you are using PORTC for data. And at the same time RC7 for the the bussy line. Which PIC are you using? For your own sake draw a schematic and post it here. Making the schematic will make things more clear for you self and us ;) Have you had any success making a small LED blinking program. Just to check if your PIC is alive?
     
  5. MMcLaren

    Well-Known Member

    Feb 14, 2010
    759
    116
    Aren't you supposed to use a '0' for Write and a '1' for Read on the RW line? Based on your comments, you seem to be doing it both ways...
     
  6. ActivePower

    Thread Starter Member

    Mar 15, 2012
    155
    23
    @MMcLaren: Oh! I did not notice that. Thanks a lot for pointing that out. I'll make the correction asap. I have always been a little confused as far as these control signals go.

    Code ( (Unknown Language)):
    1. //main.c
    2. //Driver software for LCD
    3.  
    4.  
    5. #include<htc.h>
    6. #define _XTAL_FREQ 20000000
    7.  
    8. __CONFIG(FOSC_HS & LVP_OFF & CP_OFF & CP_OFF & BOREN_OFF & DEBUG_OFF & WDTE_OFF & PWRTE_OFF);
    9.                    
    10. #define DATA PORTC              //data bus
    11. #define BUSY RC7                //busy flag
    12. #define ENABLE RD0              //enable signal
    13. #define RW RD1          //read/write signal (R=1/W=0)
    14. #define RS RD2              //register select (Text=1, Instructions=0)
    15.  
    16. #define SETBIT(x) x=x|1
    17. #define CLRBIT(x) x=x&0
    18.  
    19. void Push()         //push data into the LCD
    20. {
    21.     SETBIT(ENABLE);
    22.     CLRBIT(ENABLE);
    23. }
    24.  
    25. /* void LCD_Busy()
    26. {
    27.     TRISC7=1;       //RC7 as input
    28.     CLRBIT(ENABLE);
    29.     SETBIT(RW);         //read mode
    30.     CLRBIT(RS);         //instructions
    31.     while(1)            //code execution halted until LCD is busy
    32.     {
    33.         SETBIT(ENABLE);
    34.         if(!BUSY)
    35.             break;
    36.         CLRBIT(ENABLE);
    37.     }
    38.     CLRBIT(ENABLE);
    39.     CLRBIT(RW);         //write mode
    40.     TRISC7=0;
    41. }       */
    42.  
    43. void Init()
    44. {
    45.     TRISC=0x00;         //PORTC as output
    46.     TRISD0=0;
    47.     TRISD1=0;
    48.     TRISD2=0;           //control signals
    49. }
    50.  
    51.  
    52.  
    53. void LCD_Init()
    54. {
    55.     CLRBIT(ENABLE);     //deactivate LCD
    56.     CLRBIT(RW);         //write mode
    57.     CLRBIT(RS);         //write instructions
    58.    
    59.     //start sending instructions to the LCD    
    60.  
    61.     DATA=0x38;          //initialize two row display
    62.     Push();             //push data onto LCD
    63.     __delay_ms(2);      //wait until LCD processes it
    64.     DATA=0x1;           //clear LCD
    65.     Push();
    66.     __delay_ms(2);
    67.     DATA=0xE;           //turn cursor ON
    68.     Push();
    69.     __delay_ms(2);
    70.     DATA=0x6;           //move cursor right automatically
    71.     Push();
    72.     __delay_ms(2);
    73. }
    74.  
    75. void LCD_Write(unsigned char ch)
    76. {
    77.     CLRBIT(ENABLE);
    78.     CLRBIT(RW);         //write mode
    79.     SETBIT(RS);         //write text
    80.     DATA=ch;
    81.     Push();
    82.     __delay_ms(2);
    83. }
    84.  
    85. void LCD_Clear()
    86. {
    87.     CLRBIT(ENABLE);     //deactivate LCD
    88.     CLRBIT(RW);         //write mode
    89.     CLRBIT(RS);         //write instructions
    90.     DATA=0x1;           //clear LCD
    91.     Push();
    92.     __delay_ms(2);
    93. }
    94.  
    95. void main()
    96. {
    97.     Init();
    98.     LCD_Init();
    99.     LCD_Write('H');
    100.     LCD_Write('E');
    101.     LCD_Write('L');
    102.     LCD_Write('L');
    103.     LCD_Write('O');
    104.     LCD_Write('!');
    105.    
    106. }
    107.  
    @t06afre: Yup, I should have posted the picture of the circuit along with the schematic. Sorry for the lack of information.

    And yes, I did try the LED blink and the PIC is alive. But when I tried lighting an LED in response to a pushbutton the pin which should have been 0V initially put out some weird voltage value like 2.2 V. I tried changing the output pin to something else and ended up with the same arbitrary (seemingly) value. Anything wrong with the code?

    PS: I seem to have missed adding a resistor to ground near the pushbutton to stablize the 0 state. I'll make that correction but that doesn't have much to do with the 2.2 V output, does it?

    Code ( (Unknown Language)):
    1. //main.c
    2. //To light an LED in response to a button press
    3.  
    4. #include<htc.h>
    5. #define _XTAL_FREQ 20000000
    6.  
    7. __CONFIG(FOSC_HS & LVP_OFF & BOREN_OFF & CPD_OFF & CP_OFF & PWRTE_OFF & WDTE_OFF & DEBUG_ON);
    8.  
    9. #define SW RD0
    10. #define LED RC4
    11. #define INIT RD2
    12.  
    13.  
    14.  
    15. unsigned int num=2;
    16.  
    17. void init()
    18. {
    19.     TRISD0=1;           //switch input
    20.     TRISC4=0;               //button press
    21.     TRISD3=0;       //initialized
    22.     INIT=1;
    23.     LED=0;
    24. }
    25.  
    26. void main()
    27. {
    28.     init();
    29.     while(1)
    30.     {
    31.         if(SW)
    32.             LED=1;
    33.         else
    34.             LED=0;
    35.            
    36.     }  
    37.  
    38.  
    39. }
    40.  
    In the meantime, I'll try wiring up the LCD again. Hope for better luck this time!
     
  7. t06afre

    AAC Fanatic!

    May 11, 2009
    5,939
    1,222
    For the port dirrection just remember this 0=0utput 1=1nput. Quite logic ;)
     
  8. ActivePower

    Thread Starter Member

    Mar 15, 2012
    155
    23
    Thanks for that handy tip ;)

    I am stuck at the 2.4 V level. It doesn't switch high or low at the pin. Any suggestions?
     
  9. John P

    AAC Fanatic!

    Oct 14, 2008
    1,634
    224
    The usual way to wire up a switch to a processor is to have the switch go between the pin and Gnd, and a resistor between the pin and Vcc. But it should also work the other way (switch to Vcc, resistor to Gnd). However, if you used a pin of PortB, you could use the internal weak pullups, and leave out the external resistor.
     
  10. ActivePower

    Thread Starter Member

    Mar 15, 2012
    155
    23
    UPDATE: I wired the pull-up and the switch worked! It was a very stupid mistake with the delay time not enough to light up the LED and as a result the voltage was 2.5 V!

    UPDATE 2: On an unrelated note, I just switched off power to the MCU reset (active low) and the pin on which I had connected the initialization LED seems to be stuck at 2.5 V. No clue why, the rest of them having gone to 0 V. Any ideas?

    I'll connect the LCD and serial port in the meantime.

    Thanks for all the help! :)
     
  11. ActivePower

    Thread Starter Member

    Mar 15, 2012
    155
    23
    Sorry for the late follow-up on this thread but on a good note: The LCD worked! It was a hardware problem and apparently the wire connections weren't properly made. I'll try the rest of the code and let you know how it goes.

    Thanks for all the help!
     
  12. ActivePower

    Thread Starter Member

    Mar 15, 2012
    155
    23
    Hi,

    I have been playing around with various display effects on my LCD ever since I got it working. While everything looks fine, the program runs as if it is in a loop. The sentences, while clearly formed, are unsteady and keep sort of blinking/reloading.

    I had to introduce a 500 ms delay to make it steadier, which did not help much.
    While I do realize LCD controllers are a little slow but could this be a problem with the software?

    Does the PIC run the whole code in an infinite loop by itself even when you haven't instructed it to do so? Or is there a configuration setting I might have messed up?

    In general, what happens to an embedded program when we don't run it continuously or when the main function ends?

    PS: I can attach the Proteus simulation file if required.

    Thanks!
     
  13. spinnaker

    AAC Fanatic!

    Oct 29, 2009
    4,884
    1,002
    Sorry I have no idea what you are asking maybe others can figure it out.

    Your code will do (usually baring an internal bugs) exactly what you tell the mcu to do.

    A pic needs to have one main infinite loop to run properly. The main function should never end.


    I am guessing you have more hardware issues. Have you tried using your debugger to verify everything?
     
  14. MrChips

    Moderator

    Oct 2, 2009
    12,440
    3,361
    An embedded application never ends. You create an endless loop and you don't exit the main function.

    Code ( (Unknown Language)):
    1.  
    2. void main(void)
    3. {
    4.    Initialization();
    5.    while (1)
    6.    {
    7.  
    8.  
    9.    }
    10. }
    11.  
    12.  
    13.  
     
  15. John P

    AAC Fanatic!

    Oct 14, 2008
    1,634
    224
    This is a situation you usually want to avoid. If your code reaches the end of the main() function, it will continue to execute instructions in whatever memory locations are beyond the programmed area. If the chip was erased, this most likely means successive words containing all 1's, so you can look up whatever that is for your processor to see what it does. If the chip wasn't erased, but new code was just written over old, then you might find you're executing code left over from whatever was last written to the chip--either an old version of your current program or something totally different. But if by some chance the code reaches the end of the memory, it'll wrap around to 0000 and start running code from the beginning, but maybe with improper settings in place. A satisfactory result is unlikely!

    There are various things you can do if you want to stop executing code and wait for a reset: turn off everything and put an endless loop at the end of your code, or a sleep() instruction.
     
  16. takao21203

    Distinguished Member

    Apr 28, 2012
    3,577
    463
    It depends but I sometimes see PICs self-resetting after some 100 msec., due to banking, register trashing, or stack overflow issues. Sometimes this does not always become evident immediately.

    Weird blink or flicker patterns could mean there is something wrong with banking, register access or the stack, and the PIC is trapped in a constant process of self-resetting.
     
  17. MrChips

    Moderator

    Oct 2, 2009
    12,440
    3,361
    If you do not disable the watchdog timer you can use this to restart a frozen or runaway program.
     
  18. xainnasir

    New Member

    Nov 8, 2012
    26
    2
    which compiler u r using ..... try mikroC they have complete ecample in the help section .... just copy paste it .... schematic is also given there
     
  19. ErnieM

    AAC Fanatic!

    Apr 24, 2011
    7,386
    1,605
    It looks like your main() function ends... In a PC that would return control to the operating system. In an embedded project it just calls main() over and over.


    To get a C program to stop add a while(1); line.
     
  20. ActivePower

    Thread Starter Member

    Mar 15, 2012
    155
    23
    Thanks for all the help. Turns out the main() was looping on itself as most of you pointed out. From what I read elsewhere the behavior in such cases is uncertain and needs to be controlled using a while() loop. I added an infinite loop at the end and it seems to have sorted out the issue.

    Will keep you updated on the project!

    Thanks for all the prompt replies! :)
     
Loading...