Reading in Different IO port + debouncing

Status
Not open for further replies.

Anniyan_x

Member
hi, i have to read 8 inputs switches, 3 connected to portA and 5more in portB, i have to use this connections, if all are in single port i can read the whole and use masking to chk which pin is pressed and do deboucing then call the corresponding event..but now i face a problem coz there 2different ports, in portA the switches are connected to pin4,5,1 and in portb the pins are connected to pin3,4,5,6,7..the switches are pull to GND..LOW..and wn pressed goes high....and my question is whats the most efficient way to do this..reading the inputs+ debouncing and call the event.


last time wn i did in same port the code was as below and this time the switches are pulled up. the code is as below


/*complement coz wn pressed pull to GND */
#define PUSH_BUTTONS ( (~PCDR ) & 0x03 )

#define UART_BT5 0b00000001
#define Button_BT6 0b00000010
#define DEBOUNCE_TIME 0x3E80 // approx > 20miliseconds???


while (1)
{
unsigned char B;

B =Debounce ();
switch (B)
{
case UART_BT5 : TX_DATA();
break ;
case Button_BT6 :_nop_();
break ;
default:_nop_();
break ;
}
while ( 0 != Debounce ()) ;
// wait for release stablising..or all buttons released.

}//end while

//--------------------------

unsigned char Debounce ( void )
{
unsigned char PreviousButton = PUSH_BUTTONS ;
int DebounceTime = DEBOUNCE_TIME ;

/* Wait for state stable */
while ( DebounceTime != 0 )
{
if ( PreviousButton != PUSH_BUTTONS )
{
DebounceTime = DEBOUNCE_TIME ; /* state changed : restart delay */
PreviousButton = PUSH_BUTTONS ;
}
else
DebounceTime-- ;
}
switch ( PreviousButton )
{
case UART_BT5 :
case Button_BT6 :

return PreviousButton ;
default:
return 0 ; /* No button pressed or more than one button pressed. */
}
}

so now im thinking modifiying the above code so tht i can read frm differents ports and and do debouncing and call the event..but i need help in how is best way to do this..or modifying the above code,but im not sure how and make the above code work?? or got other methods,codes,ideas and solutions

thanks & regards
anniyan
 
Last edited:
First, what uP/uC are you working with? Can't you just read both ports and mask the bits like you would with a single port?
From the sound of your post, the inputs are interrupt driven? I don't quite understand what the issue is.
 
When I'm doing any sort of keyboard routine I use a method to detect new key presses. By combining this with a small delay you get very good debounced switches.
Code:
unsigned char GetKeys(){
static unsigned char OldKeys;	//to keep previous value
unsigned char Edges;            //local variables
    DelayMs(20);		//debounce
    OldKeys=Keys;               //make a copy of keys
    Keys=PORTB&0b00100101;      //get switch state
    Keys^=0b00100101;           //make pressed keys = 1
    Edges=(Keys^OldKeys);       //keep only keys that have changed
    Edges&=Keys;                //keep only new key presses - not key releases
    return(Edges);
}

Note that with the above code the returned value will contain a 1 bit for each new key press. If you call it again before the key is released it will return zero for that keys bit.

In the above case you can combine the keys by doing,
Code:
unsigned char GetKeys(){
static unsigned char OldKeys;	//to keep previous value
unsigned char Edges;            //local variables
    DelayMs(20);		//debounce
    OldKeys=Keys;               //make a copy of keys
    Keys=PORTB&0b11111000;	//get bits 3-7 of port b
    if(PORTAbits.RA1==1)	//add in bit 1 or port a
	Keys|=0b00000100;	//porta.1 in bit 2
    if(PORTAbits.RA4==1)	//and porta.4
	Keys|=0b00000010;	//a4 in bit 1
    if(PORTAbits.RA5==1)	//and porta.5
	Keys|=0b00000001;	//a4 in bit 0
    Keys^=0xff;			//make pressed keys = 1
    Edges=(Keys^OldKeys);       //keep only keys that have changed
    Edges&=Keys;                //keep only new key presses - not key releases
    return(Edges);
}

Mike.
 
Last edited:
First, what uP/uC are you working with? Can't you just read both ports and mask the bits like you would with a single port?
From the sound of your post, the inputs are interrupt driven? I don't quite understand what the issue is.

hello rezer...im using (ST7LITE4M) uC....ya i thk i should just read boths ports and mask the bits just like a single port.And the switches are not interrupt-driven.the issue was i worte code for single port reading..and now got 2 different ports and so i cant use the same technique as my previous single port reading method as above(i paste the code above)...but if i use the single port method i have too:-

readportA();-then debounce_A();-then call event();
readportB();-then debounce_B();-then call event();
and repeat

....so it is like i need to repeat the same code twice,one for portA read and one for portB read...just to detect which key press..so teh coding seems more...same code but repeated twice..so i thought if got some other ways to do the reading and debouncing ...mayb got betters ways..thts the issue.
 
dear pommie i really couldn't make the logics to work..coz i dont ustd a few things...

i think frm ur code the switches are pulled low..right??? and my circuit was low too...i assume the iniatialized of the keys are 0000 0000, as not any switch is pressed and the first time,

so oldkey = 0000 0000

lets say i pressed bit7 portb switch so it will be high

keys = PORTB & 0b11111000 = 10000000

no porta switch pressed so

keys^=0xFF => 01111111. ex-or

then Edges = (keys^Oldkeys) = 01111111^00000000 = 01111111

then edges = (01111111&0111111) = 0111111

return(01111111)

is it like above?? im confusing here..or am i wrong...can explain abit abt ur code???

thanks & regards
shoghi
 
Hi Anniyan,

You have the logic reversed. As you said, low=switch pressed and so,

oldkey = 0000 0000

lets say i pressed bit7 portb switch so it will be high - no it will be low

keys = PORTB & 0b111111000 = 011111000

no porta switch pressed so - so keys becomes 01111111

keys^=0xFF => 10000000. ex-or

then Edges = (keys^Oldkeys) = 10000000^00000000 = 10000000
then edges = (10000000&10000000) = 10000000

return(10000000)

If you then work out what happens second time in you should see how edges only ever gets set for new key pressed.

Mike.
 
ok now i get it...so to use code the circuit is (the switches) are normally high...and wn pressed becomes low.i think i wrongly explain before as my switches are actually normaly low and wn pressed goes high. but anyway it is ok...so at reset,the oldkeys value should iniatilized at 0000 0000.ok then thanks for u info and code.

regards
shoghi
 
Last edited:
Status
Not open for further replies.
Cookies are required to use this site. You must accept them to continue using the site. Learn more…