CCS C Software and Maintenance Offers
FAQFAQ   FAQForum Help   FAQOfficial CCS Support   SearchSearch  RegisterRegister 

ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

CCS does not monitor this forum on a regular basis.

Please do not post bug reports on this forum. Send them to CCS Technical Support

Need Help LCD 16x2
Goto page 1, 2  Next
 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
chin0609



Joined: 13 Sep 2011
Posts: 18

View user's profile Send private message

Need Help LCD 16x2
PostPosted: Tue Sep 13, 2011 9:05 pm     Reply with quote

Im using flex_lcd in my PIC16F877A but i only show black block?
here my code
flex_lcd.c
// flex_lcd.c

// These pins are for the Microchip PicDem2-Plus board,
// which is what I used to test the driver. Change these
// pins to fit your own board.

#define LCD_DB4 PIN_B4
#define LCD_DB5 PIN_B4
#define LCD_DB6 PIN_B6
#define LCD_DB7 PIN_B7

#define LCD_E PIN_B3
#define LCD_RS PIN_B2
#define LCD_RW PIN_B1

// If you only want a 6-pin interface to your LCD, then
// connect the R/W pin on the LCD to ground, and comment
// out the following line.

//#define USE_LCD_RW 1

//========================================

#define lcd_type 2 // 0=5x7, 1=5x10, 2=2 lines
#define lcd_line_two 0x40 // LCD RAM address for the 2nd line


int8 const LCD_INIT_STRING[4] =
{
0x20 | (lcd_type << 2), // Func set: 4-bit, 2 lines, 5x8 dots
0xc, // Display on
1, // Clear display
6 // Increment cursor
};


//-------------------------------------
void lcd_send_nibble(int8 nibble)
{
// Note: !! converts an integer expression
// to a boolean (1 or 0).
output_bit(LCD_DB4, !!(nibble & 1));
output_bit(LCD_DB5, !!(nibble & 2));
output_bit(LCD_DB6, !!(nibble & 4));
output_bit(LCD_DB7, !!(nibble & 8));

delay_cycles(1);
output_high(LCD_E);
delay_us(2);
output_low(LCD_E);
}

//-----------------------------------
// This sub-routine is only called by lcd_read_byte().
// It's not a stand-alone routine. For example, the
// R/W signal is set high by lcd_read_byte() before
// this routine is called.

#ifdef USE_LCD_RW
int8 lcd_read_nibble(void)
{
int8 retval;
// Create bit variables so that we can easily set
// individual bits in the retval variable.
#bit retval_0 = retval.0
#bit retval_1 = retval.1
#bit retval_2 = retval.2
#bit retval_3 = retval.3

retval = 0;

output_high(LCD_E);
delay_cycles(1);

retval_0 = input(LCD_DB4);
retval_1 = input(LCD_DB5);
retval_2 = input(LCD_DB6);
retval_3 = input(LCD_DB7);

output_low(LCD_E);

return(retval);
}
#endif

//---------------------------------------
// Read a byte from the LCD and return it.

#ifdef USE_LCD_RW
int8 lcd_read_byte(void)
{
int8 low;
int8 high;

output_high(LCD_RW);
delay_cycles(1);

high = lcd_read_nibble();

low = lcd_read_nibble();

return( (high<<4) | low);
}
#endif

//----------------------------------------
// Send a byte to the LCD.
void lcd_send_byte(int8 address, int8 n)
{
output_low(LCD_RS);

#ifdef USE_LCD_RW
while(bit_test(lcd_read_byte(),7)) ;
#else
delay_us(60);
#endif

if(address)
output_high(LCD_RS);
else
output_low(LCD_RS);

delay_cycles(1);

#ifdef USE_LCD_RW
output_low(LCD_RW);
delay_cycles(1);
#endif

output_low(LCD_E);

lcd_send_nibble(n >> 4);
lcd_send_nibble(n & 0xf);
}

