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

2x16 LCD Problem with PIC16f877A

 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
sysysy



Joined: 17 Nov 2010
Posts: 38
Location: 121

View user's profile Send private message

2x16 LCD Problem with PIC16f877A
PostPosted: Wed Nov 17, 2010 7:53 am     Reply with quote

Hi,

I am trying to interface the 2x16 (HD44780) LCD with the 16f877A PIC.

Below is the problem that i encountered.

I am using the CCS Version 4.038.

Procedure:
1. Hardware interfacing. Gnd, Vdd, Vee(with 10k pot) are connected, i manage to see the whole black rectangular block in lcd first line ---> OK

2. RS, RW,En, DB4 - DB 7 are connected to PIC pins. ---> OK

3. With using CCS build-in driver (LCD.c), i try to show something with add a main function and few statement ---> OK

4. For example: lcd_putc("\fTesting");

Most of the time, LCD display not valid output (_o<-<-ooo), just very few times, valid output (Testing) word just will display out. ---> (Fail)

5. In addition, even in lcd_init() there, we already initialize that lcd is 2 line. but how come still only first line same like original shown?
As a result, there is ntg show when i trying to show
lcd_putc("\nSecond Line"); --->(Fail)

*(I do trying to adjust the pot, but still see nothing.)

This is the 2 main problem that i encountered.
Can you give me any suggestion to solve this? (I have stucked here for 2 days already) Crying or Very sad

Below is the code:
Code:

#include <16F877A.h>
#fuses HS,NOWDT,NOPROTECT,NOLVP
#use delay(clock=20000000)

// Un-comment the following define to use port B
// #define use_portb_lcd TRUE


struct lcd_pin_map {                 // This structure is overlayed
           BOOLEAN enable;           // on to an I/O port to gain
           BOOLEAN rs;               // access to the LCD pins.
           BOOLEAN rw;               // The bits are allocated from
           BOOLEAN unused;           // low order up.  ENABLE will
           int     data : 4;         // be pin B0.
        } lcd;



   #ifdef __pch__
    #locate lcd = 0xf83
   #else
    #locate lcd = 8
   #endif
   #define set_tris_lcd(x) set_tris_d(x)


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


BYTE const LCD_INIT_STRING[6] = {0x20 | (lcd_type << 2),0xc, 1, 6};
                             // These bytes need to be sent to the LCD
                             // to start it up.


                             // The following are used for setting
                             // the I/O port direction register.

struct lcd_pin_map const LCD_WRITE = {0,0,0,0,0}; // For write mode all pins are out
struct lcd_pin_map const LCD_READ = {0,0,0,0,15}; // For read mode data pins are in



BYTE lcd_read_byte() {
      BYTE low,high;
      set_tris_lcd(LCD_READ);
      lcd.rw = 1;
      delay_cycles(1);
      lcd.enable = 1;
      delay_cycles(1);
      high = lcd.data;
      lcd.enable = 0;
      delay_cycles(1);
      lcd.enable = 1;
      delay_us(1);
      low = lcd.data;
      lcd.enable = 0;
      set_tris_lcd(LCD_WRITE);
      return( (high<<4) | low);
}


void lcd_send_nibble( BYTE n ) {
      lcd.data = n;
      delay_cycles(1);
      lcd.enable = 1;
      delay_us(2);
      lcd.enable = 0;
}


void lcd_send_byte( BYTE address, BYTE n ) {

      lcd.rs = 0;
      while ( bit_test(lcd_read_byte(),7) ) ;
      lcd.rs = address;
      delay_cycles(1);
      lcd.rw = 0;
      delay_cycles(1);
      lcd.enable = 0;
      lcd_send_nibble(n >> 4);
      lcd_send_nibble(n & 0xf);
}


void lcd_init() {
    BYTE i;
    set_tris_lcd(LCD_WRITE);
    lcd.rs = 0;
    lcd.rw = 0;
    lcd.enable = 0;
    delay_ms(15);
    for(i=1;i<=3;++i) {
       lcd_send_nibble(3);
       delay_ms(5);
    }
    lcd_send_nibble(2);
    for(i=0;i<=3;++i)
       lcd_send_byte(0,LCD_INIT_STRING[i]);
}


void lcd_gotoxy( BYTE x, BYTE y) {
   BYTE 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;
   }
}

char lcd_getc( BYTE x, BYTE y) {
   char value;

    lcd_gotoxy(x,y);
    while ( bit_test(lcd_read_byte(),7) ); // wait until busy flag is low
    lcd.rs=1;
    value = lcd_read_byte();
    lcd.rs=0;
    return(value);
}

void main()
{
   lcd_init();
   lcd_putc("\fTesting");
}


I would feel glad if anyone willing to help.

Thanks.
Wayne_



Joined: 10 Oct 2007
Posts: 681

View user's profile Send private message

PostPosted: Wed Nov 17, 2010 10:53 am     Reply with quote

Place a while(true) at the end of main.

Code:

void main()
{
   lcd_init();
   lcd_putc("\fTesting");
   
  while(true)
  {
  }
}
sysysy



Joined: 17 Nov 2010
Posts: 38
Location: 121

View user's profile Send private message

PostPosted: Wed Nov 17, 2010 10:56 am     Reply with quote

Wayne_ wrote:
Place a while(true) at the end of main.


Try this before, but it does not work.

Crying or Very sad
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Wed Nov 17, 2010 12:15 pm     Reply with quote

Use the 2x16 Flex lcd driver. It's much easier to make it work:
http://www.ccsinfo.com/forum/viewtopic.php?t=24661
Wayne_



