Hello, I'm trying to create a routine that processes the input from a 12 digit keyboard input and then display it on a 16x2 LCD display. I'm testing the reading routine with a simple output to an HEX display. Problem is that the value doesn't hold, it changes immediately back to 0 (zero - initial value). Also, while the key is being pressed there should be a sound signal from a buzzer. Here's what I've worked out so far:

$MOD51	; includes definitions

	; variable declaration
		KEYBOARD	equ		P1
		OUTPUT		equ		P3
		CONFIRM		equ		B	; key to confirm
		NPK		equ		R0	; pressed keys
		KEY_0		equ		0000H
		KEY_1		equ		0001H
		KEY_2		equ		0002H
		KEY_3		equ		0003H
		KEY_4		equ		0004H
		KEY_5		equ		0005H
		KEY_6		equ		0006H
		KEY_7		equ		0007H
		KEY_8		equ		0008H
		KEY_9		equ		0009H
		KEY_A		equ		000AH
		KEY_C		equ		000BH
		TIME		bit		TF0
		Y2		bit		KEYBOARD.0
		Y1		bit		KEYBOARD.1
		Y0		bit		KEYBOARD.2
		X3		bit		KEYBOARD.3
		X2		bit		KEYBOARD.4
		X1		bit		KEYBOARD.5
		X0		bit		KEYBOARD.6
		BUZZER		bit		KEYBOARD.7

; memory management
	ORG	0000H
		SJMP	BEGGIN
	ORG	0030H

; main
BEGGIN:	SJMP	READIN

; keyboard reading
LOOP1:	MOV	A, #00FFH
	MOV	NPK, #0
	MOV	KEYBOARD, #00FFH
	SJMP	COLY0

COLY0:	CLR	Y0
	SJMP	T_T1

T_T1:	JB	X0, T_T4
	MOV	A, #KEY_1
	INC	NPK
T_T4:	JB	X1, T_T7
	MOV 	A, #KEY_4
	INC	NPK
T_T7:	JB	X2, T_TA
	MOV	A, #KEY_7
	INC	NPK
T_TA:	JB	X3, COLY1
	MOV	A, #KEY_A
	INC	NPK

COLY1:	SETB	Y0
	CLR	Y1
	SJMP	T_T2

T_T2:	JB	X0, T_T5
	MOV	A, #KEY_2
	INC	NPK
T_T5:	JB	X1, T_T8
	MOV	A, #KEY_5
	INC	NPK
T_T8:	JB	X2, T_T0
	MOV	A, #KEY_8
	INC	NPK
T_T0:	JB	X3, COLY2
	MOV	A, #KEY_0
	INC	NPK

COLY2:	SETB	Y1
	CLR	Y2
	SJMP	T_T3

T_T3:	JB	X0, T_T6
	MOV	A, #KEY_3
	INC	NPK
T_T6:	JB	X1, T_T9
	MOV	A, #KEY_6
	INC	NPK
T_T9:	JB	X2, T_TC
	MOV	A, #KEY_9
	INC	NPK
T_TC:	JB	X3, ENDR
	MOV	A, #KEY_C
	INC	NPK

ENDR:	RET

; de-bouncing wait routine
WAITR:	CLR	TIME
	MOV	TH0, #00D8H
	MOV	TL0, #00F0H
	JNB	TIME, $
	RET

; key confirmation check routine
READIN:	MOV	TMOD, #1
	SETB	TR0
	MOV	OUTPUT, #00FFH

PREKEY:	LCALL	LOOP1

SAIR:	CJNE	NPK, #1, PREKEY
	MOV	CONFIRM, A
	LCALL	WAITR
	LCALL	LOOP1
	CJNE	NPK, #1, PREKEY
	CJNE	A, CONFIRM, PREKEY
	MOV	OUTPUT, A
	CLR	BUZZER

LIBTEC:	LCALL	LOOP1
	CJNE	NPK, #0, PREKEY
	LCALL	WAITR
	LCALL	LOOP1
	CJNE	NPK, #0, PREKEY
	SETB	BUZZER
	LJMP	PREKEY

END

Edited 6 Years Ago by kacete: n/a

You are scanning a 3x4 matrix. May I suggest building a bit array that will make edge detection and debouncing much faster. And no more multitude branch testing.

Edge[0] = Edge[1] = 0;
LastKey[0] = LastKey[1] = 0xff;
;;;  Main KeyIn Loop

Y1=Y2=1; Y0=0;
a[0] = (X << 1) & 0xF0;

Y0=1;  Y1=0;
a[0] |= (x >> 3) & 0x0f;

Y1=1; Y2=0;
a[1] = (X >> 1) & 0x0f;

;;; a[0] = 8 bits.
;;; a[1] = 4 bits.

Edge[0] = a[0] ^ LastKey[0];
Edge[1] = a[1] ^ LastKey[1];

if (Edge[0])    // Change in key
{
   // 0=down, 1=up
   if (a[0] & Edge[0])    // Just pressed
//   if (LastKey[0] & Edge[0])   // Just released
   {
      // Process keys associated with Edge[0] bits
   }
}

if (Edge[1])     // change in key
{
  // 0=down, 1=up
   if (a[1] & Edge[1])    // Just pressed
//   if (LastKey[1] & Edge[1])   // Just released
   {
      // Process keys associated with Edge[0] bits
   }

   LastKey[0] = a[0];
   LastKey[1] = a[1];
}

This will be faster key detection, and edge detection. For debounce you can also store in a secondary shadow.

b[0] = LastKey[0]
b[1] = LastKey[1]
LastKey[0] = a[0];
LastKey[1] = a[1];

Upon edge detection. If (b[0]==LastKey[0])  // Persists two cycles then good!

Thank you for the quick reply, but could you use a more Assembly syntax? I'm just starting 8051 programing this semester and I'm not used to the C algorithm.

This article has been dead for over six months. Start a new discussion instead.