Thaimicrotron.com : Home
 
MATRIX KEYBOARD 4X3
 
     
 

การใช้งานคีย์บอร์ดแบบแมตทริกซ์ (MATRIX KEYBOARD)

 
 

      การใช้งานอินพุตจำนวนมากอย่างเช่นคีย์บอร์ด หากใช้ 1 บิตต่อ 1 อินพุตจะทำให้สิ้นเปลืองพอร์ตจำนวนมาก ดั้งนั้น การใช้งานคีย์บอร์ด กับไมโครคอนโทรเลอร์ จึงนิยมใช้ คีย์บอร์ด แบบแมตทริกซ์ คือแบ่งเป็น แถว (ROW) และ หลัก (COLUMN) อินพุตที่ได้จึงเป็นผลคูณของ ROW กับ COLUMN เช่น ROW =4 ,COLUMN =3 จะได้อินพุต = 4x3 = 12 เป็นต้น

 
 
 
 
การเชื่อมต่อคีย์บอร์ดกับไมโครคอนโทรเลอร์บนบอร์ดทดลอง เมื่อมีการกดคีย์ ก็จะส่งค่าที่กด ออกทาง RS232
 
     
  ผลการทดลอง  
 
  - เมื่อจ่ายไฟให้ไมโครคอนโทรเลอร์ จะปรากฏคำว่า "*** KeyBoard ***"  
  - เมื่อกดคีย์บอร์ด  ไมโครคอนโทรเลอร์จะแสดงคำว่า KeyDown   เมื่อปล่อยคีย์ ไมโครคอนโทรเลอร์จะแสดงคำว่า KeyUp  
  และจะแสดงค่าอินพุตทาง Column,   (COL,ROW) และค่า Key Code เช่น  
     
  KeyDown,KeyUp 05H (01,03)=0B  
     
  อินพุตทาง Column=05H ,COL=1,ROW=3 Key Code =0B  
     
 
     
  วิธีการทดลอง  
     
 
 
 
ตำแหน่งของคีย์บอร์ดและ Jumper บนบอร์ดทดลอง
 
  - ให้ต่อ Jumper ทั้ง 7 ตัวดังรูป โดยย้าย Jumper มาจาก LED MATRIX  
     
   
  หลักการทำงานของคีย์บอร์ดแบบเมตทริซ์  
 
 
 
การใช้งานพอร์ตในส่วนของ อินพุต-เอาต์พุต และ KEYCODE
 
     
 
  • หลักการทำงานของคีย์บอร์ดแบบเมตทริซ์ ก็คือจะให้ด้านหนึ่งเป็นอินพุตและด้านหนึ่งเป็นเอาต์พุต คือให้ P1.0-P1.2 เป็นอินพุต ส่วน P3.0-P3.6 เป็นเอาต์พุต
  • ด้านอินพุตจะต้อง pull up ด้วยความต้านทานต่อกับ +5V เพื่อให้มีค่าเป็น 1 เมื่อไม่ได้กดคีย์ (สำหรับบนบอร์ดทดลองได้ต่อกับ RPACK 10K ไว้แล้ว)
  • การตรวจสอบการกดคีย์ จะต้องให้ด้านเอาต์พุตมีค่าเป็นโลจิก 0 ทีละแถว ในขณะเดียวกัน ก็จะอ่านด้านอินพุต ว่ามีบิตใดเป็น 0 หรือไม่ ถ้ามี ก็แสดงว่ามีการกดคีย์ วิธีการเช่นนี้เราเรียกว่า การมัลติเพล็ก (Multiplex ) และจะกระทำเช่นนี้จนครบทุกแถว
  • เนื่องจากเราใช้อินพุต และเอาต์พุตในพอร์ตเดียวกัน ดังนั้นเวลาอ่านอินพุต จึงต้องกำจัดบิตที่ไม่เกี่ยวข้องด้วยการนำมา AND กับ BIT MARK การกำหนด BIT MARK ก็คือบิตใดที่ จะกำจัด ก็กำหนด ให้เป็น 0 ส่วนบิตใด คงไว้ก็ให้เป็น 1 ในที่นี้เราใช้ P1.0-P1.2 เป็นอินพุต ดังนั้น BIT MARK = 00000111B
 
     
  ตารางการ SCAN ROW โดยให้เอาต์พุตมีค่าเป็นโลจิก 0 ทีละแถว  
 
