# Key tied to two GPIO pins not functioning correctly

#### mik3ca

##### Member
I'm posting this here because it may be more of an electronics issue.

Anyways, I have a program which calls the dkey function to try to get a value based on the key pressed. I have three keys. Two are tied to their own GPIO pins and the third key functions exactly the same as the other two pressed at the same time.

When I press any of the first two keys (tied to its own GPIO pin), this function works fine, but sometimes when I use the third key, it tries to function as if its the first key but I don't understand why.

I set the timer function to execute about every 4096 clock cycles (about 2ms). I put it in timer mode 1 with TH0 as #0E0h and TL0 as #0h.

With my code, I deliberately use a 2ms+ delay along with a shift register approach (for a 16ms+ delay) before a button can be recognized as valid.

The keys in question I'm using are omron B3F-4000.
The diodes I'm using to connect the third key to the first two are 1N914's.

Is my hardware or timing at fault or is it something else?

Code:
    ;Keys are hooked up as:
;Button 1 to P1.1
;Button 3 to P1.3
;Button 2 to P1.1 AND P1.3 (via diodes)

ALLKEYS equ P1

KEYCAP equ 2Ch  ;keys captured
KEY1 bit KEYCAP.1
KEY2 bit KEYCAP.3

KEYS equ 2Eh ;Keys detected after scan

KEY1DOWN bit KEYS.0
KEY1HELD bit KEYS.1
KEY1UP bit KEYS.2
KEY2DOWN bit KEYS.4
KEY2HELD bit KEYS.5
KEY2UP bit KEYS.6

;Our key data so timer can process new key info while we work
;with the old
IKEY1DOWN bit ACC.0
IKEY1HELD bit ACC.1
IKEY1UP bit ACC.2
IKEY2DOWN bit ACC.4
IKEY2HELD bit ACC.5
IKEY2UP bit ACC.6

;Mask value to indicate both keys are held
;This equals IKEY1HELD and IKEY2HELD
BOTHHELD equ 22h

timer:
mov KEYCAP,ALLKEYS ;capture a new set of keys so we know what key1 and key 2 equal
reti

;here key info is obtained
getkey:
mov C,KEY1
mov A,UKEY1
;and put it into an 8-bit shift register named UKEY1
;this register changes value almost everytime we ask for a key
rlc A
mov UKEY1,A
;If register value=0 then key is held down (held for at least 8 key info requests)
;since press connects port pin to ground
jnz nokeyp1h
setb KEY1HELD
nokeyp1h:
;Set key down since key is held for at least 4 key info requests
cjne A,#0F0h,nokeyp1
setb KEY1DOWN
nokeyp1:
;Set key up since key is let go for at least 4 key info requests
cjne A,#00Fh,nokeyp1b
clr KEY1HELD
setb KEY1UP
nokeyp1b:
;The following is a repeat but for the other port pin connected to the keys.
mov C,KEY2
mov A,UKEY2
rlc A
mov UKEY2,A
jnz nokeyp2h
setb KEY2HELD
nokeyp2h:
cjne A,#0F0h,nokeyp2
setb KEY2DOWN
nokeyp2:
cjne A,#00Fh,nokeyp2b
clr KEY2HELD
setb KEY2UP
nokeyp2b:
;Load keys to accumulator so we can deal with them then reset keys value
mov A,KEYS
mov KEYS,#0h
clr C
ret

;Function is called in main program to get a button press. Stall if nothing is pressed
dkey:
acall getkey ;get key info
mov B,A ;save key value
anl A,#BOTHHELD ;check to see if both keys are held down
cjne A,#BOTHHELD,o3
mov A,#08h ;it is so return 8
ret
o3:
mov A,B ;restore key value
jnb IKEY1HELD,o1
clr A ;Key one held down
ret
o1:
jnb IKEY2HELD,o2
mov A,#04h ;Key 2 held down
ret
o2:
;At this point, nothing is held down so rerun the loop
sjmp dkey

#### Pommie

##### Well-Known Member
I can't follow your code but it sounds like a timing or bouncing problem. Try reading mulitple times and if active high OR the values together, if active low then AND them together.

Mike.

#### mik3ca

##### Member
I did try that. I used jnz instruction when comparing UKEYx to see if the key is held down because when it is, the values coming in will be logic lows since one key pin is tied to ground while the other is tied to the gpio pin.

For now, I think I'll try a larger buffer approach and instead of storing bits into one byte, I'll store them into multiple bytes. Basically I'll try code listing 3 from http://www.ganssle.com/debouncing-pt2.htm