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

pic16f877a interfacing 4x7 matrix using switchs in KBD.C

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



Joined: 25 Jul 2014
Posts: 11

View user's profile Send private message

pic16f877a interfacing 4x7 matrix using switchs in KBD.C
PostPosted: Wed Dec 10, 2014 2:03 pm     Reply with quote

Hello,

I am using generic code KBD.c

the above code uses single Port with 3 column and 4 rows

Code:


#byte kbd = getenv("SFR:PORTD")
#define set_tris_kbd(x) set_tris_d(x)

#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)



and provides 4x3 matrix.

Code:

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


but i want 7x4 matrix.
i.e 4 Rows and 7 columns.
which will require 2 Ports. (consider Port A and B)
Port A -> Column.(pins 0,1,2,3,4,5,6)
Port B -> Row.(pins 0,1,2,3)
Code:

                     char const KEYS[4][7] = {{'A','B','C','D','E','F','G'},
                                             {'H','I','J','K','L','M','N'},
                                             {'O','P','Q','R','S','T','U'},
                                             {'V','W','X','Y','Z','1','2'}};


can any one help me modify the below function to get the exact value from the matrix of 4x7
Code:


#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)

#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



int16 kbd_getc( ) {
   static BYTE kbd_call_count;
   static int1 kbd_down;
   static int16 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);
}


for reference i have attached the original code of KBD.c

Code:

///////////////////////////////////////////////////////////////////////////
////                             KBD.C                                 ////
////                  Generic keypad scan driver                       ////


++++++++++++++++++++++++
kbd.c removed. Reason: Forum rule #10
10. Don't post the CCS example code or drivers
http://www.ccsinfo.com/forum/viewtopic.php?t=26245
- Forum Moderator
++++++++++++++++++++++++


please suggest me some solution so that i can adjust the rows and columns. and enable them accordingly to get the exact value from matrix..


Thank You..
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Wed Dec 10, 2014 3:17 pm     Reply with quote

Quote:
but i want 7x4 matrix.
i.e 4 Rows and 7 columns.
which will require 2 Ports. (consider Port A and B)

Here is a modified version of kbd.c, where I put the rows and columns
on separate ports. I think this code could easily be modified to do
what you need:
http://www.ccsinfo.com/forum/viewtopic.php?t=23467

Also, make sure you have pullup resistors (or the internal PIC pullups
enabled) on the row pins (not the column pins as the CCS file says).
The CCS driver reads the rows and strobes the columns low, one at
a time. Any key that is pressed will connect the low strobe (pulse) to
the row pin, where it will be read. The other row pins must be in a
defined logic state (not floating), therefore they must have pullups on
them. If the row pins are on Port B, you could turn on the internal pullups.

But there is a problem here:
Quote:

Port A -> Column.(pins 0,1,2,3,4,5,6)
Port B -> Row.(pins 0,1,2,3)

The 16F877A only has 6 pins on PortA (A0 to A5). You need 7 pins for
the columns. Can you put the columns on Port D ? Then it would work.
swapnil14327



Joined: 25 Jul 2014
Posts: 11

View user's profile Send private message

PostPosted: Thu Dec 11, 2014 12:14 am     Reply with quote

PCM programmer wrote:
Quote:
but i want 7x4 matrix.
i.e 4 Rows and 7 columns.
which will require 2 Ports. (consider Port A and B)

Here is a modified version of kbd.c, where I put the rows and columns
on separate ports. I think this code could easily be modified to do
what you need:
http://www.ccsinfo.com/forum/viewtopic.php?t=23467

Also, make sure you have pullup resistors (or the internal PIC pullups
enabled) on the row pins (not the column pins as the CCS file says).
The CCS driver reads the rows and strobes the columns low, one at
a time. Any key that is pressed will connect the low strobe (pulse) to
the row pin, where it will be read. The other row pins must be in a
defined logic state (not floating), therefore they must have pullups on
them. If the row pins are on Port B, you could turn on the internal pullups.

But there is a problem here:
Quote:

Port A -> Column.(pins 0,1,2,3,4,5,6)
Port B -> Row.(pins 0,1,2,3)

The 16F877A only has 6 pins on PortA (A0 to A5). You need 7 pins for
the columns. Can you put the columns on Port D ? Then it would work.


