Kênh Tên Miền chuyên cung cấp tên miền đẹp, giá rẻ! Hãy liên hệ kỹ thuật: 0914205579 - Kinh doanh: 0912191357 để được tư vấn, hướng dẫn miễn phí, Cảm ơn quý khách đã ủng hộ trong thời gian qua!
Saturday, December 7, 2013



Rất vui khi thấy   Bạn vào xem...




Tự làm bảng đèn Led chạy chữ trên ma trận 8x24 chỉ dùng một ic AT89C51


Dẫn nhập

Dùng ic lập trình AT89C51, Bạn có thể kiểm soát được trạng thái tắt sáng của các dãy Led trên các bảng đèn, từ đó có thể tạo ra được các hình ảnh hay các dòng con chữ cho chạy trên các bảng đèn này, công việc này hiện rất được nhiều Bạn ưa thích, trong bài viết này, tôi trình bày một bài làm thực hành khá đơn giản nhưng rất căn cơ để Bạn hiểu được nguyên lý làm việc của các bảng đèn quang báo. Từ các hiểu biết này, Bạn mới có thể sẽ mở rộng ra nhiều kiểu bảng đèn phức tạp hơn. Mong Bạn để tâm tìm hiểu.  


 


Bài thực hành này sẽ cho hiện hình và các dòng chữ chạy, nhấp nháy, trên một bảng đèn ma trận 8x8. Với ic một lập trình có 4 cảng p0, p1, p2, p3, chúng ta sẽ dùng 3 bộ ma trận 8x8 và như vậy sẽ không cần thêm một ic logic nào nữa. Mạch rất đơn giản, nhưng có cơ sở lý thuyết rất cơ bản, sẽ giúp Bạn hiểu rất rõ về các loại đèn quang báo lớn khác.




Phân tích sơ đồ mạch điện:


 




Trướt hết Bạn tạo bảng đèn dùng 3 bộ 8x8. Các hàng, trên đó là các chân Anode của các Led cho nối chung và dùng một transistor pnp để dùng bit 0 xuất trên các chân của cảng p1 cấp cho chân B của transistor để cho nối dây chung nầy lên đường nguồn 5V. Do mạch dùng kỹ thuật quét nên mỗi lần chỉ có một hàng cho nối vào đường nguồn 5V.

Do các chân của Cathode của Led cho nối chung trên một cột, chúng ta dùng các transistor npn để cho cột thông masse để lấy dòng cấp cho các Led, vậy để chân Cathode thông masse, chúng ta sẽ dùng bit 1, cho xuất trên các chân của cổng p2, p0 và p3 cấp cho chân B của các transistor. Với một cổng có 8 bit, vậy mỗi bộ mã 8 bit cho xuất ra trên các công p2, p0, p3, chúng ta có thể điều khiển mỗi nhịp được 8 Led.



Tìm hiểu bảng ma trận Led 8x8:


Hình vẽ cho thấy cách gắn các Led trên ma trận tạo bởi 8 hàng và 8 cột.



Sơ đồ dùng giải thích nguyên lý tắt mở các Led trên bảng ma trận 8x8.

 


Cách 1Mã quét xuất trên p2, p3, p0, mã hình hay chữ xuất trên cảng p1.

Sơ đồ mạch điện trên, một lần nữa, cho thấy, chúng ta cho nối 8 chân của các chân B của 8 transistor 2SA1015 và cảng p1. Vậy khi có một chân của cảng p1 xuất ra bit 0, nó sẽ làm transistor bão hòa, và lúc này dây anode chung sẽ được cho nối vào đường nguồn 5V. Ở đây, Bạn sẽ viết đoạn chương trình sao cho mỗi nhịp chỉ có một chân của cổng p1 xuất ra bit 0.

Bạn thấy khi xuất 8 bit ra trên cảng p2, 8 bit ở mức 1 ứng với mức volt cao dùng cấp cho chân B của 8 transistor 2SC1815, lúc này các transistor sẽ bị làm cho bão hòa, nó cho 8 cột trên đó có các chân Cathode nối masse, vậy 8 Led này sẽ phát sáng, trong mạch chúng ta hạn dòng với các điện trở 100 ohm. 

Tóm lại, muốn in hình hay các con chữ trên bảng Led ma trận này, Bạn phải làm được 2 việc sau:


Việc 1: Viết đoạn chương trình cấp mã quét.Tốc độ quét đủ nhanh để dùng hiện tượng lưu ảnh của mắt mà gây ra "nhầm lẫn" là trên bảng đèn đang có rất nhiều Led đang được cấp dòng phát sáng.



Viết đoạn chương trình để xuất mã quét bit 0 trên các chân B của các transistor pnp trên các cảng p1, để cho chữ trôi xuống.

 



Viết đoạn chương trình để xuất mã quét bit 0 trên các chân B của các transistor pnp trên các cảng p1, để cho chữ trôi lên.

 



Viết chương trình mã quét, cấp bit 1 cho các chân B của các transistor npn trên các cảng p2, p3, p0, để tạo hình dời ngang.



Việc 2: Viết các dãy mã 8 bit cho xuất mã hình trên các cảng p2, p3, p0 hay trên p1 để làm sáng các Led trên các cột, các mã 8 bit này viết theo kiểu hình hay dạng con chữ mà Bạn muốn nó hiện ra trên bảng đèn. Các dãy mã 8 bit này chúng ta sẽ cho cất trong các bảng, sau này sẽ dùng câu lệnh movc a, @a + dptr để lấy các dãy mã ra cho xuất trên các cảng của ic AT89C51.  


Sau đây là đoạn chương trình viết cho xuất mã quét trên p2, p3, p0 và mã hình xuất trên cảng p1.


h1b:  ;đặt tên nhãn dùng cho lệnh nhẩy        mov r0, #11111110b ; đặt trị khởi đầu dùng cho lệnh quay vòng        mov r1, #00h  ; đặt trị khởi đầu dùng cho lệnh lấy mã hình hay chữll1b:   mov a, r0  ; chuyển trị trong r0 vào thanh a        rr a   ; cho 8 bit trong a quay vòng qua hường phải        mov r0, a  ; chuyển trị trong thanh a ra r0        mov p1, r0  ; cho xuất trị trong thanh a ra cảng p1
        mov a, r1  ; chuyển trị trong thanh r1 vào thanh a        movc a, @a + dptr  ; truy lấy mã hình trong bảng cho cất vào thanh a        mov p2, a  ; cho xuất mã hình trên cảng p2

        inc r1  ; tăng trị trong thanh r1 lên +1 để lấy mã hình tiếp theo        mov a, r1  ; chuyển trị r1 vào thanh a        movc a, @a + dptr  ; truy lấy mã hình trong bảng cho cất vào thanh a        mov p3, a  
; cho xuất mã hình trên cảng p3

        inc r1  ; tăng trị trong thanh r1 lên +1 để lấy mã hình tiếp theo        mov a, r1   ; chuyển trị r1 và thanh a        movc a, @a + dptr  ; truy lấy mã hình trong bảng cho cất vào thanh a        mov p0, a  
; cho xuất mã hình trên cảng p0

        inc r1  ; lại tăng trị trong r1 lên +1        call del1   ; gọi chương trình làm chậm        mov p1, #11111111b  ; tắt 8 bit trên cảng p1        mov p0, #00h  ; tắt 8 bit trên cảng p0        mov p2, #00h  ; tắt 8 bit trên cảng p2        mov p3, #00h  ; tắt 8 bit trên cảng p3        call del1   ; gọi chương trình làm chậm        cjne r0, #11111110b, ll1b   ; so sánh mã quét để chọn hướng nhẩy        ret  
; quay lại sau lệnh call



Đoạn chương trình này viết giống như đoạn trên, điểm khác biệt là dùng câu lệnh rl a quay vòng theo hướng trái để đổi hướng chạy hình trên bảng ma trân 8x24. Mã quét đặt trên cảng p1, mã hình lần lượt cho lấy ra xuất trên cảng p2, rồi p3, rồi p0.


 h1c:   ; đặt tên nhãn dùng cho lệnh nhẩy        mov r0, #01111111b  ; đặt trị khởi đầu dùng cho lệnh quay vòng        mov r1, #00h  
ll1c:    mov a, r0  ; chuyển trị trong r0 vào thanh a        rl a   ; cho 8 bit trong thanh a quay vòng theo hướng trái        mov r0, a  ; chuyển trị trong thanh a vào thanh r0        mov p1, r0  
; cho xuất trị trong thanh r0 ra cảng p1
; lấy mã hình xuất trên cảng p2 
       mov a, r1
        movc a, @a + dptr
        mov p2, a
; lấy mã hình xuất trên cảng p3        inc r1
        mov a, r1
        movc a, @a + dptr
        mov p3, a
; lấy mã hình xuất trên cảng p0        inc r1
        mov a, r1
        movc a, @a + dptr
        mov p0, a
; tránh hình bị lem        inc r1
        call del1
        mov p1, #11111111b
        mov p0, #00h
        mov p2, #00h
        mov p3, #00h
        call del1
        cjne r0, #01111111b, ll1c
        ret  
; quay lại sau lệnh call


Một minh họa: Mã quét cho xuất trên các cảng p2 rồi p3 rồi p0. Mã hình xuất trên cảng p1.



Cho xuất mã quét nhịp nhanh trên các cảng p2, p3, p0 và cùng lúc cho xuất mã hình hay chữ trên cảng p1. Sau đây là đoạn chương trình viết cho trường hợp 2 dùng để hiện các hình và con chữ trên bảng ma trận 8x24.


Phân tích câu lệnh:


; Các câu lệnh cho xuất mã quét trên cảng p2, mã hình trên p1
h1:    ; đặt tên nhãn dùng cho lệnh nhẩy        mov r0, #00000001b  ; đặt trị khởi đầu cho thanh r0        mov r1, #00h   ; trả thanh r1 về trị 0ll1:    mov a, r0  ; cho chuyển trị trong r0 và thanh a        rr a   ; cho các 8 bit trong thanh a, quay vòng qua theo hướng bên phải        mov r0, a  ; chuyển trị có trong thanh a vào thanh r0        mov p2, r0 ; cho xuất trị trong r0 ra ở cảng p2        mov a, r1  ; bây giờ chuyển trị trong r1 vào thanh a        movc a, @a + dptr  ; lấy mã 8 bit trong bảng theo trị trong a, rồi cho cất vào thanh a        mov p1, a  ; cho xuất trị này trên cảng p1        inc r1  ; cho tăng trị trong r1 lên +1 để chuẩn bị lấy dòng mã tiếp theo         call del1 ; gọi chương trình làm châm để tạo mức sáng cho các led        mov p2, #00h  ; cho 8 chân của cảng p2 xuống mức 0 để tắt các Led.  
        mov p1, #0ffh  ; Cho 8 chân của cảng p1 lên mức 1 cũng để tắt Led        call del1  ; cho gọi trìng làm chậm để xóa các Led tránh lem         cjne r0, #00000001b, ll1  ; so sánh trị trong r0, nếu thấy chưa quay đủ 8 nhịp thì tiếp tục.

; Các câu lệnh cho xuất mã quét trên cảng p3, mã hình trên cảng p1
ll2:    ; đặt tên nhãn dùng cho lệnh nhẩy
        mov a, r0  ; lại chuyển trị trong r0 vào a 
        rr a   ; cho quay vòng 8 bit trong a theo hướng bên phải        mov r0, a  ; chuyển trị trong thanh a vào r0        mov p3, r0 ; cho xuất trị trong r0 ra trên cảng p3        mov a, r1  ; chuyển trị có trong r1 vào thanh a        movc a, @a + dptr   ; cho lấy mã trong bảng cất vào a 
        mov p1, a  ; cho trị trong a xuất ra trên cảng p1        inc r1  ; tăng trị trong r1 lên +1 để lấy dòng mã hình tiếp theo        call del1  ; gọi chương trình làm chậm        mov p3, #00h ; đặt 8 chân của cảng p3 xuống mức 0        mov p1, #0ffh  ; đặt 8 chân của cảng p1 lên mức 1        call del1  ; cho gọi chương trình làm chậm        cjne r0, #00000001b, ll2 
 ; so sánh trị trong r0 để định hướng nhẩy

; Các câu lệnh cho xuất mã quét trên cảng p0, mã hình trên cảng p1
ll3:     ; đặt tên nhãn dùng cho lệnh nhẩy
        mov a, r0  ; chuyển trị trong thanh a vào thanh r0        rr a   ; cho 8 bit trong thanh a quay vòng qua hướng phải        mov r0, a  ; chuyển trị trong thanh a trở lại r0        mov p0, r0 ; cho trị trong r0 xuất ra trên cảng p0        mov a, r1  ; chuyển trị trong r1 vào thanh a        movc a, @a + dptr  ; lấy mã 8 bit trong bảng cất vào thanh a        mov p1, a  ; cho trị trong a xuất ra trên cảng p1        inc r1  ; tăng trị trong r1 lên +1 để lấy dòng mã kế tiếp        call del1  ; gọi chương trình làm chậm        mov p0, #00h  ; đặt 8 chân của cảng p0 xuống mức 0        mov p1, #0ffh  ; đặt 8 bit của cảng p1 lên mức 1        call del1  ; gọi chương trình làm chậm        cjne r0, #00000001b, ll3  ; so sánh trị trong r0 để định hướng nhẩy        ret  ; quay lại sau lệnh call 


Cách 2:  Mã quét cho xuất trên p1và mã hình hay chữ cho xuất trên cảng p2, p3, p0


Một minh họa: Cho xuất mã quét nhanh trên cảng p1, các mã hình lần lượt cho xuất trên cảng p2, cảng p3, cảng p0





Phân tích câu lệnh:

h1b:      ; đặt tên nhãn cho lệnh nhẩy        mov r0, #11111110b   ; đặt trị khởi đầu cho nhịp quét        mov r1, #00h   ; trả trị khởi đầu cho r1 về 0ll1b:   mov a, r0  ; chuyển trị r0 vào thanh a        rr a   ; cho 8 bit trong a quay vòng qua phải        mov r0, a   ; chuyển trị trong a ra r0        mov p1, r0  ; cho xuất trị trong r0 ra cảng p1
        mov a, r1  ; chuyển trị r1 vào a        movc a, @a + dptr   ; lấy mã địa chỉ trong bảng cho cất vào thanh a        mov p2, a  ; cho xuất 8 bit mã hình ra trên cảng p2        inc r1 ; tăng trị trong r1 lên +1 
        mov a, r1 ; lại chuyển trị trong r1 vào thanh a        movc a, @a + dptr  ; lại lấy tiếp 8 bit mã hình cất vào thanh a        mov p3, a  ; cho xuất 8 bit mã hình ra trên cảng p3        inc r1  ; một lần nữa laị tăng trị trong r1 lên +1        mov a, r1   ; lại chuyển trị của r1 vào thanh a        movc a, @a + dptr  ; lại lấy tiếp 8 bit mã hình cho cất vào thanh a        mov p0, a  ; bây giờ cho xuất 8 bit mã hình ra trên cảng p0        inc r1  ; lại tăng trị r1 lên +1, chuẩn bị lấy tiếp các mã hình tiếp theo        call del1  ; gọi chương trình làm chậm        mov p1, #11111111b  ; xóa xung quét tránh lem hình        mov p0, #00h  ; xóa mã hình trên p0        mov p2, #00h  ; xóa mã hình trên p2        mov p3, #00h  ; xóa mã hình trên p3        call del1  ; gọi chương trình làm chậm        cjne r0, #11111110b, ll1b  ; so sánh trị trong a với mã quét khởi đầu để nhẩy.
        ret  
; quay lại sau lệnh call 




Phân tích cách viết chương trình nguồn tổng hợp:


 org 0000h    ; khởi đầu chương trìng nguồn        slan equ 20h   ; đặt tên slan "số lần" cho thanh 20hbd:     call xoa   ; gọi chương trình xóa       mov r3, #0  ; đặt trị 3 vào thanh r1        call h2                 ; cho gọi trình mở màn        mov p1, #11111111b ; xóa         mov dptr, #b_1          ; cho hiện chữ Phúcst:     mov r4, #10  ; nạp trị 10 vào thanh r4tta:    call h1   ; cho gọi chương trình có tên nhãn h1        djnz r4, tta  ; cho lập lại call h1 10 lần ;        inc dptr  ; tạm dừng dời chữ Phúc        inc r3  ; tăng trị r3 theo bước +1        cjne r3, #26, st  ; so sánh trị trong r3 để định hướng nhẩy        mov r3, #0   ; trả trị trong r3 về 0
        mov p1, #11111111b ; cho tắt 8 bit trên cảng p1        mov dptr, #b_2          ; cho hiện chữ Lanst2:    mov r4, #10
ttb:    call h1
        djnz r4, ttb
;        inc dptr
        inc r3
        cjne r3, #26, st2
        mov 3, #0
        call h4a        ; bỏ màn xuống        call h4          ;  kéo màn lên
        call xoa
        mov dptr, #b_2b         ; cho hiện chữ Nst21:   mov r4, #2
ttb1:   call h1
        djnz r4, ttb1
;        inc dptr
        inc r3
        cjne r3, #26, st21
        mov 3, #0
        call xoa
        mov dptr, #b_2ba        ; cho hiện chữ NHst21a:  mov r4, #2
ttb1a:  call h1
        djnz r4, ttb1a
;        inc dptr
        inc r3
        cjne r3, #26, st21a
        mov 3, #0
        call xoa
        mov dptr, #b_2bb        ; cho hiến chữ NHẬst21b:  mov r4, #2
ttb1b:  call h1
        djnz r4, ttb1b
;        inc dptr
        inc r3
        cjne r3, #26, st21b
        mov 3, #0
        call xoa
        mov dptr, #b_2bc        ; cho hiện chữ NHẬTst21c:  mov r4, #10
ttb1c:  call h1
        djnz r4, ttb1c
;        inc dptr
        inc r3
        cjne r3, #26, st21c
        mov 3, #0
        call xoa
        mov dptr, #b_2c          ; cho hiện chữ Tst22:   mov r4, #2
ttb2:   call h1
        djnz r4, ttb2
;        inc dptr
        inc r3
        cjne r3, #26, st22
        mov 3, #0
        call xoa
        mov dptr, #b_2ca          ; cho hiện chữ TÂst22a:  mov r4, #2
ttb2a:  call h1
        djnz r4, ttb2a
;        inc dptr
        inc r3
        cjne r3, #26, st22a
        mov 3, #0
        call xoa
        mov dptr, #b_2cb          ; cho hiện chữ TÂNst22b:  mov r4, #10
ttb2b:  call h1
        djnz r4, ttb2b
;        inc dptr
        inc r3
        cjne r3, #26, st22b
        mov 3, #0
        call h4a        ; hạ màn xuống        call h4         ; kéo màn lên
        call xoa
        mov dptr, #b_2a  ; cho hiện chữ Phúc Lan, chữ chạyst5a:   mov r4, #20
tte1:   call h1
        djnz r4, tte1
        inc dptr
        inc r3
        cjne r3, #54, st5a
        mov r3, #0
        call xoa
        mov slan, #3
ttuc:   mov dptr, #b_4          ; cho hiện chữ Chàost4:    mov r4, #10
ttd:    call h1
        djnz r4, ttd
        ;inc dptr
        inc r3
        cjne r3, #10, st4
        mov r3, #0
        mov p0, #00h
        mov p2, #00h
        mov p3, #00h
        call delay
        call xoa
        mov dptr, #b_4b         ; cho hiện chữ Bạnst4a:   mov r4, #10
ttd1:   call h1
        djnz r4, ttd1
        ;inc dptr
        inc r3
        cjne r3, #10, st4a
        mov r3, #0
        mov p0, #00h
        mov p2, #00h
        mov p3, #00h
        call delay
        djnz slan, ttuc
        call xoa
        mov dptr, #b_3  ; cho hiện chữ Tạp chí điện tử Việt Nam, chữ chạyst3:    mov r4, #15
ttc:    call h1
        djnz r4, ttc
        inc dptr
        inc r3
        cjne r3, #122, st3
        mov r3, #0
        call xoa
        mov dptr, #b_5  ; PHONE : 39235347, hiện số điện thoại, chữ chạyst5:    mov r4, #20
tte:    call h1
        djnz r4, tte
        inc dptr
        inc r3
        cjne r3, #79, st5
        mov r3, #0
        call h4a        ; hạ màn xuống        call h4         ; kéo màn lên
        call xoa
        mov dptr, #b_9  ; cho hiện hình hàng câyst9:    mov r4, #20
tti:    call h1
        djnz r4, tti
;        inc dptr
        inc r3
        cjne r3, #26, st9
        mov 3, #0
        call xoa
        mov slan, #14
lamt:   mov dptr, #b_10 ; hiện hình Logo 1        mov r3, #0
qlai:   mov r2, #12
llai:   call h1b
        djnz r2, llai
        inc dptr
        inc dptr
        inc dptr
        inc r3
        cjne r3, #16, qlai
        djnz slan, lamt
        call xoa
        mov dptr, #b_6  ; hiện hàng chữ CHUYEN BAN CAC LINH KIEN DIEN TU ABCDEFGHIJKLMNOPQst6:    mov r4, #8
ttf:    call h1
        djnz r4, ttf
        inc dptr
        inc r3
        cjne r3, #255, st6
        mov r3, #0
        call xoa
        mov dptr, #b_7  ; hiện hàng chữ RSTXYZUVWst7:    mov r4, #8
ttg:    call h1
        djnz r4, ttg
        inc dptr
        inc r3
        cjne r3, #52, st7
        mov r3, #0
        call xoa
        mov slan, #6
lamt1:  mov dptr, #b_11 ; cho hiện hình Logo 2        mov r3, #0
qlai1:  mov r2, #12
llai1:  call h1b
        djnz r2, llai1
        inc dptr
        inc dptr
        inc dptr
        inc r3
        cjne r3, #16, qlai1
        djnz slan, lamt1
        call xoa
        mov slan, #2
lamt2:  mov dptr, #b_12 ; cho hiện hình Logo 3 điện trở        mov r3, #0
qlai2:  mov r2, #50
llai2:  call h1b
        djnz r2, llai2
        inc dptr
        inc dptr
        inc dptr
        inc r3
        cjne r3, #16, qlai2
        djnz slan, lamt2
        call xoa
        mov slan, #10
lamt3:  mov dptr, #b_13   
; cho hiện hình Logo 4 giọt nước
        mov r3, #0
qlai3:  mov r2, #40
llai3:  call h1c
        djnz r2, llai3
        inc dptr
        inc dptr
        inc dptr
        inc r3
        cjne r3, #16, qlai3
        djnz slan, lamt3
        call xoa
        mov slan, #4
lamt4:  mov dptr, #b_14 ; cho hiện hình Logo 5        mov r3, #0
qlai4:  mov r2, #12
llai4:  call h1b
        djnz r2, llai4
        inc dptr
        inc dptr
        inc dptr
        inc r3
        cjne r3, #16, qlai4
        djnz slan, lamt4
        call xoa
        mov dptr, #b_8  ; hiện hình căn nhàst8:    mov r4, #30
tth:    call h1
        djnz r4, tth