ROW
SCAN ROW
DESCRIBTION
0
10111111B
P1.6 = 0
1
11011111B
P1.5 = 0
2
11101111B
P1.4 = 0
3
11110111B
P1.3 = 0
 
     
     
  ค่าของอินพุตในแต่ละหลักเมื่อมีการกดคีย์  
 
COLUMN
READ INPUT
VALUE
DESCRIBTION
0
00000110B
06H
Column 0 press
1
00000101B
05H
Column 1 press
2
00000011B
03H
Column 2 press
x
00000111B
07H
No Key press
 
     
  ค่าที่อ่านได้ KEY=(ROW * MAXCOLUMN)+COLUMN+1  
     
  ตัวอย่างโปรแกรมการอ่านค่าจากคีย์บอร์ด 4x3  
     
  EXAM10  
 
;EXAM10.ASM
;Matrix KeyBoard 3x4
;
MAXCOL		EQU	3		;Max Column = 3
KEYMARK		EQU	00000111B	;Mark bit Use input bit
;User internal ram area

	ORG     30H
KeyBuff:	DS	1	;
KeyRow:		DS	1	;Hold Key Row
KeyCol:		DS	1	;Hold Key Col
Key:		DS	1

	ORG	0000H

;*** Power up delay ***
;Wait for other Device
RES:	MOV	R2,#40H
RES1:	MOV	R3,#0
RES2:	DJNZ	R3,RES2
	DJNZ	R2,RES1

;*** MAIN ***
MAIN:	LCALL	InitUART	;Initial UART 9600,n,8,1 no parity

	MOV	DPTR,#Hello
	LCALL	SendSROM

Next:	LCALL	ScanKey		;Read Key Board
	MOV	A,KEY		;Test Key
	XRL	A,#00		;if key = 0
	JZ	Next		;   Yes Scan Next
	
	MOV	A,KEY		;Get Key value
	LCALL	SNDASCII	;Display Key Code
	LCALL	LineFeed	;Send Line Feed

	SJMP	Next		;Scan Next
;End Main


;*** Scan Key Board ***
;IN no
;Out	KEY =0 not key press
;	KEY = 1-n Key press
;
ScanKey:
;ROW0
	MOV	KeyRow,#00H	;KeyRow = 0
	MOV	P1,#10111111B	;Test Row0 P1.6 =0
	LCALL	CHKCOL		;Check Column at Row=0
	XRL	A,#00H		;Check Key Press
	JNZ	ScanKX		;Yes Calculate Key Code
;ROW1
	MOV	KeyRow,#01H	;KeyRow = 1
	MOV	P1,#1011111B	;Test Row0 P1.5 =0
	LCALL	CHKCOL		;Check Column at Row=1
	XRL	A,#00H		;Check Key Press       
	JNZ	ScanKX		;Yes Calculate Key Code

;ROW2
	MOV	KeyRow,#02H	;KeyRow = 2
	MOV	P1,#1101111B	;Test Row0 P1.4 =0
	LCALL	CHKCOL		;Check Column at Row=2
	XRL	A,#00H		;Check Key Press       
	JNZ	ScanKX		;Yes Calculate Key Code

;ROW3
	MOV	KeyRow,#03H	;KeyRow = 3
	MOV	P1,#1110111B	;Test Row0 P1.3 =0
	LCALL	CHKCOL		;Check Column at Row=3
	XRL	A,#00H		;Check Key Press       
	JNZ	ScanKX		;Yes Calculate Key Code

	MOV	Key,#00H	;Return 0 no Key Press
	RET

ScanKX:	
;Calculate Key Code
;KEY = (ROW*MAXCOL)+COL+1 when Key Code =1 to n
	MOV	A,KeyRow	;A=ROW
	MOV	B,#MAXCOL	;B=MAXCOL
	MUL	AB		;A = ROW*MAXCOL
	ADD	A,KeyCol	;A = (ROW*MAXCOL)+COL
	ADD	A,#01H		;A = (ROW*MAXCOL)+COL+1

	MOV	Key,A		;Save Result to A
	RET