//----------------------------
void lcd_init(void)
{
int8 i;

output_low(LCD_RS);

#ifdef USE_LCD_RW
output_low(LCD_RW);
#endif

output_low(LCD_E);

delay_ms(15);

for(i=0 ;i < 3; i++)
{
lcd_send_nibble(0x03);
delay_ms(5);
}

lcd_send_nibble(0x02);

for(i=0; i < sizeof(LCD_INIT_STRING); i++)
{
lcd_send_byte(0, LCD_INIT_STRING[i]);

// If the R/W signal is not used, then
// the busy bit can't be polled. One of
// the init commands takes longer than
// the hard-coded delay of 60 us, so in
// that case, lets just do a 5 ms delay
// after all four of them.
#ifndef USE_LCD_RW
delay_ms(5);
#endif
}

}

//----------------------------

void lcd_gotoxy(int8 x, int8 y)
{
int8 address;

if(y != 1)
address = lcd_line_two;
else
address=0;

address += x-1;
lcd_send_byte(0, 0x80 | address);
}

//-----------------------------
void lcd_putc(char c)
{
switch(c)
{
case '\f':
lcd_send_byte(0,1);
delay_ms(2);
break;

case '\n':
lcd_gotoxy(1,2);
break;

case '\b':
lcd_send_byte(0,0x10);
break;

default:
lcd_send_byte(1,c);
break;
}
}

//------------------------------
#ifdef USE_LCD_RW
char lcd_getc(int8 x, int8 y)
{
char value;

lcd_gotoxy(x,y);

// Wait until busy flag is low.
while(bit_test(lcd_read_byte(),7));

output_high(LCD_RS);
value = lcd_read_byte();
output_low(lcd_RS);

return(value);
}
#endif

main code
#include <16F877A.H>
#use delay (clock=20000000) // 20MHz
#define LCD_POWER PIN_B0
#include <flex_lcd.c>
#FUSES HS,NOWDT, NOPROTECT, BROWNOUT, NOLVP, PUT
#use rs232 (baud=9600, xmit=PIN_C6, rcv=PIN_C7) //serial

#define SERVO1 PIN_c1
#define led_green PIN_d1
#define led_red PIN_d0
int8 i; // looping

void nocar()
{

for (i=0;i<30;i++) //0 deg
{
output_low(led_green);
output_high(led_red);

output_high(SERVO1);
delay_us(1500);
output_low(SERVO1);
delay_ms(18);
}
lcd_init();
lcd_putc("\fDoor Closed");
}

void car()
{

for (i=0;i<30;i++) // 90 deg
{

output_low(led_red);
output_high(led_green);


output_high(SERVO1);
delay_us(2000);
output_low(SERVO1);
delay_ms(18);
}
lcd_init();
lcd_putc("\fDoor Opened");
}

void main()
{
output_high(LCD_POWER); // Turn on power to LCD
output_low(LCD_RW);

while(1)
{
if(input(PIN_C0)) //Sensor input

{ nocar(); }


else

{ car(); }

}
}
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Tue Sep 13, 2011 10:24 pm     Reply with quote

Fix this:
Quote:

#define LCD_DB4 PIN_B4
#define LCD_DB5 PIN_B4
#define LCD_DB6 PIN_B6
#define LCD_DB7 PIN_B7

#define LCD_E PIN_B3
#define LCD_RS PIN_B2
#define LCD_RW PIN_B1

Each signal must be on a separate pin. You can't use the same pin 2 times.
chin0609



Joined: 13 Sep 2011
Posts: 18

View user's profile Send private message

PostPosted: Wed Sep 14, 2011 12:20 am     Reply with quote

I'm changed still come out black block.
Code:
// flex_lcd.c

// These pins are for the Microchip PicDem2-Plus board,
// which is what I used to test the driver.  Change these
// pins to fit your own board.

#define LCD_DB4   PIN_B4
#define LCD_DB5   PIN_B5
#define LCD_DB6   PIN_B6
#define LCD_DB7   PIN_B7

#define LCD_E     PIN_B3
#define LCD_RS    PIN_B1
#define LCD_RW    PIN_B2