;        inc dptr
        inc r3
        cjne r3, #26, st8
        mov 3, #0
        call h3         ; kéo màn lên        call delay
        call delay
        jmp bd

h2:                     ; trình mở màn        mov p1, #00h
        mov p0, #0ffh
        mov p2, #0ffh
        mov p3, #0ffh
        call delay
        mov p3, #11100111b
        call delay
        mov p3, #11000011b
        call delay
        mov p3, #10000001b
        call delay
        mov p3, #00000000b
        call delay
        mov p2, #11111110b
        mov p0, #01111111b
        call delay
        mov p2, #11111100b
        mov p0, #00111111b
        call delay
        mov p2, #11111000b
        mov p0, #00011111b
        call delay
        mov p2, #11110000b
        mov p0, #00001111b
        call delay
        mov p2, #11100000b
        mov p0, #00000111b
        call delay
        mov p2, #11000000b
        mov p0, #00000011b
        call delay
        mov p2, #10000000b
        mov p0, #00000001b
        call delay
        mov p2, #00000000b
        mov p0, #00000000b
        call delay
        call delay
        ret

h3:                     ; trình kéo màn, sáng từ 2 bên vào        mov p1, #00h
        mov p0, #00h
        mov p2, #00h
        mov p3, #00h
        call delay
        mov p2, #10000000b
        mov p0, #00000001b
        call delay
        mov p2, #11000000b
        mov p0, #00000011b
        call delay
        mov p2, #11100000b
        mov p0, #00000111b
        call delay
        mov p2, #11110000b
        mov p0, #00001111b
        call delay
        mov p2, #11111000b
        mov p0, #00011111b
        call delay
        mov p2, #11111100b
        mov p0, #00111111b
        call delay
        mov p2, #11111110b
        mov p0, #01111111b
        call delay
        mov p2, #11111111b
        mov p0, #11111111b
        call delay
        mov p3, #10000001b
        call delay
        mov p3, #11000011b
        call delay
        mov p3, #11100111b
        call delay
        mov p3, #11111111b
        call delay
        call delay
        ret


h4:                     ; kéo màn lên.         mov p1, #00h
        mov p0, #0ffh
        mov p2, #0ffh
        mov p3, #0ffh
        call delay
        call delay
        setb p1.7
        call delay
        setb p1.6
        call delay
        setb p1.5
        call delay
        setb p1.4
        call delay
        setb p1.3
        call delay
        setb p1.2
        call delay
        setb p1.1
        call delay
        setb p1.0
        call delay
        call delay
        ret

h4a:            ; hạ màn xuống        mov p1, #0ffh
        call delay
        call delay
        mov p0, #0ffh
        mov p2, #0ffh
        mov p3, #0ffh
        clr p1.0
        call delay
        mov p0, #0ffh
        mov p2, #0ffh
        mov p3, #0ffh
        clr p1.1
        call delay
        mov p0, #0ffh
        mov p2, #0ffh
        mov p3, #0ffh
        clr p1.2
        call delay
        mov p0, #0ffh
        mov p2, #0ffh
        mov p3, #0ffh
        clr p1.3
        call delay
        mov p0, #0ffh
        mov p2, #0ffh
        mov p3, #0ffh
        clr p1.4
        call  delay
        mov p0, #0ffh
        mov p2, #0ffh
        mov p3, #0ffh
        clr p1.5
        call delay
        mov p0, #0ffh
        mov p2, #0ffh
        mov p3, #0ffh
        clr p1.6
        call delay
        mov p0, #0ffh
        mov p2, #0ffh
        mov p3, #0ffh
        clr p1.7
        call delay
        call delay
        ret

; đoạn chương trình dùng để in hình trên ma trận 8x24, mã hình xuất trên cảng p1
h1:  ; đặt tên nhãn dùng cho lệnh nhẩy        mov r0, #00000001b  ; đặt trị khởi đầu cho lệnh quay vòng        mov r1, #00h ; đặt trị khởi đầu dùng để lấy mã hình trong bảng

ll1:    mov a, r0  ; chuyển trị trong r0 vào thanh a để dùng lệnh rr a        rr a  ;  cho 8 bit trong thanh a quay vòng theo hướng phải        mov r0, a  ; chuyển trị trong a trở lại thanh r0        mov p2, r0 
; cho xuất trị trong r0 ra cảng p2
 
        mov a, r1  ; chuyển trị trong r1 vào thanh a        movc a, @a + dptr  ; truy lấy mã hình trong bảng cất vào thanh a        mov p1, a  
; cho xuất mã hình trong a ra cảng p1

        inc r1 ; tăng trị trong r1 lên +1 để lấy mã hình tiếp theo        call del1  ; gọi trễ        mov p2, #00h  ; tắt 8 bit trên cảng p2        mov p1, #0ffh  ; tắt ́ bit trên cảng p1        call del1  ; gọi trễ        cjne r0, #00000001b, ll1  
; so sánh thanh r0 với mã quét để chọn hướng nhẩy

ll2:    mov a, r0  ; chuyển trị trong r0 vào thanh a        rr a   ; cho 8 bit trong thanh a quay vòng theo hướng phải        mov r0, a  ; chuyển trị trong a vào thanh r0        mov p3, r0  ; cho trị mã quét trong r0 xuất ra  ở cảng p3

        mov a, r1  ; chuyển trị trong thanh r1 vào thanh a        movc a, @a + dptr  ; truy lấy mã hình trong bảng cất vào thanh a         mov p1, a  
; cho xuất mã hình trong a ra cảng p1

        inc r1   ; tăng trị trong r1 lên +1 để lấy mã hình tiếp theo        call del1  ; gọi trễ        mov p3, #00h  ; tắt 8 bit trên cảng p3        mov p1, #0ffh  ; tắt 8 bit trên cảng p1        call del1   ; gọi trễ        cjne r0, #00000001b, ll2  
; so sánh r0 và mã quét để chọn hướng nhẩy

ll3:    mov a, r0   ; chuyển trị trong r0 vào thanh a        rr a  ; cho 8 bit trong thanh a quay vòng theo hướng phải        mov r0, a  ; chuyển trị trong thanh a trở lại thanh r0        mov p0, r0  ; cho xuất trị mã quét trong r0 ra cảng p0

        mov a, r1   ; chuyển trị trong thanh r1 vào thanh a        movc a, @a + dptr  ; truy lấy mã hình trong bảng cất vào thanh a        mov p1, a   
; cho xuất trị mã hình trong thanh a ra cảng p1

        inc r1  ; tăng trị trong r1 lên +1 để lấy mã hình tiếp theo         call del1  ; gọi trễ        mov p0, #00h   ; cho tắt 8 bit trên cảng p0        mov p1, #0ffh   ; cho tắt 8 bit trên cảng p1        call del1  ; gọi trễ        cjne r0, #00000001b, ll3  ; so sánh trị trong r0 với mã quét để định hướng nhẩy        ret  
; quay lại sau lệnh call


del1:
        mov r7, #3
v6:     mov r6, #50
        djnz r6, $
        djnz r7, v6
        ret

delay:
        mov r7, #5
v6a:    mov r6, #50
v5:     mov r5, #250
        djnz r5, $
        djnz r6, v5
        djnz r7, v6a
        ret
xoa:    mov p0, #00000000b
        mov p2, #00000000b
        mov p3, #00000000b
        mov p1, #11111111b
        ret

; đoạn chương trình cho xuất mã hình trên cảng p2, p3, p0h1b:
        mov r0, #11111110b
        mov r1, #00h
ll1b:   mov a, r0
        rr a
        mov r0, a
        mov p1, r0
        mov a, r1
        movc a, @a + dptr
        mov p2, a
        inc r1
        mov a, r1
        movc a, @a + dptr
        mov p3, a
        inc r1
        mov a, r1
        movc a, @a + dptr
        mov p0, a
        inc r1
        call del1
        mov p1, #11111111b
        mov p0, #00h
        mov p2, #00h
        mov p3, #00h
        call del1
        cjne r0, #11111110b, ll1b
        ret

; đoạn chương trình cho xuất mã hình trên cảng p2, p3, p0h1c:
        mov r0, #01111111b
        mov r1, #00h
ll1c:    mov a, r0
        rl a
        mov r0, a
        mov p1, r0
        mov a, r1
        movc a, @a + dptr
        mov p2, a
        inc r1
        mov a, r1
        movc a, @a + dptr
        mov p3, a
        inc r1
        mov a, r1
        movc a, @a + dptr
        mov p0, a
        inc r1
        call del1
        mov p1, #11111111b
        mov p0, #00h
        mov p2, #00h
        mov p3, #00h
        call del1
        cjne r0, #01111111b, ll1c
        ret

; các bảng dùng đặt mã hình và chữ do Bạn tự soạnb_1:    ; tạo chữ Phúcdb 11111111b
db 00000001b
db 00000001b
db 11101101b
db 11101101b
db 11110011b
db 11111111b
db 00000001b
db 00000001b
db 11101111b
db 11101111b
db 00000001b
db 11111111b
db 10000001b
db 00000001b
db 01111101b
db 01111110b
db 10000001b
db 11111111b
db 10000011b
db 00000001b
db 01111101b
db 01111101b
db 10011011b

b_2:  ; tạo chữ Landb 11111111b
db 11111111b
db 11111111b
db 00000001b
db 00000001b
db 01111111b
db 01111111b
db 01111111b
db 11111111b
db 00000111b
db 00000011b
db 11011101b
db 11011011b
db 00000111b
db 11111111b
db 00000001b
db 00000011b
db 11110111b
db 11101111b
db 00000001b
db 11111111b
db 11111111b
db 11111111b
db 11111111b

b_2a:      ; tạo chữ Phúc * Landb 11111111b
db 11111111b
db 00000001b
db 00000001b
db 11101101b
db 11101101b
db 11110011b
db 11111111b
db 00000001b
db 00000001b
db 11101111b
db 11101111b
db 00000001b
db 11111111b
db 10000001b
db 00000001b
db 01111101b
db 01111110b
db 10000001b
db 11111111b
db 10000011b
db 00000001b
db 01111101b
db 01111101b
db 10011011b
db 11111111b
db 11111111b
db 10111011b
db 11010111b
db 00000001b
db 11010111b
db 10111011b
db 11111111b
db 11111111b
db 00000001b
db 00000001b
db 01111111b
db 01111111b
db 01111111b
db 11111111b
db 00000111b
db 00000011b
db 11011101b
db 11011011b
db 00000111b
db 11111111b
db 00000001b
db 00000011b
db 11110111b
db 11101111b
db 00000001b
db 11111111b
db 11111111b
db 11111111b
db 11111111b
db 11111111b
db 11111111b
db 11111111b
db 11111111b
db 11111111b
db 11111111b
db 11111111b
db 11111111b
db 11111111b
db 11111111b
db 11111111b
db 11111111b
db 11111111b
db 11111111b
db 11111111b
db 11111111b
db 11111111b
db 11111111b
db 11111111b
db 11111111b
b_2b:            ; tạo chữ Ndb 11111111b
db 00000011b
db 11110111b
db 11101111b
db 11011111b
db 00000011b
db 11111111b
db 11111111b
db 11111111b
db 11111111b
db 11111111b
db 11111111b
db 11111111b
db 11111111b
db 11111111b
db 11111111b
db 11111111b
db 11111111b
db 11111111b
db 11111111b
db 11111111b
db 11111111b
db 11111111b
db 11111111b
db 11111111b
b_2ba:            ; tạo chữ NHdb 11111111b
db 00000011b
db 11110111b
db 11101111b
db 11011111b
db 00000011b
db 11111111b
db 00000011b
db 11011111b
db 11011111b
db 11011111b
db 00000011b
db 11111111b
db 11111111b
db 11111111b
db 11111111b
db 11111111b
db 11111111b
db 11111111b
db 11111111b
db 11111111b
db 11111111b
db 11111111b
db 11111111b
db 11111111b
b_2bb:            ; tạo chữ NHẬdb 11111111b
db 00000011b
db 11110111b
db 11101111b
db 11011111b
db 00000011b
db 11111111b
db 00000011b
db 11011111b
db 11011111b
db 11011111b
db 00000011b
db 11111111b
db 00001111b
db 11010101b
db 01011010b
db 11010101b
db 00001111b
db 11111111b
db 11111111b
db 11111111b
db 11111111b
db 11111111b
db 11111111b
db 11111111b
b_2bc:            ; tạo chữ NHẬTdb 11111111b
db 00000011b
db 11110111b
db 11101111b
db 11011111b
db 00000011b
db 11111111b
db 00000011b
db 11011111b
db 11011111b
db 11011111b
db 00000011b
db 11111111b
db 00001111b
db 11010101b
db 01011010b
db 11010101b
db 00001111b
db 11111111b
db 11111011b
db 11111011b
db 00000011b
db 11111011b
db 11111011b
db 11111111b
b_2c:            ; tạo chữ Tdb 11111111b
db 11111111b
db 11111111b
db 11111011b
db 11111011b
db 00000011b
db 11111011b
db 11111011b
db 11111111b
db 11111111b
db 11111111b
db 11111111b
db 11111111b
db 11111111b
db 11111111b
db 11111111b
db 11111111b
db 11111111b
db 11111111b
db 11111111b
db 11111111b
db 11111111b
db 11111111b
db 11111111b
db 11111111b
b_2ca:            ; tạo chữ TÂdb 11111111b
db 11111111b
db 11111111b
db 11111011b
db 11111011b
db 00000011b
db 11111011b
db 11111011b
db 11111111b
db 11111111b
db 00001111b
db 11010101b
db 11011010b
db 11010101b
db 00001111b
db 11111111b
db 11111111b
db 11111111b
db 11111111b
db 11111111b
db 11111111b
db 11111111b
db 11111111b
db 11111111b
db 11111111b
b_2cb:            ; tạo chữ TÂNdb 11111111b
db 11111111b
db 11111111b
db 11111011b
db 11111011b
db 00000011b
db 11111011b
db 11111011b
db 11111111b
db 11111111b
db 00001111b
db 11010101b
db 11011010b
db 11010101b
db 00001111b
db 11111111b
db 11111111b
db 00000011b
db 11110111b
db 11101111b
db 11011111b
db 00000011b
db 11111111b
db 11111111b
db 11111111b
b_3:     ; tạo chữ Tạp Chí Điện Tử Việt Namdb 11111111b
db 11111101b
db 11111101b
db 00000001b
db 11111101b
db 11111101b
db 11111111b
db 00001111b
db 11010111b
db 01011011b
db 11010111b
db 00001111b
db 11111111b
db 00000011b
db 11011011b
db 11011011b
db 11011011b
db 11100111b
db 11111111b
db 11011111b
db 11011111b
db 11011111b
db 11111111b
db 10000111b
db 01111011b
db 01111011b
db 01111011b
db 10110111b
db 11111111b
db 00000011b
db 11101111b
db 11101111b
db 11101111b
db 00000011b
db 11111111b
db 00000011b
db 11111111b
db 11011101b
db 11011110b
db 11011111b
db 11111111b
db 00000001b
db 01101101b
db 01101101b
db 01111101b
db 10000011b
db 11111111b
db 00000010b
db 11111111b
db 00000111b
db 01010101b
db 01010110b
db 01010101b
db 01110111b
db 11111111b
db 00000011b
db 11110111b
db 11101111b
db 11011111b
db 00000011b
db 11111111b
db 11011111b
db 11011111b
db 11011111b
db 11111111b
db 11111101b
db 11111101b
db 00000001b
db 11111101b
db 11111101b
db 11111111b
db 10000111b
db 01111111b
db 01110010b
db 01111101b
db 10000111b
db 11111001b
db 11011111b
db 11011111b
db 11011111b
db 11111111b
db 11000001b
db 10111111b
db 01111111b
db 10111111b
db 11000001b
db 11111111b
db 00000010b
db 11111111b
db 00000111b
db 01010101b
db 01010110b
db 01010101b
db 01110111b
db 11111111b
db 11111011b
db 11111011b
db 00000011b
db 11111011b
db 11111011b
db 11111111b
db 11101111b
db 11101111b
db 11101111b
db 11111111b
db 00000001b
db 11111011b
db 11110111b
db 11101111b
db 00000001b
db 11111111b
db 00001111b
db 10110111b
db 10111011b
db 10110111b
db 00001111b
db 11111111b
db 00000011b
db 11110111b
db 11101111b
db 11110111b
db 00000011b
db 11111111b
db 11111111b
db 11111111b
db 11111111b
db 11111111b
db 11111111b
db 11111111b
db 11111111b
db 11111111b
db 11111111b
db 11111111b
db 11111111b
db 11111111b
db 11111111b
db 11111111b
db 11111111b
db 11111111b
db 11111111b
db 11111111b
db 11111111b
db 11111111b
db 11111111b
db 11111111b
db 11111111b
db 11111111b

b_4:          ; tạo chữ Chàodb 10000111b
db 01111011b
db 01111011b
db 01111011b
db 10110111b
db 11111111b
db 00000011b
db 11011111b
db 11011111b
db 11011111b
db 00000011b
db 11111111b
db 00001111b
db 11010111b
db 11011011b
db 11010110b
db 00001101b
db 11111111b
db 10000111b
db 01111011b
db 01111011b
db 01111011b
db 10000111b
db 11111111b

b_4b:     ; tạo chữ Bạndb 11111111b
db 11111111b
db 00000011b
db 01101011b
db 01101011b
db 01101011b
db 10010111b
db 11111111b
db 11111111b
db 00001111b
db 11010111b
db 01011011b
db 11010111b
db 00001111b
db 11111111b
db 11111111b
db 00000011b
db 11110111b
db 11101111b
db 11011111b
db 00000011b
db 11111111b
db 11111111b
db 11111111b
b_5:    ; tạo chữ Phone: 39235347db 11111111b
db 11111111b
db 00000011b
db 11011011b
db 11011011b
db 11100111b
db 11111111b
db 00000011b
db 11101111b
db 11101111b
db 00000011b
db 11111111b
db 10000111b
db 01111011b
db 01111011b
db 10000111b
db 11111111b
db 00000011b
db 11110111b
db 11101111b
db 00000011b
db 11111111b
db 00000011b
db 01101011b
db 01101011b
db 11111111b
db 11111111b
db 11101111b
db 11010111b
db 10111011b
db 11010111b
db 11010111b
db 10111011b
db 11010111b
db 11101111b
db 11111111b
db 11111111b
db 10111011b
db 01111101b
db 01101101b
db 01101101b
db 10010011b
db 11111111b
db 01110011b
db 01101101b
db 01101101b
db 01101101b
db 10000011b
db 11111111b
db 00111011b
db 01011101b
db 01011101b
db 01011101b
db 01100011b
db 11111111b
db 10111011b
db 01111101b
db 01101101b
db 01101101b
db 10010011b
db 11111111b
db 10110001b
db 01110101b
db 01110101b
db 01110101b
db 10001101b
db 11111111b
db 10111011b
db 01111101b
db 01101101b
db 01101101b
db 10010011b
db 11111111b
db 11001111b
db 11010111b
db 11011011b
db 00000001b
db 11011111b
db 11111111b
db 11111001b
db 11111101b
db 00001101b
db 11110101b
db 11111001b
db 11111111b
db 11111111b
db 11111111b
db 11111111b
db 11111111b
db 11111111b
db 11111111b
db 11111111b
db 11111111b
db 11111111b
db 11111111b
db 11111111b
db 11111111b
db 11111111b
db 11111111b
db 11111111b
db 11111111b
db 11111111b
db 11111111b
db 11111111b
db 11111111b
db 11111111b
db 11111111b
db 11111111b

b_6:    ; tạo chữ Chuyên Mua Bán Các Linh Kiện Điện Tửdb 10000111b
db 01111011b
db 01111011b
db 01111011b
db 10110111b
db 11111111b
db 00000011b
db 11101111b
db 11101111b
db 11101111b
db 00000011b
db 11111111b
db 10000011b
db 01111111b
db 01111111b
db 01111111b
db 10000011b
db 11111111b
db 11110011b
db 11101111b
db 00011111b
db 11101111b
db 11110011b
db 11111111b
db 00000111b
db 01010101b
db 01010110b
db 01010101b
db 01110111b
db 11111111b
db 00000011b
db 11110111b
db 11101111b
db 11011111b
db 00000011b
db 11111111b
db 11111111b
db 11111111b
db 00000011b
db 11110111b
db 11101111b
db 11110111b
db 00000011b
db 11111111b
db 10000011b
db 01111111b
db 01111111b
db 01111111b
db 10000011b
db 11111111b
db 00001111b
db 10110111b
db 10111011b
db 10110111b
db 00001111b
db 11111111b
db 11111111b
db 11111111b
db 00000011b
db 01101011b
db 01101011b
db 01101011b
db 10010111b
db 11111111b
db 00001111b
db 10110111b
db 10111011b
db 10110111b
db 00001101b
db 11111110b
db 00000011b
db 11110111b
db 11101111b
db 11011111b
db 00000011b
db 11111111b
db 11111111b
db 11111111b
db 10000111b
db 01111011b
db 01111011b
db 01111011b
db 10110111b
db 11111111b
db 00001111b
db 10110111b
db 10111011b
db 10110111b
db 00001101b
db 11111110b
db 10000111b
db 01111011b
db 01111011b
db 01111011b
db 10110111b
db 11111111b
db 11111111b
db 11111111b
db 00000011b
db 01111111b
db 01111111b
db 01111111b
db 01111111b
db 11111111b
db 00000101b
db 11111111b
db 00000011b
db 11110111b
db 11101111b
db 11011111b
db 00000011b
db 11111111b
db 00000011b
db 11011111b
db 11011111b
db 11011111b
db 00000011b
db 11111111b
db 11111111b
db 11111111b
db 00000011b
db 11011111b
db 11001111b
db 10110111b
db 01111111b
db 11111111b
db 00000101b
db 11111111b
db 00000111b
db 01010011b
db 01010101b
db 01010011b
db 01110111b
db 11111111b
db 00000011b
db 11110111b
db 11101111b
db 11011111b
db 00000011b
db 11111111b
db 11111111b
db 11111111b
db 00000011b
db 01011011b
db 01011011b
db 01111011b
db 10000111b
db 11111111b
db 00000101b
db 11111111b
db 00000111b
db 01010011b
db 01010101b
db 01010011b
db 01110111b
db 11111111b
db 00000011b
db 11110111b
db 11101111b
db 11011111b
db 00000011b
db 11111111b
db 11111111b
db 11111111b
db 11111011b
db 11111011b
db 00000011b
db 11111011b
db 11111011b
db 11111111b
db 10000011b
db 01111111b
db 01110010b
db 01111101b
db 10000111b
db 11111001b
db 11111111b
db 11111111b
db 00000111b
db 11011011b
db 11011101b
db 11011011b
db 00000111b
db 11111111b
db 00000001b
db 01101101b
db 01101101b
db 01101101b
db 10010011b
db 11111111b
db 10000011b
db 01111101b
db 01111101b
db 01111101b
db 10111011b
db 11111111b
db 00000001b
db 01111101b
db 01111101b
db 01111101b
db 10000011b
db 11111111b
db 00000001b
db 01101101b
db 01101101b
db 01101101b
db 01111101b
db 11111111b
db 00000001b
db 11101101b
db 11101101b
db 11101101b
db 11111101b
db 11111111b
db 10000011b
db 01111101b
db 01101101b
db 01101101b
db 10001011b
db 11111111b
db 00000001b
db 11101111b
db 11101111b
db 11101111b
db 00000001b
db 11111111b
db 00000001b
db 11111111b
db 10111101b
db 01111101b
db 10000001b
db 11111101b
db 11111101b
db 11111111b
db 00000001b
db 11101111b
db 11010111b
db 10111011b
db 01111101b
db 11111111b
db 00000001b
db 01111111b
db 01111111b
db 01111111b
db 01111111b
db 11111111b
db 00000001b
db 11111011b
db 11110111b
db 11111011b
db 00000001b
db 11111111b
db 00000001b
db 11111011b
db 11110111b
db 11101111b
db 00000001b
db 11111111b
db 10000011b
db 01111101b
db 01111101b
db 01111101b
db 10000011b
db 11111111b
db 00000001b
db 11101101b
db 11101101b
db 11101101b
db 11110011b
db 11111111b
db 10000011b
db 01111101b
db 01111101b
db 01011101b
db 10000011b
db 01111111b
db 11111111b