thanks mate..
I will try out asap..

also I have one question..

I am driving 28 LED using this technique..
1) Will LED will work in Matrix formation.?
2) I will have to connect each LED to a separate pin of PIC.?

if 2 case then i might need bigger pic with more pins on it..

my main motive is:
Once I press and hold "Switch 1" "LED 1" will be ON. Release switch LED OFF.

MOTIVE::

1)"Switch 1" pressed and hold. "LED 1" ON.
2)Considering "Switch 1" is pressed, I press and hold "Switch 2" "LED 1" should be "OFF" and "LED 2" should be ON
3)Switch 1(pressed) - - LED 1(ON)
Switch 1(pressed)Switch 2(pressed) - - LED 1(OFF) LED 2(ON)
Switch 1(pressed)Switch 2(pressed)Switch 3(pressed) - - LED 1(OFF) LED 2(OFF)LED 3(ON)

and so on when all Switches pressed(Serially 1 to 28) only LED 28 will be ON


will the above concept work with the code ?
Ttelmah



Joined: 11 Mar 2010
Posts: 19520

View user's profile Send private message

PostPosted: Thu Dec 11, 2014 1:36 am     Reply with quote

LED multiplexing.

Perfectly standard. Just about every display you see with more than a handful of LED's, will be multiplex driven.

But. Remember that each LED will only be 'on' for 1/nth the time. If you have an 8 column LED matrix, each column is only on for 1/8th the time. If you want the LED's to look as bright as when they are driven directly, and you use (perhaps) 10mA for direct drive, then you will need to deliver 80mA for the 1/8th the time the LED is 'on', to make the multiplexed display look as bright. Beyond the capabilities of a PIC pin, without transistors or similar buffers. Then remember that the switching will need to be regular and fast. The whole display must be refreshed perhaps at least 100* per second.

As a comment on the switches, you could drive the matrix as (say) 7*4, and then use a 3-8line decoder to drive the rows. Total of 7 pins, to drive the entire keyboard.
swapnil14327



Joined: 25 Jul 2014
Posts: 11

View user's profile Send private message

4x7 keypad with pic16f946
PostPosted: Thu Dec 11, 2014 2:21 pm     Reply with quote

hello can any one help me with the below code..
its not working..
as pic16f877a was not sufficient with IO.
i am using pic16f946.


kbd.c
Code:
#byte kbd_rows = 0x189    // Port g
#byte kbd_cols = 0x188    // Port f

#define set_tris_kbd_rows(x) set_tris_g(x)
#define set_tris_kbd_cols(x) set_tris_f(x)


#define Bitmask(x) (1 << (x & 7))


#define COL0  Bitmask(PIN_F0)
#define COL1  Bitmask(PIN_F1)
#define COL2  Bitmask(PIN_F2)
#define COL3  Bitmask(PIN_F3)
#define COL4  Bitmask(PIN_F4)
#define COL5  Bitmask(PIN_F5)
#define COL6  Bitmask(PIN_F6)

#define ROW0  Bitmask(PIN_G0)
#define ROW1  Bitmask(PIN_G1)
#define ROW2  Bitmask(PIN_G2)
#define ROW3  Bitmask(PIN_G3)


#define ALL_ROWS (ROW0|ROW1|ROW2|ROW3)
#define ALL_PINS (ALL_ROWS|COL0|COL1|COL2|COL3|COL4|COL5|COL6)

// Keypad layout:
char const KEYS[4][3] = {{'A','B','C','D','E','F','G'},
                         {'H','I','J','K','L','M','N'},
                         {'O','P','Q','R','S','T','U'},
                         {'V','W','X','Y','Z','1','2'}};

#define KBD_DEBOUNCE_FACTOR 333    // 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() {
}

int16 kbd_getc( ) {
   static BYTE kbd_call_count;
   static int1 kbd_down;
   static int16 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;
         case 3   : set_tris_kbd(ALL_PINS&~COL3);
                    kbd=~COL3&ALL_PINS;
                    break;
         case 4   : set_tris_kbd(ALL_PINS&~COL4);
                    kbd=~COL4&ALL_PINS;
                    break;
         case 5   : set_tris_kbd(ALL_PINS&~COL5);
                    kbd=~COL5&ALL_PINS;
                    break;
         case 6   : set_tris_kbd(ALL_PINS&~COL6);
                    kbd=~COL6&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);
}