// If you only want a 6-pin interface to your LCD, then
// connect the R/W pin on the LCD to ground, and comment
// out the following line.

//#define USE_LCD_RW   1     

//========================================

#define lcd_type 2        // 0=5x7, 1=5x10, 2=2 lines
#define lcd_line_two 0x40 // LCD RAM address for the 2nd line


int8 const LCD_INIT_STRING[4] =
{
 0x20 | (lcd_type << 2), // Func set: 4-bit, 2 lines, 5x8 dots
 0xc,                    // Display on
 1,                      // Clear display
 6                       // Increment cursor
 };
                             

//-------------------------------------
void lcd_send_nibble(int8 nibble)
{
// Note:  !! converts an integer expression
// to a boolean (1 or 0).
 output_bit(LCD_DB4, !!(nibble & 1));
 output_bit(LCD_DB5, !!(nibble & 2)); 
 output_bit(LCD_DB6, !!(nibble & 4));   
 output_bit(LCD_DB7, !!(nibble & 8));   

 delay_cycles(1);
 output_high(LCD_E);
 delay_us(2);
 output_low(LCD_E);
}

//-----------------------------------
// This sub-routine is only called by lcd_read_byte().
// It's not a stand-alone routine.  For example, the
// R/W signal is set high by lcd_read_byte() before
// this routine is called.     

#ifdef USE_LCD_RW
int8 lcd_read_nibble(void)
{
int8 retval;
// Create bit variables so that we can easily set
// individual bits in the retval variable.
#bit retval_0 = retval.0
#bit retval_1 = retval.1
#bit retval_2 = retval.2
#bit retval_3 = retval.3

retval = 0;
   
output_high(LCD_E);
delay_cycles(1);

retval_0 = input(LCD_DB4);
retval_1 = input(LCD_DB5);
retval_2 = input(LCD_DB6);
retval_3 = input(LCD_DB7);
 
output_low(LCD_E);
   
return(retval);   
}   
#endif

//---------------------------------------
// Read a byte from the LCD and return it.

#ifdef USE_LCD_RW
int8 lcd_read_byte(void)
{
int8 low;
int8 high;

output_high(LCD_RW);
delay_cycles(1);

high = lcd_read_nibble();

low = lcd_read_nibble();

return( (high<<4) | low);
}
#endif

//----------------------------------------
// Send a byte to the LCD.
void lcd_send_byte(int8 address, int8 n)
{
output_low(LCD_RS);

#ifdef USE_LCD_RW
while(bit_test(lcd_read_byte(),7)) ;
#else
delay_us(60); 
#endif

if(address)
   output_high(LCD_RS);
else
   output_low(LCD_RS);
     
 delay_cycles(1);

#ifdef USE_LCD_RW
output_low(LCD_RW);
delay_cycles(1);
#endif

output_low(LCD_E);

lcd_send_nibble(n >> 4);
lcd_send_nibble(n & 0xf);
}

//----------------------------
void lcd_init(void)
{
int8 i;

output_low(LCD_RS);

#ifdef USE_LCD_RW
output_low(LCD_RW);
#endif

output_low(LCD_E);

delay_ms(15);

for(i=0 ;i < 3; i++)
   {
    lcd_send_nibble(0x03);
    delay_ms(5);
   }

lcd_send_nibble(0x02);

for(i=0; i < sizeof(LCD_INIT_STRING); i++)
   {
    lcd_send_byte(0, LCD_INIT_STRING[i]);
   
    // If the R/W signal is not used, then
    // the busy bit can't be polled.  One of
    // the init commands takes longer than
    // the hard-coded delay of 60 us, so in
    // that case, lets just do a 5 ms delay
    // after all four of them.
    #ifndef USE_LCD_RW
    delay_ms(5);
    #endif
   }

}

//----------------------------

void lcd_gotoxy(int8 x, int8 y)
{
int8 address;

if(y != 1)
   address = lcd_line_two;
else
   address=0;

address += x-1;
lcd_send_byte(0, 0x80 | address);
}

