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 support@ccsinfo.com

LCD & 16F877....weird INIT behaviour !?!?!?!

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



Joined: 10 Feb 2004
Posts: 12
Location: Denmark, (Scandinavia-Europe)

View user's profile Send private message ICQ Number

LCD & 16F877....weird INIT behaviour !?!?!?!
PostPosted: Fri Feb 27, 2004 2:20 pm     Reply with quote

Hi guys,

I have connected a HD77480 2x16 lcd to Pic 16F877.
Compiler: PCM 3.173
20Mhz Quartz

I experience weird behaviour after my lcd_init() functions has run through a clean main() as the only function besides the while(1). Problems include but are not limited to:
- a semi-visible/transparent grey-boxed line on line 1 (e.g. like a konstant curser all the way through line 1)
- nothing on display

Once in a while it will boot ok and work......even if I have several lcd_putc functions in main, like it is supposed to.

I tried to switch the EN and RS lines and that produces a VERY visible grey-boxed line on line 1.

I switched them back again and the behaviour mentioned first starts all over.

I have removed all code not nescesary but not my diretives, as I need them for later.

I'm all out of ideas :-(

I hope someone can tell me if the set_tris_x are in the correct places.
I suspect it is my timing of outputting stuff to the display during the lcd_init that does not entirely corespond to:
http://preterhuman.net/texts/computing/HardwareDIY/LCDFaq.txt
2.6.1
If someone would modify the code or point out excactly where I mess up, I would be most grateful.

Code:


#device PIC16F877 *=16
#include <16F877.h>
#include <F877.h>  // the file Microchip used to supply, with port def's etc.
#include <string.h>

#fuses HS,NOWDT,NOPROTECT,NOBROWNOUT,NOLVP,WRT
#use delay(clock=20000000)            
#use rs232(baud=9600,xmit=PIN_C6, rcv=PIN_C7)      
#use I2C(master, sda=PIN_C4, scl=PIN_C3, slow, force_hw)   

#use fast_io(A)
#use fast_io(B)
#use fast_io(C)
#use fast_io(D)
#use fast_io(E)

#bit LCD_RS = PORTA.3   // RA3   
#bit LCD_RW = PORTA.2   // RA2
#bit LCD_EN = PORTA.1   // RA1
#byte LCD_DATA = PORTD   // PORTD
void lcd_init()

{
   byte i;
   SET_TRIS_A(0x00);         // set port A, output
   SET_TRIS_D(0x00);         // set port D, output
   LCD_RS = 0;
   LCD_RW = 0;
   delay_ms(15);
   for(i=1;i<=3;++i)         // init af LCD
   {
      LCD_EN = 0;
      LCD_DATA=0b00111000;   //8 Bit Interface, 2 Lines
      delay_cycles(1);
      LCD_EN = 1;
      delay_ms(5);
   }
                        // konfig af LCD
   lcd_write(0,0b00111000);   // 8 Bit Interface, 2 Lines
   lcd_write(0,0b00001101);   // Turn on display, cursor off, blink ON
   lcd_write(0,0x00000001);   // clear display
   lcd_write(0,0x00000110);   // Increment cursor
}

void lcd_gotoxy(byte x, byte y)
{
   byte address;
   if(y!=1)
   address=0x40;
   else
   address=0;
   address+=x-1;
   lcd_write(0,0x80|address);
}

void lcd_putc(char c)
{
   switch (c)
   {
      case '\f' :
         lcd_write(0,1);
         break;      
      case '\n' :
         lcd_gotoxy(1,2);
         break;
      default :
         lcd_write(1,c);
         break;
   }
}


byte lcd_read(void)
{
   byte word;
   SET_TRIS_D(0xFF);      // set port D as inputs
   delay_cycles(1);
   LCD_RW = 1;
   delay_cycles(1);
   LCD_EN = 1;
   delay_cycles(4);
   word = LCD_DATA;
   LCD_EN = 0;
   LCD_RW = 0;
   SET_TRIS_D(0x00);      //set port D as outputs
   return( word );
}

void lcd_write(byte address, byte b)
{
   SET_TRIS_A(0x00);      // set port A, output
   LCD_EN = 0;
   LCD_RS = 0;
   delay_cycles(4);
   SET_TRIS_D(0xFF);      // set port D, input
   while ( bit_test(lcd_read(),7) ) ;
   SET_TRIS_A(0x00);      // set port A, output
   LCD_RS = address;
   LCD_RW = 0;
   delay_cycles(1);
   SET_TRIS_D(0x00);      // set port D, output
   LCD_DATA=b;
   delay_cycles(1);
   LCD_EN = 1;
   delay_cycles(4);
   LCD_EN = 0;
}

main()
{
lcd_init();

lcd_putc("\ftest");   // clears display with \f and writes test in line 1, as expected.
// I have tried with other text's like "test", "\f\ntest" ...etc., same problem.

while(1) {}
}