b_7:   ; tạo mẫu các con chữdb 11111111b
db 00000001b
db 11101101b
db 11001101b
db 10101101b
db 01110011b
db 11111111b
db 10011011b
db 01110101b
db 01101101b
db 10011011b
db 11111111b
db 11111101b
db 11111101b
db 00000001b
db 11111101b
db 11111101b
db 11111111b
db 10000001b
db 01111111b
db 01111111b
db 01111111b
db 10000001b
db 11111111b
db 11000001b
db 10111111b
db 01111111b
db 10111111b
db 11000001b
db 11111111b
db 10000001b
db 01111111b
db 10011111b
db 01111111b
db 10000001b
db 11111111b
db 01111101b
db 11011011b
db 11110111b
db 11011011b
db 01111101b
db 11111111b
db 11111001b
db 11110111b
db 00001111b
db 11110111b
db 11111001b
db 11111111b
db 00111101b
db 01011101b
db 01101101b
db 01110101b
db 01111001b
db 11111111b
db 11111111b
db 11111111b
db 11111111b
db 11111111b
db 11111111b
db 11111111b
db 11111111b
db 11111111b
db 11111111b
db 11111111b
db 11111111b
db 11111111b
db 11111111b
db 11111111b
db 11111111b
db 11111111b
db 11111111b
db 11111111b
db 11111111b
db 11111111b
db 11111111b
db 11111111b
db 11111111b
db 11111111b

b_8:   ; tạo hình căn nhà và câydb 01110011b
db 00001101b
db 01110011b
db 00000111b
db 01111011b
db 01000101b
db 01010110b
db 01000100b
db 01111000b
db 00000000b
db 01110000b
db 01110000b
db 01110000b
db 01110000b
db 01110000b
db 01110001b
db 00000011b
db 00110111b
db 00011111b
db 00001111b
db 00111001b
db 00000110b
db 00111001b
db 01111111b

b_9:   ; tạo hình rừng câydb 00111111b
db 01111001b
db 00000110b
db 01111001b
db 00111111b
db 00000111b
db 00001111b
db 00111111b
db 00111111b
db 00000011b
db 00011111b
db 00000011b
db 00000000b
db 00000111b
db 00011111b
db 00111111b
db 01110001b
db 00000000b
db 01110001b
db 01111111b
db 00111111b
db 00011111b
db 00000111b
db 00011111b
db 11111111b
db 11111111b
db 11111111b
db 11111111b
db 11111111b
db 11111111b
db 11111111b
db 11111111b
db 11111111b
db 11111111b
db 11111111b
db 11111111b
db 11111111b
db 11111111b
db 11111111b
db 11111111b
db 11111111b
db 11111111b
db 11111111b
db 11111111b
db 11111111b

b_10:   ; tạo hình hoa văndb 00000000b,00000000b,00000000b
db 00000000b,00000000b,00000000b
db 00000000b,00000000b,00000000b
db 00000000b,00000000b,00000000b
db 00000000b,00000000b,00000000b
db 00000000b,00000000b,00000000b
db 00000000b,00000000b,00000000b
db 00000000b,00000000b,00000000b
db 01000100b,01000100b,01000100b
db 00101000b,00101000b,00101000b
db 01000100b,01000100b,01000100b
db 10010010b,10010010b,10010010b
db 01000100b,01000100b,01000100b
db 00101000b,00101000b,00101000b
db 01000100b,01000100b,01000100b
db 00101000b,00101000b,00101000b
db 00000000b,00000000b,00000000b
db 00000000b,00000000b,00000000b
db 00000000b,00000000b,00000000b
db 00000000b,00000000b,00000000b
db 00000000b,00000000b,00000000b
db 00000000b,00000000b,00000000b
db 00000000b,00000000b,00000000b
db 00000000b,00000000b,00000000b

b_11:   ; tạo hình các mũi têndb 00000000b,00000000b,00000000b
db 00000000b,00000000b,00000000b
db 00000000b,00000000b,00000000b
db 00000000b,00000000b,00000000b
db 00000000b,00000000b,00000000b
db 00000000b,00000000b,00000000b
db 00000000b,00000000b,00000000b
db 00000000b,00000000b,00000000b
db 00000000b,00000000b,00000000b
db 00000000b,00000000b,00000000b
db 00010000b,00001000b,00000100b
db 00111000b,00011100b,00001110b
db 11111110b,01111111b,00111111b
db 01111100b,00111110b,00011111b
db 01000100b,00100010b,00010001b
db 11000110b,01100011b,00110001b
db 00000000b,00000000b,00000000b
db 00000000b,00000000b,00000000b
db 00000000b,00000000b,00000000b
db 00000000b,00000000b,00000000b
db 00000000b,00000000b,00000000b
db 00000000b,00000000b,00000000b
db 00000000b,00000000b,00000000b
db 00000000b,00000000b,00000000b

b_12:   ; tạo hình các ký hiệu điện tửdb 11111111b,11111111b,11111111b
db 10000000b,00001100b,11000001b
db 10000000b,00001110b,11000001b
db 10000001b,11111111b,11111001b
db 10000000b,00001110b,11000001b
db 10000000b,00001100b,11000001b
db 10000000b,00001000b,00000001b
db 11111111b,11111111b,11111111b
db 00000000b,00000000b,00000000b
db 11111111b,11111111b,11111111b
db 10000000b,00000000b,00000001b
db 10000010b,00100010b,00000001b
db 10011101b,01010101b,01110001b
db 10000000b,10001000b,10000001b
db 10000000b,00000000b,00000001b
db 11111111b,11111111b,11111111b
db 00000000b,00000000b,00000000b
db 00000000b,01001000b,00000000b
db 00000000b,01001000b,00000000b
db 00011111b,11001111b,11100000b
db 00000000b,01001000b,00000000b
db 00000000b,01001000b,00000000b
db 00000000b,00000000b,00000000b
db 00000000b,00000000b,00000000b

b_13:     ; tạo hình các bông hoadb 00000000b,00000000b,00000000b
db 00000000b,00000000b,00000000b
db 00000000b,00000000b,00000000b
db 00000000b,00000000b,00000000b
db 00000000b,00000000b,00000000b
db 00000000b,00000000b,00000000b
db 00000000b,00000000b,00000000b
db 00000000b,00000000b,00000000b
db 00011100b,00011100b,00011100b
db 00111110b,00111110b,00111110b
db 00011100b,00011100b,00011100b
db 10001001b,10001001b,10001001b
db 01001010b,01001010b,01001010b
db 00101100b,00101100b,00101100b
db 00011000b,00011000b,00011000b
db 11111111b,11111111b,11111111b
db 00000000b,00000000b,00000000b
db 00000000b,00000000b,00000000b
db 00000000b,00000000b,00000000b
db 00000000b,00000000b,00000000b
db 00000000b,00000000b,00000000b
db 00000000b,00000000b,00000000b
db 00000000b,00000000b,00000000b
db 00000000b,00000000b,00000000b

b_14:   ; tạo hình các giọt nướcdb 00000000b,00000000b,00000000b
db 00000000b,00000000b,00000000b
db 00000000b,00000000b,00000000b
db 00000000b,00000000b,00000000b
db 00000000b,00000000b,00000000b
db 00000000b,00000000b,00000000b
db 00000000b,00000000b,00000000b
db 00000000b,00000000b,00000000b
db 00100000b,10000010b,00001000b
db 01110001b,11000111b,00011100b
db 11111011b,11101111b,10111110b
db 01110001b,11000111b,00011100b
db 00000100b,00010000b,01000000b
db 00001110b,00111000b,11100000b
db 00011111b,01111101b,11110000b
db 00001110b,00111000b,11100000b
db 00000000b,00000000b,00000000b
db 00000000b,00000000b,00000000b
db 00000000b,00000000b,00000000b
db 00000000b,00000000b,00000000b
db 00000000b,00000000b,00000000b
db 00000000b,00000000b,00000000b
db 00000000b,00000000b,00000000b
db 00000000b,00000000b,00000000b
end




Nói rõ hơn: Cách tạo hình trên bảng đèn ma trận 8x24 



❶ Hình vẽ dưới đây cho thấy cách Bạn tạo ra khung mã hình dùng bit 0 để tạo hình.


 

Muốn in hình ra trên bảng ma trận 8x24, trước hết Bạn hãy đặt tên bảng, rồi tạo khung hình tương ứng với bảng đèn. Một thí dụ:

b_8:  ; đặt tên nhãn của bảng mã hìnhdb 01110011b
db 00001101b
db 01110011b
db 00000111b
db 01111011b
db 01000101b
db 01010110b
db 01000100b
db 01111000b
db 00000000b
db 01110000b
db 01110000b
db 01110000b
db 01110000b
db 01110000b
db 01110001b
db 00000011b
db 00110111b
db 00011111b
db 00001111b
db 00111001b
db 00000110b
db 00111001b
db 01111111b

Trên đây là 24 dòng mã 8 bit viết ở dạng hệ cơ 2. Trong đó ứng với vị trí bit 0 sẽ làm cho Led sáng. Hình trên cho thấy chúng ta đã dùng bit 0 để tạo ra hình một ngôi nhà trên bảng đèn. Tóm lại, muốn Led nào sáng, chúng ta đặt vào số 0, và số 1 sẽ làm tắt Led. Kết quả chúng ta sẽ có hình hiện ra như sau:


Bạn có thể viết gọn lại bảng mã hình trên nếu dùng mã 8 bit viết ở dạng hệ 16, kết quả chúng ta có bảng mã hinh trên như sau:



b_8:  ; đặt tên nhãn của bảng mã hìnhdb 0111 0011b   ; 73h
db 0000 1101b   ; 0dh
db 0111 0011b   ; 73h
db 0000 0111b   ; 07h
db 0111 1011b   ; 7bh
db 0100 0101b   ; 45h
db 0100110b   ; 56h
db 0100 0100b   ; 44h
db 0111 1000b   ; 78h
db 0000 0000b   ; 00h
db 0111 0000b   ; 70h
db 0111 0000b   ; 70h
db 0111 0000b   ; 70h
db 0111 0000b   ; 70h 
db 0111 0000b   ; 70h
db 0111 0001b   ; 71h
db 0000 0011b   ; 03h
db 0011 0111b   ; 37h
db 0001 1111b   ; 1fh
db 0000 1111b   ; 0fh
db 0011 1001b   ; 39h
db 0000 0110b   ; 06h
db 0011 1001b   ; 39h
db 0111 1111b   ; 7fh


Ghi nhận: Viết mã hình ở dạng hệ 16, tuy ngắn gọn hơn, nhưng Bạn sẽ không nhìn thấy trong các dòng mã này nó là hình gì và khi hình hay chữ bị sai rất khó sửa lai cho đúng. 

b_8:  ; đặt tên nhãn của bảng mã hìnhdb 73h, 0dh, 73h, 07h, 7bh, 45h, 56h, 44h
db 78h, 00h, 70h, 70h, 70h, 70h, 70h, 71h
db 03h, 37h, 1fh, 0fh, 39h, 06h, 39h, 7fh



Dưới đây là một khung hình trắng, vì toàn bit 1 (tắt Led), muốn tạo hình trên các điểm Led của ma trận 8x24, Bạn dùng bit 0.

b_vkh:        ; đặt tên nhãn cho bảng    db 11111111b
db 11111111b
db 11111111b
db 11111111b
db 11111111b
db 11111111b
db 11111111b
db 11111111b  ;
db 11111111b
db 11111111b
db 11111111b
db 11111111b
db 11111111b
db 11111111b
db 11111111b
db 11111111b  ;
db 11111111b
db 11111111b
db 11111111b
db 11111111b
db 11111111b
db 11111111b
db 11111111b
db 11111111b

  

❷ Hình vẽ dưới đây cho thấy cách Bạn dùng bit 1 để tạo hình



 


Bạn có thể đặt mã quét trên cảng p1, và cho xuất mã hình trên các cảng p2, p3, p0. Lúc này ứng với bit 1 sẽ làm cho Led sáng. Bạn xem một thí dụ, minh họa bằng hình sau:


 

Như vậy khung để tạo hình cho kiểu quét này sẽ như sau:

 b_14:  
; đặt tên nhãn để dùng lệnh mov dptr, #b_14
; câu lệnh này cho đặt bảng vào thanh địa chỉ dptr.db 00000000b,00000000b,00000000b
db 00000000b,00000000b,00000000b
db 00000000b,00000000b,00000000b
db 00000000b,00000000b,00000000b
db 00000000b,00000000b,00000000b
db 00000000b,00000000b,00000000b
db 00000000b,00000000b,00000000b
db 00000000b,00000000b,00000000b

Trên đây là một khung mẫu trắng vì toàn là bit 0, nếu Bạn muốn có hình gì hiện trên ma trận 8x24, thì hãy dùng bit 1 làm sáng các Led ở các vị trí tương ứng. Bạn cũng có thể viết các mã hình 8 bit này ở dạng hệ cơ 16, lúc đó bảng sẽ ngắn gọn hơn, nhưng Bạn sẽ không thấy được hình gì trên các dòng mã này, và khi cần sửa đổi sẽ rất khó khăn.


Ý kiến chúng tôi:


 


 


Nếu Bạn muốn làm thực hành bài viết trên, đầu tiên Bạn phải có bảng đèn ma trận 8x24 như hình trên, Bạn có thể mua bản mạch in ở cửa hàng Phúc Lan Shop, sau đó gắn Led lên bản mạch in và kết nối với ic lập trình AT89C52 (dùng ic AT89C52 có bộ nhớ 8K lớn hơn ic AT89C51 chỉ có 4K). Tiếp theo Bạn cắt đoạn chương trình nguồn trên và dán vào vùng biên soạn của MIDE-51 (xem hình bên dưới), đặt cho nó một cái tên với họ là .asm, rồi gõ phím F9 để biên dịch file .asm ra file .hex, bây giờ Bạn cho nạp đoạn chương trình mã hệ 16 này vào bộ nhớ EEPROM của ic lập trình AT89C52, gắn vào board test, Bạn sẽ thấy hình và dòng chữ mà Bạn soạn trong các khung hình xuất hiện trên bảng đèn. Thích không? 






Sau khi biên dịch xong, chúng ta có file .hex như sau:

:1000000012043B7B001202347590FF9004A07C0A1E
:100010001203D5DCFB0BBB1AF57B007590FF900437
:10002000B87C0A1203D5DCFB0BBB1AF57503001272
:10003000035812031A12043B90051B7C021203D5CD
:10004000DCFB0BBB1AF575030012043B9005347CF6
:10005000021203D5DCFB0BBB1AF575030012043B3F
:1000600090054D7C021203D5DCFB0BBB1AF5750322
:100070000012043B9005667C0A1203D5DCFB0BBB27
:100080001AF575030012043B90057F7C021203D51C
:10009000DCFB0BBB1AF575030012043B9005987C42
:1000A000021203D5DCFB0BBB1AF575030012043BEF
:1000B0009005B17C0A1203D5DCFB0BBB1AF5750366
:1000C0000012035812031A12043B9004D07C14123D
:1000D00003D5DCFBA30BBB36F47B0012043B75207D
:1000E0000390065D7C0A1203D5DCFB0BBB0AF57B93
:1000F0000075800075A00075B00012042E12043B3C
:100100009006757C0A1203D5DCFB0BBB0AF57B005D
:1001100075800075A00075B00012042ED520C212A3
:10012000043B9005CA7C0F1203D5DCFBA30BBB7A02
:10013000F47B0012043B90068D7C141203D5DCFB8B
:10014000A30BBB4FF47B0012035812031A12043B9B
:100150009008747C141203D5DCFB0BBB1AF57503F5
:100160000012043B75200E9008A17B007A0C12044B
:1001700048DAFBA3A3A30BBB10F2D520EA12043B81
:100180009006F97C081203D5DCFBA30BBBFFF47BC4
:100190000012043B90080E7C081203D5DCFBA30B75
:1001A000BB34F47B0012043B7520069008E97B0009
:1001B0007A0C120448DAFBA3A3A30BBB10F2D520E0
:1001C000EA12043B7520029009317B007A32120456
:1001D00048DAFBA3A3A30BBB10F2D520EA12043B21
:1001E00075200A9009797B007A28120474DAFBA33F
:1001F000A3A30BBB10F2D520EA12043B7520049098
:1002000009C17B007A0C120448DAFBA3A3A30BBB41
:1002100010F2D520EA12043B90085C7C1E1203D534
:10022000DCFB0BBB1AF57503001202A712042E1299
:10023000042E01007590007580FF75A0FF75B0FF5A
:1002400012042E75B0E712042E75B0C312042E7579
:10025000B08112042E75B00012042E75A0FE7580B8
:100260007F12042E75A0FC75803F12042E75A0F835
:1002700075801F12042E75A0F075800F12042E7564
:10028000A0E075800712042E75A0C07580031204CB
:100290002E75A08075800112042E75A00075800057
:1002A00012042E12042E2275900075800075A00095
:1002B00075B00012042E75A08075800112042E7591
:1002C000A0C075800312042E75A0E075800712048B
:1002D0002E75A0F075800F12042E75A0F875801F82
:1002E00012042E75A0FC75803F12042E75A0FE75B9
:1002F000807F12042E75A0FF7580FF12042E75B04A
:100300008112042E75B0C312042E75B0E712042EAC
:1003100075B0FF12042E12042E227590007580FF16
:1003200075A0FF75B0FF12042E12042ED29712048E
:100330002ED29612042ED29512042ED29412042E8E
:10034000D29312042ED29212042ED29112042ED2E3
:100350009012042E12042E227590FF12042E120405
:100360002E7580FF75A0FF75B0FFC29012042E7528
:1003700080FF75A0FF75B0FFC29112042E7580FF3B
:1003800075A0FF75B0FFC29212042E7580FF75A094
:10039000FF75B0FFC29312042E7580FF75A0FF7524
:1003A000B0FFC29412042E7580FF75A0FF75B0FFD8
:1003B000C29512042E7580FF75A0FF75B0FFC2961E
:1003C00012042E7580FF75A0FF75B0FFC29712044E
:1003D0002E12042E2278017900E803F888A0E99310
:1003E000F5900912042575A0007590FF120425B838
:1003F00001E7E803F888B0E993F590091204257540
:10040000B0007590FF120425B801E7E803F8888072
:10041000E993F590091204257580007590FF120488
:1004200025B801E7227F037E32DEFEDFFA227F0558
:100430007E327DFADDFEDEFADFF62275800075A0E1
:100440000075B0007590FF2278FE7900E803F88807
:1004500090E993F5A009E993F5B009E993F58009CE
:1004600091257590FF75800075A00075B0009125ED
:10047000B8FED922787F7900E823F88890E993F5CF
:10048000A009E993F5B009E993F5800991257590E4
:10049000FF75800075A00075B0009125B87FD92246
:1004A000FF0101EDEDF3FF0101EFEF01FF81017DA0
:1004B0007E81FF83017D7D9BFFFFFF01017F7F7FA9
:1004C000FF0703DDDB07FF0103F7EF01FFFFFFFF7E
:1004D000FFFF0101EDEDF3FF0101EFEF01FF8101EE
:1004E0007D7E81FF83017D7D9BFFFFBBD701D7BB55
:1004F000FFFF01017F7F7FFF0703DDDB07FF0103B4
:10050000F7EF01FFFFFFFFFFFFFFFFFFFFFFFFFF11
:10051000FFFFFFFFFFFFFFFFFFFFFFFF03F7EFDF1F
:1005200003FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFD7
:10053000FFFFFFFFFF03F7EFDF03FF03DFDFDF0353
:10054000FFFFFFFFFFFFFFFFFFFFFFFFFFFF03F7BF
:10055000EFDF03FF03DFDFDF03FF0FD55AD50FFF08
:10056000FFFFFFFFFFFFFF03F7EFDF03FF03DFDF07
:10057000DF03FF0FD55AD50FFFFBFB03FBFBFFFF8C
:10058000FFFFFBFB03FBFBFFFFFFFFFFFFFFFFFF87
:10059000FFFFFFFFFFFFFFFFFFFFFFFBFB03FBFB77
:1005A000FFFF0FD5DAD50FFFFFFFFFFFFFFFFFFFB4
:1005B000FFFFFFFFFBFB03FBFBFFFF0FD5DAD50FB0
:1005C000FFFF03F7EFDF03FFFFFFFFFDFD01FDFD71
:1005D000FF0FD75BD70FFF03DBDBDBE7FFDFDFDFDF
:1005E000FF877B7B7BB7FF03EFEFEF03FF03FFDDAD
:1005F000DEDFFF016D6D7D83FF02FF0755565577E6
:10060000FF03F7EFDF03FFDFDFDFFFFDFD01FDFD90
:10061000FF877F727D87F9DFDFDFFFC1BF7FBFC14B
:10062000FF02FF0755565577FFFBFB03FBFBFFEF70
:10063000EFEFFF01FBF7EF01FF0FB7BBB70FFF03B2
:10064000F7EFF703FFFFFFFFFFFFFFFFFFFFFFFFD6
:10065000FFFFFFFFFFFFFFFFFFFFFFFFFF877B7B2A
:100660007BB7FF03DFDFDF03FF0FD7DBD60DFF878D
:100670007B7B7B87FFFFFF036B6B6B97FFFF0FD7C6
:100680005BD70FFFFF03F7EFDF03FFFFFFFFFF0362
:10069000DBDBE7FF03EFEF03FF877B7B87FF03F7DE
:1006A000EF03FF036B6BFFFFEFD7BBD7D7BBD7EFD2
:1006B000FFFFBB7D6D6D93FF736D6D6D83FF3B5DC4
:1006C0005D5D63FFBB7D6D6D93FFB17575758DFFCE
:1006D000BB7D6D6D93FFCFD7DB01DFFFF9FD0DF51E
:1006E000F9FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF20
:1006F000FFFFFFFFFFFFFFFFFF877B7B7BB7FF0352
:10070000EFEFEF03FF837F7F7F83FFF3EF1FEFF3B5
:10071000FF0755565577FF03F7EFDF03FFFFFF0392
:10072000F7EFF703FF837F7F7F83FF0FB7BBB70F21
:10073000FFFFFF036B6B6B97FF0FB7BBB70DFE039C
:10074000F7EFDF03FFFFFF877B7B7BB7FF0FB7BBB5
:10075000B70DFE877B7B7BB7FFFFFF037F7F7F7F2C
:10076000FF05FF03F7EFDF03FF03DFDFDF03FFFF1B
:10077000FF03DFCFB77FFF05FF0753555377FF0315
:10078000F7EFDF03FFFFFF035B5B7B87FF05FF07DF
:1007900053555377FF03F7EFDF03FFFFFFFBFB0327
:1007A000FBFBFF837F727D87F9FFFF07DBDDDB0744
:1007B000FF016D6D6D93FF837D7D7DBBFF017D7DB1
:1007C0007D83FF016D6D6D7DFF01EDEDEDFDFF831F
:1007D0007D6D6D8BFF01EFEFEF01FF01FFBD7D81AF
:1007E000FDFDFF01EFD7BB7DFF017F7F7F7FFF0115
:1007F000FBF7FB01FF01FBF7EF01FF837D7D7D83AD
:10080000FF01EDEDEDF3FF837D7D5D837FFFFF0154
:10081000EDCDAD73FF9B756D9BFFFDFD01FDFDFFF4
:10082000817F7F7F81FFC1BF7FBFC1FF817F9F7FAE
:1008300081FF7DDBF7DB7DFFF9F70FF7F9FF3D5D0A
:100840006D7579FFFFFFFFFFFFFFFFFFFFFFFFFF5A
:10085000FFFFFFFFFFFFFFFFFFFFFFFF730D7307AA
:100860007B455644780070707070707103371F0FAD
:100870003906397F3F7906793F070F3F3F031F0352
:1008800000071F3F7100717F3F1F071FFFFFFFFF22
:10089000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF68
:1008A000FF00000000000000000000000000000049
:1008B00000000000000000000044444428282844B0
:1008C000444492929244444428282844444428288A
:1008D00028000000000000000000000000000000F0
:1008E0000000000000000000000000000000000008
:1008F00000000000000000000000000000000000F8
:1009000000000000000000100804381C0EFE7F3FAD
:100910007C3E1F442211C66331000000000000002D
:1009200000000000000000000000000000000000C7
:1009300000FFFFFF800CC1800EC181FFF9800EC156
:10094000800CC1800801FFFFFF000000FFFFFF8057
:1009500000018222019D5571808881800001FFFF86
:10096000FF0000000048000048001FCFE0004800E2
:10097000004800000000000000000000000000002F
:100980000000000000000000000000000000000067
:10099000001C1C1C3E3E3E1C1C1C8989894A4A4A7C
:1009A0002C2C2C181818FFFFFF000000000000007E
:1009B0000000000000000000000000000000000037
:1009C0000000000000000000000000000000000027
:1009D00000000000000000000020820871C71CFB1E
:1009E000EFBE71C71C0410400E38E01F7DF00E38BA
:1009F000E000000000000000000000000000000017
:090A0000000000000000000000ED
:00000001FF