//-----------------------------
void lcd_putc(char c)
{
 switch(c)
   {
    case '\f':
      lcd_send_byte(0,1);
      delay_ms(2);
      break;
   
    case '\n':
       lcd_gotoxy(1,2);
       break;
   
    case '\b':
       lcd_send_byte(0,0x10);
       break;
   
    default:
       lcd_send_byte(1,c);
       break;
   }
}

//------------------------------
#ifdef USE_LCD_RW
char lcd_getc(int8 x, int8 y)
{
char value;

lcd_gotoxy(x,y);

// Wait until busy flag is low.
while(bit_test(lcd_read_byte(),7)); 

output_high(LCD_RS);
value = lcd_read_byte();
output_low(lcd_RS);

return(value);
}
#endif


main code:
Code:
#include <16F877A.H>
#use delay (clock=20000000) // 20MHz
#define LCD_POWER  PIN_B0
#include <flex_lcd.c>
#FUSES HS,NOWDT, NOPROTECT, BROWNOUT, NOLVP, PUT
#use rs232 (baud=9600, xmit=PIN_C6, rcv=PIN_C7) //serial

#define SERVO1 PIN_c1
#define led_green PIN_d1
#define led_red PIN_d0
int8 i; // looping

void nocar()
{
     
       for (i=0;i<30;i++)                //0 deg
      {
         output_low(led_green);
         output_high(led_red);

         output_high(SERVO1);
         delay_us(1500);
         output_low(SERVO1);
         delay_ms(18); 
      }
lcd_init();
lcd_putc("\fDoor Closed");
}

void car()
{
   
      for (i=0;i<30;i++)             // 90 deg
     {
         
         output_low(led_red);
         output_high(led_green);
       

         output_high(SERVO1);
         delay_us(2000);
         output_low(SERVO1);
         delay_ms(18); 
     }
lcd_init();
lcd_putc("\fDoor Opened");
}

void main()
{
  output_high(LCD_POWER);  // Turn on power to LCD
  output_low(LCD_RW);
   lcd_init();         
   while(1)
      {
if(input(PIN_C0)) //Sensor input

    {  nocar();  }
   

 else   
     
  {  car();  }

}
}


LCD pin configure.
VSS to ground
VDD to +5v
VEE to potentiometer
RS to PortB1
RW to ground
E to PortB3
D4 to PortB4
D5 to PortB5
D6 to PortB6
D7 to PortB7
albal



Joined: 13 Sep 2011
Posts: 4
Location: United Kingdom

View user's profile Send private message

PostPosted: Wed Sep 14, 2011 1:37 am     Reply with quote

I don't think you mean to wire RW to GND. You should have it connected to PORTB2.

I would once again go over your physical connections and check that there are correct and valid against your declarations in your C code.
temtronic



Joined: 01 Jul 2010
Posts: 9226
Location: Greensville,Ontario

View user's profile Send private message

PostPosted: Wed Sep 14, 2011 5:13 am     Reply with quote

RW can go to ground..it's the '6 pin' wiring for common LCDs that you use in 'write only'(please read comments at the top of the flex driver).I've done it for years, and I currently have an 877 with 2x16 LCD in this mode.
BTW you typically only need .5 volts for VEE, so the pot only needs to be a little above ground.
Also try connecting LCD VDD(+5v) directly to +5V,not controlled by I/O pin B0.

oh and add 'errors' to your use rs232(...) options otherwise the UART buffer with trap out and stall.
chin0609



Joined: 13 Sep 2011
Posts: 18

View user's profile Send private message

PostPosted: Wed Sep 14, 2011 6:31 am     Reply with quote

my lcd only display black block only even i adjusted pot.

any wrong in my main code ?
i am new in ccs c..anyone can help me check the main code and lcd?





Quote:
and add 'errors' to your use rs232(...) options otherwise the UART buffer with trap out and stall.
temtronic



Joined: 01 Jul 2010
Posts: 9226
Location: Greensville,Ontario