;*** Check Column ***
;Scan Colume
;if Key Press
;	A=1;
;	KeyCol=Column
;	KeyRow=Row

CHKCOL:
	MOV	A,P1		;Read P1
	ANL	A,#KEYMARK	;Clear not use bit
	MOV	KeyBuff,A	;Save to KeyBuff
	XRL	A,#KEYMARK	;Compare with no Key Conts
	JZ	CHKCEX		;not Key Press Exit
	
	MOV	DPTR,#KDown	;Display Key Down
	LCALL	SendSROM

;Check Debounce
	MOV	R2,#10		;Wait for Read again
	LCALL	DMSEC

;Read Key again
	MOV	A,P1		;Read P1
	ANL	A,#KEYMARK	;Clear not use bit
	XRL	A,KeyBuff	;Compare with Old Key
	JNZ	CHKCEX		;Not same exit

;Release Key
CHKWT:	MOV	A,P1		;Read P1
	ANL	A,#KEYMARK	;Clear not use bit
	XRL	A,KeyBuff	;Compare with Old Key
	JZ	CHKWT

	MOV	DPTR,#KUp	;Display Key UP
	LCALL	SendSROM

;Get Key Code
	MOV	A,KeyBuff
	ANL	A,#KEYMARK	;Clear not use bit
	LCALL	SNDASCII
	MOV	A,#'H'
	LCALL	SBYTE
	MOV	A,#' '
	LCALL	SBYTE

;Get Column
	MOV	A,KeyBuff
	ANL	A,#KEYMARK	;Clear not use bit
	LCALL	GetColNo
	MOV	KeyCol,A	;Save Colunm

	MOV	A,#'('
	LCALL	SBYTE

	MOV	A,KeyCol	;Restore Column for print
	LCALL	SNDASCII

	MOV	A,#','
	LCALL	SBYTE

;Get Row
	MOV	A,KeyRow
	LCALL	SNDASCII

	MOV	A,#')'
	LCALL	SBYTE
	MOV	A,#'='
	LCALL	SBYTE

	MOV	A,#01H		;Key Press A=1
	RET

CHKCEX:	CLR	A		;No Key Press A=0
	RET

;*** Get Column in Count Number 0-n***
GetColNo:
	MOV	R2,#00H		;Start with 0
GCNX:	
	RRC	A		;Rotage A to Carry
	JNC	GCEXIT		;Test C=0 (Key Press)
	INC	R2		;Increment R2 
	SJMP	GCNX		; and Check nect bit

GCEXIT:
	MOV	A,R2		;Store R2 to A
	RET

;*** Send ASCII 2 Byte ***
;IN A
;REG R2,R3
SNDASCII:
	LCALL	HTOA
	MOV	A,R2
	LCALL	SBYTE
	MOV	A,R3
	LCALL	SBYTE
;	LCALL	LineFeed
	
	RET

;*** Send String in Program Memory ***
;Input 	DPTR
SendSROM:
	CLR	A
	MOVC	A,@A+DPTR	;load char
	JZ	EndStr		;yes end
	LCALL	SBYTE		;send 1	byte
	INC	DPTR		;point to next char
	SJMP	SendSROM		;load next char

EndStr:	RET

;*** Send String in RAM ***
;Input 	R0
SendSRAM:
	MOV	A,@R0
	XRL	A,#00
	JZ	EndRStr		;yes end
	MOV	A,@R0
	LCALL	SBYTE		;send 1	byte
	INC	R0		;point to next char
	SJMP	SendSRAM	;load next char

EndRStr:
	RET


;*** Initial UART ***
InitUART:
	MOV	SCON,#01010010B	;Set SCON Serial Control Mode 1: 8-bit UART (Timer-Based). 
	MOV	TMOD,#00100000B	;Set Mode 2  8-bit Auto-Reload
	MOV	TH1,#0FDH	;Set Baud Rate 9600
	SETB	TR1		;Enable Timer 1
	RET

; ********** SBYTE SUB **********
;SEND BYTE
;IN  =	A
;REG =	NO
SBYTE:	JNB	TI,SBYTE	;Wait For Sending done
	CLR	TI
	MOV	SBUF,A
	RET

