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

LCD And Keypad Basics Gone Wrong

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



Joined: 02 Jun 2004
Posts: 16

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

LCD And Keypad Basics Gone Wrong
PostPosted: Fri Apr 21, 2006 1:28 pm     Reply with quote

I am trying to run a 4X3 keypad and 16X2 LCD off port D on a PIC16F877. I am using the CCS LCD.C and KBD.C drivers. My pinout is as follows

PIC----LCD---KBD

D0-----EN----NC
D1-----RS----R1-----10K Pullup
D2-----RW----R2-----10K Pullup
D3-----NC----R3-----10K Pullup
D4-----D4----R4-----10K Pullup
D5-----D5----C1
D6-----D6----C2
D7-----D7----C3

NC=N0 connection.

When the pullup resistors are in place nothing happens.
When the pullup resistors are removed the LCD says "Ready..."
below is the code that i am using both drivers and main. I have had this working once upon a time but i cant find my example and it has got me stumped. I seem to recall there being resistors or diode between the keypad and lcd but i could be mistaken. Heres the code

Code:

***********Lcd.c***************
// As defined in the following structure the pin connection is as follows:
//     D0  enable
//     D1  rs
//     D2  rw
//     D4  D4
//     D5  D5
//     D6  D6
//     D7  D7
//
//   LCD pins D0-D3 are not used and PIC D3 is not used.

// 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;


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

#if defined use_portb_lcd
   #define set_tris_lcd(x) set_tris_b(x)
#else
   #define set_tris_lcd(x) set_tris_d(x)
#endif


#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[4] = {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);
}

***********Lcd.c***************

Code:

***********Kbd.c***************
//The following defines the keypad layout on port D
// Un-comment the following define to use port B
//#define use_portb_kbd TRUE

// Make sure the port used has pull-up resistors (or the LCD) on
// the column pins

#if defined(__PCH__)
#if defined use_portb_kbd
   #byte kbd = 0xF81                   // This puts the entire structure
#else
   #byte kbd = 0xF83                   // This puts the entire structure
#endif
#else
#if defined use_portb_kbd
   #byte kbd = 6                  // on to port B (at address 6)
#else
   #byte kbd = 8                 // on to port D (at address 8)
#endif
#endif

#if defined use_portb_kbd
   #define set_tris_kbd(x) set_tris_b(x)
#else
   #define set_tris_kbd(x) set_tris_d(x)
#endif



//Keypad connection:   (for example column 0 is B2)
//                Bx:

#ifdef blue_keypad  ///////////////////////////////////// For the blue keypad
#define COL0 (1 << 2)
#define COL1 (1 << 3)
#define COL2 (1 << 6)

#define ROW0 (1 << 4)
#define ROW1 (1 << 7)
#define ROW2 (1 << 1)
#define ROW3 (1 << 5)

#else ////////////////////////////////////////////////// For the black keypad
#define COL0 (1 << 5)
#define COL1 (1 << 6)
#define COL2 (1 << 7)

#define ROW0 (1 << 1)
#define ROW1 (1 << 2)
#define ROW2 (1 << 3)
#define ROW3 (1 << 4)

#endif

#define ALL_ROWS (ROW0|ROW1|ROW2|ROW3)
#define ALL_PINS (ALL_ROWS|COL0|COL1|COL2)

// Keypad layout:
char const KEYS[4][3] = {{'1','2','3'},
                         {'4','5','6'},
                         {'7','8','9'},
                         {'*','0','#'}};

#define KBD_DEBOUNCE_FACTOR 33    // Set this number to apx n/333 where
                                  // n is the number of times you expect
                                  // to call kbd_getc each second


void kbd_init() {
}

