Chúng ta biết ic lập trình AT89C51 có 4 cảng 8 bit nên tổng cộng có 32 
chân có thể xuất nhập dữ liệu dạng bit. Cách nhập dữ liệu đơn
giản nhất là dùng các phím nhấn. Phím nhấn chỉ làm việc 
theo logic nhị giá, nghĩa là đóng hoặc hở. Với các phím nhấn,
người ta có thể dùng đơn lẻ hay tổ hợp theo dạng matrix. Hình 
vẽ dưới đây cho thấy:

Các phím gắn trên ma trận 4x4, người ta nói matrix 4x4 có 4 hàng và 4
cột. Trên ma trận 4x4 chúng ta chỉ dùng có 8 dây mà có thể 
gắn được đấn 16 phím, đó là một ưu điểm của loại bàn phím 
matrix, dùng số chân ít mà gắn được nhiều phím. Với các phím 
đơn lập thì mỗi phím thường gắn trên một chân của IC, vậy trên 
một cảng 8 chân chúng ta chỉ có thể gắn được 8 phím.

Các phím nhấn phân ra làm 2 kiểu: Kiểu phím nhấn
thường hở
và kiểu phím nhấn
thường đóng
. Khi sử dụng các phím nhấn, chúng ta thường gặp vấn đề sau: Sự rung phím.

Vậy sự
rung phím
là gì?



cho thấy: Khi phím hở thì nó cho mức áp cao, ngay khi phím 
được nhấn xuống, nó sẽ kéo mức áp xuống mức thấp, nhưng do 
hiện tượng rung phím, lúc này có sự rung động ở tiếp xúc 
điểm, khiến cho tiếp điểm lúc dính lúc hở và mức áp sẽ dao 
động lúc lên lúc xuống và phải sau một lúc mới ổn định 
được ở mức thấp. Khi bỏ phím nhấn ra, chúng ta cũng gặp hiện 
tượng tương tự nhưng ít tác hại hơn. Khi dùng phím nhấn với 
các ic lập trình có phản ứng cực nhanh hiện tượng rung phím 
sẽ gây ra các điều khiển sai. Khi viết chương trình cho các phím
nhấn, chúng ta phải chú ý đến ảnh hưởng của hiện tượng rung 
phím, nhất là mỗi khi phím được đóng lại.

Trong 
thực hành, người ta thường dùng một đoạn chương trình làm chậm
khoảng 3ms đến 10ms và cho dò lại lần nữa trạng thái của 
phím để tránh sự sai lầm có thể xẩy ra do hiện tượng rung 
phím.


* Mạch AT89C51 dùng 8 phím nhấn đơn lập



Khi dùng
sơ đồ mạch điện này, trạng thái bit 1 trên các chân của cảng
p1 được xem như không có nhấn phím, khi có nhấn phím thì chân
có phím được nhấn sẽ xuất hiện bit 0. Khi một trong 8 chân của
cảng p1 có chân ở bit 0, chúng ta biết là có nhấn phím, như
vậy chúng ta sẽ viết câu lệnh tìm xem trên cảng p1 có xuất
hiện bit 0 hay không? Nếu không có bit 0 trên p1 thì tiếp tục
dò tìm, khi có chân có bit 0 thì hiểu là đã có phím bị nhấn
xuống, lúc đó chuyển qua tìm xem phím nào đã được nhấn và
rồi tiếp theo là cho chạy chương trình tương ứng với phím đã
được nhấn.

Sau đây là một đoạn chương trình dùng dò xem có phím nhấn không?

loop: ; đặt tên nhãn cho lệnh nhẩy
call do_key ; cho gọi chương trình dò phím, tên nhãn do_key
jnb f0, ttuc ; nhẩy theo bit của f0, f0=0, tiếp tục dò phím
call tim_phim ; cho gọi trình xác định phím nào được nhấn