View user's profile Send private message

PostPosted: Wed Sep 14, 2011 7:07 am     Reply with quote

Ok...best to start over and just test the LCD without the other code...
something like....
Code:

void main()
{
   lcd_init();         
   while(1)
      {
      lcd_putc("Hello World");
      delay_ms(500);
}

}

You do NOT have to run lcd_init() more than once in your program.
Your program might be clearing the LCD in the loop that you have and you can't see what's really going on,so try the simple 'Hello world' test and then build upon that.
It helps to make changes, save as a new file 'test001, test002,test 003,...
That way you can always go back to a program that you know worked.
chin0609



Joined: 13 Sep 2011
Posts: 18

View user's profile Send private message

PostPosted: Wed Sep 14, 2011 7:24 am     Reply with quote

Code:
void main()
{
lcd_init();
while(1)
{
lcd_putc("Hello World");
delay_ms(500);
}

}


tested this code..result still same ( black block)

just want to ask is the Flex_lcd.c only compatible in Microchip PicDem2-Plus board or??

BTW i am build the simple PIC16F877A board myself not using the PicDem2-Plus board.
temtronic



Joined: 01 Jul 2010
Posts: 9226
Location: Greensville,Ontario

View user's profile Send private message

PostPosted: Wed Sep 14, 2011 8:47 am     Reply with quote

Ok...I downloaded the schematic of the PicDem-2 board and found your problem.
You have to redefine the correct pins for the onboard LCD. PicDem uses port D NOT B for the LCD connections.
Simply alter the flex_lcd driver to use the correct pins. I'd rename this new version to say 'picdem2_lcd.c' to keep the original 'safe'.
Be sure to include the new version NOT the original !
Also note that Microchip use a pin to control the voltage to the LCD, be sure to set that pin high to provide power to the LCD.A simple output_high(...) will do the job !
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Wed Sep 14, 2011 12:30 pm     Reply with quote

Quote:

i am build the simple PIC16F877A board myself not using the PicDem2-Plus board


I think the Flex driver should work with any normal 16x2 lcd, or it
can be configured to do so.

But in your posted code, you are using special commands that are ONLY
for the "Rohs" version of the PicDem2-Plus board.

The following lines in your code would be used for the "Rohs" version of
the PicDem2-Plus. If you don't have that board, you don't need to do this !
Quote:

//#define USE_LCD_RW 1 // commented out

output_high(LCD_POWER); // Turn on power to LCD
output_low(LCD_RW);



Also, you have the two lines below, as if you are controlling the LCD power
with the PIC:
Quote:
#define LCD_POWER PIN_B0

output_high(LCD_POWER);


But then, in your list of connections below, you show that the LCD is
hard-wired to the +5v power supply rail ! So you don't need a pin called
"LCD Power".
Quote:

LCD pin configure.

VSS to ground
VDD to +5v
VEE to potentiometer
RS to PortB1
RW to ground
E to PortB3
D4 to PortB4
D5 to PortB5
D6 to PortB6
D7 to PortB7


Go through your program and get rid of all the useless lines that are
for the "Rohs" board. Only put in code that is used by your board.

Go here, and get the "plain" Flex lcd driver. It's in the first post:
http://www.ccsinfo.com/forum/viewtopic.php?t=24661
Use it.

Also, in your list of LCD connections, you are using pins B6 and B7.
These pins are used by the ICD programmer/debugger. It needs those
pins. You can't run the debugger and the LCD together on those pins.
Quote:

D4 to PortB4
D5 to PortB5
D6 to PortB6
D7 to PortB7

My advice is to use two other PIC pins for D6 and D7. Change the
connections on your board, and edit the list of pin #define statements
at the top of the flex lcd file, so it matches the new connections on your
board.
chin0609



Joined: 13 Sep 2011
Posts: 18

View user's profile Send private message

PostPosted: Wed Sep 14, 2011 10:25 pm     Reply with quote

followed the plain flex_lcd still get the same result
Code:
// flex_lcd.c