Joined: 10 Oct 2007
Posts: 681

View user's profile Send private message

PostPosted: Thu Nov 18, 2010 2:59 am     Reply with quote

sysysy wrote:
Wayne_ wrote:
Place a while(true) at the end of main.


Try this before, but it does not work.

Crying or Very sad


Just because your code does not work with the while loop in does not mean you can leave it off. Without it your pic will go into sleep mode which may shut down your outputs, timers, clock etc, depending on configuration.

With the while loop it won't so you won't be chasing your own tail.

Leave it in then you will only have the 1 problem to fix.
sysysy



Joined: 17 Nov 2010
Posts: 38
Location: 121

View user's profile Send private message

PostPosted: Thu Nov 18, 2010 6:39 am     Reply with quote

Thanks Wayne.
u've taught me 1 more thing Very Happy

PCM_Programmer,

i tried the driver, it does not work at all.

by the way, i have 2 question here:

1. when we use 4 bit mode, is it pins db0 to db3 from lcd must connect to ground or optional?

2.when the invalid character display on lcd, what is that mean? delay problem or? (for example, when i wanna display "ABC", but the lcd display
"o/<")
temtronic



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

View user's profile Send private message

PostPosted: Thu Nov 18, 2010 7:07 am     Reply with quote

I think you might want to try 8 bit mode for the display interface.

It's the simplest way to prove hardware and software as no 'drivers' are involved, no fancy code,etc.

Just wire up the LCD to an 8 bit port and set it to say 55x( 'U').
If that works, create a simple loop to send several letters,numbers,etc.

Once you've got it working perfect, rewire to 4bit mode,use the 'flex' driver, and test it out.

Build upon small sucessful steps.
sysysy



Joined: 17 Nov 2010
Posts: 38
Location: 121

View user's profile Send private message

PostPosted: Thu Nov 18, 2010 7:26 am     Reply with quote

hi Temtronic,

Thanks for your suggestion. Anyway, do you have 8 bit driver code?

I try to write for it before, not so sure, and does not work. I don't how to send the data to those 8pins (db0 to db7).

3Anyway, below is my code.

I make it very very simple (based on my own understanding from lcd), and some part just copy from other driver example, because I don't know how to write.
Code:

#include <16F877A.h>
#fuses HS,NOWDT,NOPROTECT,NOLVP
#use delay(clock=20000000)

#define use_portb_lcd TRUE

struct lcd_pin_map {                           
           int     data : 8;         
        } lcd;
       
#if defined use_portb_lcd
   //#locate lcd = getenv("sfr:PORTB")    // This puts the entire structure over the port
   #ifdef __pch__
    #locate lcd = 0xf81
   #else
    #locate lcd = 6
#endif
   
//#define set_tris_lcd(x) set_tris_b(x)

#define RS PIN_B0
#define RW PIN_B1
#define EN PIN_B2

void WRT_COMM(char COMM)
{
   output_low(RS);
   output_low(RW);
   lcd.data = COMM;
   output_high(EN);
   delay_cycles(1);
   output_low(EN);
   delay_ms(2);
   //while ( bit_test(lcd_read_byte(),7) ) ;
}

void WRT_DATA(char DATA)
{   
   output_high(RS);
   output_low(RW);
   lcd.data = DATA;
   output_high(EN);
   delay_cycles(1);
   output_low(EN);
   delay_ms(2);
   //busy();
}

void lcd_init()
{
   set_tris_b(0);
   set_tris_d(0);
   WRT_COMM(0x38);
   //WRT_COMM(0x38);
   //WRT_COMM(0x38);
   WRT_COMM(0x0E);   
   WRT_COMM(0x01);     
   WRT_COMM(0x06);     
   WRT_COMM(0x80);   
}

void main()
{
   lcd_init();
   printf("Testing");

   while(1);
}


Anyone can take a look and give some suggestion?

Thanks a lot.
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Thu Nov 18, 2010 1:39 pm     Reply with quote

I don't want to work on your 8-bit driver code, but I will try to help you
get the flex driver working.

1. What's the manufacturer and part number of your LCD ?
Also post a link to the webpage for the LCD.

2. Is the LCD installed on a PIC board ? Did you buy the board, or did
you build it yourself ? If you bought the board, post the manufacturer
and part number of the board.

3. Have you ever made this PIC and board do a simple thing, such as
blinking an LED ? Do you know that the board works ?

4. Post a list of the pin connections between the PIC and the LCD.
Don't just post this:
Quote:
RS, RW,En, DB4 - DB 7 are connected to PIC pins. ---> OK

Post the pin number on the PIC, and the pin number on the LCD for
each connection.

5. Use a voltmeter or oscilloscope to measure the Contrast voltage
on the lcd. What voltage do you see ?

---------------------

Quote:
1. when we use 4 bit mode, is it pins db0 to db3 from lcd must connect to ground or optional?

Those pins should be unconnected. The LCD has built-in pull-up resistors
on those pins, so the LCD pulls them up to a logic high level. The pins
are not floating. They are at a safe logic level.

Quote:
2. when the invalid character display on lcd, what is that mean? delay problem or? (for example, when i wanna display "ABC", but the lcd display
"o/<")

It could be a timing problem in the lcd driver program. It could be that
your LCD has special timing requirements. It could be a power supply
problem on your board (power supply voltage is too low, or not regulated
at a stable voltage). Or something else.
Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion All times are GMT - 6 Hours
Page 1 of 1

 
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