main code:
Code:

#include <kbd.c>
void main()
{
      char k,s;
   int i=0;                     //counter

      kbd_init();



      while (TRUE)
   {

         k=kbd_getc();
   
     switch(k)
     {
        case 'A':
        output_high(PIN_A0);   
        break;
       
        case 'B' :
        output_high(PIN_A1);   
        break;
       
     }
            
      
   
         
   }

}
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Thu Dec 11, 2014 2:49 pm     Reply with quote

You changed a whole bunch of stuff from my example code in the link.

In my example code for 2 ports, I've got this:
Code:
#define ALL_ROWS (ROW0|ROW1|ROW2|ROW3)
#define ALL_COLS (COL0|COL1|COL2)

For some reason, you changed it to this:
Quote:
#define ALL_ROWS (ROW0|ROW1|ROW2|ROW3)
#define ALL_PINS (ALL_ROWS|COL0|COL1|COL2|COL3|COL4|COL5|COL6)

How is the ALL_PINS thing going to work ? The rows and columns are
on different i/o ports. The CCS functions only work on one port at a time !


Then you changed this. I would just leave it at the default 33 for now.
Quote:
#define KBD_DEBOUNCE_FACTOR 333 // Set this number to apx n/333



Next, you've got the switch-case statement where you're loading 'kbd'
with the column strobe bitmask. But there is no 'kbd' variable in the
2 port code in the link that I gave you. Also you're putting in ALL_PINS
and as I explained, you can't set tris on two ports at a time with the
CCS functions.
Quote:
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;


