Continue to Site

Welcome to our site!

Electro Tech is an online community (with over 170,000 members) who enjoy talking about and building electronic circuits, projects and gadgets. To participate you need to register. Registration is free. Click here to register now.

  • Welcome to our site! Electro Tech is an online community (with over 170,000 members) who enjoy talking about and building electronic circuits, projects and gadgets. To participate you need to register. Registration is free. Click here to register now.

keypad scanning programming in C

Status
Not open for further replies.

okbro

Member
hi,

I have a problem in writing code for keypad scanning in C. My rows are connected to PORTB pin 0,1,2,3 and columns are connected to PORTC pin 0,1,2,3. Now for scanning purpose, how to concatenate each port 4 bits to form 8 bit and write in the form:
PINB.0 PINB.1 PINB.2 PINB.3 PINC.0 PINC.1 PINC.2 PINC.3
(written in this form to clarify)
so that i can perform comparison to some values like ==0x0F, 0x0D etc.
eg: if(PINB.0 PINB.1 PINB.2 PINB.3 PINC.0 PINC.1 PINC.2 PINC.3 == 0x0D ){}
Attached is interfacing picture.
keypad.png


thanks
 
I would use the Pullups of the 2 Posts, cause when setting one output to High and another to Low and Press 2 Switches at the same time You'll make a short.

I would set the Port C as input DDRC = 0b00000000;
Then activate the Pullups PORTC = 0b00001111;

Activate the Pullups of Port B PORTB = 0b00001110;
Also make at first the line 0 of Port B as Output DDRB = 0b00000001;
Now You ca read in colums into a variable.
I = PINC & 0b00001111; // The & avoid to use the PC.4 ... PC.7 Ports for Calculating.

Now switch the PORTB PORTB = 0b00001101;
And set the next Port of the DDRB register as output and the other port as input DDRB=0b00000010;
Now You can read the next colums into a variable.
I = PINC & 0b00001111; // The & avoid to use the PC.4 ... PC.7 Ports for Calculating.
if ( i < 0x0F )
{
I=I+0x10; //Shows You witch colum was active, for the next use I=I+0x02
}
And so on until any row was set once.

The Variable will give You witch switch is pressed.
Now give back Your Value.
return (I);

That should work
To decode the switches You can define some possible Bytes
#define one 0b00101101
...
#define seven 0b00001110

In main routine You can use the switch command to compute something with the pressed switches
 
I've tried to built a code snippet:
C:
uint8_t taste = 0;

#define ta1 0b00001110   //Switch definations You can also use tamul or tadiv
#define ta2 0b00001101
#define ta3 0b00001011
#define ta4 0b00000111
#define ta5 0b00011110
#define ta6 0b00011101
#define ta7 0b00011011
#define ta8 0b00010111
#define ta9 0b00101110
#define ta10 0b00101101
#define ta11 0b00101011
#define ta12 0b00100111
#define ta13 0b00111110
#define ta14 0b00111101
#define ta15 0b00111011
#define ta16 0b00110111
//...
uint8_t readtast (void)
{
uint8_t r = 0, i = 0;
DDRB = 0b00000001;
PORTB = 0b00001110;
r = PINC & 0b00001111;
if (r<0x0F)
    {
    i=r;
    }
    
DDRB = 0b00000010;
PORTB = 0b00001101;
r = PINC & 0b00001111;
if (r<0x0F)
    {
    i=r+0x10;
    }

DDRB = 0b00000100;
PORTB = 0b00001011;
r = PINC & 0b00001111;
if (r<0x0F)
    {
    i=r + 0x20;
    }

DDRB = 0b00001000;
PORTB = 0b00000111;
r = PINC & 0b00001111;
if (r<0x0F)
    {
    i=r+0x30;
    }

if ( i == 0b00001111)
{
    i=0;
}
    
return i;            
}

void dosome (uint8_t tasi)
{
    switch (tasi)
    {
        case ta1:
        asm ("nop");
        // do something
        break;
        
        case ta2:
        asm ("nop");
        // do something other
        break;
        //...
    }
    
}
int main(void)
{
  
    DDRC = 0b00000000;
    PORTC = 0b00001111;
    DDRB = 0b00000000;
    PORTB = 0b00001111;

    //sei();
    while (1)
    {
        //asm ("nop");
        taste = readtast(); //Repeated action has to be avoid not in code yet
        dosome(taste);
        
        
        // Place your code here

    }
}

At 16Mhz Clock the routine takes 3.25µs for running once.
A repeated action triggering isn't avoided.
Normally I use a old tast variable for that usage.
Only when something changes on switch matrix an action will be done.
To open a switch is an action too.
I don't want to make it complicated.
 
hi wkrug,

I doubt your code, don't understand, when the program reaches the first if statement, if(r <0x0F) in the readtast() function, it will always be evaluated true, thus i will get value of r(i=r). After that, the program continues and reaches the point where the 2nd row is made output and send low, then checked for column, where it reaches the 2nd if statement if(r<0x0F) which will also be evaluated always true so i changes value from r to a new value i=r+0x10. This process continues and value of i at the end gets i=r+0x30 whatsoever.

Correct me since I am not sure.

thanks
 
I doubt your code, don't understand, when the program reaches the first if statement, if(r <0x0F) in the readtast() function, it will always be evaluated true, thus i will get value of r(i=r).
When one switch is pressed the value is smaller then 0x0F.
Only when no switch is pressed the value = 0x0F.
Only at a pressed switch i will be changed.
In other cases it return the start value of 0.
You not can detect 2 pressed switches at the same time - That's right.

Normally all Ports of PORTC are pulled up by software, so they all give You back a 1 when readout PINC, else when the Port is pulled down external.

Try it out - I've only simulated that.
 
Status
Not open for further replies.

New Articles From Microcontroller Tips

Back
Top