Tạm kết: Qua phần trình bày trên, Bạn thấy dùng ic lập trình AT89C51, chúng ta đã có thể điều khiển được sự tắt sáng của bất kỳ con Led nào trên bảng đèn, điều này cho chúng ta một sự thích thú khó tả, cũng qua bài viết này tôi nghĩ Bạn đã làm quen với cách dùng bàng Led ma trận để làm hiện hình và cho chạy chữ, đây là một đề tài rất rất hấp dẫn, khi có dịp chúng tôi sẽ trở lại đề tài này với một mức độ rộng hơn, cao hơn. Mong Bạn thích bài viết này.


 Ứng dụng ic lập trình AT89C51: Dùng bàn phím điều khiển motor, relay, đèn...

        Bạn vào xem...


Dẫn nhập

Chúng ta biết, một "vật thể tự động hoàn chỉnh" phải gồm có: Ngả vào - Bộ nhớ Ngả raNgả vào là chỉ tác động bên ngoài đi vào vật thể, như ở con người, chúng ta có mắt để ghi nhận các thực thể xuất hiện ở dạng quang năngcó tai để nghe biết các sóng âmcó mũi để nhận ra mùi,có lưỡi để nhận biết vị và có lớp da bao bọc toàn thân để cảm nhận ra sự nóng lạnh, cứng mềm, nặng nhẹ... Đó là ngủ quan của con người. Bộ nhớ được dùng đề lưu giữ các chương trình, chương trình là "trí tuệ" mà thực thể có thể truy cập, lấy ra thao tác mỗi khi gặp các đối ứng cần giải quyết và Ngả ra chính là các tạo thể trang bị trên các vật thể nó chấp hành theo các chương trình, như trên cơ thể của chúng ta các thực thể thấy được như tứ chi hai tay hai chân, tim, phổi, gan, ruột...là các tạo thể luôn vận hành theo các chương trình đã có trong bộ nhớ. Khi con người đứng gần chổ quá nóng, chúng ta biết nóng và đã kịp đi ra xa chổ nóng, đó là phản ứng rất cơ bản của một vật thể tự động hoàn chỉnh.

Con người là sinh vật thông minh có khả năng học hỏi các chứng vật hiện diện chung quanh trong thiên nhiên chung quanh và con người còn muốn tự mình tạo ra các "vật thể tự động hoàn chỉnh" nữa. Ước muốn này đã có bước tiến vượt bậc từ khi người ta chế tạo ra được các ic lập trình, nó hoạt động theo các chương trình đã có trong các bộ nhớ. Trong lần này chúng ta sẽ nói đến tính năng nhập thông tin từ bên ngoài vào bên trong của các ic lập trình, cơ bản nhất là dùng các phím nhấn, sau đó sẽ mở rộng qua các cách lấy thông tin qua các cảm biến, như: quang trở, nhiệt trở, vị trở, từ trở, ẩm trở, áp trở, phong trở, động trở, ... Với các cảm biến này, chúng ta có thể mô phỏng nhiều chức năng giống như ngủ quan của các sinh vật vậy.  

 

Trước khi nói đến điều cao siêu, chúng ta hãy tìm hiểu một hệ vận hành cơ bản và đơn giản cái đã. 



Các phím nhấn dùng với ic lập trình AT89C51


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ì?


 

Hình vẽ 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ấntim_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 1tt1:  ; đặ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ấnchtrinh1: 
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ắtORG 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ímSTAR1:  ; đặ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.4WAITL0:   ; trình chờ bỏ phím     JNB P3.4,WAITL0 ; chờ bỏ phím    SETB F0  ; đặt bit kiểm tra f0 lên 1FUN01:  ; đặ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ênFUN1:
    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ênFUN2:
   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ênFUN3:
   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.3WAITL3:   ; 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ênFUN00:  
   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ẩyFUN11:
   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 



Một thí dụ khác nữa: Dùng 8 phím trên cảng 1 để điều khiển các động thái của một motor DC

Trước hết tìm hiểu nguyên lý vận hành của các thành phần dùng trong mạch điện:

1. Tìm hiểu ic điều khiển motor:


IC BA6209 có 10 chân, công dụng của các chân như sau:

Chân 1 cho nối masse, chân 7 cho nối nguồn VCC1, chân 8 lấy nguồn VCC2 qua một điện trở 10 ohm. Mức áp chuẩn định tốc độ quay chọn theo diode Zener trên chân số 4. Chân số 3 và số 9 mắc tụ lọc và chân số 2 và chân số 10 cấp điện cho motor. Ngang motor gắn một tụ lọc nhiễu ồn phát ra từ motor. Tín hiệu điều khiển đưa vào trên chân 5 và chân 6. Bản logic cho thấy:

* Khi chân 5 Fin và chân 6 Rin đều ở mức áp thấp, thì mức áp ngả ra trên chân 2, 10 đều ở mức áp thấp: Motor không quay.

* Khi chân Fin ở mức áp cao, chân Rin ở mức áp thấp, thì chân 2 ở mức cao và chân 10 ở mức áp thấp: Motor quay thuận.

* Khi chân Fin ở mức áp thấp, chân Rin ở mức áp cao, thì chân 2 ở mức thấp và chân 10 ở mức áp cao: Motor quay ngược.

* Khi chân 5 Fin và chân 6 Rin đều ở mức áp cao, thì mức áp ngả ra trên chân 2, 10 đều ở mức áp thấp: Motor không quay. 

Phân tích trên cho thấy, chúng ta có thể dùng 3 chân 4, 5, 6 của ic lập trình để điều khiển các trạng thái quay của motor


 2. Tìm hiểu nguyên lý làm việc của motor DC.

Motor DC gồm có:

* Phần tĩnh là một nam châm vĩnh cữu, đặt cố định, một bên là cực nam thì bên kia là cực bắc.

* Phần quay gồm có các cuộn dây ứng quấn trên các từ cực. Trên trục quay người ta đặt một cổ lấy điện bằng các vòng đồng, dùng chổi than đè lên cổ lấy điện để cấp điện cho các cuộn dây ứng đặt trên phần quay, cuộn dây có điện sẽ trở thành các nam châm điện.

Do tương tác, các nam châm (ở đây là nam châm vĩnh cữu của phần tĩnh và nam châm điện trên phần quay) đặt gần nhau, khi có tên cực giống nhau sẽ đẩy nhau và khác tên thì sẽ hút nhau, điều này sẽ làm quay phần ứng, khi phần ứng quay nó đồng thời làm quay cổ lấy điện, điều này sẽ làm đảo chiều dòng chảy qua các cuộn dây ứng, như vậy các nam châm sẽ lại đổi cực tính, do vậy cuộn dây sẽ luôn phải ở trạng thái quay.

 




Chúng ta biết, khi được cấp điện thì motor DC sẽ quay, mức áp cấp cho motor càng cao thì motor quay càng nhanh. Và nếu Bạn dùng lực làm quay một motor DC thì trên 2 cực của motor DC sẽ phát ra điện áp ứng, nếu motor bị kéo quay càng nhanh thì mức điện áp ứng phát ra càng cao. Điều này cho thấy motor DC khi được cấp điện nó sẽ quay, và khi bị kèo quay nó sẽ phát ra điện. Dùng luật ohm, chúng ta có thể viết hệ thức sau:

                          dòng điện I = (điện áp cung cấp) - (điện áp ứng) / điện trở R của cuộn ứng

Trong đó:   

(điện áp ứng) là một hàm của tốc độ quay. Khi motor quay càng chậm, điện áp ứng phát ra càng yếu và ngược lại. 

(lực quay) là một hàm của dòng điện I. Khi dòng điện càng lớn thì lực kéo càng mạnh.

Điều này cho thấy: Khi bị tải nặng, tốc độ quay của motor sẽ có khuynh hướng bị chậm lại, tốc độ quay giảm sẽ làm cho điện áp ứng giảm, hệ thức trên cho thấy dòng điện I sẽ tăng lên, dòng điện I tăng sẽ gia tăng khả năng mang tải của motor DC, nhờ phản ứng này, mà motor DC có khả năng mang tải rất tốt. 
  
Khi dùng motor DC chúng ta chú ý các điểm sau:

* Điện áp DC cấp cho motor DC càng cao, motor quay càng nhanh.

* Đảo chiều điện áp cấp điện, chiều quay của motor sẽ đổi chiều quay.

* Điện trở phần ứng càng nhò, dòng chảy qua motor DC càng lớn, lực quay sẽ càng mạnh.

* Khi motor DC quay, từ hai chổi quét điện sẽ luôn phát ra nhiễu ồn rất lớn, phải dùng tụ và cuộn dây để lọc nhiễu.

* Không để motor bị kẹt trục không quay, điều này sẽ khiến cho dòng chảy qua motor sẽ rất lớn, motor có thể bị cháy.



3. Phân tích sơ đồ điều khiển các động thái của motor dùng ic AT89C51


Mạch điện cho thấy: 

8 nút nhấn dùng điều khiển 2 motor DC gắn trên xe đều cho kết nối trên cảng p1. Motor DC gắn bên phải qua ic BA6209, chân p3.0 điều khiển chiều quay thuận, chân p3.1 điều khiển chiều quay nghịch và chân p3.2 điều khiển tốc độ quay. Motor DC gắn bên trái qua ic BA6209, với chân p3.3 điều khiển chiều quay thuận, chân p3.4 điều khiển chiều quay ngược và chân p3.5 điều khiển tốc độ quay.


4. Viết chương trình nguồn theo yêu cầu trên:


org 0000h
qua0:  
       jb p1.0, qua1
        call del   ; gọi trình làm trể, tránh ảnh hưởng rung phím        jnb p1.0, $
        jmp chay_toi ; Cho chạy tới, 2 motor quay cùng chiều

qua1:  
        jb p1.1, qua2
        call del
        jnb p1.1, $
        jmp chay_lui ; chạy lùi, 2 motor cho quay ngược chiều

qua2:  
       jb p1.2, qua3
        call del
        jnb p1.2, $
        jmp queo_trai ; quẹo trái, motor trái dừng, motor phải quay tới

qua3:  
        jb p1.3, qua4
        call del
        jnb p1.3, $
        jmp queo_phai ; quẹo phải, motor phải dừng và motor trái quay tới 

qua4:  
        jb p1.4, qua5
        call del
        jnb p1.4, $
        jmp dung  ; dừng, cả 2 motor đều dừng, không quay

qua5:  
        jb p1.5, qua6
        call del
        jnb p1.5, $
        jmp cham_lai ; chậm lại, 2 motor quay với tốc độ chậm 

qua6:  
       jb p1.6, qua7
        call del
        jnb p1.6, $
        jmp quay_trai ; quay vòng qua trái, motor trái quay ngược, motor phải quay thuận

qua7:  
        jb p1.7, qua0
        call del
        jnb p1.7, $
        jmp quay_phai
 ; quay vòng qua phải, motor trái quay thuận, motor phải quay ngược

chay_toi: ; trình cho chạy tới        setb p3.0
        clr p3.1
        setb p3.2
        setb p3.3
        clr p3.4
        setb p3.5
        jmp qua0  ;
 trở lại chương trình qué phím

chay_lui: ; trình cho chạy lùi         clr p3.0
        setb p3.1
        setb p3.2
        clr p3.3
        setb p3.4
        setb p3.5
        jmp qua0  ; 
trở lại trình quét phím

queo_trai: ; cho quẹo trái          setb p3.0
        clr p3.1
        setb p3.2
        setb p3.3
        clr p3.4
        clr p3.5
        jmp qua0  ; 
trở lại trình quét phím

queo_phai: ; cho quẹo phải         setb p3.0
        clr p3.1
        clr p3.2
        setb p3.3
        clr p3.4
        setb p3.5
        jmp qua0  ; 
trở lại trình quét phím

dung:  ;  cho dừng        setb p3.0
        clr p3.1
        clr p3.2
        setb p3.3
        clr p3.4
        clr p3.5
        jmp qua0  ; 
trở lại trình quét phím

cham_lai: ;  cho chậm lại         setb p3.0
        clr p3.1
        setb p3.3
        clr p3.4
        mov r4, #100
llai:   setb p3.2
        setb p3.5
        call delay
        clr p3.2
        clr p3.5
        call delay
        djnz r4, llai
        jmp qua0  ; 
trở lại trình quét phím

quay_trai: ; cho quay vòng qua trái         setb p3.0
        clr p3.1
        setb p3.2
        clr p3.3
        setb p3.4
        setb p3.5
        jmp qua0  ; 
trở lại trình quét phím

quay_phai: ; cho quay vòng qua phải          clr p3.0
        setb p3.1
        setb p3.2
        setb p3.3
        clr p3.4
        setb p3.5
        jmp qua0  ; 
trở lại trình quét phím

del:   ; đặt tên nhãn dùng cho lệnh nhẩy
      mov r3, # 10  ; nạp trị 10 vào thanh ghi r3
      mov r4, #200  ; nạp trị 200 vào thanh ghi r4
v_r4:   ; đặt tên nhãn dùng cho lệnh nhẩy
      djnz r4, $  ; giảm -1 đến khi trị trong r4 băng 0
      djnz r3, v_r4  ; giảm trị trong r3 theo bước -1, r3 0?, định hướng nhẩy
      ret  ; quay lại sau lệnh call del

delay:   ; đặt tên nhãn cho trình làm trể        mov r5, #100  ; 
nạp trị 100 vào thanh ghi r5
v_r6:   ; đặt tên nhãn dùng cho lệnh nhẩy
        mov r6, #250  ; nạp trị 250 vào thanh ghi r5        djnz r6, $ ; giảm theo bước -1 cho đến khi bằng 0 
        djnz r5, v_r6 ; giảm r5 theo bước -1, r5=0? chọn hướng nhẩy        ret   ; quay lại sau lệnh call delayend  ; dừng biên dịch tại dòng này 


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




2. Cách dùng phím kiểu ma trận 


Chúng ta sẽ viết chương trình nguồn cho kiểu bàn phím ma trận 4x4 như hình vẽ. 




 Trong bài thực hành này, chúng ta sẽ cho lấy mã có trong bảng xuất ra trên cảng p3 khi nhấn một trong các phím trên ma trận 4x4. 


org 0000h  ; Khởi đầu từ thanh nhớ 0000h    mov p2, #11111111b   ; đặt các chân Input lên 1k1:  ; tên nhãn    mov p1, #00000000b  ; đặt các chân Ouput xuống 0    mov a, p2  ; chuyển hiện trạng của p2 vào a    anl a, #00001111b  ; lấy logic AND để che 4 bit cao    cjne a, #00001111b, k1 ; kiểm tra xem có phím nhấn chưa?k2:  ; đặt tên nhãn    call delay  ; gọi chương trình trể tránh rung phím    mov a, p2  ; chuyển trạng thái p2 vào a    anl a, #00001111b  ; lấy logic AND che 4 bit cao    cjne a, #00001111b, tim_hang ; so sánh để nhẩy    jmp k2  ; nhẩy về k2tim_hang:  ; đặt tên nhãn    mov p1, #11111110b  ; đặt hàng 0, xuống bit 0    mov a, p2  ; chuyển p2 vào a    anl a, #00001111b  ; lấy logic AND, che 4 bit cao    cjne a, #00001111b, hang_0  ; so sánh để nhẩy ;
    mov p1, #11111101b ; đặt hàng 1, xuống bit 0    mov a, p2  ; chuyển p2 vào a    anl a, #00001111b  ; lấy logic AND, che 4 bit cao    cjne a, #00001111b, hang_1 ; so sánh để nhẩy ;
    mov p1, #11111011b ; đặt hàng 2, xuống bit 0    mov a, p2  ; chuyển p2 vào a    anl a, #00001111b  ; lấy logic AND, che 4 bit cao    cjne a, #00001111b, hang_2  ; so sánh để nhẩy ;
    mov p1, #11110111b  ; đặt hàng 3, xuống bit 0    mov a, p2  ; chuyển p2 vào a    anl a, #00001111b  ; lấy logic AND, che 4 bit cao    cjne a, #00001111b, hang_3  ; so sánh để nhẩy ;
hang_0:  ; tìm ra một trong 4 phím hàng 0    mov dptr, #m_hang_0
    jmp tim_phim  ; qua trình tìm phímhang_1:  ; tìm ra một trong 4 phím hàng 1    mov dptr, #m_hang_1
    jmp tim_phim  ; qua trình tìm phímhang_2:  ; tìm ra một trong 4 phím hàng 2    mov dptr, #m_hang_2
    jmp tim_phim  ; qua trình tìm phímhang_3:  ; tìm ra một trong 4 phím hàng 3    mov dptr, #m_hang_3
    jmp tim_phim     ; qua trình tìm phím ;
tim_phim:  ; đặt tên nhãn cho trình tìm phím    rrc a  ; cho 8 bit trong a quay vòng có qua bit cờ C    jnc out  ; kiểm tra bit 0 vào bit cờ C để nhẩy    inc dptr  ; cho tăng trị trong bảng lên một nhịp    jmp tim_phim  ; quay lại tên nhãn tim_phimout:  ; đặt tên nhãn    clr a ; xóa sạch trị trong thanh a    movc a, @a+dptr  ; lấy mã trong  bảng theo a và cất vào a    mov p3, a  ; chuyển kết quả ra cảng p3    jmp k1   ; nhẩy về k1m_hang_0:  ; đặt tên bảngdb 01h, 02h, 03h, 04h  ; mã trong bảng hàng 0m_hang_1: ; đặt tên bảngdb 05h, 06h, 07h, 08h  ; mã trong bảng hàng 1m_hang_2:  ; đặt tên bảngdb 09h, 0ah, 0bh, 0ch  ; mã trong bảng hàng 2m_hang_3:   ; đặt tên bảngdb 0dh, 0eh, 0fh, 00h  ; mã trong bảng hàng 3    
;
delay:  ; trình làm trể    mov r5, #100  ; đặt trị 100 vào thanh ghi r5v_r6:   
; đặt tên nhãn cho lệnh nhẩy
    mov r6, #100  ; đặt trị 100 vào thanh ghi r6    djnz r6, $  ; giảm theo bước -1 trị trong r6 cho đến khi bằng 0    djnz r5, v_r6  ; giảm trị trong r5 theo bước -1, r5=0?, chọn hướng nhẩy    ret  ; quay lại sau lệnh call delayend  ; dừng biên dịch tại dòng này

  
Giải thích cách dùng các câu lệnh trên:


Bước 1: viết trình dò xem có phím nào được nhấn xuống không. 




Bước 2: Dò có phím nhấn không, tránh ảnh hưởng của rung phím

 




Bước 3: Tìm xem phím trên hàng nào đã được nhấn xuống

 



Bước 4 và Bước 5: Tìm xem phím nào đã được nhấn xuống và xuất kết quả



Nhắn Bạn: Mã xuất theo phím nhấn đặt trong các bảng: m_hang_0, m_hang_1, m_hang_2 và m_hang_3. Vậy nếu Bạn muốn dùng các mã để điều khiển các thiết bị theo bảng 16 phím nhấn này, thì các mã điều khiển do Bạn tạo ra hãy cho cất trong các bảng theo đúng vị trí. Vậy, khi Bạn nhấn phím 0 sẽ có mã 0 xuất ra trên cảng p3, nhấn phím 1 sẽ có mã 1 xuất ra trên cảng p3, nhấn phím 2 sẽ có mã 2 xuất ra trên cảng p3....Bạn sẽ có 16 mã điều khiển ứng với 16 phím nhấn.

Nếu Bạn dùng ma trận 8 chân trên cảng p1 làm 8 hàng và dùng 8 chân trên cảng p2 làm 8 cột. Bạn sẽ có ma trận 8x8, trên ma trận này Bạn có thể gắn đến 64 phím nhấn và như vậy Bạn có thể có đến 64 mã lệnh dùng để điều khiển các thiết bị. Phải không?  



Mở rộng: Nhập tín hiệu vào ic lập trình lấy từ các bộ cảm biến

Chúng ta biết trong thiên nhiên có rất nhiều "thực thể" không thuộc điện, vậy nếu muốn đưa các "thực thể" này vào các ic lập trình, chúng ta phải dùng đến các sensor, quen gọi là các cảm biến. Phần tiếp theo chúng ta sẽ tìm hiểu một vài cảm biến thường dùng, dễ tìm, trong việc biến đổi các đại lượng không thuộc điện ra điện và tìm cách chuyển các đại lượng này vào ic lập trình để được xử lý.  