; ********** RBYTE SUB **********
;OUT =	A
;REG =	A
RBYTE:	JNB	RI,RBYTE	;Wait For Receive already
	CLR	RI
	MOV	A,SBUF
	RET

;*** Send line feed ***
LineFeed:
	MOV	A,#0Dh
	LCALL	SBYTE
feed:	MOV	A,#0Ah
	LCALL	SBYTE
	RET

;*** HTOA SUB ***
;CONVERT HEX TO ASCII
;IN  = A
;OUT = R2,R3
;REG = A,R2,R3

HTOA:	PUSH	ACC
	SWAP	A
	LCALL	HTOAS
	MOV	R2,A
	POP	ACC
	LCALL	HTOAS
	MOV	R3,A
	RET

HTOAS:	ANL	A,#0FH
	CJNE	A,#0AH,$+3
	JNC	HTOAS1
	ORL	A,#30H
	RET
HTOAS1:	SUBB	A,#9
	ORL	A,#40H
	RET

;*** DMSEC SUB ***
;DELAY 1/1000 SECOND
;IN  = R2
;REG = R2,R3
DMSEC:   MOV    R3,#230
DMSEC1:  NOP
	 NOP
	 DJNZ   R3,DMSEC1
	 DJNZ   R2,DMSEC
	 RET


Hello:	DB	0DH,"*** KeyBoard ***",0DH,0AH,00
KDown:	DB	"KeyDown",00
KUp:	DB	",KeyUp   ",00

END
 
 
DOWNLOAD
 
     
  แบบฝึกหัด  
  -เมื่อให้คีย์บอร์ดมีหมายเลขดังรูป  
     
   
     
  ให้เขียนโปรแกรมเพิ่มเติมจาก EXAM10 เพื่อให้แสดงค่าของคีย์ที่กดเช่น กดหมายเลข 1  
     
  KeyDown,KeyUp 03H (02,00)=03
1
 
     
  หรือกดคีย์ # ก็ให้แสดง  
     
  KeyDown,KeyUp 06H (00,03)=0A
#
 
     
  แนวทางปฏิบัติ  
  - จะเห็นว่า Key Code กับ KeyBoard มีตำแหน่ง และความหมาย ของคีย์ไม่ตรงกัน ดังนั้นเราต้องสร้างตาราง (KEYMAP) แทนค่าคีย์ เหล่านั้นก่อน ด้วยคำสั่ง DB เพื่อที่จะใช้วิธี LOOK UP TABLE และนำค่า Key Code ที่ได้มาเปรียบเทียบกับตำแหน่งในตาราง  
     
  1). ออกแบบตารางไว้ในส่วนท้ายของโปรแกรมก่อนคำสั่ง END  
     
 
KEYMAP: DB "321........" ;ให้ออกแบบตารางเมื่อเทียบกับ Key Code
 
     
  2). เขียนโปรแกรมเพิ่ม  
 
       
;*** MAIN ***    
MAIN: LCALL InitUART ;Initial UART 9600,n,8,1 no parity
       
  MOV DPTR,#Hello  
  LCALL SendSROM  
       
Next: LCALL
ScanKey ;Read Key Board
  MOV A,KEY ;Test Key
  XRL A,#00 ;if key = 0
  JZ Next ; Yes Scan Next
       
  MOV A,KEY ;Get Key value
  LCALL SNDASCII ;Display Key Code
  LCALL LineFeed ;Send Line Feed
 
   
  ........   ;อ่านค่าจาก KEY มาไว้ที่ A
  ........   ;ลดค่า A ลงหนึ่ง
  ........   ;ให้ DPTR มีค่าเท่ากับ Address ของ KEYMAP
  ........   ;Load Charracter จากตารางมาไว้ที่ A
  ........   ;เรียกโปรแกรมย่อย SBYTE
  ........   ;เรียกโปรแกรมย่อย LineFeed
       
  SJMP Next ;Scan Next
       
 
     
     
  หมายเหตุ  
 
    ข้อความเดิม
    ส่วนที่ต้องคีย์เพิ่มขึ้นมาใหม่ และ ,........ เป็นส่วนที่ให้เติมคำสั่งหรือข้อมูลให้ครบ