// These pins are for the Microchip PicDem2-Plus board,
// which is what I used to test the driver.  Change these
// pins to fit your own board.

#define LCD_DB4   PIN_B4
#define LCD_DB5   PIN_B5
#define LCD_DB6   PIN_A1
#define LCD_DB7   PIN_A2

#define LCD_E     PIN_B3
#define LCD_RS    PIN_B1
#define LCD_RW    PIN_B2

// If you only want a 6-pin interface to your LCD, then
// connect the R/W pin on the LCD to ground, and comment
// out the following line.

#define USE_LCD_RW   1   


Code:
void main()

{



lcd_init();

while(1)
{
   output_high(PIN_A1);
   delay_ms(1000);
   output_low(PIN_A1);

   printf(lcd_putc, "Hello World.");


   delay_ms(1000);
}
}


im using lcd jhd162a...does the unused pin connect to ground or just left it?
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Wed Sep 14, 2011 10:59 pm     Reply with quote

Quote:

#define LCD_DB4 PIN_B4
#define LCD_DB5 PIN_B5
#define LCD_DB6 PIN_A1
#define LCD_DB7 PIN_A2

#define LCD_E PIN_B3
#define LCD_RS PIN_B1
#define LCD_RW PIN_B2

// If you only want a 6-pin interface to your LCD, then
// connect the R/W pin on the LCD to ground, and comment
// out the following line.

#define USE_LCD_RW 1





lcd_init();

while(1)
{
output_high(PIN_A1);
delay_ms(1000);
output_low(PIN_A1);

printf(lcd_putc, "Hello World.");


delay_ms(1000);
}

Don't toggle a pin that you use for the LCD !

Quote:
does the unused pin connect to ground or just left it?

Which unused pins ? Do you mean DB0 to DB3 on the LCD ?
Just leave them unconnected.

Upload a schematic of your board to a free image hosting website,
such as http://www.imageshack.com
Then post a link to the schematic in this thread, so we can look at it.
chin0609



Joined: 13 Sep 2011
Posts: 18

View user's profile Send private message

PostPosted: Wed Sep 14, 2011 11:47 pm     Reply with quote

http://imageshack.us/photo/my-images/546/20110915133012.jpg/

black block
http://imageshack.us/photo/my-images/23/20110915133809.jpg/
temtronic



Joined: 01 Jul 2010
Posts: 9226
Location: Greensville,Ontario

View user's profile Send private message

PostPosted: Thu Sep 15, 2011 9:29 am     Reply with quote

OK....I've confirmed it is NOT a basic driver or hardware problem.

I've used your pin assignments..
// modified flex_lcd.c

#define LCD_DB4 PIN_B4
#define LCD_DB5 PIN_B5
#define LCD_DB6 PIN_A1
#define LCD_DB7 PIN_A2

#define LCD_E PIN_B1
#define LCD_RS PIN_B3
#define LCD_RW PIN_B2 //not used !

with LCD_RW pin(5) on LCD tied to ground( write only mode).
This is how I always wire LCDs as I do not need to read from them.

Hooked up to my trusty 16F877 with 20MHz xtal and it works fine
I do have fixed resistors on the LCD Vee pin3,about .5volts.

So the problem is NOT the flex_LCD driver,unless you've changed something other than the pin assignments.
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Thu Sep 15, 2011 1:40 pm     Reply with quote

Post another photo of your LCD that is in focus and a close-up,
and that shows all the pins. I am beginning to suspect that you have
solder shorts between the pins, or you may picked the wrong side of
the connector as "pin 1". If you post a clear photo of the pins and wires
connected to them, then maybe it will show the problem.

Also, your schematic shows "switch" on the MCLR pin. Do you have a
pull-up resistor on MCLR ? You need one. Usually it's a 10K resistor to +5v.

Have you measured the voltage on the contrast pin of the LCD ?
It should be set to about 0.5 volts.
Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion All times are GMT - 6 Hours
Goto page 1, 2  Next
Page 1 of 2

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001, 2005 phpBB Group