ttuc: ; tên nhãn cho lệnh nhẩy
jmp loop ; nhẩy về tên nhãn loop, bắt đầu lại công việc dò phím
....
do_key: ; tên nhãn dùng cho lệnh nhẩy
clr f0 ; cho xóa bit f0, bit kiểm tra có phím nhấn hay không?
mov a, p1 ; chuyển trạng thái bit trên p1 vào thanh ghi a
orl a, #00000000b ; lấy logic OR trị trong a với 00000000b, để tìm bit 0 trên p1
cpl a ; đảo trị trong thanh ghi a
jz key_ret ; nếu trị trong a là 0, nhẩy đến key_ret, không có phím nhấn
call del ; gọi chương trình trể
mov a, p1 ; lại chuyển trạng thái của p1 vào a, kiểm tra lần nữa
orl a, #00000000b ; lại cho lấy logic OR trị trong a với 00000000b
cpl a ; đảo trị trong a để dò xem có phím nhấn không
jz key_ret ; nhẩy đến tên nhãn key_ret nếu không có phím nào được nhấn
setb f0 ; nếu có phím nhấn, cho set bit kiểm tra f0
mov b,a ; cho chuyển trị trong a cho cất vào b để dùng xác định phím nào được nhấn

key_ret: ; tên nhãn dùng cho lệnh nhẩy
mov a, p1 ; cho chuyển trạng thái cảng p1 vào a 
orl a, #00000000b ; lấy logic OR trị trong a với 00000000b
cpl a ; đảo trị trong thanh ghi a
jz key_ret1 ; nhẩy đến tên nhãn key_ret1, nếu thanh a bằng 0
jmp key_ret ; nhẩy đến tên nhãn key_ret, tiếp tục kiểm tra p1
key_ret1: ret ; quay lại sau lệnh: call do_key

tim_phim: ; chương trình xác định phím nào đã được nhấn
.....




Hình động trên đây cho thấy cách viết các câu lệnh dùng dò xem có phím nhấn hay không?



* Mạch AT89C51 dùng 16 phím gắn trên ma trận 4x4



Hình vẽ
cho thấy, 16 phím nhấn gắn trên ma trận 4x4. Ở đây 4 hàng cho
nối vào p2.0, p2.1, p2.2, p2.3, chúng ta gọi 4 hàng này là ngả
ra OUTPUT và 4 cột cho nối vào p2.4, p2.5, p2.6, p2.7 và gọi 4
cột là ngả vào INPUT. Có thể thấy:
Trên các
cảng p1 cho gắn 8 Led và trên cảng p3 chúng ta cũng cho gắn 8
Led. Từ sơ đồ mạch điện này, chúng ta sẽ lập trình để dùng
các phím trên bảng ma trận điều khiển các Led.



Cách viết chương trình vận hành các phím ráp theo kiểu ma trận 4x4:
Trước hết người ta đặt các hàng làm ngả ra OUTPUT và đặt các cột làm ngả vào INPUT.
Khởi
đầu cho các ngả vào ở bit 1 và cho các ngả ra ở bit 0, và
chạy trình dò phím, để xem có phím nào đã được nhấn xuống
không?

* Khi đã
xác nhận là đã có nhấn phím rồi thì cho chạy chương trình
tìm phím nhấn. Lúc này mỗi lần chỉ cho một chân INPUT ở bit 0,
khởi đầu cho cột 1 ở bit 0 rồi tìm xem trong 4 hàng, xem trên
ngả ra OUTPUT nào đang ở bit 0, làm vậy sẽ xác định được một
trong 4 phím của cột 1.

* Khi
chỉ cho cột 2 ở bit 0, rồi tìm xem ở hàng nào đang ở bit 0,
làm vậy sẽ xác định được một trong 4 phím của cột 2.

* Khi
chỉ cho cột 3 ở bit 0, rồi tìm xem ở hàng nào đang ở bit 0,
làm vậy sẽ xác định được một trong 4 phím của cột 3.