In my link, I use kbd_cols, as shown below:
Code:
if(++kbd_call_count>KBD_DEBOUNCE_FACTOR) {
       switch (col) {
         case 0   : set_tris_kbd_cols(ALL_COLS&~COL0);
                    kbd_cols=~COL0&ALL_COLS;
                    break;
         case 1   : set_tris_kbd_cols(ALL_COLS&~COL1);
                    kbd_cols=~COL1&ALL_COLS;
                    break;


Basically you need to copy what I'm doing in the example that I gave
you and not invent stuff.


Last edited by PCM programmer on Thu Dec 11, 2014 2:54 pm; edited 1 time in total
swapnil14327



Joined: 25 Jul 2014
Posts: 11

View user's profile Send private message

PostPosted: Thu Dec 11, 2014 2:53 pm     Reply with quote

i want to use 4x7 keypad
so i have to use two ports.. one for rows and other for coulum..

the example you gave is for 4x3 keypad..(12 switches)

i tried the modification but its not working..

can you suggest me some design for 4x7 keypad..(28 switches)
swapnil14327



Joined: 25 Jul 2014
Posts: 11

View user's profile Send private message

PostPosted: Thu Dec 11, 2014 2:56 pm     Reply with quote

how do i upload an image in here..?
i have the design but not able to upload the photo..
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Thu Dec 11, 2014 3:43 pm     Reply with quote

Quote:
i want to use 4x7 keypad
so i have to use two ports.. one for rows and other for coulum..

the example you gave is for 4x3 keypad..(12 switches)

i tried the modification but its not working..

I gave you some of the reasons why it's not working. The code is easily
expandable to a 4x7 keypad. I don't think I can do much more on this
thread.

Quote:
how do i upload an image in here..?

Use http://www.postimage.com or http://www.imageshack.com
or some other free image hosting service.
Upload your schematic to that website. Preferably a .JPG file or some
other commonly used image format.
Then post a link to your image here in the forum. Use the Preview
button to view your post and see if the link is working correctly, before
you press the Submit button.
swapnil14327



Joined: 25 Jul 2014
Posts: 11

View user's profile Send private message

PostPosted: Thu Dec 11, 2014 5:17 pm     Reply with quote

Thanks again mate...
works fine now changed completely according to your code..

just some glitches....
working with them now..

Code:

#byte kbd_rows = 0x189    // Port g
#byte kbd_cols = 0x188    // Port f

#define set_tris_kbd_rows(x) set_tris_g(x)
#define set_tris_kbd_cols(x) set_tris_f(x)


#define Bitmask(x) (1 << (x & 7))
//Keypad connection:   (for example column 0 is B2)

#define COL0  Bitmask(PIN_F0)
#define COL1  Bitmask(PIN_F1)
#define COL2  Bitmask(PIN_F2)
#define COL3  Bitmask(PIN_F3)
#define COL4  Bitmask(PIN_F4)
#define COL5  Bitmask(PIN_F5)
#define COL6  Bitmask(PIN_F6)

#define ROW0  Bitmask(PIN_G0)
#define ROW1  Bitmask(PIN_G1)
#define ROW2  Bitmask(PIN_G2)
#define ROW3  Bitmask(PIN_G3)



#define ALL_ROWS (ROW0|ROW1|ROW2|ROW3)
#define ALL_COLS (COL0|COL1|COL2|COL3|COL4|COL5|COL6)

// Keypad layout:
char const KEYS[4][7] = {{'A','B','C','D','E','F','G'},
                         {'H','I','J','K','L','M','N'},
                         {'O','P','Q','R','S','T','U'},
                         {'V','W','X','Y','Z','1','2'}};

#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() {
}

int16 kbd_getc( ) {
   static BYTE kbd_call_count;
   static int1 kbd_down;
   static int16 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_cols(ALL_COLS&~COL0);
                    kbd_cols=~COL0&ALL_COLS;
                    break;
         case 1   : set_tris_kbd_cols(ALL_COLS&~COL1);
                    kbd_cols=~COL1&ALL_COLS;
                    break;
         case 2   : set_tris_kbd_cols(ALL_COLS&~COL2);
                    kbd_cols=~COL2&ALL_COLS;
                    break;
         case 3   : set_tris_kbd_cols(ALL_COLS&~COL3);
                    kbd_cols=~COL3&ALL_COLS;
                    break;
         case 4   : set_tris_kbd_cols(ALL_COLS&~COL4);
                    kbd_cols=~COL4&ALL_COLS;
                    break;
         case 5   : set_tris_kbd_cols(ALL_COLS&~COL5);
                    kbd_cols=~COL5&ALL_COLS;
                    break;
         case 6   : set_tris_kbd_cols(ALL_COLS&~COL6);
                    kbd_cols=~COL6&ALL_COLS;
                    break;
       }

       if(kbd_down) {
         if((kbd_rows & (ALL_ROWS))==(ALL_ROWS)) {
           kbd_down=FALSE;
           kchar=last_key;
           last_key='\0';
         }
       } else {
          if((kbd_rows & (ALL_ROWS))!=(ALL_ROWS)) {
             if((kbd_rows & ROW0)==0)
               row=0;
             else if((kbd_rows & ROW1)==0)
               row=1;
             else if((kbd_rows & ROW2)==0)
               row=2;
             else if((kbd_rows & 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_rows(ALL_ROWS);
  set_tris_kbd_cols(ALL_COLS);
  return(kchar);
}


now this happens.:

Switch 1 ON -> Led 1 ON.
Switch 1 and 2 ON -> Led 1 and 2 ON..

i want only led 2 to be ON in second case and Led 1 OFF..

how can i reset the earlier LED before making next LED ON.

I am using output_high(pin) / output_low(pin) function.. is there any other way to do this..
temtronic



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

View user's profile Send private message

PostPosted: Thu Dec 11, 2014 5:25 pm     Reply with quote

You'll have to post your 'LED control' portion of code to get a reply !! Without seeing that,we can't make a proper assessment of what you're doing and how to correct it.


Jay
swapnil14327



Joined: 25 Jul 2014
Posts: 11

View user's profile Send private message

PostPosted: Thu Dec 11, 2014 5:35 pm     Reply with quote

Code:

#include "kbd.c"
void main()
{
char k,s;
int i=0;  //counter

kbd_init();


while (TRUE)
  {
   k = kbd_getc();
   if(k != 0)
      if(k=='A')
        {
         output_high(PIN_A0);
        }   
      elseif(k=='B')
        {
         output_low(PIN_A0);
         output_high(PIN_A1);
        }
      elseif(k=='C')
        {
         output_low(PIN_A1);
         output_high(PIN_A2);
        }
   }
}



I have also used If-else.. but still i have to do it manually every time(reseting previous LED before next led to be ON)..
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