Trước hết, hãy nói đến cảm biến quang.

Chúng ta biết, ánh sáng là một thực thể rất phổ biến, chúng ta nhận biết ánh sáng bằng các tế bào thị giác đặt ở mắt. Trong kỹ thuật điện tử, người ta cũng chế tạo được nhiều bộ cảm biến có thể chuyển đổi ánh sáng ra dạng tín hiệu điện, như: quang trở, quang diode, pin quang điện... Ở đây chúng ta thử dùng quang cảm biến để tạo ra các tín hiệu cho nhập vài ic lập trình và viết các chương trình nguồn dùng để điều khiển các thiết bị theo quang năng  


Quang trở là một điện trở, nghĩa là nó có thể cho dòng điện chảy qua theo cả hai chiều như nhau, Bạn cũng có thể dùng quang trở kết hợp với các điện trở khác làm thành các cầu chia áp. Quang trở khi bị chiếu sáng sẽ giảm ohm, do vậy nó sẽ làm thay đổi cường độ dòng điện chảy qua nó. Trong các máy ảnh người ta thường dùng quang trở và máy đo dòng để làm thiết bị đo cường độ ánh sáng. Trong các TV đời mới, người ta dùng quang trở làm thiết bị tự động điều chỉnh mức sáng của màn hình tùy theo mức sáng của phòng. Trong các đầu dò PIR, người ta dùng quang trở để cho mở mạch tắt mở sáng mỗi khi trời về tối, người ta dùng quang trở với các kính lọc màu để làm các bộ cảm biến dò tìm màu...Bạn có thể dùng một Ohm kế thông thường để kiểm tra các quang trở. Khi đo ohm, nếu cho chiếu sáng, quang trở sẽ giảm ohm và khi bị che sáng quang trở sẽ tăng ohm.





Photo diode, hay diode hồng ngoại vốn là một mối nối bán dẫn PN, nó có đặc tính làm thay đổi cường độ dòng điện mỗi khi mối nối PN bị kích sáng. Trong mạch, photo diode thường cho ghép với một điện trở lớn ohm, nó đặt ở trạng thái phân cực nghịch. Khi bị che sáng, photo diode dẫn điện yếu và khi bị chiếu sáng, nó sẽ dẫn điện mạnh hơn. Ở trạng thái phân cực thuận, nó cũng có tính ghim áp như các diode thông thường khác. Photo diode có hoán tính nhỏ, cho thay đổi nhanh, nên người ta thích dùng photo diode trong các thiết bị điều khiển hồng ngoại, dùng trong các thiết bị điều khiển tốc độ quay của các motor, dùng trong mạch đo tốc. Bạn cũng có thể dùng ohm kế thông thường để kiểm tra các photo diode, dùng thang đo Rx10K, lúc này điện áp có trên 2 dây đo là 12V, đặt photo diode vào dây đo theo kiểu phân cực nghịch, dùng một hộp điều khiển Remote thông dụng, cho phát lệnh điều khiển, chiếu remote vào photo diode, Bạn sẽ thấy kim máy đo rung theo xung lệnh, dấu hiệu này cho biết photo diode còn tốt. Photo diode có rất nhiều trong các đầu máy hát băng hình.




Diode Laser, vốn là một mối nối bán dẫn PN, khi bị kích thích, cấp dòng, nó sẽ phát ra thứ ánh sáng Laser. Ánh sáng Laser khác với ánh sáng thường là các tia sáng phát ra có tính đồng pha, nghĩa là nó tác kích vào các vật cản với pha giống nhau, nhờ vậy khi Bạn cho hội tụ các chùm tia sáng Laser tại một điểm nhỏ, tại điểm này cường độ sáng vẫn sẽ rất mạnh và rất nóng (Điều này sẽ không làm được với loại ánh sáng thường), nên điểm hội tụ gọi là tiêu điểm (tiêu  có nghĩa là điểm nóng). Ngày nay người ta dùng điểm sáng Laser để đọc lại các điểm tín hiệu lồi lõm rất nhỏ đã đặt trên các vòng quay nằm trên các mặt đĩa CD hay DVD. Tia sáng Laser còn dùng làm tia chiếu định vị cho các máy ngắm, và với các chùm tia laser có cường độ mạnh, nó còn dùng làm vũ khí tấn công đốt cháy các vật bay. Bạn có thể dùng một Ohm kế thông thường để đo các diode Laser. Lấy thang đo Rx1 để có dòng chảy ra trên 2 dây đo lớn, trên 100mA, khi đo, diode Laser được cho phân cực thuận, bên trong sẽ ánh lên một điểm sáng màu đỏ rất nhỏ. Khi xử dụng các diode Laser, Bạn tránh nhìn thẳng vào tia sáng Laser vì mức sáng quá mạnh có thể làm hư mắt.



Opto là các bộ ghép quang điện. Người ta cho tổ hợp một bên là diode phát quang, phát ra tia sáng hồng ngoại và một bên là quang transistor dùng thâu nhận tia sáng hồng ngoại. Hai thành phần này có thể đặt trên hai mạch điện riêng biệt cách ly nhau, và trao đổi thông tin với nhau qua các tia sáng của bên phát và của bên nhận. Opto có 2 dạng: dạng đóng kín và dạng để hở. Dạng đóng kín thường dùng để trao đổi thông tin giữa các bo mạch, và dạng để hở thường dùng để phát hiện các vật thể, như: dò tìm vật quay, dò tìm các chuyển động, dò tìm các đường kẻ, dùng để đo tốc...Bạn có thể tìm thấy các loại opto có trong các mạch điều khiển và dĩ nhiên, Bạn cũng có thể dùng Ohm kế để đo kiểm tra các opto. Dùng tính thuận (kim lên) nghịch (kim không lên) để kiểm tra quang diode trong opto, rồi tìm cách cho cấp dòng qua quang diode, dùng ohm kế đo thuận nghịch trên quang transistor để kiểm tra bên nhận. 



 

Solar Cell hay pin mặt trời, là một bộ chuyển đổi năng lượng, nó chuyển đổi quang năng ra dạng điện năng. Khi trên mặt pin solar cell được chiếu sáng, trên các dây cực âm và dương sẽ xuất hiện điện áp, mức áp thường biến đổi theo cường độ sáng và tùy theo nội trở của tải. Trong ứng dụng người ta thường dùng pin mặt trời phát ra điện năng để nạp tích trữ vào các nguồn pin charge, và dùng nguồn pin này để thắp sáng hay làm quay các motor. Chúng ta thường thấy trên các máy tính số (calculator) có trang bị lá pin mặt trời để có thể vận hành trong các nguồn sáng trong phòng. Ngày nay, người ta có nhiều nghiên cứu về cách khai thác dùng năng lượng sạch, như nắng như gió, với nắng pin mặt trời là không thể thiếu được. Ngày mai, với các tấm pin hiệu suất cao, người ta sẽ có thể dùng điện lấy từ nguồn sáng tự nhiên, đó là ánh nắng vô tận của thái dương. Bạn hãy dùng một Volt kế thông thường để đo kiểm tra các Solar Cell, và dùng các Led để kiểm tra khả năng cấp tải của các pin mặt trời. 


Khảo sát: Cách dùng cảm biến quang điện để tạo xung nhịp đưa vào ic lập trình. 



Trong sơ đồ này chúng ta dùng bộ đếm của timer 0 chạy ở mode 2 để đếm xung nhịp đưa vào trên chân p3.4, tức chân T0, để đơn giản quá bài thực hành chúng ta chỉ dùng số đếm trong thanh tl0, nghĩa là đếm tối đa 255 nhịp và quay lại. Kết quả đếm sẽ cho hiển thị trên bảng đèn số dùng mã 7 đoạn.

Mạch dùng cảm biến quang điện, chúng ta dùng Led hồng ngoại cho chiếu sáng vào một quang transistor, bình thường quang transistor dẫn điện, nó kích dẫn Q1 và tạo mức áp cao trên chân T0, khi có người đi qua, tia sáng bị che và làm cho quang transistor ngưng dẫn, Q1 tắt và mức áp trên chân p3.4 giảm xuống mức áp 0V và lúc này xung nhịp vào thanh ghi tl0, thanh ghi tl0 sẽ tiếp tục tích cất số liệu này và luôn cho hiển thị kết quả con số có trong tl0 trên bảng đèn số.


Chương trình nguồn này đơn giản, dùng cho thực hành, tìm hiểu cách viết các câu lệnh cơ bản:


; Chú thích
; a,b,c,d,e,f,g -> Đèn số 7 đoạn trên Port 2
; P3.0 -> đèn LED1 hàng đơn vị  
; P3.1 -> đèn LED2 hàng chục
; P3.2 -> đèn LED3 hàng trăm
; P3.4(T0) -> cảm biến quang điện
; 30h  ; thanh ghi giữ số hàng đơn vi
; 31h  : thanh ghi giữ số hàng chục
; 32h  : thanh ghi giữ số hàng trăm

; Chỉ đếm với thanh tl0, trong đó hàng đơn vị đếm đến  10, hàng chục đến 5 hàng trăm đến 2.
 
ORG     0000h
        SJMP    MAIN
        
ORG     0030H
MAIN:  
        MOV     DPTR,#LED7SEG   ; vào bảng lấy mã hiện số trên đèn 7 đoạn        MOV     TMOD,#06h       ; counter 0, mode 2, đếm xung vào trên chân T0        
        MOV     TH0,#0C4H       ; nạp trị vào thanh th0        SETB    P3.0                  ; tắt đèn số hàng đơn vị        SETB    P3.1                  ; tắt đèn số hàng chục        SETB    P3.2                  ; tắt đèn số hàng trăm        SETB    P3.4             ; xung đếm vào ở chân này, T0        SETB    TR0             
; mở mạch cho xung đếm vào thanh ghi tl0
BEGIN:  
        MOV     A,TL0              ; cho chuyển trị trong tl0 vào thanh ghi a        CALL   BIN2BCD         ; gọi chương trình đổi số ra dạng thập phân        MOV     A,30h              ; chuyển trị có trong thanh 30h vào thanh ghi a 
        CJNE    A, #10,qua1 ; so sánh trị trong a với số 10, để định hướng nhẩy        MOV     A,#00H   ; trả trị trong a về 0qua1:   ; đặt tên nhãn cho lệnh nhẩy        MOVC    A,@A+DPTR  ; lấy trị trong bảng cho vào thanh ghi a        MOV     30h,A      ; cất trị trong a vào thanh 30h        MOV     A,31h      ; chuyển trị có trong thanh 31h vào thanh ghi a        CJNE    A,#6,qua2  ; so sánh trị trong a với số 6, để chọn hướng nhẩy         MOV     A,#00   ; trả trị trong a về 0qua2:  ; đặt tên nhãn cho lệnh nhẩy        MOVC    A,@A+DPTR  ; lấy trị trong bảng cho vào thanh ghi a        MOV     31h,A   ; cất trị trong a vào thanh 31h        MOV     A,32h   ; chuyển trị có trong thanh 32h vào thanh ghi a        CJNE    A,#1, qua3  ; so sánh trị trong a với số 1, để chọn hướng nhẩy        MOV     A,#00H  ; trả trị trong a về 0qua3:  ; đặt tên nhãn cho lệnh nhẩy        MOVC    A,@A+DPTR  ; lấy trị trong bảng cho vào thanh ghi a        MOV     32h,A  ; cất trị trong a vào thanh 32hKET_THUC:   ; đặt tên nhãn        CALL   DISPLAY ; cho gọi chương trình hiển thị số        JMP    BEGIN  ; trở lại tên nhãn beginDISPLAY:  ; trình hiển thị số trên bảng đèn        MOV     P1,30H          ; xuất trị trong thanh 30h ra cảng p1        CLR     P3.0                ; mở đèn hàng đơn vị        CALL   DELAY            ; gọi delay        SETB    P3.0               
; tắt đèn tránh lem
        MOV     P1,31H          ;  xuất trị trong thanh 31h ra cảng p1        CLR     P3.1                ; mở đèn Led hàng chục        CALL   DELAY            ; gọi delay        SETB    P3.1              ; tắt đèn tránh lem
        MOV     P1,32H          ; xuất trị trong thanh 32h ra cảng p1        CLR     P3.2                ; mở đèn Led hàng trăm        CALL   DELAY            ; gọi delay        SETB    P3.2               ; tắt đèn tránh lem        RET
BIN2BCD:  ; trình làm phép toán đổi trị nhị phân ra dạng số thập phân        MOV     B,#10           ;  đặt trị 10 vào thanh b, để làm phép toán chia 10        DIV     AB                   ; chia trị trong a cho 10        MOV     30h,B           ; cất kết quả trong b vào thanh 30h        MOV     B,#10           ; đặt trị 10 vào thanh b, để làm phép toán chia 10        DIV     AB                  ; chia trị trong a cho 10        MOV     31H,B          ; cất kết quả trong b vào thanh 31h        MOV     32h,A           ; cất kết quả trong a vào 32h        RET                          ; quay lại sau lệnh gọi call bin2bcdDELAY:   ; đặt tên nhãn cho lệnh nhẩy        MOV     R6,#10   ; nạp trị 10 vào thanh ghi r6v_r7:
        MOV     R7,#0FFh ; nạp trị 0ffh vào thanh ghi r7        DJNZ    R7, $        ; cho trị trong r7 giảm theo bước -1 đến lúc bằng 0         DJNZ    R6, v_r7  ; cho trị trong r6 giảm theo bước -1, r6=0?, định hướng nhẩy        RET      ; quay lại sau lệnh call delay Bảng tạo mã hiện số trên đèn Led 7 đoạnLED7SEG:   ; mã 7 đoạn cho hiện các số 0, 1, 2, 3, 4, 5, 6, 7, 8, 9DB      0C0H,0F9H,0A4H,0B0H,99H,92H,82H,0F8H,80H,90H
END            
 ; dừng biên dịch tại dòng này



Phân tích ý nghĩa các câu lệnh trong chương trình nguồn trên: 

 




Tạm kết

Khi viết đến đây, tôi mời một đồng nghiệp vào xem thử, anh nói bài viết quá dài đọc thấy mệt, tôi cũng cảm thấy như vậy, nên cho dừng ở đây. Phần viết mở rộng nói về cách dùng các dạng cảm biến sẽ được viết lại trong một bài khác. Chúng ta chuyển qua một đề tài khác cũng cơ bản và cần thiết cho dân điện tử, đó là: "Thử dùng trình PSpice để mô phỏng nguyên lý làm việc của một mạch nâng áp dạng xung". 

Ứng dụng ic lập trình AT89C51: Đồng hồ có hẹn giờ mở và giờ tắt


 Rất vui khi thấy   Bạn vào xem...






Mạch điện đồng hồ có hẹn giờ dùng ic lập trình AT89C51


  

Trước hết hãy tìm hiểu cách cho hiển thị các số dùng mã quét trên các chân Anode của các đèn số dùng mã 7 đoạn và sơ đồ mạch điện đồng hồ dùng để chạy đoạn chương trình nguồn sau đây:



 

Tất cả các linh kiện cho ráp trên một bảng mạch in nhỏ. Trên đó dùng 6 đèn số mã 7 đoạn để hiển thị giờ - phút - giây.



Sơ đồ mạch điện cho thấy, chúng ta dùng các xung ra ứng với bit 0, tuần tự cho ra trên các chân của các chân p2.0, p2.1, p2.2, p2.3, p2.4 và p2.5 để lần lượt cho chân anode của các đèn số nối lên nguồn 5V, như vậy trong một lúc chỉ có một đèn số phát sáng, với nhịp xung quay vòng nhanh và do mắt có hiện tượng lưu ảnh, chúng ta có cảm tưởng là 6 đèn Led cùng được kích sáng.

Chúng ta dùng 7 chân của cảng p1 để cho xuất các con số theo dạng mã 7 đoạn. Muốn Led nào sáng, chúng ta đặt bit 0 vào chân cathode của nó, vậy bit 1 tắt Led và bit 0 cấp dòng cho Led sáng. Theo sơ đồ chúng ta thấy:

Chân p1.0 kiểm soát dòng cấp cho Led-a trong đèn số. 
Chân p1.1 kiểm soát dòng cấp cho Led-b trong đèn số. 
Chân p1.2 kiểm soát dòng cấp cho Led-c trong đèn số. 
Chân p1.3 kiểm soát dòng cấp cho Led-d trong đèn số. 
Chân p1.4 kiểm soát dòng cấp cho Led-e trong đèn số. 
Chân p1.5 kiểm soát dòng cấp cho Led-f trong đèn số. 
Chân p1.6 kiểm soát dòng cấp cho Led-g trong đèn số. 

Sau khi đã chọn định phân cứng như sơ đồ mạch điện trên, chúng ta sẽ định ra được các dạng mã bit để tuần tự cho hiện các con số: 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 trên các đèn số mã 7 đoạn.


tab:    ; Các mã dùng để hiện số trên đèn 7 đoạn đặt trong bảng có tên nhãn là tab:
db 0c0h, 0f9h, 0a4h, 0b0h, 99h, 92h, 82h, 0f8h, 80h, 90h    ; các mã hiện số viết theo dạng hệ 16.



Để dễ thấy ý nghĩa vật lý chúng ta sẽ viết lại các mã hệ 16 ở dạng mã hệ cơ 2 theo trọng giá  8-4-2-1.


* 0c0h,   viết lại ở dạng mã hệ cơ 2: 1100 0000b ứng với số 0
* 0f9h,    viết lại ở dạng mã hệ cơ 2: 1111 1001b ứng với số 1
* 0a4h,   viết lại ở dạng mã hệ cơ 2: 1010 0100b ứng với số 2
* 0b0h,   viết lại ở dạng mã hệ cơ 2: 1011 0000b ứng với số 3
* 99h,     viết lại ở dạng mã hệ cơ 2: 1001 1001b ứng với số 4
* 92h,     viết lại ở dạng mã hệ cơ 2: 1001 0010b ứng với số 5
* 82h,     viết lại ở dạng mã hệ cơ 2: 1000 0010b ứng với số 6
* 0f8h,    viết lại ở dạng mã hệ cơ 2: 1111 1000b ứng với số 7
* 80h,     viết lại ở dạng mã hệ cơ 2: 1000 0000b ứng với số 8
* 90h,     viết lại ở dạng mã hệ cơ 2: 1001 0000b ứng với số 9



 Tìm hiểu tác dụng của các nút nhấn và các led chỉ thị trạng thái:

 



Dùng hình động để giải thích hoạt động của đèn số dùng mã 7 đoạn:


Cách cho xuất số liệu trên mã 7 đoạn, để hiện các số 0, 1, 2, 3, 4, 5, 6, 7, 8, 9.



Cách dùng mã quét quay vòng, mỗi lần chỉ có một đèn số phát sáng:







Cách dùng MIDE-51 cho biên dịch đoạn chương trình nguồn sau đây ra dạng mã lệnh:



 



Sau khi biên dịch thành công, chúng ta có các dòng mã lệnh như sau: 

:020000000130CD
:0200030021B921
:02000B0001E30F
:10003000758150C20075210075220075230075245A
:1000400000752500752600752700752800752900A4
:10005000758C05758A05758902D2AFD2A8C2A9C26E
:100060008CC288E523B52609E524B52704D2B7015B
:100070007DE523B52807E524B52902C2B73000E3A2
:10008000118E0163C0F9A4B0999282F88090A823E0
:10009000900084E8C4540F93F590C2A0319FD2A081
:1000A000E8540F93F590C2A1319FD2A1A924E9C4CD
:1000B000540F93F590C2A2319FD2A2E9540F93F549
:1000C00090C2A3319FD2A3AA25EAC4540F93F590FE
:1000D000C2A4319FD2A4EA540F93F590C2A5319FD8
:1000E000D2A522C0E0C0D00521E521B4C8387521D1
:1000F000000522E522B40A2E752200B280B2817476
:10010000012525D4F525B4601D752500740125242D
:10011000D4F524B4601075240074012523D4F5238C
:10012000B42403752300D0D0D0E032A826900084F8
:10013000E8C4540F93F590C2A0319FD2A0E8540FA9
:1001400093F590C2A1319FD2A1A927E9C4540F937E
:10015000F590C2A2319FD2A2E9540F93F590C2A3A9
:10016000319FD2A322A828900084E8C4540F93F5AD
:1001700090C2A0319FD2A0E8540F93F590C2A13154
:100180009FD2A1A929E9C4540F93F590C2A2319F2F
:10019000D2A2E9540F93F590C2A3319FD2A3227546
:1001A00030027531FFD531FDD530F72275326475D7
:1001B00033FAD533FDD532F722C0E0C0D0C2A8C291
:1001C0008CC2A9118E20B2FB118E30B2FBD2B1D2FB
:1001D000B0118E20B413118E30B4FBA82374012803
:1001E000D4F523B424EB75230020B313118E30B360
:1001F000FBA824740128D4F524B460D5752400200C
:10020000B507118E30B5FB418720B2C5118E30B2D3
:10021000FBC2B0D2B1312B20B413312B30B4FBA8C8
:1002200026740128D4F526B424EB75260020B313D8
:10023000312B30B3FBA827740128D4F527B460D53F
:1002400075270020B2CF312B30B2FBD2B0C2B13112
:100250006520B413316530B4FBA828740128D4F5A7
:1002600028B424EB75280020B313316530B3FBA804
:1002700029740128D4F529B460D575290020B2CF9E
:10028000316530B2FB21CDD2A8D28CD200D2A9D216
:06029000B7D0D0D0E0322F
:00000001FF



Bây giờ Bạn dùng hộp nạp, cho nạp các dòng mã lệnh này vào bộ nhớ EEPROM của ic lập trình AT89C51, gắn IC này vào mạch điện, Bạn sẽ có một đồng hồ có chức năng chỉnh giờ mở giờ tắt và có thể dùng chân p3.7 để điều khiển các thiết bị điện tử kh́ac.


Đây là chương trình nguồn của mạch điện đồng hồ có hẹn, Bạn có thể cắt chương trình này dán vào vùng soạn thảo của MIDE-51 gõ phím F9 để cho dịch ra file .hex, và nạp các dòng mã lệnh này vào bộ nhớ EEPROM nằm trong ic lập trình AT89C51 để làm mạch điện đồng hồ có hẹn. Bạn xem phần giải thích cách dùng các câu lệnh ở phần bên dưới. 