* Khi
chỉ cho cột 4 ở bit 0, rồi tìm xem ở hàng nào đang ở bit 0,
làm vậy sẽ xác định được một trong 4 phím của cột 4.





Sau đây là một chương trình mẫu:

org 0000b

start: ; đặt tên nhãn dùng cho lệnh nhẩy
clr p2.0 ; cho Led chỉ thị trên chân p2.0 sáng
; vào chương trình dò phím
do_phim: ; đoạn chương trình dùng để dò phím
mov p1, #00001111b ; đặt 4 chân Input lên 1 và 4 chân Output xuống 0
mov a, p1 ; cho chuyển hiện trạng của cảng p1 vào a
orl a, #11110000b ; lấy logic OR a với trị 11110000b
cpl a ; đảo các trị trong thanh ghi a
jz do_phim ; nếu a bằng 0 thì tiếp tục dò phím, nếu a khác 0 thì tìm phím nhấn
jmp tim_phim ; nhẩy đến chương trình tìm phím nhấn
; vào chương trình tìm phín nhấn
tim_phim: ; đoạn chương trình tìm phín nhấn
mov a, p1 ; chuyển hiện trạng của cảng p1 vào thanh ghi a
cjne a, #11101110b, tt1 ; chỉ cho chân p1.0 là 0, tìm phím trên p1.4
jmp chtrinh1 ; nếu đúng phím cho chạy chương trình 1
tt1: ; đặt tên nhãn dùng cho lệnh nhẩy
cjne a, #11011110b, tt2 ; chỉ cho chân p1.0 là 0, tìm phím trên p1.5
jmp chtrinh2

tt2: ; đặt tên nhãn dùng cho lệnh nhẩy
cjne a, #10111110b, tt3 ; chỉ cho chân p1.0 là 0, tìm phím trên p1.6
jmp chtrinh3

tt3: ; đặt tên nhãn dùng cho lệnh nhẩy
cjne a, #01111110b, tt4 ; chỉ cho chân p1.0 là 0, tìm phím trên p1.7
jmp chtrinh4

;

tt4: ; đặt tên nhãn dùng cho lệnh nhẩy
cjne a, #11101101b, tt5 ; chỉ cho chân p1.1 là 0, tìm phím trên p1.4
jmp chtrinh5

tt5: ; đặt tên nhãn dùng cho lệnh nhẩy
cjne a, #11011101b, tt6 ; chỉ cho chân p1.1 là 0, tìm phím trên p1.5
jmp chtrinh6

tt6: ; đặt tên nhãn dùng cho lệnh nhẩy
cjne a, #10111101b, tt7 ; chỉ cho chân p1.1 là 0, tìm phím trên p1.6
jmp chtrinh7

tt7: ; đặt tên nhãn dùng cho lệnh nhẩy
cjne a, #01111101b, tt8 ; chỉ cho chân p1.1 là 0, tìm phím trên p1.7
jmp chtrinh8

;

tt8: ; đặt tên nhãn dùng cho lệnh nhẩy
cjne a, #11101011b, tt9 ; chỉ cho chân p1.2 là 0, tìm phím trên p1.4
jmp chtrinh9

tt9: ; đặt tên nhãn dùng cho lệnh nhẩy
cjne a, #11011011b, tt10 ; chỉ cho chân p1.2 là 0, tìm phím trên p1.5
jmp chtrinh10

tt10: ; đặt tên nhãn dùng cho lệnh nhẩy
cjne a, #10111011b, tt11 ; chỉ cho chân p1.2 là 0, tìm phím trên p1.6
jmp chtrinh11

tt11: ; đặt tên nhãn dùng cho lệnh nhẩy
cjne a, #01111011b, tt12 ; chỉ cho chân p1.2 là 0, tìm phím trên p1.7
jmp chtrinh12

;