Best Regards
Rasmus 'Izolator'
Kasper



Joined: 14 Jan 2004
Posts: 88
Location: Aurora, Ontario, Canada

View user's profile Send private message Visit poster's website

PostPosted: Fri Feb 27, 2004 2:47 pm     Reply with quote

double check with the lcd.c driver which shipped with the compiler. it may give you a hint
Izolator



Joined: 10 Feb 2004
Posts: 12
Location: Denmark, (Scandinavia-Europe)

View user's profile Send private message ICQ Number

PostPosted: Fri Feb 27, 2004 2:55 pm     Reply with quote

I'm a complete newie and I really need the features that my program offers. I looked at the lcd.c and it is for 4 line lcd, not my cup of tea.

I think my problems are related to the timing and was hoping others had used the code by mr. Troy Schultz, e.g. the lcd code I am using.

....any ideas ?


BR
Rasmus 'Izolator'
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Fri Feb 27, 2004 3:14 pm     Reply with quote

Check if you have the LCD wired correctly. Go to the following
page, and click on some of the links at the bottom. Especially
look at the sections on Contrast control.
http://www.crystalfontz.com/forum/showthread.php?s=8b2fca0a105842afce0e2bf7804c1f7a&threadid=1288
Izolator



Joined: 10 Feb 2004
Posts: 12
Location: Denmark, (Scandinavia-Europe)

View user's profile Send private message ICQ Number

PostPosted: Fri Feb 27, 2004 3:34 pm     Reply with quote

I have it wired up ok, I guess:

LCD:Pic16F877
0: ground
1: +5V
3: -1.5V ( I got a potentiometer and steal the negative voltage from a maxim max233a, p10 => steady negative voltage)
4: pin5
5: pin6
6: pin4
7-14: D0-D7
15-16: not connected, backlight not present, I'm told

I dont have a scope, but I do have a voltmeter and I tested the pins, they are ok.

The problem is most notorious when it has been powered off for a few hours....weird.


Anyone else use the code posted who has had similar problems or solved them ?

BR
Rasmus 'Izolator'
chava



Joined: 07 Sep 2003
Posts: 56

View user's profile Send private message Send e-mail

are you?...
PostPosted: Fri Feb 27, 2004 4:31 pm     Reply with quote

are you using picdem2 board?
I remember when I started using the lcd, i had problems (can't remember what problems..)

if your using the picdem2 board ,here is a code I use which WORK
you may change the pin defines to alter it for your own connection
hope it will help

Code:

//LCD   //////////////////////////////


// As defined in the following structure the pin connection is as follows:
//    pic      lcd
//   ---------------
//     A1     enable
//     A2     rw
//     A3     rs

//     D0     D4
//     D1     D5
//     D2     D6
//     D3     D7
//
//   LCD pins D0-D3 are not used and PIC D3 is not used.



//***********************************************************#if defined(__PCH__)
   #byte lcd = 0xF83      // This puts the entire structure
#else
   #byte lcd = 8          // on to port D (at address 8)
#endif


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


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


//***** lcd command port  ******
struct lcd_command{
   char none:1;
   char enable:1;
   char read_write:1;//rw
   char data_command:1;//rs
   };
struct lcd_command lcd_command_port;

#locate lcd_command_port=5

//---------------------------------------------------
struct lcd_data{
   char data:4;
   };
struct lcd_data lcd_data_port;
#locate lcd_data_port=8

//************  "COMMAND / DATA definition 
#define COMMAND0 0
#define DATA1 1

//************  "READ / WRITE definition 
#define WRITE0 0   //LCD <- MPU
#define READ1 1  //LCD -> MPU

//************  "E_UP / E_DOWN definition 
#define E_DOWN 0
#define E_UP 1


//**********eeprom or flash*********************
#define EEPROM0 0   ;eeprom - not the program  memory
#define FLASH1 1   ;program memory

//*********  set tris d  *********
#define set_tris_lcd_read(){\
   set_tris_a(TRISA & 0xf1/*0b11110001*/);\
   set_tris_d(TRISD | 0x0f/*0b00001111*/);\
   }
#define set_tris_lcd_write(){\
   set_tris_a(TRISA & 0xf1/*0b11110001*/);\
   set_tris_d(TRISD & 0xf0/*0b11110000*/);\
   }

//***********   clear LCD  ***********************************
#define clear_lcd   lcd_send_byte(0x1,COMMAND0);//clear lcd display