;; Dong ho co nut chinh mo chinh tat
;;------------------------------------------
k1 bit p3.2
k2 bit p3.4
k3 bit p3.3
k4 bit p3.5
c_hour equ 23h
c_minute equ 24h
c_second equ 25h
on_hour equ 26h
on_minute equ 27h
off_hour equ 28h
off_minute equ 29h
org 0000h
jmp main
org 0003h
jmp wint0
org 000bh
jmp wt0
org 0030h
main:
mov sp, #50h
clr 00h
mov 21h, #0
mov 22h, #0
mov c_hour, #0
mov c_minute, #0
mov c_second, #0
mov on_hour, #0
mov on_minute, #0
mov off_hour, #0
mov off_minute, #0
;;
mov th0, #05
mov tl0, #05
mov tmod, #00000010b ;02h
;;
setb ea
setb ex0
clr et0
clr tr0
clr it0
m:
mov a, c_hour
cjne a, on_hour, off_time
mov a, c_minute
cjne a, on_minute, off_time
setb p3.7
jmp next
off_time:
mov a, c_hour
cjne a, off_hour, next
mov a, c_minute
cjne a, off_minute, next
clr p3.7
next: jnb 00h, m
call disp1
jmp m
;;
tab:
db 0c0h, 0f9h, 0a4h, 0b0h, 99h, 92h, 82h, 0f8h, 80h
db 90h
;;
disp1:
mov r0, c_hour
mov dptr, #tab
mov a, r0
swap a
anl a, #0fh
movc a, @a+dptr
mov p1, a
clr p2.0
call dl
setb p2.0
mov a, r0
anl a, #0fh
movc a, @a+dptr
mov p1, a
clr p2.1
call dl
setb p2.1
;;
mov r1, c_minute
mov a, r1
swap a
anl a, #0fh
movc a, @a+dptr
mov p1, a
clr p2.2
call dl
setb p2.2
mov a, r1
anl a, #0fh
movc a, @a+dptr
mov p1, a
clr p2.3
call dl
setb p2.3
;;
mov r2, c_second
mov a, r2
swap a
anl a, #0fh
movc a, @a+dptr
mov p1, a
clr p2.4
call dl
setb p2.4
mov a, r2
anl a, #0fh
movc a, @a+dptr
mov p1, a
clr p2.5
call dl
setb p2.5
ret
;;
wt0:
push acc
push psw
inc 21h
mov a, 21h
cjne a, 0c8h, t0reti ; 200d=0c8h 0.5ms*200=100ms
mov 21h, #0
inc 22h
mov a, 22h
cjne a, #10, t0reti ; 100ms*10=1s
mov 22h, #0
cpl p0.0
cpl p0.1
;;
mov a, #01h
add a, c_second
da a
mov c_second, a
cjne a, #60h, t0reti
mov c_second, #0
;;
mov a, #01h
add a, c_minute
da a
mov c_minute, a
cjne a, #60h, t0reti
mov c_minute, #0
;;
mov a, #01h
add a, c_hour
da a
mov c_hour, a
cjne a, #24h, t0reti
mov c_hour, #0
;;
t0reti:
pop psw
pop acc
reti
;;
disp2:
mov r0, on_hour
mov dptr, #tab
mov a, r0
swap a
anl a, #0fh
movc a, @a+dptr
mov p1, a
clr p2.0
call dl
setb p2.0
mov a, r0
anl a, #0fh
movc a, @a+dptr
mov p1, a
clr p2.1
call dl
setb p2.1
;;
mov r1, on_minute
mov a, r1
swap a
anl a, #0fh
movc a, @a+dptr
mov p1, a
clr p2.2
call dl
setb p2.2
mov a, r1
anl a, #0fh
movc a, @a+dptr
mov p1, a
clr p2.3
call dl
setb p2.3
ret
;;
disp3:
mov r0, off_hour
mov dptr, #tab
mov a, r0
swap a
anl a, #0fh
movc a, @a+dptr
mov p1, a
clr p2.0
call dl
setb p2.0
mov a, r0
anl a, #0fh
movc a, @a+dptr
mov p1, a
clr p2.1
call dl
setb p2.1
;;
mov r1, off_minute
mov a, r1
swap a
anl a, #0fh
movc a, @a+dptr
mov p1, a
clr p2.2
call dl
setb p2.2
mov a, r1
anl a, #0fh
movc a, @a+dptr
mov p1, a
clr p2.3
call dl
setb p2.3
ret
;;
dl:
mov 30h, #02h
dl1: mov 31h, #0ffh
djnz 31h, $
djnz 30h, dl1
ret
;;
del:
mov 32h, #100
del1: mov 33h, #250
djnz 33h, $
djnz 32h, del1
ret
;;
wint0:
push acc
push psw
clr ex0
clr tr0
clr et0
k1_11:
call disp1
jb k1, k1_11
k11_1:
call disp1
jnb k1, k11_1
;;
ph4:
setb p3.1
setb p3.0
ph0: call disp1
jb k2, ph01
;;
k2_1:
call disp1
jnb k2, k2_1
mov r0, c_hour
mov a, #01h
add a, r0
da a
mov c_hour, a
cjne a, #24h, ph0
mov c_hour, #0
ph01:
jb k3, ph1
k3_1:
call disp1
jnb k3, k3_1
mov r0, c_minute
mov a, #01h
add a, r0
da a
mov c_minute, a
cjne a, #60h, ph0
mov c_minute, #0
ph1:
jb k4, ph10
k4_1:
call disp1
jnb k4, k4_1
jmp tend
ph10:
jb k1, ph0
k1_1:
call disp1
jnb k1, k1_1
clr p3.0
setb p3.1
;;--------------------------------
ph2:
call disp2
jb k2, ph201
k22_1:
call disp2
jnb k2, k22_1
mov r0, on_hour
mov a, #01h
add a, r0
da a
mov on_hour, a
cjne a, #24h, ph2
mov on_hour, #0
ph201:
jb k3, ph210
k22_2:
call disp2
jnb k3, k22_2
mov r0, on_minute
mov a, #01h
add a, r0
da a
mov on_minute, a
cjne a, #60h, ph2
mov on_minute, #0
ph210: jb k1, ph2
k22_3:
call disp2
jnb k1, k22_3
setb p3.0
clr p3.1
;;----------------------------------------
ph3:
call disp3
jb k2, ph301
k33_1:
call disp3
jnb k2, k33_1
mov r0, off_hour
mov a, #01h
add a, r0
da a
mov off_hour, a
cjne a, #24h, ph3
mov off_hour, #0
ph301:
jb k3, ph310
k33_2:
call disp3
jnb k3, k33_2
mov r0, off_minute
mov a, #01h
add a, r0
da a
mov off_minute, a
cjne a, #60h, ph3
mov off_minute, #0
ph310: jb k1, ph3
k33_3:
call disp3
jnb k1, k33_3
jmp ph4
;;----------------------------------------
tend:
setb ex0
setb tr0
setb 00h
setb et0
setb p3.7
pop psw
pop acc
reti
end




Phân tích ý nghĩa và cách dùng của các câu lệnh trong chương trình nguồn:



1. Khởi đầu Bạn dùng các định nghĩa bit và equ để đặt tên cho các bit và thanh ghi để tiện dụng.

;; Dong ho co nut chinh mo chinh tat
;;------------------------------------------

; đặt tên cho các nút nhấn
k1 bit p3.2   ; đặt tên chân p3.2 là k1
k2 bit p3.4   ; như trên
k3 bit p3.3   ; như trên 
k4 bit p3.5   ; như trên


; đặt tên các thanh nhớ dùng cất các con số chỉ giờ-phút- giây 
c_hour equ 23h     ; đặt tên cho thanh nhớ có địa chỉ 23h là c_hour
c_minute equ 24h  ; làm như trên
c_second equ 25h ; làm như trên 


; đặt tên cho các thanh nhớ dùng cất số giờ cho mở
on_hour equ 26h   ; làm như trên
on_minute equ 27h ; làm như trên


; đặt tên cho các thanh nhớ dùng cất số giờ cho tắt
off_hour equ 28h  ; làm như trên
off_minute equ 29h  ; làm như trên



2. Cho chương trình khởi đầu từ thanh reset, có địa chỉ 0000h. 

; Vào chương trình 
org 0000h
jmp main  ; cho nhẩy đến tên nhãn main, nhẩy qua các thanh dùng cho ngắt


3. Đặt các chương trình cho các dạng ngắt

org 0003h ; ngắt theo bit trên INT0
jmp wint0  ; nhẩy đến tên nhãn wint0
org 000bh ; ngắt theo bit TF0, bit trang của Timer10
jmp wt0   ; nhẩy đến tên nhãn wt0


org 0030h  ; Các chương trình điều khiển đồng hồ khởi từ địa chỉ này
main:   ; tên nhãn dùng cho lệnh nhẩy
mov sp, #50h  định địa chỉ cho ngăn xếp
clr 00h     ; cho xóa bit có địa chỉ 00h


; Đặt trị khởi đầu cho các thanh ghi dùng hiển thị giờ-phút-giây
mov 21h, #0   ; trị khởi đầu đặt số 0 vào thanh ghi 21h
mov 22h, #0  ; làm như trên
mov c_hour, #0 ; làm như trên
mov c_minute, #0  ; làm như trên
mov c_second, #0  ; làm như trên
mov on_hour, #0  ; làm như trên
mov on_minute, #0 ; làm như trên
mov off_hour, #0  ; làm như trên
mov off_minute, #0 ; làm như trên


; Khai báo các trị cho Timer 0
mov th0, #05 ; nạp trị khởi đầu cho thanh đếm 8 bit th0
mov tl0, #05  ; nạp trị khởi đầu cho thanh đếm 8 bit tl0
mov tmod, #00000010b ; chọn định cho timer 0 làm việc ở mode 2

Để hiểu rõ hơn hoạt động của các timer trong AT89C51, Bạn xem hình sau:


  

Trong thanh tmod, có 2 bit dùng để chọn mode cho các đồng hồ timer trong AT89C51.

Nếu Bạn chọn:

M1 = 0 , M0 = 0 là cho timer chạy ở mode 0, mode dùng thanh đếm 13 bit
M1 = 0 , M0 = 1 là cho timer chạy ở mode 1, mode dùng thanh đếm 16 bit
M1 = 1 , M0 = 0 là cho timer chạy ở mode 2, mode dùng thanh đếm 8 bit
M1 = 1 , M0 = 1 là cho timer chạy ở mode 3, mode hổn hợp.

Với dòng khai báo trong thanh tmod là 00000010b thì chúng ta chọn timer 0 cho làm việc ở mode 2, tức dùng thanh tl0 làm thanh đếm 8 bit. Khi thanh tl0 đếm đến tràn số, bit báo tràn tf0sẽ nhẩy lên 1. Nó sẽ có 2 tác dụng.

* Tác dụng thứ nhất: là cho trị trong tl0 về 0 và đồng thời lấy trị có trong th0 cho nạp vào thanh tl0.
* Tác dụng thứ hai: là nhẩy ngắt theo bit tf0. Chương trình nhẩy về địa chỉ 000bh của bộ nhớ 


Hình vẽ trên cho thấy hoạt động của Timer 0 (giải thích tương tự cho Timer 1) như sau: Trong AT89C51 có mạch dao động tạo ra xung nhịp, tần số xung lấy theo thạnh anh trên chân 18, 19. Xung này có thể đưa vào bộ đếm của các timer, Bạn cũng có thể lấy xung ngoài đưa vào thanh đếm trên chân T0 hay chân p3.4. Để cho xung nhịp đưa vào thanh đếm, Bạn hãy định  bit cho C/T đảo, nếu định nó là bit 1 thì mạch đếm sẽ lấy xung ngoài đưa vào trên chân T0, nếu định là bit 0 thì mạch đếm sẽ lấy xung của mạch dao động nội. Xung nhịp trước khi vào bộ đếm còn phải qua một khóa điện, khóa điện này chịu điều khiển theo các bit sau:

* Bit tr0, nếu cho tr0 được định ở bit 1, khóa điện sẽ đóng lại và nếu tr0 ở bit 0 nó sẽ làm hở khóa điện và cắt xung nhịp không cho vào thanh đếm.

* Bit INT0 đảo, khi bit Gate chọn ở bit 1 thì ngắt ngoài INT0 sẽ có tác dụng đến mạch đếm, khi INT0 là bit 1 nó cho đếm và khi INT0 ở bit 0, nó sẽ ngắt mạch đếm. Khi bit Gate chọn ở bit 0 thì ngắt ngoài trên chân INT0 sẽ mất tác dụng.

Tóm lại, nếu Bạn không dùng ngắt ngoài INT0 thì đặt bit Gate ở mức bit 0. Lúc này dùng bit tr0 để đóng mở mạch đếm. Nghĩa là:

setb tr0 là cho xung nhịp vào bộ đếm của timer 0
clr tr0 là ngắt xung nhịp không cho vào bộ đếm của timer0
  

; Khai báo chọn dạng ngắt và điều khiển hoạt động của timer 0.
 setb ea  ; bit ea dùng tắt/mở 6 dạng ngắt trong AT89C51, set cho dùng ngắt
setb ex0 ; đặt ex0 = 1 là cho dùng ngắt ngoài trên chân INT0
clr et0   ; tạm thời cho tắt ngắt theo bit báo tràn tf0
clr tr0    ; tạm thời cho tắt xung nhịp vào bộ đếm tl0, tắt time 0
clr it0    ; chọn hình thức ngắt theo mức volt thấp của ngắt ngoài INT0

Muốn hiều rõ vai trò của các ngắt trong AT89C51, chúng ta xem hình vẽ sau:

 

Chức năng Ngắt là gì?

Ngắt là một chức năng rất hay của các ic lập trình, khi Bạn đã chọn dấu hiệu nhẩy ngắt, tức chọn kiểu ngắt, không cần biết chương trình của Bạn lúc này đang làm gì, mỗi khi xuất hiện dấu hiện báo ngắt, chương trình đang chạy sẽ dừng lại và cho nhẩy đến địa chỉ đã qui định của các ngắt để chạy chương trình ngắt, cho đến khi gặp câu lệnh reti thì kết thúc chương trình ngắt và quay trở lại tiếp tục làm công việc đã tạm dừng trước đó. Thí dụ:

Bạn đã chọn dạng ngắt theo bit báo tràn của timer 0, đó là bit tf0. Khi timer 0 đang đếm xung nhịp, xung vào các thanh đếm tl0, th0, bit tf0 đã cho ở bit 0 với câu lệnh clr tf0, khi các thanh đếm tràn số thì bit tf0 sẽ nhẩy lên bit 1 và lúc này ngắt tf0 sẽ bị kích hoạt, nó tạm dừng chương trình đang chạy, nhẩy về địa chỉ 000bh và chạy chương trình có ở địa chỉ này, cho đến khi gặp câu lệnh reti, nó sẽ ngưng chạy chương trình ngắt và quay lại tiếp tục chạy chương trình đã tạm dừng trước đó.



4. Cho kiểm tra với các trị đã định trước

; Cho kiểm tra trị trong các vùng nhớ off_timer và on_timer
m:  ; đặt tên nhãn m:
mov a, c_hour ; chuyển trị trong c_hour vào a
cjne a, on_hour, off_time ; cho so sánh trị trong on_hour và a để chọn kiểu nhẩy
mov a, c_minute ; chuyển trị trong c_minute vào a
cjne a, on_minute, off_time ; cho so sánh trị trong on_minute với a để chọn kiểu nhẩy
setb p3.7 ; đặt bit điều khiển trạng thái trên chân p3.7 lên mức áp cao
jmp next ; cho nhẩy đến tên nhãn next:
off_time: ; đặt tên nhãn off_time
mov a, c_hour ; chuyển trị trong c_hour vào a
cjne a, off_hour, next ; cho so sánh trị trong off_hour và a để chọn kiểu nhẩy
mov a, c_minute ; chuyển trị trong c_minute vào a
cjne a, off_minute, next ; so sánh trị trong off_minute và a để chọn kiểu nhẩy
clr p3.7 ; đặt bit trên chân p3.7 xuống mức áp thấp
next: jnb 00h, m ; cho nhẩy theo bit kiểm tra 00h
call disp1  ; cho gọi trình hiển thị số
jmp m  ; nhẩy về tên nhãn m:


Ý nghĩa của đoạn chương trình trên là cho kiểm tra trị có trong c_hour và c_minute với các trị đã có trong on_hour, on_minute và off_hour, off_minute để điều khiển trạng thái bit p3.7. Ở đây Bạn chú ý cách dùng câu lệnh cjne (compare jump no equal), một câu lệnh dùng phép so sánh 2 trị xem bằng hay không bằng để chọn kiểu nhẩy, đây là một lệnh rất hay. Cũng chú ý đến bit kiểm tra có địa chỉ bit được chọn là 00h

 ; tạo bảng để cất các trị dùng làm hiện các số mã thập phân trên các Led 7 đoạn 
tab:   ; đặt tên nhãn
db 0c0h, 0f9h, 0a4h, 0b0h, 99h, 92h, 82h, 0f8h, 80h, 90h  ; mã hiện số khi cho xuất trên cảng p1


Bạn xem phần giải thích cách cho hiện các số trên các đèn số dùng mã 7 đoạn


5. Viết chương trình hiển thị số 

; đây là đoạn chương trình dùng hiển thị số lên bảng đèn số

; Viết chương trình hiển thị giờ (hour)
disp1:   ; đặt tên nhãn hiện số là disp1:
mov r0, c_hour ; chuyển trị trong c_hour vào r0
mov dptr, #tab ; đặt bảng tra mã con số vào thanh ghi con trỏ
mov a, r0  ; chuyển trị trong r0 vào a
swap a  ; cho đảo vị trí 4 bit cao / thấp trong thanh a
anl a, #0fh  ; lấy logic and để che 4 bit cao, giữ nguyên trị ở 4 bit thấp
movc a, @a+dptr  ; lấy trị trong bảng hiện số gắn vào a
mov p1, a  ; cho xuất trị trong a ra cảng p1 để hiện số
clr p2.0  ; đặt chân p2.0 xuống mức thấp để mở đèn số này
call dl  ; gọi chương trình làm chậm dl: để tạo mức sáng cho con số
setb p2.0  ; tắt đèn số đã mở trước khi mở qua đèn số khác
mov a, r0 ; chuyển trị còn trong r0 vào a
anl a, #0fh  ; dùng logic and để che 4 bit cao, giữ nguyên 4 bit thấp
movc a, @a+dptr  ; truy bảng lấy mã hiện số chuyển vào a
mov p1, a  ; lại cho xuất mã con số trong a ra cảng p1
clr p2.1  ; đặt chân p2.1 xuống mức áp thấp để mở đèn số
call dl  ; cho làm chậm để có mức sáng tốt
setb p2.1 ; đặt chân p2.1 lên cao để tắt đèn số này tránh lem số


; Viết chương trình hiển thị các con số chỉ phút (minute)
; Bạn xem cách viết tương tự như phần trên
mov r1, c_minute
mov a, r1
swap a
anl a, #0fh
movc a, @a+dptr
mov p1, a
clr p2.2
call dl
setb p2.2
mov a, r1
anl a, #0fh
movc a, @a+dptr
mov p1, a
clr p2.3
call dl
setb p2.3


; Viết chương trình cho hiển thị giây ̣(second)
; Bạn xem cách viết tương tự như phần trên. 
mov r2, c_second
mov a, r2
swap a
anl a, #0fh
movc a, @a+dptr
mov p1, a
clr p2.4
call dl
setb p2.4
mov a, r2
anl a, #0fh
movc a, @a+dptr
mov p1, a
clr p2.5
call dl
setb p2.5
ret

Trong các câu lệnh trên có nhiều câu lệnh dùng rất hay, như:

* Trong thanh đếm 8 bit, 4 bit cao có thể là hàng chục và 4 bit thấp là hàng đơn vị, trong trường hợp này Bạn dùng lệnh swap  a để chuyển đổi vị trí của 4 bit thấp lên cao và cao qua thấp.

* Muốn lấy trị thập phân có trên 4 bit thấp chúng ta có thể cho 4 bit cao đều bằng 0, và cho bảo toàn trị của 4 bit thấp, muốn vậy, chúng ta dùng logic and, câu lệnh anl a, #0fh (00001111b). 

* Để lấy các số mã có trong bảng với tên nhãn là tab: , chúng ta dùng câu lệnh: movc a, @a+dptr. Trước đó trong a chứa trị thập phân ở dạng cơ 2, từ trị này sẽ tìm ra được mã của con số có trong bảng tra tab:, và mã này được lấy ra và rồi cũng cho cất vào a, để sau đó sẽ cho xuất ra trên cảng p1.


6. Đoạn chương trình dùng cho mạch đếm theo bước tăng 1

; đây là chương trình ngắt mỗi khi xuất hiện bit báo tràn tf0
wt0:   ; đặt tên nhã wt0
push acc  ; tạm cho cất trị của a vào ngăn xếp, để mượn dùng a
push psw  ; tạm cho cất trị trong thanh psw vào ngăn xếp
inc 21h  ; cho tăng trị có trong thanh 21h lên +1
mov a, 21h  ; cho chuyển trị của thanh 21h vào a
cjne a, 0c8h, t0reti ; 200d=0c8h 0.5ms*200=100ms ; so sánh trị trong a bằng 0c8h chưa để nhẩy đến tắt ngắt
mov 21h, #0 ; trả trị trong thanh 21h trở về 0
inc 22h  ; bây giờ cho tăng trị trong thanh 22h
mov a, 22h  ; cũng chuyển trị trong thanh 22h vào a
cjne a, #10, t0reti ; 100ms*10=1s  ; lại so sánh trị trong a với trị 10, để nhẩy đến tắt ngắt
mov 22h, #0 ; lại trả trị trong 22h về mức đếm 0
cpl p0.0  ; lấy bù bit trên chân p0.0, có thể gắn led trên chân này để hiển thị trang thái đếm
cpl p0.1 ; lấy bù bit trên chân p0.1, có thể gắn led trên chân này để hiển thị trang thái đếm


7. Tạo trị tăng trong các thanh nhớ c_second, c_minute, c_hour 


;;
mov a, #01h ; cho trị 1 vào thanh a
add a, c_second ; cho cộng trị trong a với trị trong c_second, kết quả cất vào a
da a ; biến đổi tạo trị thập phân dạng cơ 2 đặt trong vùng 4 bit thấp, 4 bit cao
mov c_second, a  ; chuyển trị có trong a cất vào c_second
cjne a, #60h, t0reti  ; so sánh trị trong a bằng 60 chưa để chọn hướng nhẩy
mov c_second, #0 ; trả trị trong c_second về lại mức 0.


;;
mov a, #01h  ; đặt trị 1 vào thanh a
add a, c_minute ; cho cộng trị trong a và trị của c_minute, kết quả cất vào a
da a  ; biến đổi trị trong a ra số hệ thập phân dạng cơ 2, đặt trong 4 bit thấp và 4 bit cao
mov c_minute, a ; chuyển trị trong a vào cất trong c_minute
cjne a, #60h, t0reti  ; cho a so sánh với trị 60 để chọn hướng nhẩy
mov c_minute, #0  ; trả trị trong c_minute về lại mức 0


;;
mov a, #01h  ; đặt trị 1 vào thanh a
add a, c_hour  ; cho cộng trị trong a và trị của c_hour, kết quả cất vào a
da a  ; biến đổi trị trong a ra dạng số thập phân hệ cơ 2, cất ở vùng 4 bit thấp và 4 bit cao
mov c_hour, a  ; chuyển trị trong a vào cất trong c_hour
cjne a, #24h, t0reti ; so sánh trị trong a với số 24, để chọn hướng nhẩy
mov c_hour, #0  ; trả trị trong c_hour về lại mức 0