tt12: ; đặt tên nhãn dùng cho lệnh nhẩy
cjne a, #11100111b, tt13 ; chỉ cho chân p1.3 là 0, tìm phím trên p1.4
jmp chtrinh13

tt13: ; đặt tên nhãn dùng cho lệnh nhẩy
cjne a, #11010111b, tt14 ; chỉ cho chân p1.3 là 0, tìm phím trên p1.5
jmp chtrinh14

tt14: ; đặt tên nhãn dùng cho lệnh nhẩy
cjne a, #10110111b, tt15 ; chỉ cho chân p1.3 là 0, tìm phím trên p1.6
jmp chtrinh15

tt15: ; đặt tên nhãn dùng cho lệnh nhẩy
cjne a, #01110111b, start ; chỉ cho chân p1.3 là 0, tìm phím trên p1.7
jmp chtrinh16

; Các chương trình ứng với các phím nhấn
chtrinh1:

chtrinh2:

chtrinh3:

chtrinh4:

chtrinh5:

chtrinh6:

chtrinh7:

chtrinh8:

chtrinh9:

chtrinh10:

chtrinh11:

chtrinh12:

chtrinh13:

chtrinh14:

chtrinh15:

chtrinh16:

end
Các thí dụ cho thấy cách dùng bàn phím trong điều khiển
1. Cách dùng phím kiểu đơn lập
Một thí dụ về cách dùng các phím nhấn đơn lập



Phân tích mạch:

Sơ đồ
cho thấy, chúng ta cấp điện cho ic lập trình AT89C51 với chân 20
cho nối masse và chân 40 cho nối vào đường nguồn 5V. Trên chân 9
gắn tụ C1 (10uF) và điện trở R1 (10K) dùng tạo tính năng reset
mỗi khi mạch được cấp nguồn. Trên chân 18, 19 gắn thạch anh định
tần, chúng ta dùng thạch anh 12MHz. Để mạch chỉ làm việc với
bộ nhớ trong chúng ta cho chân 31 nối vào đường nguồn 5V.
Đề làm
thực hành với các phím nhấn đơn lập, chúng ta dùng 4 phím
nhấn, gắn trên các chân p1.2, p1.3, p1.4, p1.5 của cảng p1 và gắn
8 Led trên cảng p3 để hiển thị tác dụng của các phím nhấn.
Ở đây
chúng ta sẽ tạo tính năng cho 4 phím nhấn như sau: phím S1 cho
mở phím, phím S4 cho tắt phím, phím S2 cho 8 Led trên p3 tuần tự
dời qua phải và phím S3 cho 8 Led trên p3 dời qua trái.
Tóm lại công dụng của các phím như sau:
* Nhấn nút S1 vào mode khởi động, cho mở phím.
* Nhấn nút S2, 8 Led trên cảng p3 dời bit qua phải
* Nhất nút S3, 8 Led trên cảng p3 dời bit qua trái
* Nhấn nút S4 vào mode tắt phím
Chương trình nguồn:
UpDown EQU 00H ; đặt tên bit 00h là updown
StartEnd EQU 01H ; đặt tên bit 01h là startend
LAMPCODE EQU 21H ; đặt tên thanh ghi 21h là lampcode
ORG 0000H ; địa chỉ thanh ghi khởi đầu
JMP MAIN ; nhẩy đến tên nhãn
ORG 30H ; vùng địa chỉ bên ngoài chức năng ngắt
MAIN: ; đặt tên nhãn dùng cho lệnh nhẩy
MOV SP,#5FH ; chọn địa chỉ làm ngăn xếp
MOV P3,#0FFH ; đặt trị 11111111b vào cảng p3 để tắt 8 led
; điều kiện khởi đầu
CLR UpDown ; đặt bit 0 vào bit updown
CLR StartEnd ; đặt bit 0 vào bit startend
MOV LAMPCODE,#0FEH ; chuyển trị 11111110b vào lampcode
LOOP: ; đặt tên nhãn dùng cho lệnh nhẩy
CALL KEY ; gọi chương trình dò phím, tên nhãn key
JNB F0,LNEXT ; cho nhẩy theo bit f0
CALL KEYPROC ; gọi chương trình xử lý phím