char kbd_getc( ) {
   static BYTE kbd_call_count;
   static short int kbd_down;
   static char last_key;
   static BYTE col;

   BYTE kchar;
   BYTE row;

   kchar='\0';
   if(++kbd_call_count>KBD_DEBOUNCE_FACTOR) {
       switch (col) {
         case 0   : set_tris_kbd(ALL_PINS&~COL0);
                    kbd=~COL0&ALL_PINS;
                    break;
         case 1   : set_tris_kbd(ALL_PINS&~COL1);
                    kbd=~COL1&ALL_PINS;
                    break;
         case 2   : set_tris_kbd(ALL_PINS&~COL2);
                    kbd=~COL2&ALL_PINS;
                    break;
       }

       if(kbd_down) {
         if((kbd & (ALL_ROWS))==(ALL_ROWS)) {
           kbd_down=FALSE;
           kchar=last_key;
           last_key='\0';
         }
       } else {
          if((kbd & (ALL_ROWS))!=(ALL_ROWS)) {
             if((kbd & ROW0)==0)
               row=0;
             else if((kbd & ROW1)==0)
               row=1;
             else if((kbd & ROW2)==0)
               row=2;
             else if((kbd & ROW3)==0)
               row=3;
             last_key =KEYS[row][col];
             kbd_down = TRUE;
          } else {
             ++col;
             if(col==3)
               col=0;
          }
       }
      kbd_call_count=0;
   }
  set_tris_kbd(ALL_PINS);
  return(kchar);
}
***********Kbd.c***************

Code:

***********EX_LcdKb.c***************
#include <16F877.h>
#fuses HS,NOWDT,NOPROTECT,NOLVP
#use delay(clock=4000000)


#include <lcd.c>
#include <kbd.c>


void main() {
   char k;

   lcd_init();
   kbd_init();

   lcd_putc("\fReady...\n");

   while (TRUE) {
      k=kbd_getc();
      if(k!=0)
        if(k=='*')
          lcd_putc('\f');
        else
          lcd_putc(k);
   }
}


If anyone can see where i have gone wrong or if anyone has any clues to point me in the right direction as always it is greatly appreciated.

Thanks
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Fri Apr 21, 2006 1:44 pm     Reply with quote

It looks similar to what I'm doing in this thread, except that
you're using Port D instead of Port B. So it should work.
http://www.ccsinfo.com/forum/viewtopic.php?t=26229

1. What happens if you disconnect the keypad and its cable
from the board ? Does the LCD display "Ready" then ?
If so, there maybe a defect in the keypad or cable.

2. What happens if you comment out the init_kbd() line ?

Basically, I'm trying to see if the keypad is the problem.
zogbog



Joined: 02 Jun 2004
Posts: 16

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

Keypad And LCD
PostPosted: Fri Apr 21, 2006 2:09 pm     Reply with quote

I am simulating the software on proteus. I get the same effect on port b.

I have had the code working on the PICDEM2+ dev board with the changed LCD.C for that board and i have had it working on both port b and d in proteus before but for some reason now i cant figure it out. I noticed in your thread you changed the fuse from HS to XT to account for the 4MHz crystal so i wil check my clock speeds are correct and try again.

thanks
zogbog



Joined: 02 Jun 2004
Posts: 16

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

Port D LCD And Keypad
PostPosted: Mon Apr 24, 2006 12:20 pm     Reply with quote

So far i have managed to simulate
1)The Keypad on PORT D and the LCD on PORT B
2)The Keypad on PORT B and the LCD on PORT D
3)The Keypad and the LCD in parallel on PORT B.

But when i put both in parrallel on PORT D the LCD is blank.
If i remove the pullup resistors the LCD displays "Ready..." but the keypad is dead.
The circuits are exactly the same as when I have had success on PORT B but parallel on PORT D no joy.
I am sure its not the drivers because they work but iIthink there is something missing from the circuit.
Maybe some resistors or diodes between the LCD and the keypad?... If anyone has had any success with this circuit on port D the please could you help me.

Thanks

[/img]
zogbog



Joined: 02 Jun 2004
Posts: 16

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

PostPosted: Mon Apr 24, 2006 12:59 pm     Reply with quote

Here is a link to the circuit diagram

[img]http://homepage.mac.com/damienpattrick/.Public/CCSDEMOPORTD.BMP[/img]
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