//***********************************************************
//**********************************************************
char lcd_read_byte(void){
      char low,high;
      set_tris_lcd_read();
      lcd_command_port.read_write = READ1;
      delay_cycles(1);
     
      lcd_command_port.enable = E_UP;
      delay_cycles(1);
      high = lcd_data_port.data & 0x0f;
      lcd_command_port.enable = E_DOWN;
      delay_cycles(1);
     
      lcd_command_port.enable = E_UP;
      delay_us(1);
      low = lcd_data_port.data & 0x0f;
      lcd_command_port.enable = E_DOWN;
      set_tris_lcd_write();
      return( (high << 4) | low);
}

//*************** -   -
void lcd_write_nibble(char temp_wr){
//Purpose:
      lcd_data_port.data = temp_wr;
      delay_cycles(1);
      lcd_command_port.enable = 1;
      delay_us(2);
      lcd_command_port.enable = 0;
}
//*************** -   -
void lcd_send_byte(char data , char data_or_command ) {

      lcd_command_port.data_command = COMMAND0;
      while ( bit_test(lcd_read_byte(),7) ) ;
      lcd_command_port.data_command = data_or_command;
      delay_cycles(1);
      lcd_command_port.read_write = WRITE0;
      delay_cycles(1);
      lcd_command_port.enable = E_DOWN;
      lcd_write_nibble(data >> 4);
      lcd_write_nibble(data & 0xf);
}
//*********************************************************
void lcd_gotoxy( char location, char line) {//location 0...
   char address;

   if(line!=1)
     address=40;//was80
   else
     address=0;
   address+=location;
   lcd_send_byte(0x80|address,COMMAND0);
}
//********** -  1 -
void lcd_init(void){
//Purpose: initiate the lcd
   //turnning PORTA0=analog, PORTA1-7=digital
   ADCON1=0x0e;
   
   //turnning command pin of lcd to output
   set_tris_lcd_write();

   //delay 15msec
   delay_ms(15);   
   lcd_command_port.enable=0;
   lcd_command_port.data_command=0;
   lcd_command_port.read_write=0;
   lcd_data_port.data=0;
   delay_ms(2);
   lcd_write_nibble(0x03);//was 30  ddram address: 1:1bit,line:1bit,address:4bit
   delay_ms(10);//more then 4.1msec

   lcd_write_nibble(0x03);//was 30
   delay_us(150);//more then 100usec

   lcd_write_nibble(0x03);//was 30
   delay_us(100);

   lcd_write_nibble(0x02);//was 20
   while(bit_test(lcd_read_byte(),7));

   lcd_send_byte(0x28,COMMAND0);                  
   //  4 bit low nibble, ddram address=0 first line
   lcd_send_byte(0x0c,COMMAND0);//disp on

   clear_lcd;

   lcd_send_byte(0x6,COMMAND0);//entry inc

   lcd_gotoxy(1,1);
   
   
   

}
//*********************************************************
void lcd_putc( char c) {//this function works good
   switch (c) {
     case '\f'   : lcd_send_byte(1,COMMAND0);   delay_ms(2);   break;   //Clear display
     case '\n'   : lcd_gotoxy(1,2);                        break;   //Go to start of second line
     case '\b'   : lcd_send_byte(0x10,COMMAND0);               break;   //Move back one position
     default     : lcd_send_byte(c,DATA1);                  break;   //send the actual character
   }
}
//*************** -   -
char lcd_getc( char location, char line) {
      char value;

    lcd_gotoxy(location,line);
    while ( bit_test(lcd_read_byte(),7) ); // wait until busy flag is low
    lcd_command_port.data_command=1;
    value = lcd_read_byte();
    lcd_command_port.data_command=0;
    return(value);
      return 1;
}
//**********************************************************
//*************************----
void lcd_put_string(char *string){
//put string, starting  from the curren cursor position
//assume that string not excides from lcd displayed RAM
   char index=0;

   while(string[index]!=0){
      lcd_putc(string[index++]);
   
   }
}

Izolator



Joined: 10 Feb 2004
Posts: 12
Location: Denmark, (Scandinavia-Europe)

View user's profile Send private message ICQ Number

PostPosted: Fri Feb 27, 2004 4:37 pm     Reply with quote

Problem solved, it seems:

Code:

void lcd_write(byte address, byte b)
{
   SET_TRIS_A(0x00);      // set port A, output
   LCD_EN = 0;
   LCD_RS = 0;
   delay_cycles(4);
 //  SET_TRIS_D(0xFF);      <= problem line, allready tris'ed input in lcd_read
   while ( bit_test(lcd_read(),7) ) ;
//   SET_TRIS_A(0x00);      <= problem line, allready tris'ed output in lcd_read
   LCD_RS = address;
   LCD_RW = 0;
   delay_cycles(1);
   SET_TRIS_D(0x00);      // set port D, output
   LCD_DATA=b;
   delay_cycles(1);
   LCD_EN = 1;
   delay_cycles(4);
   LCD_EN = 0;
}

Apparently setting the same tris as the port direction already has is not a good idea.....or that is my theory, because it works now :-)