LNEXT: ;đặt tên nhãn dùng cho lệnh nhẩy
CALL LAMP ; gọi chương trình điều khiển 8 Led trên cảng p3
JMP LOOP ; quay lại tên nhãn loop
DELAY: chương trình tạo trể
MOV R7,#100 ; đặt trị 100 vào thanh ghi r7
D1: ;đặt tên nhãn dùng cho lệnh nhẩy
MOV R6,#100 ; đặt trị 100 vào thanh ghi r6
DJNZ R6,$ ; nhẩy tại chổ, chờ trị trong r6 bằng 0
DJNZ R7,D1 ; giảm trị trong r7 theo bước -1, r7=0?, định hướng nhẩy
RET ; qua lại sau lệnh call delay

;----------------------------------------
KEYPROC: ; chương trình xử lý phím
MOV A,B ; chuyển trị trong b vào thanh ghi a
JB ACC.2,KeyStart ; xét bit acc.2 để định hướng nhẩy 
JB ACC.3,KeyOver ; xét bit acc.3 để định hướng nhẩy
JB ACC.4,KeyUp ; xét bit acc.4 để định hướng nhẩy
JB ACC.5,KeyDown ; xét bit acc.5 để định hướng nhẩy
JMP KEY_RET ; nhẩy về tên nhãn key_ret
KeyStart: ; trình vào mode khởi động
SETB StartEnd ; đặt bit startend lên 1, cho khởi động
JMP KEY_RET ; nhẩy đến tên nhãn key_ret
KeyOver: ; trình cho tắt, kết thúc
CLR StartEnd ; đặt bit startend xuống 0, kết thúc
JMP KEY_RET ; nhẩy đến tên nhãn key_ret
KeyUp: ; trình cho 8 Led dời qua phải
SETB UpDown ; đặt bit updown lên 1, dời qua phải
JMP KEY_RET ; nhẩy đến tên nhãn key_ret
KeyDown: ; trình cho 8 Led dời qua trái
CLR UpDown ; đặt bit updown xuống 0, dời qua trái
KEY_RET: ; đặt tên nhãn dùng cho lệnh nhẩy
RET ; quay lại sau lệnh call keyproc
KEY: ; đặt tên nhãn dùng cho lệnh nhẩy, trình dùng dò phím
CLR F0 ; xóa bit f0
ORL P1,#00111100B ; lấy logic OR trị 00111100b và cảng p1
MOV A,P1 ; chuyển trị hiện có của p1 vào thanh ghi a
ORL A,#11000011B ; lấy logic OR a và 11000011b, xét trạng thái 4 phím
CPL A ; lấy bù a, đảo 8 bit trong thanh ghi a
JZ K_RET ; xét trị trong thanh a, có bằng 0 không? để nhẩy
CALL DELAY ; cho gọi chương trình trể
OR P1,#00111100B ; lại lấy logia OR trị 00111100b cho cảng p1 
MOV A,P1 ; lại chuyển trị hiện có của cảng p1 vào thanh ghi a
ORL A,#11000011B ; cho lấy logic OR trị trong a và trị 11000011b
CPL A ; lại cho bù a, đảo 8 bit trong thanh ghi a
JZ K_RET ; lại xét trị trong thanh a, có bằng 0? để nhẩy
MOV B,A ; chuyển trị trong a vào thanh b
SETB F0 ; đặt bit kiểm tra f0 lên 1, báo đã có phím nhấn