;;
t0reti:   ; đặt tên nhãn để dừng chạy chương trình ngắt
pop psw  ; lấy trị đã cất trong ngăn xếp  trả lại cho thanh psw
pop acc  ; lấy trị đã cất trong ngăn xếp tra lại thanh a
reti   ; dừng chạy chương trình ngắt, quay lại chạy chương trình chính


8. Viết chương trình hiển thị số cho mode chỉnh giờ


; Hiện số lúc đang chỉnh định hẹn giờ mở
; Tham khảo chương hình hiện giờ lúc bình thường
;;
disp2:  ; tên nhãn dùng cho lệnh nhẩy
mov r0, on_hour
mov dptr, #tab
mov a, r0
swap a
anl a, #0fh
movc a, @a+dptr
mov p1, a
clr p2.0
call dl
setb p2.0
mov a, r0
anl a, #0fh
movc a, @a+dptr
mov p1, a
clr p2.1
call dl
setb p2.1


;;
mov r1, on_minute
mov a, r1
swap a
anl a, #0fh
movc a, @a+dptr
mov p1, a
clr p2.2
call dl
setb p2.2
mov a, r1
anl a, #0fh
movc a, @a+dptr
mov p1, a
clr p2.3
call dl
setb p2.3
ret

; Hiện số lúc đang chỉnh định hẹn giờ tắt
; Tham khảo chương hình hiện giờ lúc bình thường
 ;;
disp3:  ; tên nhãn dùng cho lệnh nhẩy
mov r0, off_hour
mov dptr, #tab
mov a, r0
swap a
anl a, #0fh
movc a, @a+dptr
mov p1, a
clr p2.0
call dl
setb p2.0
mov a, r0
anl a, #0fh
movc a, @a+dptr
mov p1, a
clr p2.1
call dl
setb p2.1


;;
mov r1, off_minute
mov a, r1
swap a
anl a, #0fh
movc a, @a+dptr
mov p1, a
clr p2.2
call dl
setb p2.2
mov a, r1
anl a, #0fh
movc a, @a+dptr
mov p1, a
clr p2.3
call dl
setb p2.3
ret

̣9. Các đoạn chương trình làm trể


; Làm trể để có độ sáng rõ
;;
dl:
mov 30h, #02h
dl1: mov 31h, #0ffh
djnz 31h, $
djnz 30h, dl1
ret


;;
del:
mov 32h, #100
del1: mov 33h, #250
djnz 33h, $
djnz 32h, del1
ret


10. Chương trình viết cho các nút chỉnh




Hình vẽ trên cho thấy công dụng được giao cho các nút chỉnh. Đoạn chương trình sau được viết cho 4 nút chỉnh K1, K2, K3 và K4. Khi Bạn nhất nút K1 sẽ nhẩy ngắt ngoài và vào mode chỉnh.Nhấn K1 lần đầu sẽ cho chỉnh giờ-phút bình thường, lúc này K2 dùng chỉnh giờ và K3 dùng chỉnh phút. Nhấn K4 ra mode chỉnh. Nhấn K1 lần nữa vào vào mode chỉnh giờ-phút cho mode on_timer, lúc này K2 cũng dùng chỉnh giờ và K3 dùng chỉnh phút. Nhấn K4 ra mode chỉnh. Nhấn K1 lần nữa vào mode chỉnh off_timer và lúc này K2 cũng dùng chỉnh giờ, K3 dùng chỉnh phút. Nhấn K4 ra mode chỉnh.


;;
wint0:   ; đặt tên nhãn cho lệnh ngắt ngoài ứng với nút nhấn K1
push acc  ; tạm cho cất trị trong thanh acc vào ngăn xếp
push psw  ; tạm cho cất trị trong thanh psw vào ngăn xếp
clr ex0   ; tạm cho tắt ngắt ngoài
clr tr0  ; tạm dừng mạch đếm của timer 0
clr et0   ; tạm dừng ngắt theo bit báo tràn tf0

k1_11:  ; đặt tên nhãn cho lệnh nhẩy
call disp1  ; cho gọi chương trình hiển thị số
jb k1, k1_11 ; kiểm tra bit 1 của nút nhấn K1

k11_1:  ; đặt tên nhãn cho lệnh nhẩy
call disp1  ; tiếp tục cho gọi chương trình hiện số
jnb k1, k11_1 ; kiểm tra bit 0 trên nút nhấn K1

; Khi nhất nút K1, sẽ kích nhẩy ngắt ngoài _INT0, chương trình sẽ nhẩy đến tên nhãn WINT0:, ở đây người ta tiếp tục cho kiểm tra trạng thái bit của nút nhấn K1, đồng thời luôn cho gọi chương trình hiển thị để tránh hiển thị số bị gián đoạn trong mode điều chỉnh giờ. Chỉ khi bỏ nút nhất K1 ra, lúc đó sẽ chuyển qua kiểm tra trạng thái bit của các nút nhấn khác, như K2, K3.

;;
ph4:   ; đặt tên nhãn cho lệnh nhẩy
setb p3.1 ; cho tắt Led trên chân p3.1
setb p3.0  ; cho tắt Led trên chân p3.0

ph0:  ; đặt tên nhãn cho lệnh nhẩy
call disp1  ; tiếp tục cho gọi chương trình hiển thị số
jb k2, ph01 ; kiểm tra bit 1 trên nút nhấn K2


;;
k2_1:  ; đặt tên nhãn cho lệnh nhẩy
call disp1  ; tiếp tục cho hiển thị số
jnb k2, k2_1  ; kiểm tra bit 0 trên nút nhấn K2
mov r0, c_hour ; chuyển trị trong c_hour vào thanh r0
mov a, #01h  ; đặt trị 1 vào thanh a
add a, r0  ; cho trị trong r0 cộng với trị trong a, kết quả cất vào a
da a  ; biến đổi ra dạng hai số thập phân dạng cơ 2, cất trong 4 bit thấp và 4 bit cao
mov c_hour, a  ; chuyển trị có trong a vào thanh c_hour
cjne a, #24h, ph0  ; so sáng trị trong a với số 24, để định hướng nhẩy
mov c_hour, #0  ; đến đây trả trị trong c_hour về lại mức 0

ph01:   ; đặt tên nhãn cho lệnh nhẩy
jb k3, ph1 ; kiểm tra bit 1 trên nút nhấn K3

k3_1:  ; đặt tên nhãn cho lệnh nhẩy
call disp1 ; tiếp tục cho hiện số tránh gián đoạn lúc vào mode chỉnh
jnb k3, k3_1 ; kiểm tra bit 0 trên nút nhấn K3
mov r0, c_minute ; chuyển trị có trong c_minute vào thanh r0
mov a, #01h ; đặt trị 1 vào thanh a
add a, r0  ; cho trị trong r0 cộng với trị trong a, kết quả cất vào
da a  ; biến đổi ra dạng số thập phân hệ cơ 2, cất trong 4 bit thấp và 4 bit cao
mov c_minute, a  ; chuyển trị có trong a cất vào thanh c_minute
cjne a, #60h, ph0   ; cho so sánh a với trị 60 để chọn hướng nhẩy
mov c_minute, #0  ; trả trị trong c_minute về mức 0

ph1:  ; đặt tên nhãn dùng cho lệnh nhẩy
jb k4, ph10 ; kiểm tra bit 1 trên nút nhất K4

k4_1:   ; đặt tên nhãn dùng cho lệnh nhẩy
call disp1  ; tiếp tục gọi trình hiển thị số
jnb k4, k4_1  ; kiểm tra bit 0 trên nút nhấn K4
jmp tend  ; nhẩy đến tên nhãn tend:, kết thục trình đồng hồ

ph10:  ; đặt tên nhãn dùng cho lệnh nhẩy
jb k1, ph0 ; kiểm tra bit 1 trên nút nhấn K1

k1_1:  ; đặt tên nhãn dùng cho lệnh nhẩy
call disp1  ; tiếp tục gọi trình hiển thị số
jnb k1, k1_1  ; kiểm tra bit 0 trên nút nhấn K1 
clr p3.0   ; làm sáng Led trên chân p3.0
setb p3.1  ; làm tắt Led trên chân p3.1


;;--------------------------------
ph2:  ; đặt tên nhãn dùng cho lệnh nhẩy
call disp2  ; cho gọi chương trình hiển thị 2 con số
jb k2, ph201  ; kiểm tra bit 1 trên nút nhấn K2

k22_1:  ; đặt tên nh̃n dùng cho lệnh nhẩy
call disp2  ; tiếp tục cho gọi trình hiển thị số disp2
jnb k2, k22_1 ; kiểm tra bit 0 trên nút nhấn K2
mov r0, on_hour ; chuyển trị có trong on_hour vào r0
mov a, #01h ; cho trị 1 vào thanh a
add a, r0  ; cho trị trong r0 cộng với trị trong a, kết quả cất vào a
da a ; biến đổi thành hai số thập phân hệ cơ 2, cho cất vào 4 bit thấp và 4 bit cao
mov on_hour, a ; chuyển trị trong a vào cất trong thanh on_hour
cjne a, #24h, ph2 ; cho so sánh trị trong a với số 24 để chọn hướng nhẩy
mov on_hour, #0 ; trả trị trong thanh on_hour về mức 0

ph201:  ; đặt tên nhãn dùng cho lệnh nhẩy
jb k3, ph210  ; cho kiểm tra bit 1 trên nút nhấn K3

k22_2:  ; đặt tên nhãn dùng cho lệnh nhẩy
call disp2 ; tiếp tục cho hiển thị số với disp2
jnb k3, k22_2  ; kiểm tra bit 0 trên nút nhấn K3
mov r0, on_minute  ; cho chuyển trị trong on_hour vào thanh r0
mov a, #01h ; đặt trị 1 vào thanh a
add a, r0  ; cho trị trong r0 cộng với trị trong a, kết quả cất vào a
da a  ; biến đổi trị trong a ra hai số thập phân hệ cơ 2, cho cất vào 4 bit thấp và 4 bit cao
mov on_minute, a  ; chuyển trị trong a cất vào thanh on_minute
cjne a, #60h, ph2  ; cho so sánh trị trong a với số 60 để chọn hướng nhẩy
mov on_minute, #0  ; trả trị trong thanh on_minute về mức 0

ph210:   ; đặt tên nhãn dùng cho lệnh nhẩy
jb k1, ph2  ; kiểm tra bit 1 trên nút chỉnh K1

k22_3:  ; đặt tên nhãn dùng cho lệnh nhẩy
call disp2  ; tiếp tục cho hiển thị số với disp2
jnb k1, k22_3 ; kiểm tra bit 0 trên nút nhấn K1
setb p3.0  ; cho tắt Led trên chân p3.0
clr p3.1   ; cho sáng Led trên chân p3.1


;;----------------------------------------
ph3:   ; đặt tên nhãn dùng cho lệnh nhẩy
call disp3  ; cho hiển thị số với trình disp3
jb k2, ph301  ; kiểm tra bit 1 trên nút nhấn K2

k33_1:   ; đặt tên nhãn dùng cho lệnh nhẩy
call disp3  ; tiếp tục cho hiện số với trình disp3
jnb k2, k33_1  ; kiểm tra bit 0 trên nút nhấn K2
mov r0, off_hour  ; chuyển trị trong off_hour vào thanh r0
mov a, #01h  ; đặt trị 1 vào thanh a
add a, r0  ; cho cộng trị trong r0 với a, kết quả cho cất trong a
da a  ; biến đổi số trong a ra dạng hai số thập phân hệ cơ 2, cất vào 4 bit thấp và 4 bit cao
mov off_hour, a ; chuyển trị trong a cất vào thanh off_hour
cjne a, #24h, ph3  ; cho a so sánh với trị 24, để định hướng nhẩy
mov off_hour, #0  ; trả trị trong off_hour về lại mức 0

ph301:  ; đặt tên nhãn dùng cho lệnh nhẩy
jb k3, ph310  ; kiểm tra bit 1 trên nút nhấn K3

k33_2:  ; đặt tên nhãn dùng cho lệnh nhẩy
call disp3  ; tiếp tục cho hiện số với trình disp3
jnb k3, k33_2  ; kiểm tra bit 0 trên nút nhấn K3
mov r0, off_minute  ; chuyển trị trong off_minute vào thanh r0
mov a, #01h  ; đặt trị 1 vào thanh ghi a
add a, r0  ; cho trị trong r0 cộng với trị trong a, kết quả cất vào a
da a  ; biến đổi trị trong a ra hai số thập phân hệ cơ 2, cất trong 4 bit thấp và 4 bit cao
mov off_minute, a  ; chuyển trị trong a cất vào thanh off_minute
cjne a, #60h, ph3   ; cho trị trong a so sánh với con số 60, để định hướng nhẩy
mov off_minute, #0  ; trả trị trong thanh off_minute về mức 0

ph310:  ; đặt tên nhãn dùng cho lệnh nhẩy
jb k1, ph3  ; kiểm tra bit 1 trên nút nhấn K1

k33_3:  ; đặt tên nhãn dùng cho lệnh nhẩy
call disp3 ; tiếp tục cho hiển thị số với trình disp3
jnb k1, k33_3  ; kiểm tra bit 0 trên nút nhấn K1
jmp ph4  ; nhẩy đến tên nhãn ph4


;;----------------------------------------
tend:  ; đặt tên nhãn dùng cho lệnh nhẩy
setb ex0  ; cho mở lại chức năng ngắt ngoài, ngắt với _INT0
setb tr0  ; cho xung vào mạch đếm của timer 0
setb 00h  ; đặt bit kiểm tra về trạng thái 00h
setb et0 ; cho mở ngắt theo bit báo tràn tf0
setb p3.7  ; đặt chân p3.7 lên mức áp cao
pop psw  ; hoàn trả lại trị trước đó cho thanh psw
pop acc  ; hoàn trả lại trị trước đó cho thanh a
reti  ; dùng chương trình ngắt
end ; dừng biên dịch ra mã lệnh tại đây

Tạm kết bài viết này


Trên đây là một thí dụ về cách dùng ic lập trình AT89C51 40 chân để làm mạch điện đồng hồ có thêm chức năng chỉnh giờ mở (on_timer) và chỉnh giờ tắt (off_timer), nó có thể dùng làm đồng hồ hẹn giờ để đóng mở các thiết bị. Thật ra còn có rất nhiều cách viết các chương trình đồng hồ cho các ic lập trình, tuy nhiên nếu Bạn xem và hiểu kỹ bài viết này Bạn sẽ thấy được nhiều phương hướng để có thể viết được các chương trình khác tương tự, hay hơn và có nhiều tính năng hơn. Khi có dịp chúng ta sẽ trở lại chuyên đề này với các thí dụ hấp dẫn hơn.  


Cách làm mạch điện "Đố vui để học" dùng AT89C2051 với 8 nút nhấn




Rất vui  khi thấy Bạn vào xem...



Phần dẫn nhập.

Có một Bạn viết e-mail cho tôi với câu hỏi như sau:

Kinh chao thay Hung !
Em la giao sinh moi ra truong, hien dang di day hoc cho cac em hoc sinh Tieu hoc, trong qua trinh  day hoc em rat thich cho cac em choi tro choi do em co su dung mach nhan chuong uu tien nhung mach chuong hien tai chi co the su dung duoc cho toi da la 4 doi nhung lop hoc cua em lai can den 8 doi hoac nhieu hon nua. Thay co the tang em chuong trình hoac huong dan em cach viet chuong trinh nay duoc khong ? Em dang su dung bi vi dieu khien AT89C2951. Cam on thay rat nhieu !


Đặc tính của một mạch điện “Đố vui để học”, là:


Theo giả định của tôi là: Trên mỗi bàn có một nút nhấn (có thể mắc song song 3 nút nhấn cho 3 người cùng bàn).

* Khi nghe xong câu hỏi thì người điều khiển chương trình sẽ nhấn nút “Bắt đầu”.

* Lúc này, các em sẽ suy nghĩ và khi ai có câu trả lời thì nhấn nút “Trả lời”.

* Ở đây có 8 nút nhấn chính. Khi một nút đã nhấn thì tất cả các nút còn lại sẽ không còn tác dụng.

* Trên bảng đèn sẽ có đèn báo “Bắt đầu”, nó sáng ngay khi người điều khiển chương trình nhấn nút Reset. Và khi đã có nút nhấn trả lời thì đèn báo “Bắt đầu” sẽ tắt và lúc này một đèn báo “Đang trả lời sẽ nhấp nháy (có thể cho kèm tiếng nhịp)”. Và lúc đang trả lời sẽ có một đèn sáng liên tục xác nhận mạch đang ở “trạng thái trả lời”.

* Muốn trở lại trạng thái đầu cho câu hỏi kế tiếp, người điều khiển chỉ cần nhấn nút Reset.

Dĩ nhiên phần trên đây là các đặc tính mà tôi tự đặt ra và vựa vào đó để thiết kế phần cứng và rồi sẽ viết chương trình nguồn cho mạch điện này. Tôi nghĩ sau khi Bạn đã hiểu rõ công việc thiết kế loại mạch này rồi, Bạn sẽ tự có thể viết các chương trình nguồn khác, nó sẽ thực hiện theo đúng các ý muốn của Bạn.


Sơ đồ mạch điện mẫu (tôi vẽ trong OrCAD và tô màu trong trình Paint).




 Phân tích sơ đồ mạch điện:


Khi dùng ic vi điều khiển AT89C2051, mạch điện cơ bản sẽ gồm các phần sau:

* Phần cấp nguồn: Dùng ic ổn áp 3 chân 7805 để có nguồn 5V ổn định cấp cho chân số 20 và chân số 10 cho nối masse để lấy dòng (Dòng điện tử chảy vào ic qua chân số 10 và ra trên chân số 20). Ở đây dùng Led D1 làm Led báo nguồn. mạch làm việc với mức nguồn ngả vào là 12V. Nguồn 12V còn được dùng để cấp điện cho các relay. Chúng ta dùng 3 relay và dùng các tiếp điểm lá kim K1,K2, K3 của các relay này để điều khiển các bóng đèn điện hay chuông báo.

* Phần mạch Reset. Tác dụng Reset khi chân số 1 ở mức áp cao. Khi mạch được cấp nguồn, tụ C5 (10uF) sẽ nạp điện, dòng nạo chảy qua điện trở R1 (10K), nó kéo chân số 1 lên mức áp cao và chương trình sẽ quay về thanh nhớ 0000h (đó là vị trí khỏi đầu của tác dụng reset). Chỉ sau một lúc tụ C5 sẽ nạp đầy mức nguồn, chân 1 được trả về mức áp thấp và ic vi điều khiển bắt đầu chạy chương trình có trong bộ nhớ EEP-ROM. Trong mạch chúng ta dùng nút nhấn reset để đưa chương trình trở lại trạng thái khởi đầu.

* Phần định tần cho mạch dao động tạo xung nhịp. Xung nhịp được định tần theo thạch anh gắn trên chân 4 và chân 5. Với thạch anh 12MHz, tần số xung nhịp sẽ là 1MHz và chu kỳ lệnh sẽ là 1us. Các tụ nhỏ C6, C7 có tác dụng bù nhiệt ổn tần.

* 8 Nút nhấn gắn trên port 1 và chúng ta dùng chân p3.0 điều khiển relay 3, chân p3.1 điều khiển relay 2 và chân p3.2 điều khiển relay 1.


 Cách viết chương trình nguồn:

org 0000h
               mov p3, #00000001b   ; Đặt 7 chân của p3 xuống mức áp thấp, chân p3.0 ở mức 1, relay 3 đóng.
        call del                            ; Chờ một lúc cho ổn định.

q1:                                          ; Viết cho phím S1
        jb p1.0, q2        ; Chờ phím S1 nhấn xuống, chưa nhấn thì qua kiểm tra phím S2   

        call del              ; tránh hiện tượng rung phím làm kết quả sai
        jb p1.0, $           ; kiểm tra lần nữa phím S1cho chắc chắn
        jmp ctr_1           ; Vào chương trình điều khiển các đèn báo
    
q2:                                         ; Viết cho phím S2
        jb p1.1, q3
        call del
        jb p1.1, $
        jmp ctr_1

q3:                                          ; Viết cho phím S3
        jb p1.2, q4
        call del
        jb p1.2, $
        jmp ctr_1

q4:                                          ; Viết cho phím S4
        jb p1.3, q5
        call del
        jb p1.3, $
        jmp ctr_1

q5:                                        ; Viết cho phím S5
        jb p1.4, q6
        call del
        jb p1.4, $
        jmp ctr_1

q6:                                          ; Viết cho phím S6
        jb p1.5, q7
        call del
        jb p1.5, $
        jmp ctr_1

q7:                                         ; Viết cho phím S7
        jb p1.6, q8
        call del
        jb p1.6, $
        jmp ctr_1

q8:                                ; Viết cho phím S8
        jb p1.7, q1
        call del
        jb p1.7, $
        jmp ctr_1

ctr_1:
        mov p3, #00000110b           ; Tắt relay 3, mở relay 2 và mở relay 1
        call delay                                ; Chương trình làm chậm
        mov p3, #00000100b           ; Tắt relay 3, tắt relay 2 và mở relay 1
        call delay                                ; Chương trình làm chậm    

        jmp ctr_1                                ; Tiếp tục chương trình 1 


del:                                                   ; Chương trình trể dùng tánh hiện tượng rung phím.
        mov r7, #30
v6:   mov r6, #100
        djnz r6, $
        djnz r7, v6
        ret
delay:                                               ; Chương trình trễ tạo nhịp nhấp nháy.
        mov r5, #250
tt:     call del
        djnz r5, tt
        ret
end



Sau khi đã có file nguồn, lấy họ là .asm, Bạn cho chuyển vào trình M-IDE để biên dịch ra file có họ là .hex. Bạn xem, tôi cắt các câu lệnh trên và dán vào cửa sổ của trình MIDE, rồi chọn mục Build và trong cửa sổ Build lại chọn mục Build lần nữa để cho biên dịch ra file .hex (Khi có file nguồn trong MIDE, Bạn nhấn phím F9 để cho dịch ra file .hex cũng được).





 Kết quả trong thư mục của file 8-nut.asm (file nguồn), Bạn thấy xuất hiện file 8-nut.hex (file mã). Bây giờ Bạn dùng hộp nạp cho nạp file này vào ic vi điều khiển AT89C2051 là xong chuyện.




Đây là file văn bản của file 8-nut.hex (Nếu như Bạn không có trình biên dịch MIDE, Bạn có thể dùng các mã này bằng cách cắt lấy, rồi tạo ra file lấy họ là .hex và dùng hộp nạp cho nạp vào ic AT89C2051 cũng được). 

:1000000075B0011200742090091200742090FD0256
:1000100000662091091200742091FD020066209272
:10002000091200742092FD020066209309120074E8
:100030002093FD0200662094091200742094FD02B2
:1000400000662095091200742095FD020066209636
:10005000091200742096FD0200662097A912007410
:100060002097FD02006675B00612007D75B004127F
:10007000007D80F27F1E7E64DEFEDFFA227DFA11B3
:0400800074DDFC220D
:00000001FF

 


Về cách dùng hộp nạp các file .hex cho các bộ nhớ EEP-ROM trong các ic vi điều khiển, Bạn tham khảo bài viết sau:


  
  