Thankyou for your time guys, I was about to panick Shocked
...taught me to check the tris before asking again Very Happy

BR
Rasmus 'Izolator'
Guest








PostPosted: Mon Mar 01, 2004 6:33 pm     Reply with quote

while were on the topic,
could anybody tell me which is easier to use a parallel or serial LCD.

if anybody has some sample code for displaying on a serial LCD, from a 16f877

if you could mail it to kitedude@kitedemon.com it would be much appreciated.

Brian
treitmey



Joined: 23 Jan 2004
Posts: 1094
Location: Appleton,WI USA

View user's profile Send private message Visit poster's website

PostPosted: Tue Mar 02, 2004 9:55 am     Reply with quote

Here is the PICDEM2 PLUS driver I came up with.
Code:

//////////////////////////////////////////////////////////////////////////
////                 PICDEM2_LCD.C                                 ////
////                 Driver for common PICDEM2 PLUS LCD modules        ////
////                                                                   ////
////  lcd_init()   Must be called before any other function.           ////
////                                                                   ////
////  lcd_putc(c)  Will display c on the next position of the LCD.     ////
////                     The following have special meaning:           ////
////                      \f  Clear display                            ////
////                      \n  Go to start of second line               ////
////                      \b  Move back one position                   ////
////                                                                   ////
////  lcd_gotoxy(x,y) Set write position on LCD (upper left is 1,1)    ////
////                                                                   ////
////  lcd_getc(x,y)   Returns character at position x,y on LCD         ////
////                                                                   ////
///////////////////////////////////////////////////////////////////////////

#define use_PICDEM2_lcd TRUE


#if defined use_PICDEM2_lcd
   #define  lcd_en  PIN_A1   
   #define  lcd_rw  PIN_A2   
   #define  lcd_rs  PIN_A3   
   #define  lcd_type 2           // 0=5x7, 1=5x10, 2=2 lines
   #define  lcd_line_two 0x40    // LCD RAM address for the second line
   #define  d_cycle 1
#endif

void lcd_send_nibble( BYTE n ) {
   n=n&0x0f; //Strip off the top 4 bits.. This only sends bit 3:0
   output_d(n);
   delay_cycles(d_cycle);
   output_high(lcd_en);
   delay_us(20);
   output_low(lcd_en);
}
   
BYTE lcd_read_byte() {
   BYTE low,high;
   output_high(lcd_rw);
   delay_cycles(d_cycle);
   output_high(lcd_en);
   delay_cycles(d_cycle);
   high = input_d(); //using d0:d3 for 4 bit data bus
   output_low(lcd_en);
   delay_cycles(d_cycle);
   output_high(lcd_en);
   delay_us(1);
   low = input_d(); //using d0:d3 for 4 bit data bus
   output_low(lcd_en);
   return((high<<4) | low);
}
   
void lcd_send_byte( BYTE A0, BYTE n ) {    //A0:  0=instruction, 1=Data
   output_low(lcd_rs);
   while ( bit_test(lcd_read_byte(),7) ) ; // wait until busy flag is low
   if (A0==0){ output_low(lcd_rs);} //0=Instruction  and 1=Data
   if (A0==1){output_high(lcd_rs);} //0=Instruction  and 1=Data
   delay_cycles(d_cycle);
   output_low(lcd_rw);
   delay_cycles(d_cycle);
   output_low(lcd_en);
   lcd_send_nibble(n >> 4);
   lcd_send_nibble(n & 0xf);
}
   
void lcd_init() {
   BYTE const LCD_INIT_STRING[4] = {0x20 | (lcd_type << 2), 0xc, 1, 6};
   // These bytes need to be sent to the LCD for initialization.
   BYTE i;
   fprintf(debug,"Init!!\n\r");
   output_low(lcd_rs);
   output_low(lcd_rw);
   output_low(lcd_en);
   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 Data;
   if(y!=1)
      Data=lcd_line_two;
   else
      Data=0;
   Data+=x-1;
   lcd_send_byte(0,0x80|Data);
}
   
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
   output_high(lcd_rs);   
   value = lcd_read_byte();
   output_low(lcd_rs);   
   return(value);
}


Also double check that the circuit doesn't need any pull-up resisters.
treitmey



Joined: 23 Jan 2004
Posts: 1094
Location: Appleton,WI USA

View user's profile Send private message Visit poster's website

PostPosted: Tue Mar 02, 2004 9:57 am     Reply with quote

Opps,.. you wanted code for a serial LCD,... This was 4 bit parallel
Guest








PostPosted: Wed Mar 10, 2004 6:43 pm     Reply with quote

the problem with the ide board is that pin 39 and 40 ar enot connected to the board so they can not be used.

the lcd.cd supplied with ccs uses these ports and hence has to be modified before its used
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