K_RET: ; đặt tên nhãn dùng cho lệnh nhẩy
ORL P1,#00111100B ; Lấy logic OR trị hiện có trong p1 và 00111100b
MOV A,P1 ; chuyển trị hiện có trên cảng p1 vào thanh ghi a
ORL A,#11000011B ; lấy logic OR trị trong a và 11000011b
CPL A ; lấy bù a, đảo 8 bit trong thanh ghi a
JZ K_RET1 ; xét trị trong a có bằng 0 không? để nhẩy
JMP K_RET ; nhẩy đến tên nhãn k_ret

K_RET1: ; đặt tên nhãn dùng cho lệnh nhẩy
RET ; quay lại sau lệnh call key

D500MS: ; chương trình làm trể
PUSH PSW ; tạm cho cất trị trong thanh ghi psw vào ngăn xếp
SETB RS0 ; đặt trị rs0 trong thanh ghi trạng thái psw lên 1
MOV R7,#200 ; chuyển trị 200 vào thanh ghi r7

D51: ; đặt tên nhãn dùng cho lệnh nhẩy
MOV R6,#250 ; đặt trị 250 vào thanh ghi r6

D52: ; đặt tên nhãn dùng cho lệnh nhẩy
NOP ; dòng không tác vụ
NOP ; dòng không tác vụ
NOP ; dòng không tác vụ
NOP ; dòng không tác vụ
DJNZ R6,D52 ; giảm trị trong r6 theo bước -1, r6=0?, chọn hướng nhẩy
DJNZ R7,D51 ; giảm trị trong r7 theo bước -1, r7=0?, chọn hướng nhẩy
POP PSW ; lấy lại trị trước đó cho thanh ghi psw
RET ; quay lại sau lệnh gọi call d500ms

LAMP: ; chương trình điều khiển 8 Led trên cảng p3
JB StartEnd,LampStart ; chọn hướng nhẩy theo bit startend
MOV P3,#0FFH ; đặt trị 11111111b vào cảng p3, tắt hết 8 Led
JMP LAMPRET ; nhẩy về tên nhãn lampret
LampStart: ; đặt tên nhãn cho lệnh nhẩy, trình dời 8 bit trong a qua trái
JB UpDown,LAMPUP ; nhẩy theo bit updown
MOV A,LAMPCODE ; chuyển trị trong lampcode cho thanh ghi
RL A ; cho quay vòng 8 bit trong thanh ghi aqua hướng trái
MOV LAMPCODE,A ; chuyển trị trong a vào lampcode
MOV P3,A ; cho xuất trị trong a ra cảng p3
CALL D500MS ; gọi chương trình làm chậm d500ms
JMP LAMPRET ; nhẩy về tên nhãn lampret

LAMPUP: ; đặt tên nhãn cho lệnh nhẩy, trình cho dời 8 bit qua phải
MOV A,LAMPCODE ; chuyển trị trong lampcode vào thanh ghi a
RR A ; cho quay vòng 8 bit trong a qua hướng phải
MOV LAMPCODE,A ; chuyển trị trong a vào lampcode
MOV P3,A ; xuất trị trong a ra cảng p3
CALL D500MS ; cho gọi chương trình trể d500ms

LAMPRET: ; đặt tên nhãn cho lệnh nhẩy
RET ; quay lại sau lệnh call
END ; dừng biên dịch tại dòng này


Phân tích cách viết các câu lệnh chương trình nguồn trên:





Tìm hiểu thêm một cách viết khác. Bạn xem thí dụ sau:

Trong
thí dụ này, chúng ta gắn 4 phím trên cảng p3 và dùng các phím
này điều khiển trạng thái nhấp nháy của 8 Led đặt trên cảng
p1.





Chương trình nguồn viết như sau:


ORG 0000H ; Khởi đầu từ thanh ghi 0000h
LJMP START ; nhẩy đến tên nhãn start
; các thanh ghi chuyên dùng cho chức năng ngắt
ORG 0003H ; vị trí chạy ngắt INT0
RETI

ORG 000BH ; vị trí chạy ngắt TF0
RETI

ORG 0013H ; vị trí chạy ngắt INT1
RETI

ORG 001BH ; vị trí chạy ngắt TF1
RETI