Phân tích các câu lệnh trong chường trình nguồn:


 

Mới vào Bạn phải dùng câu lệnh:

mov p3, #00000001b

Với câu lệnh này, chỉ có chân p3.0 (tức chân số 2 của ic) là ở mức áp cao, vậy transistor Q3 sẽ bão hòa , nó cấp dòng cho relay 3 và relay này đóng tiếp điểm lá kim K3. Trên tiếp điểm này Bạn gắn một bóng điện, bóng điện sẽ phát sáng, nó cho biết là lúc này 8 nút nhấn đã được kích hoạt, tứ cho quyền nhấn. Khi relay 3 được cấp nguồn, Led chỉ thị D4 cũng sẽ phát sáng.

Do các chân p3.1 (chúng ta dùng đóng mở relay 2), và chân p3.2 (chúng ta dùng đóng mở relay 1) đều cho ở mức áp thấp nên các transistor Q2, Q1 đều ngưng dẫn.

Trong mạch các điện trở 2.2K dùng hạn dòng chân B. các Led D2, D3, D4 dùng chỉ thị trạng thái của relay. Ở mỗi Led phải có điện trở hạn dòng 560 ohm.

Chúng ta không cần dùng câu lệnh:

mov p1, #11111111b  hay: mov p1, #0ffh

để đặt 8 chân của port1 lên mức áp cao, vì sau lệnh reset, các chân port1 đều đã cho ở mức áp cao. Vậy khi mới vào chúng ta sẽ viết:

org 0000h  ; Cho khởi đầu từ thanh nhớ có địa chỉ là 0000h            mov p3, #00000001b   ; Đặt 7 chân của p3 xuống mức áp thấp, chân p3.0 ở mức 1, relay 3 đóng.
        call del                            ; Chờ một lúc cho ổn định.
(Trên đây là các câu lệnh mở đầu)





Chúng ta đặt 8 nút nhấn thường hở trên port1. Vậy trạng thái áp cao trên các chân của port1 là trạng thái chờ.

Để bảo đảm là bình thường lúc ở trạng thái chờ các chân của port1 đều ở mức áp cao, chúng ta cho treo áp các chân của port1 bằng các điện trở 10K.

Vậy, mỗi khi nút reset đã được nhấn, chương trình khởi đầu từ thanh nhớ 0000h, sau khi qua các câu lệnh khởi đầu (phần trình bày trên), nó vào chương trình dò phím. Ở đây chúng ta dùng lệnh nhẩy theo bit cao trên các chân của port1. Các câu lệnh được viết như sau:

q1:                            ; Viết cho phím S1
        jb p1.0, q2        ; Chờ phím S1 nhấn xuống, chưa nhấn thì qua kiểm tra phím S2   
        call del              ; tránh hiện tượng rung phím làm kết quả sai
        jb p1.0, $           ; kiểm tra lần nữa phím S1cho chắc chắn, nó phải ở mức áp thấp.
        jmp ctr_1           ; Vào chương trình điều khiển các đèn báo


Giải thích các câu lệnh trên:

q1:          

; Đây là tên nhãn của phím S1   


jb p1.0, q2   
; Nếu phím S1 trên chân p1.0 ở mức áp cao (chưa nhấn) thì nhẩy qua tên nhãn q2 dò phím S2.

call del
; cho trễ một chút để tránh ảnh hưởng của việc rung phím. Khi Bạn nhấn phím xuống, mặt tiếp xúc sẽ rung và ạo ra hiện tượng lúc dính lúc không, phải chờ sau một thời gian mới chắc chắn là nó đã dính.

jb p1.0, $
; Đến đây nếu phím S1 còn ở mức áp cao thì chương trình sẽ dừng lại chờ, chương trình sẽ phải khởi động lại bằng nút nhấn reset. Do đó, chúng ta phải yêu cầu các em tham gia trò chơi, khi nhấn phím rồi thì phải giữ phím, không buôn ra ngay.

Ghi chú: Nếu không muốn có tính năng này phải giữ phím nhấn đủ lâu, thì Bạn bỏ câu lệnh: jb p1.0, $

Trường hợp muốn có thêm tính năng là chờ bỏ phím mới bắt đầu nhẩy vào chương trình ctr_1, thì Bạn thêm vào câu lệnh:

jnb p1.0, $   ; lúc này người chơi phải bỏ phím nhấn mới vào cuộc chơi.

jmp ctr_1
; Đến đây chương trình sẽ nhẩy vào đoạn điều khiển các đèn báo, có tên nhãn là ctr_1.



Giải thích đoạn chương trình điều khiển các đèn báo:


ctr_1:
        mov p3, #00000110b           ; Tắt relay 3, mở relay 2 và mở relay 1
        call delay                                ; Chương trình làm chậm
        mov p3, #00000100b           ; Tắt relay 3, tắt relay 2 và mở relay 1
        call delay                                ; Chương trình làm chậm    

        jmp ctr_1                                ; Tiếp tục chương trình 1 


Bạn dùng câu lệnh:

mov p3, #00000110b
; Câu lệnh này đặt chân p3.0 ở mức áp thấp, các chân p3.1, p3.2 ở mức áp cao. Vậy tắt đèn ở tiếp điểm lá kim K3, cho sáng đèn ở tiếp điểm lá kim K1 và K2.

call delay
; Cho gọi chương trình làm chậm.

mov p3, #00000100b
; Câu lệnh này đặt chân p3.0 ở mức áp thấp, chân p3.1 ở mức áp thấp , và p3.2 ở mức áp cao. Vậy tắt đèn ở tiếp điểm lá kim K3 và K2,  cho sáng đèn ở tiếp điểm lá kim K1.

call delay
; Cho gọi chương trình làm chậm.

jmp ctr_1
; Tức cho quay lại tiếp tục thực hiện các câu lệnh trên. Kết quả, Bạn thấy:

Đèn trên tiếp điểm K3 đã tắt
Đèn trên tiếp điểm K1 sáng
Đèn trên tiếp điểm K2 sẽ nhấp nháy.

….và trạng thái này được giữ cho đến khi Bạn nhấn phím reset.



Mở rộng:

Muốn tăng số phím nhấn và viết chương trình điều khiển phức tạp hơn Bạn có thể dùng ic vi điều khiển AT89C51. Với 4 port 32 chân, việc gắn các nút nhấn tất nhiên sẽ nhiều hơn và cách hiển thị sẽ hấp dẫn hơn.

Sau đây là một sơ đồ phát thảo dùng ic vi điều khiển AT89C51, chỉ là một  gợi ý:



Giải thích sơ đồ mạch điện:


Sơ đồ mạch điện cho thấy cách dùng ic vi điều khiển AT89C51 làm mạch “Đố vui để học” với 16 nút nhấn. Các nút nhấn gắn trên port 1 và port 3 (ở port 1 và port 3 Bạn không cần dùng các điện trở treo áp). Ở trạng thái thường, các nút nhấn hở, các chân đều ở mức 1, chương trình sẽ ở đoạn quét phím, chỉ khi có một nút nhấn nhấn xuống, thì chân đó sẽ bị cho nối masse và sẽ xuống mức 0. Chúng ta sẽ dùng lệnh nhẩy jb (jump bit) hay jnb (jump nobit) để viết chương trình dò phím, dùng để phát hiện ra vị trí của các phím đã nhấn.

Trên port 0 và port 2 dùng làm bảng đèn số để hiển thị con số thứ tự mà phím đã nhấn. Thí dụ: như khi phím 5 nhấn thì trên bảng đèn sẽ hiện ra con số 5… Sau đó bảng đèn sẽ chuyển qua làm nhiệm vụ của một đồng hồ đếm thời gian.

Chúng ta dùng các chân còn lại của port 2 để điều khiển các relay (relay 1 và relay 2), các tiếp điểm lá kim của các realy dùng đóng mở các đèn, hay các chuông báo.

Tóm lại:

Sau khi cho khởi động với nút Reset thì bảng đèn sẽ chuyển qua trạng thái chờ để hiển thị con số thứ tự của phím nhấn. Lúc này Bạn có thể cho đèn báo nhấp nháy để chỉ là đang ở trạng thái chờ. Khi có một phím nhấn xuống, trên bảng đèn sẽ hiện ra con số thứ tự của phím đã được nhấn, đèn nhấp nháy sẽ chuyển qua sáng liên tục, mạch chuông sẽ báo nhịp và bảng đèn Led 7 đoạn chuyển qua làm công việc đếm thời gian.

Khi nào trả lời xong, muốn trở lại trạng thái khởi đầu thì nhấn nút Start.

Trên đây là một mạch điện gợi ý mà tôi phát thảo ra để các Bạn góp ý và nếu thấy thích thì thử viết chương trình nguồn cho mạch điện này. Khi có thời gian rảnh tôi sẽ trở lại chuyên đề này. Chào Bạn nhé!

Tạm kết.

Bạn biết môn điện tử phát triển với tốc độ phi mã, "Nhật tân, Nhật tân, Nhật Nhật tân", nghĩa là mỗi ngày mỗi mớiCho đến hôm nay... thì các kiểu mạch điện tử ráp theo cách xưa rất khó đáp ứng được với cách yêu cầu thực tế luôn cần phải nâng cấp, do đó Bạn phải làm quen với các kiểu mạch điện vi điều khiển, đặc điểm của loại mạch dùng ic vi điểu khiển là cấu trúc phần cứng đơn giản, ít thay đổi, nhưng công năng của nó có thể thay đổi dễ dàng, mở rộng ứng dụng bằng các phần mềm, tức thay đổi hay thêm vào các chức năng mới chỉ bằng các câu lệnh (mà không phải đụng đến phần cứng). Trong các bài viết sau này, tôi sẽ thường xuyên trình bày cách thiết kế và lắp ráp các kiểu mạch điện này, mong Bạn vào đọc.Hướng dẫn Bạn cách 

tạo khung đèn Led cho bảng đèn quảng cáo


 



Rất vui  khi thấy Bạn vào xem...


Dẫn nhập

Chào Bạn! Trong bài này tôi sẽ hướng dẫn Bạn cách dùng ic AT89Cxxx chỉ với 3 ngả ra  lấy trên cảng p2 để tạo ra khung đèn Led cho các bảng quảng cáo. Bạn có thể cho các Led trên khung chạy theo nhiều kiểu, và nhờ vậy, bảng đèn rất hấp dẫn và sẽ gây được sự chú ý rất lớn của người xem, như vậy không phải là bảng đèn của Bạn đã thành công lắm rồi sao?


Sơ đồ mạch điện:

 

Qua các bài trước đây, Bạn thấy khi dùng ic vi điều khiển AT89C51, ở phần mạch cơ bản Bạn cần chú ý có 4 phần:

Phần nguồn nuôi: Chân 20 cho nối masse, chân 40 cho nối vào đường nguồn 5V.

Phần mạch reset: Bạn dùng một tụ C3 (10uF) và một điện trở R1 (8.2K) để tạo mức áp cao trên chân số 9, mỗi khi mạch được cấp nguồn. Ngay khi mạch được cấp nguồn, tụ C3 nạp điện sẽ kéo chân 9 lên mức áp cao để tạo tác dụng reset, chỉ sau một lúc, chân số 9 sẽ trở lại mức áp thấp và lúc này ic sẽ vào trạng thái hoạt động với câu lệnh khởi từ thanh 0000h (hay cũng là thanh reset).

Phần định tần cho mạch dao động tạo xung nhịp: Trong ic vi điều khiển AT89C51 có mạch dao động tạo xung nhịp, tần số định theo thạch anh gắn trên chân số 18 (chân Out), 19 (chân In). Khi Bạn dùng thạch anh 12MHz thì tần số xung nhịp sẽ là 1MHz (hay chu kỳ lệnh là 1us). Ở đây dùng 2 tụ nhỏ C1 (33pF), C2 (33pF) để bù nhiệt ổn tần.

Phần khai báo dùng chương trình trong bộ nhớ nội: nếu Bạn chỉ muốn chạy chương trình trong bộ nhớ nội, muốn vậy Bạn cho chân 31 ở mức áp cao, bằng cách nối chân 31 vào đường nguồn 5V.









Hình vẽ cho thấy: Bạn dùng transistor 2SC1815 ghép phức hợp với transistor 2SD468 để cấp dòng cho các Led (ở đây dùng loại Led siêu sáng) để tạo khung cho bảng đèn quảng cáo. Trên chân B gắn điện trở hạn dòng 1K. Trên chân C, Bạn gắn nhiều nhánh, mỗi từng nhánh 2 Led (ở mỗi nhánh có điện trở hạn dòng 680). Một đơn vị cơ bản sẽ gồm tổ hợp 6 Led (Bạn xem hình).

Ở hình vẽ này, Bạn thấy Led D1, D2 (và tất cả các Led của nhóm 1) được kích sáng bởi chân p2.0. Led D3, D4 (và tất cả các Led của nhóm 2) được kích sáng bởi chân p2.1 và Led D5, D6 (và tất cả các Led của nhóm 3) được kích sáng bởi chân P2.2.

Tóm lại:

* Khi Bạn cho chân p2.0 lên mức áp cao, thì tất cả các Led của nhóm 1 sẽ phát sáng.
* Khi Bạn cho chân p2.1 lên mức áp cao, thì tất cả các Led của nhóm 2 sẽ phát sáng.
* Khi Bạn cho chân p2.2 lên mức áp cao, thì tất cả các Led của nhóm 3 sẽ phát sáng.

Các Led của nhóm 1, nhóm 2 và nhóm 3 được cho đặt xen kẽ để tạo hiệu ứng Led chạy.




Hình vẽ trên đây cho thấy cách tạo khung cho một bảng đèn quảng cáo. Tôi dùng màu để Bạn phân định là trên khung bảng đèn có 3 nhóm Led.

* Nhóm các Led siêu sáng (màu đỏ) cho kích sáng với mức volt cao trên chân p2.0.
* Nhóm các Led siêu sáng (màu xanh lơ) cho kích sáng với mức volt cao trên chân p2.1
* Nhóm các Led siêu sáng (màu xanh lục) cho kích sáng với mức volt cao trên chân p22.


Nguyên lý vận hành:

Như Bạn đã biết chúng ta có thể dùng câu lệnh rất đơn giản để đặt các chân của các cảng p0, p1, p2, p3 của ic vi điều khiển AT89C51 lên mức áp cao hay xuống mức áp thấp.

Để đặt chân p2.0 lên mức áp cao, chúng ta dùng câu lệnh:

setb p2.0

Và muốn đặt chân p2.0 xuống mức áp thấp, chúng ta dùng câu lệnh:

clr p2.0

Vậy:


* Nếu muốn các Led màu xanh lơ trên khung bảng đèn quảng cáo sáng chúng ta dùng lệnh: setb p2.1


Và:

* Nếu muốn các Led màu đỏ trên khung bảng đèn quảng cáo tắt chúng ta dùng lệnh: clr p2.0
* Nếu muốn các Led màu xanh lơ trên khung bảng đèn quảng cáo tắt chúng ta dùng lệnh: clr p2.1
* Nếu muốn các Led màu xanh lục trên khung bảng đèn quảng cáo tắt chúng ta dùng lệnh: clr p2.2

Bây giờ Bạn có thể dùng các câu lệnh set bit, clear bit để tạo ra các trạng thái của khung bảng đèn. Chúng ta có thể có các trạng thái khung như các hình sau (Bạn xem hình):

Trạng thái 1: Muốn tất cả các Led đều tắt. Bạn chọn câu lệnh.

clr p2.0
clr p2.1
clr p2.2


Trạng thái 2: Muốn tất cả các Led đều sáng hết.

setb p2.0
setb p2.1
setb p2.2


Trạng thái 3: Muốn có trạng thái như hình sau. Bạn dùng các câu lệnh.

clr p2.0
setb p2.1
setb p2.2


Trạng thái 4: Muốn có trạng thái như hình sau. Bạn dùng các câu lệnh.

setb p2.0
clr p2.1
setb p2.2


Trạng thái 5: Muốn có trạng thái như hình sau. Bạn dùng các câu lệnh.

setb p2.0
setb p2.1
clr p2.2


Trạng thái 6: Muốn có trạng thái như hình sau. Bạn dùng các câu lệnh.

setb p2.0
clr p2.1
clr p2.2


Trạng thái 7: Muốn có trạng thái như hình sau. Bạn dùng các câu lệnh.

clr p2.0
setb p2.1
clr p2.2


Trạng thái 8: Muốn có trạng thái như hình sau. Bạn dùng các câu lệnh.

clr p2.0
clr p2.1
setb p2.2


Cách viết chương trình nguồn:

; Kiểu các Led trên khung nhấp nháy.
k_1:
        clr p2.0
      clr p2.1
      clr p2.2
      call delay
      setb p2.0
      setb p2.1
      setb p2.2
      call delay
         ret
    
; Kiểu các Led trên khung chạy qua trái tốc độ chậm.
k_2:
        clr p2.0
      setb p2.1
      setb p2.2
      call delay_slow
      setb p2.0
      clr p2.1
      setb p2.2
      call delay_slow
      setb p2.0
      setb p2.1
      clr p2.2
      call delay_slow
         ret



; Kiểu các Led trên khung chạy qua trái tốc độ nhanh.
k_3:
        clr p2.0
      setb p2.1
      setb p2.2
      call delay_high
      setb p2.0
      clr p2.1
      setb p2.2
      call delay_high
      setb p2.0
      setb p2.1
      clr p2.2
      call delay_high
         ret

; Kiểu các Led trên khung chạy qua trái tốc độ thật nhanh (hiệu ứng từng Led chạy nhanh qua trái).
k_4:
        clr p2.0
      setb p2.1
      setb p2.2
      call del
      setb p2.0
      clr p2.1
      setb p2.2
      call del
      setb p2.0
      setb p2.1
      clr p2.2
      call del
         ret


; Kiểu các Led trên khung chạy qua phải tốc độ chậm.
k_5:
        setb p2.0
      setb p2.1
      clr p2.2
      call delay_slow
      setb p2.0
      clr p2.1
      setb p2.2
      call delay_slow
      clr p2.0
      setb p2.1
      setb p2.2
      call delay_slow
         ret

  
; Kiểu các Led trên khung chạy qua phải tốc độ nhanh.
k_6:
        setb p2.0
      setb p2.1
      clr p2.2
      call delay_high
      setb p2.0
      clr p2.1
      setb p2.2
      call delay_high
      clr p2.0
      setb p2.1
      setb p2.2
      call delay_high
         ret

; Kiểu các Led trên khung chạy qua phải tốc độ thật nhanh (hiệu ứng từng Led chạy nhanh qua phải).
k_7:
        clr p2.0
      setb p2.1
      setb p2.2
      call del
      setb p2.0
      clr p2.1
      setb p2.2
      call del
      setb p2.0
      setb p2.1
      clr p2.2
      call del
         ret

Cơ bản thì dùng cách phối hợp các câu lệnh trên Bạn sẽ có thể tạo ra nhiều kiểu "chạy Led" trênkhung bảng quảng cáo theo ý tưởng riêng của Bạn.



Cách phối hợp các trạng thái tạo ra các dạng chạy Led trên khung của bảng đèn.


 Trạng thái 1: Tất cả các Led đều tắt.

 Trạng thái 2: Tất cả các Led đều sáng.
 


Kết hợp trạng thái 1 (tắt hết) và 2 (sáng hết) tạo ra kiểu nhấp nháy như hình sau:
  



 Trạng thái 3: Tắt các Led với clr p2.0, mở các Led với setb p2.1, và setb p2.2.

 Trạng thái 4: Tắt các Led với clr p2.1, mở các Led với setb p2.0, và setb p2.2.

 Trạng thái 5: Tắt các Led với clr p2.2, mở các Led với setb p2.0, và setb p2.1.

Kết hợp trạng thái 3, 4 và 5 tạo ra kiểu nhấp nháy như hình sau:
Dùng delay_ slow hình quay qua trái chậm

 Dùng delay_high  hình quay trái nhanh

 
  Dùng delay_ slow hình quay qua phải chậm     
               
Dùng delay_high  hình quay phải nhanh




Trạng thái 6: Mở các Led với setb p2.0, tắt các Led với clr p2.1, và clr p2.2.

Trạng thái 7: Tắt các Led với clr p2.0, mở các Led với setb p2.1, và tắt các Led với clr p2.2.

 Trạng thái 8: Tắt các Led với clr p2.0, tắt các Led với clr p2.1, và mở các Led với setb p2.2.


Kết hợp trạng thái 6, 7 và 8 tạo ra kiểu nhấp nháy như hình sau:
Dùng delay_slow  hình quay trái chậm

 Dùng delay_high  hình quay trái nhanh

 Dùng delay_slow  hình quay phải chậm

 Dùng delay_high  hình quay phải nhanh


Kết hợp trạng thái 2, 3, 4, 5, 6, 7 và 8 tạo ra kiểu nhấp nháy như hình sau:




Sau đây là một bảng đèn quảng cáo được gửi qua Mỹ từ VN, hàng của chợ Nhật Tảo treo trên cửa hàng làm Nails ở Quincy-Boston Mỹ.



Tôi tháo bảng đèn ra để Bạn thấy board mạch điều khiển đèn, rất đơn giản, chỉ với i ic vi điều khiển AT89C51. Dùng 3 transistor phức hợp trên các chân 6, 7, 8 để điều khiển các Led trên khung và dùng 4 transistor phức hợp trên các chân 35, 36, 37, 38 để điều khiển các con chữ.



Cách hàn dây thủ công các Led của bảng đèn quảng cáo: NAILs




Một ý tưởng

Giới thiệu các dây đèn Led dùng tạo khung  cho các bảng đèn lớn


Trường hợp Bạn muốn tạo dãy đèn cho chạy theo các khung cửa lớn, như tạo đường viềng cho các khung cửa của các cửa hàng, việc dùng các Led như trên rất phiền phức, nhất là trong chế tạo các dãy Led dài năm mười mét. Lúc đó Bạn có thể dùng giải pháp như sau: Tìm mua dãy Led 3 màu như hình chụp (Bạn xem hình).



Hình chụp cho thấy Bạn điều khiển đèn bằng hộp kết nối 4 dây (các dây điện có màu), mạch điện này làm việc với mức nguồn nuôi là 12V và điều khiển theo nguyên lý hồng ngoại.
  


Hình chụp cho thấy hộp điều khiển dãy đèn Led 3 màu vào hộp remote hồng ngoại với nhiều nút nhấn. Bạn muốn các Led nháy theo kiểu nào, muốn lấy màu gì thì nhấn váo phím của hộp điều khiển là được. Rất tiện dùng.

  

Trên dãy đèn Led người ta phủ nhựa kín để tránh nước và cứ cách khoản ghi dấu hình cây kéo, ở các vị trí này Bạn có thể cắt rời dây ra rồi dùng 4 sợi dây điện nối vào, nhờ vậy, Bạn có thể chia dãy đèn ra nhiều khúc nhỏ, cho uốn theo các hình ảnh hay uốn theo các con chữ để tạo ta các hình quảng cáo, rất nhanh và tiện lợi.

 

0 comments:

Post a Comment

domain, domain name, premium domain name for sales

Popular Posts