ORG 0023H ; vị trí chạy ngắt RI var TI
RETI

;

CLEAR: ; đặt tên nhãn cho lệnh nhẩy
RET

;

START: ; đặn tên nhãn cho khời đầu
CALL CLEAR ; gọi chương trình clear
; trình dò phím
STAR1: ; đặt tên nhãn dùng cho lệnh nhẩy
MOV P3,#0FFH ; đặt trị 11111111b vào p3, định trạng thái đầu
JNB P3.4,FUN0 ; dò bit 0 trên chân p3.4, để nhẩy
JNB P3.5,FUN1 ; dò bit 0 trên chân p3.5 để nhẩy
JNB P3.2,FUN2 ; dò bit 0 trên chân p3.2 để nhẩy
JNB P3.3,FUN3 ; dò bit 0 trên chân p3.3 để nhẩy
JNB F0,STAR1 ; nhẩy theo bit f0, f0=1, có nhấn phím
RET ; quay lại sau lệnh call start
;

FUN0: ; tên nhãn dùng cho phím p3.4
CALL DL10MS ; gọi chương trình trể 10ms, tránh rung phím
JB P3.4,STAR1 ; kiểm tra lại phím nhấn trên p3.4
WAITL0: ; trình chờ bỏ phím
JNB P3.4,WAITL0 ; chờ bỏ phím
SETB F0 ; đặt bit kiểm tra f0 lên 1
FUN01: ; đặt tên nhãn dùng cho lệnh nhẩy
CALL FUN00 ; cho gọi chương trình fun00
CALL STAR1 ; quay lại tên nhãn star1
JMP FUN01 ; nhẩy về tên nhãn fun01
; Viết tương dạng như trên
FUN1:

CALL DL10MS ;

JB P3.5,STAR1

WAITL1:

JNB P3.5,WAITL1 ;

SETB F0

FUN10:

CALL FUN11

CALL STAR1

JMP FUN10

; Viết tương dạng như trên
FUN2:

CALL DL10MS ;

JB P3.2,STAR1

WAITL2:

JNB P3.2,WAITL2 ;

SETB F0

FUN20:

CALL FUN22

CALL STAR1

JMP FUN20

; viết tương dạng như trên
FUN3:

CALL DL10MS ; gọi trể 10ms tránh ảnh hưởng của rung phím
JB P3.3,STAR1 ; kiểm tra lần nữa phím trên p3.3
WAITL3: ; tên nhãn
JNB P3.3,WAITL3 ; chờ bỏ phím ra
CLR F0 ; xóa bit f0, về trạng thái chờ nhấn phím
MOV P1,#0FFH ; đặt trị 11111111b để tắt 8 Led trên p1
JMP STAR1 ; quay lại tên nhãn star1
; trình cho Led sáng lan lên
FUN00:

MOV A,#0FEH

FUN000:

MOV P1,A

CALL DL05S

JNB ACC.7,OUT

RL A

JMP FUN000

OUT: RET


; trình cho các Led sáng nhẩy
FUN11:

MOV A,#0FEH

FUN111:

MOV P1,A

CALL DL05S

JZ OUT

RL A

ANL A,P1

JMP FUN111


; trình cho các 4 Led nhấp nháy xen kẻ
FUN22:

MOV A,#0AAH

MOV P1,A

CALL DL30S

CPL A

MOV P1,A

CALL DL30S

RET
; chương trình làm trể
DL512:

MOV R2,#0FFH

LOOP1:

DJNZ R2,LOOP1

RET

DL10MS:

MOV R3,#14H

LOOP2:

CALL DL512

DJNZ R3,LOOP2

RET

DL05S:

MOV R4,#0AH

LOOP3:

CALL DL10MS

DJNZ R4,LOOP3

RET

DL30S:

MOV R5,#03H

LOOP4:

CALL DL05S

DJNZ R5,LOOP4

RET
end