Thứ Ba, 26 tháng 7, 2011

Hướng dẫn Bạn viết 10 chương trình ứng dụng cơ bản cho ic vi điều khiển AT89C51

Hướng dẫn Bạn viết 10 chương trình ứng dụng cơ bản cho ic vi điều khiển AT89C51


 

Lời nói đầu



Bạn biết, kiến thức là luôn luôn cải biến và phát triển, do đó các bài viết của tôi ở đây cũng luôn theo tôn chỉ của RIXIN, nghĩa là Nhật Tân 日新 (Ngày mới, ngày mới, ngày ngày mới。日新,日新,日日新). Các bài viết luôn được người soạn  đọc đi đọc lại và sửa lỗi, viết thêm vào các ý tưởng mới và các bài viết luôn được làm tươi. Nó giống như một vườn cây  được người trồng  vườn chăm coi cẩn thận và khu vườn thì đang ngày ngày sinh trưởng, các bài viết sẽ luôn mới, luôn khác và mỗi ngày đều được bổ xung tu chỉnh, và thêm mới. Mong Bạn thường xuyên quay lại để xem và góp ý. Người soạn: Vương Khánh Hưng.


Trước hết chúng ta hãy tìm hiểu nguyên lý làm việc của ic vi điều khiển AT89C51 (Bạn xem hình).


IC AT89C51 có 40 chân. Công dụng của các chân như sau:

* Chân 40 nối vào đường nguồn 5V, chân 20 cho nối masse.

* Chân 9 nối vào mạch reset với điện trở 10K và tụ 10uF. Khi mạch vừa được cấp điện, tụ nạp và kéo chân 9 lên mức áp cao tạo tác động reset. Sau một lúc chân 9 trở lại mức áp thấp. IC AT89C51 bắt đầu hoạt động từ trạng thái khởi đầu.

* Chân 18, 19 mắc thạch anh định tần. Như vậy tần số xung nhịp sẽ là 1Mhz (hay 1us). Ngang thạch anh mắc 2 tụ nhỏ dùng để bù nhiệt ổn tần (Bạn xem hình).



* Chân 31 Bạn phải cho treo lên mức áp cao, để xác định là mạch chỉ làm việc với bộ nhớ nội (Vì mạch không dùng thêm bộ nhớ ngoài).

* Bạn chú ý, ic có 4 cảng, đó là port 0 (p0), port 1 (p1),  port 2  (p2) và port 3 (p3). Mỗi cảng có 8 chân. Mọi hoạt động của ic vi điều khiển đều được thực hiện trên các cảng này.

Ghi nhận: Bạn thấy ic AT89C51 chỉ cần một ít linh kiện bên ngoài là đã có thể chấp hành các câu lệnh đã có trong bộ nhớ EEP-ROMBạn dùng các câu lệnh này để xác định trạng thái điện áp cao thấp trên các cảng và dùng các mức áp cao thấp này cho việc điều khiển các dạng mạch điện, hay các thiết bị.


Bài 1: Viết chương trình để Led trên chân số 1 (p1.0) luôn nhấp nháy.

ORG  0000h                                                ; Khởi đầu từ thanh ghi có địa chỉ là 0000h

START:               CLR P1.0                         ; Đặt chân p1.0 xuống mức áp thấp, Led sẽ sáng.

                            LCALL DELAY                 ; Cho gọi trình làm trễ (có tên nhãn là delay).

                            SETB P1.0                       ; Đặt chân p1.0 lên mức áp cao, Led sẽ tắt

                            LCALL DELAY                  ; Lại cho gọi trình làm trễ (có tên nhãn là delay).    

                            LJMP START                    ; Cho nhẩy về dòng lệnh với tên nhãn là start, công việc sẽ lập lại.

DELAY:              MOV R5,#20                      ; Nạp trị 50 vào thanh nhớ r5.                
D1:                      MOV R6,#20                     ; Nạp trị 20 vào thanh nhớ r6.

D2:                      MOV R7,#248                   ; Nạp trị 248 vào thanh nhớ r7.

                            DJNZ R7,$                        ; Cho giảm r7 theo bước -1 cho đến 0.

                            DJNZ R6,D2                      ; Cho giảm r6 theo bước -1, chưa bằng 0 thì nhẩy về D2.

                            DJNZ R5,D1                      ; Cho giảm r5  theo bước -1, chưa bằng 0 thì nhẩy về D1.

                            RET                                   ; Quay lại dòng lệnh sau lệnh lcall.

                            END                                   ; dừng biên dịch.

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

Bạn thấy khởi đầu luôn dùng câu khai báo giả lệnh:  org 0000h

Nghĩa là mọi việc sẽ bắt đầu từ thanh nhớ có địa chỉ là 0000h. Đây cũng là thanh mà chương trình sẽ nhấy đến mỗi khi Bạn nhấn nút Reset.

và kết thúc với khai báo giả lệnh: end

Các câu lệnh sau khai báo bởi giả lệnh "end" sẽ không được biên dịch.

Nói rõ hơn về cách tính thời gian trễ của đoạn chương trình con delay:

Trong hình trên do dùng thạch anh 12MHz nên một chu kỳ máy sẽ là 1us. 


Vậy câu lệnh:  mov r6,#20    sẽ thực hiện 2 lần. Bạn phải cho nhân 2. Từ đó cách tính như sau:
             MOV R6,#20                       2lần          2

D1:       MOV R7,#248                     2 lần         2       2+2×248=498 20×

              DJNZ R7,$                          2 lần         2×248             (498
              DJNZ R6,D1                       2 lần   2×20=40           10002

Qua các nhân thời gian trễ của đoạn chương trình delay này là 10.002ms.
Nếu Bạn mov vào r6=10 thì thời gian trễ sẽ là 5ms.
Nếu Bạn mov vào r6=20 thì thời gian trễ sẽ là 10ms.

Và để có thời gian trễ là 200ms. Bạn dùng thêm thanh nhớ r5. Mov vào r5=20. Và như vậy đoạn chương trình trễ delay 200ms như sau:


DELAY:     MOV R5,#20     ; chuyển vào thanh ghi r5 số thập phân 20.

D1:             MOV R6,#20     
; chuyển vào thanh ghi r6 số thập phân 20.

D2:             MOV R7,#248   
; chuyển vào thanh ghi r7 số thập phân 248.

                   DJNZ R7,$         ; cho số trong r7 giảm theo bước -1, ở tại chổ và chờ đến khi bằng 0.

                   DJNZ R6,D2      
; cho số trong r6 giảm theo bước -1, và nhẩy về D2 nếu chưa bằng 0.

                   DJNZ R5,D1     
; cho số trong r5 giảm theo bước -1, và nhẩy về D1 nếu chưa bằng 0.

                   RET                   ; quay trở lại thực hiện dóng lệnh sau lệnh call.


 
Bài 2: Viết chương trình dùng Led trên chân 1 (p1.0) theo dõi khóa điện K1 trên chân 10 (p3.0).

* K1 đóng lại Led sáng.
* K1 bỏ ra Led tắt.
ORG 0000H                                      ; Khởi đầu từ thanh ghi 0000h

START:               JB P3.0, LIG         ; Lệnh nhẩy. Nếu chân p3.0 ở bit 1 thì nhẩy đến tên nhãn LIG, Led tắt

                            CLR P1.0             ; Đặt p1.0 về bit 0, chân p1.0 ở mức áp thấp. Led sẽ sáng

                           SJMP START        ; Nhảy về tên nhãn START.

LIG:                    SETB P1.0             ; Đặt p1.0 về bit 1, chân p1.0 ở mức áp cao, Led tắt.

                            SJMP START       
; Nhảy về tên nhãn START.

                           END                       ; Dừng biên dịch ở đây.

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

Ở đây, Bạn dùng lệnh nhẩy theo điều kiện bit, tức lệnh jb (jump bit) hay jnb (jump no bit).

JB P3.0, LIG

Lệnh này có nghĩa là sẽ nhẩy theo trạng thái bit trên chân p3.0.

Nếu xét chân p3.0 ở mức áp cao (nút nhấn K1 hở) thì nhẩy đến tên nhãn LIG, và
Nếu xét chân p3.0 ở mức áp thấp (nút nhấn K1 kín) thì thực hiện câu lệnh kế tiếp bên dưới.

Bạn nhớ, khi chân p3.0 ở mức áp cao thì Led tắt và khi chân p3.0 ở mức áp thấp thì Led sẽ sáng.



Bài 3: Viết chương trình dùng 4 led trên các chân 1 (p0.0), 2 (p0.1), 3 (p0.2), 4 (p0.3) để cho biết trạng thái của 4 khóa điện trên các chân 5 (p0.4), 6 (p0.5), 7(p0.6), 8 (p0.7).

* Khi khóa điện đóng lại Led tương ứng sáng.
* Khi khóa điện nhã ra, Led tương tứng tắt.
ORG 0000H                                               ; Bắt đầu từ thanh ghi 0000h

START:                        MOV A,P1             ; Lấy trang thái trên cảng port 1 nạp vào thanh ghi tích lũy a.

                                      ANL A,#0F0H       ; dùng logic AND để che 4 bit thấp, giữ nguyên trạng thái 4 bit cao.

                                      RR A                    ; cho nội dung trong thanh ghi a quay qua phải 1 bit. 

                                      RR A                    
; cho nội dung trong thanh ghi a quay qua phải 2 bit. 

                                      RR A                    
; cho nội dung trong thanh ghi a quay qua phải 3 bit. 

                                      RR A                    
; cho nội dung trong thanh ghi a quay qua phải 4 bit. 

                                      XOR A,#0F0H      ; dùng logic Ex-OR để phát hiện sự khác bit trên 4 bit thấp.
                                                                   ; như vậy Led ứng với vị trí có bit 0 sẽ phát sáng.

                                      MOV P1,A            ; Chuyển trạng thái của thanh ghi a ra trên port 1 để làm sáng Led. 

                                      SJMP START      ; nhẩy về tên nhãn start để tiếp tục làm như trên.

                                      END                     ; ngừng biên dịch ở dòng lệnh này.

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

a- Dùng 4 phím để tắt mở 4 Led trên port 1
Bạn cho chuyển trạng thái của port 1 vào thanh ghi tích lũy a, chú ý trạng thái của 4 bit cao. Nó phản ảnh nút nhấn K1, K2, K3, K4.


 b- Dùng logic And với hằng 11110000b để cho che 4 bit thấp.
Bạn lấy logic AND giữa thanh a và hằng 0f0h (hay là 11110000b), cách làm này là để bảo toàn trạng thái của 4 bit cao, còn 4 bit thấp đều hóa ra bit 0. Người ta quen gọi là cho che 4 bit thấp.



c- Dùng lệnh quay phải 4 lần để dời 4 bit cao xuống 4 bit thấp.
Dùng lệnh rr a cho quay bit qua phải, nếu cho quay 4 lần thì 4 bit thấp sẽ lên nằm ở vùng 4 bit cao và 4 bit cao sẽ xuống nằm ở vùng 4 bit thấp. Chúng ta nói cho chuyển trạng thái của 4 bit cao xuống vùng 4 bit thấp. Cũng có thể dùng lệnh swap.



d- Dùng logic Ex-Or để phát hiện các bit khác nhau.
Lấy logic Dị-OR để phát hiện các bit giống nhau hay khác nhau:

Nếu các bit giống nhau, kết quả sẽ là bit 0.
Nếu các bit khác nhau, kết quả sẽ là bit 1.

Từ ngả ra, Bạn sẽ thấy Led nằm trên bit 0 sẽ phát sáng. Các Led nằm trên bit 1 sẽ tắt.



Bài 4: Viết chương trình cho 8 Led trên port 1 lần lượt nhấp nháy,  nhẩy qua trái rồi nhẩy qua phải.

ORG  0000h
START:      MOV R2,#8            ; Đặt trị 8 (số lần đếm) vào thanh ghi r2
                   MOV A,#0FEH        ; Đặt trị 0feh tức 11111110b và thanh ghi a.
                   SETB C                  ; Đặt bit Cary lên mức 1.
LOOP:       MOV P1,A               ; Chuyển nội dung trong thanh ghi a vào cảng port 1.
                   LCALL DELAY        ; Cho gọi chương trình làm trễ
                   RLC A                     ; Cho nội dung trong thanh ghi a quay qua trái có cho quay qua bit cờ C.
                   DJNZ R2,LOOP      ; Đếm lùi trị trong thanh ghi r2. Nếu chưa bằng 0 thì làm tiếp lệnh ở LOOP. 
                   MOV R2,#8             ; Nạp lại trị 8 vào thanh ghi r2.
LOOP1:      MOV P1,A               
 ; Chuyển nội dung trong thanh ghi a vào cảng port 1. 
                   LCALL DELAY         
; Cho gọi chương trình làm trễ   
                   RRC A                     
; Cho nội dung trong thanh ghi a quay qua phải có cho quay qua bit cờ C.
                   DJNZ R2,LOOP1     ; Đếm lùi trị trong thanh ghi r2. Nếu chưa bằng 0 thì làm tiếp lệnh ở LOOP1. 
                   LJMP START           ; Nhẩy không điều kiện về tên nhãn start để lại tiếp tục.
DELAY:      MOV R5,#20             ; Chương trình dùng làm trễ (xem lại phần thí dụ 1) 
D1:             MOV R6,#20 
D2:             MOV R7,#248 
                   DJNZ R7,$ 
                   DJNZ R6,D2 
                   DJNZ R5,D1 
                   RET 
                   END                         ; Dừng biên dịch.

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

Bài này dùng lệnh quay bit qua phải và rồi cho quay bit qua trái để dời bit 0 lần lượt đi qua 8 chân của port 1, chúng ta biết bit 0 sẽ làm sáng Led. Như vậy Bạn sẽ thấy các Led trên port 1 sẽ lần lượt sáng và nhẩy qua phải rồi đổi chiều nhẩy qua trái. Để bit 0 có thể đi đủ trên 8 chân của port 1, chúng ta dùng lệnh quay có  quay qua bit cờ C (rrl và rlc), dĩ nhiên trước đó phài nhờ set bit cờ C lên mức 1.

Trình bày lệnh quay rrc và rlc bằng hình minh họa (Bạn xem hình):

a- Bạn dùng lệnh quay có qua cờ C, vậy qua 8 nhịp bit 0 sẽ vào nằm trong cờ C, lúc này 8 bit ở port 1 đều ở mức 1 và như vậy 8 Led trên port 1 đều sẽ tắt. Với lệnh rlc a (rotate left Carry). Bạn sẽ thấy từng Led sáng lên và nhẩy qua bên trái.



b- Bạn dùng lệnh quay có qua cờ C, vậy qua 8 nhịp bit 0 sẽ vào nằm trong cờ C, lúc này 8 bit ở port 1 đều ở mức 1 và như vậy 8 Led trên port 1 đều sẽ tắt. Với lệnh rrc a (rotate right Carry). Bạn sẽ thấy từng Led sáng lên và nhẩy qua bên phải.


c- Lệnh quay (rotate) chỉ có tác dụng với thanh ghi a, do đó Bạn muốn thểhiện kết quả ra 8 Led trên port 1, Bạn phải chuyển nội dung có trong a ra port 1. Bạn dùng lệnh mov p1, a.

Tóm lại, trong bài này Bạn đã làm quen với cách dùng lệnh quay có cho qua cờ C. Với cách viết này, Bạn  thấy chúng ta dùng rất ít câu lệnh mà vẫn khiến cho các Led sáng nhẩy (nhẩy qua nhẩy lại) trên port 1.


Bài 5: Viết chương trình để mạch phát ra tiếng cảnh báo.
Tín hiệu 1KHz và 500Hz phát ra trên chân 1 (p1.0), thời gian phát tín hiệu 1KHz là 100ms và thời gian phát tín hiệu 500Hz là 200ms.

Khóa điện trên chân 8 (p1.7) dùng tắt mở tín hiệu cảnh báo.

FLAG                           BIT 00h                       ; Định nghĩ Flag dùng làm bit cờ, hiện có trị là 0.
ORG 0000H 
START:                        JB P1.7,START         ; Chờ đặt nút K1 đặt xuống mức 0.
                                      JNB FLAG,NEXT      ; Nếu bit cờ Flag là 0 thì nhẩy đến tên nhãn NEXT. 
                                      MOV R2,#200           ; Nạp số thập phân 200 vào thanh ghi r2.
DV:                               CPL P1.0                   ; Lấy bù chân p1.0, lệnh bù bit có chức năng tự đảo. 
                                      LCALL DELY500      ; Cho gọi chương trình làm trễ 500us.
                                      LCALL DELY500      ; gọi lần nữa chương trình dely500.
                                      DJNZ R2,DV             ; Cho đếm lùi và thực hiện lệnh bù cpl p1.0 đến 200 lần.
                                      CPL FLAG                ; Đảo bit trong cờ Flag.
NEXT:                         MOV R2,#200             
 ; Nạp lại số thập phân 200 vào thanh ghi r2. 
DV1:                            CPL P1.0                    
; Lấy bù chân p1.0, có chức năng tự đảo. 
                                      LCALL DELY500      ; Cho gọi chương trình làm trễ 500us.
                                      DJNZ R2,DV1           ; Cho đếm lùi và thực hiện bù cpl p1.0 đến 200 lần.
                                      CPL FLAG                ; Lại cho đảo bit trong cờ Flag.
                                      SJMP START           ; Lập lại lệnh từ tên nhãn START. 
DELY500:                   MOV R7,#250             ; Viết chương trình con làm trễ 500us. Nạp số 250 và thanh ghi r7.
LOOP:                         NOP                            ; Lệnh trống, dùng nó làm tăng thời gian trễ lên gấp đôi.
                                      DJNZ R7,LOOP        ; Đếm lùi r7 để làm trễ.
                                      RET                           ; Cho quay lại thực hiện dòng lệnh sau lệnh call.
END                                                                 ; Dừng biên dịch

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

Trong bài nầy, Bạn thấy dùng khai báo bit để định nghĩa tên tự đặt của Bạn, như:

flag  BIT 0    ; Chữ flag do Bạn tự đặt là một BIT, hiện có giá trị là bit 0.

Bạn dùng lệnh nhẩy theo bit để kiểm tra khóa điện K1.

start: jb p1.7, start     ; Lệnh này sẽ chờ chân p1.7 xuống bit 0, nếu không nó sẽ luôn dừng lại ở đây.

cpl p1.0     ; Lệnh lấy bù trên chân p1.0, nghĩa là nó đang ở mức 0 thì cho chuyển lên 1 và ngước lại.

Phân tích các câu lệnh trên Bạn thấy:

Loa sẽ hú với tín hiệu 1000us  (do 2 lần gọi dely500) và kéo dài 200 lần rồi chuyển qua hú với tín hiệu 500us  (do chỉ gọi dely500 có 1 lần) cũng thức hiện 200 lần. Với cách tạo ra tín hiệu hú 2 nhịp này, Bạn sẽ nghe  tiếng hú từ Loa phát ra, tín hiệu nghe như tiếng còi hụ cảnh báo..



Bài 6: Viết chương trình dùng cách lấy dữ liệu khai báo trong bảng, để tắt mở 8 Led trên port 1.

* Nháy nhẩy qua trái 2 lần. 
* Nháy nhẩy qua phải 2 lần.
* Toàn phần nhấp nháy 2 lần.
(Thời gian trễ 0.2 giấy).

ORG    0000h 
START:               MOV DPTR,#TABLE     ; Lệnh cho đặt địa chỉ bảng vào thanh ghi con trỏ.                         
LOOP:                CLR A                            ; cho xóa nội dung trong thanh ghi a, lúc này a = 00000000b
                            MOVC A,@A+DPTR     ; Cho lấy nội dung trong bảng theo trị trong a, và cho cất kết quả vào a.
                            CJNE A,#01H,LOOP1   ; Nếu a chưa bằng 01h thì nhẩy qua tên nhãn LOOP1.
                            JMP START                   ; Nếu trong a đã bằng 01h thì nhẩy về tên nhãn START.
LOOP1:              MOV P1,A                       ; Chuyển nội dung trong a ra trên cảng port 1.
                           MOV R3,#20                   ; Nạp số thập phân 20 vào thanh ghi r3.
                            LCALL DELAY               ; Gọi chương trình làm trễ, tên nhãn là delay.
                            INC DPTR                      ; cho tăng địa chỉ bảng lên +1. 
                           JMP LOOP                      ; Nhẩy về tên nhãn LOOP.
DELAY:              MOV R4,#20                    ; Viết chương trình con dùng làm trễ, tên nhãn là delay
D1:                     MOV R5,#248                  ; Nạp trị thập phân 248 vào r5.
                            DJNZ R5,$                      ; Cho giảm theo bước -1, chờ r5 bằng 0.
                            DJNZ R4,D1                   ; Cho r4 giảm theo bước -1, chưa bằng 0, nhẩy về D1.
                           DJNZ R3,DELAY              ; Cho r3 giảm theo bước -1, chưa bằng 0, nhẩy về DELAY. 
                            RET                                ; Quay lại chạy câu lệnh nằm sau lệnh call.

TABLE:              DB 0FEH,0FDH,0FBH,0F7H   ; Khai báo các dữ liệu đặt trong bảng, tên bảng là TABLE.
                            DB 0EFH,0DFH,0BFH,07FH  ; các dữ liệu lần lượt sắp trong bảng.
                           DB 0FEH,0FDH,0FBH,0F7H   
; các dữ liệu lần lượt sắp trong bảng.
                            DB 0EFH,0DFH,0BFH,07FH   ; các dữ liệu lần lượt sắp trong bảng.              
                           DB 07FH,0BFH,0DFH,0EFH    
; các dữ liệu lần lượt sắp trong bảng.
                            DB 0F7H,0FBH,0FDH,0FEH   ; các dữ liệu lần lượt sắp trong bảng.
                            DB 07FH,0BFH,0DFH,0EFH   ; các dữ liệu lần lượt sắp trong bảng.
                            DB 0F7H,0FBH,0FDH,0FEH   ; các dữ liệu lần lượt sắp trong bảng.
                            DB 00H, 0FFH,00H, 0FFH       ; các dữ liệu lần lượt sắp trong bảng.
                            DB 01H                                    ; Dữ liệu dùng soa sánh để nhẩy (Xem câu lệnh trên).
  END                                                                   ; Dừng biên dịch tại đây.


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

Trong bài này, chúng ta cho lấy dữ liệu liệt kê trong bảng để làm sáng các Led trên port 1. Trình tự làm như sau:

Trước hết Bạn chọn cách làm sáng tắt cho 8 Led trên port 1 với mã 0/1. Chúng ta nhớ bit 0 làm Led sáng và bit 1 sẽ làm Led tắt. Thí dụ: Muốn Led sáng nhẩy qua trái, chúng ta sẽ chọn mã điều khiển như sau:

11111110b   đổi ra dạng mã hệ 16 sẽ là 0FEH.

11111101b   đổi ra dạng mã hệ 16 sẽ là 0FDH.
11111011b   đổi ra dạng mã hệ 16 sẽ là 0FBH.
11110111b   đổi ra dạng mã hệ 16 sẽ là 0F7H.
11101111b   đổi ra dạng mã hệ 16 sẽ là 0EFH.

11011111b   đổi ra dạng mã hệ 16 sẽ là 0DFH.
10111111b   đổi ra dạng mã hệ 16 sẽ là 0BFH.
01111111b   đổi ra dạng mã hệ 16 sẽ là 07FH.

Bạn cứ liệt kê ra trong bảng. Sau này sẽ dùng lệnh: movc a, @a + dptr. Để lấy các mã này cất vào a. Ý nghĩa của câu lệnh này như sau:

Nếu khởi đầu a=0 thì nó sẽ lấy mã dữ liệu đầu trong bảng và rồi cất vào thanh ghia.
Bạn dùng lệnh inc dptr dể cho trị trong a tăng lên +1.
Vậy khi dùng câu lệnh: movc a, @a +dptr, Bạn sẽ cho lấy mã dữ liệu tiếp theo...

Sau mỗi lần lấy dữ liệu từ bảng ra, Bạn dùng câu lệnh nhẩy theo phép so sánh: cjne a, #01h, loop1 để xem đã lấy đến mã dữ liệu cuối cùng chưa, vì Bạn đặt mả 01H ở cuối bảng.

Ghi nhận: Dùng cách viết này, Bạn rất dễ chọn các kiểu nhấp nháy cho các Led trên port 1. Bạn chỉ cần khai báo các mã điều khiển trong bảng là được. bạn có thể khai báo theo dạng mã nhị phân cho dễ nhìn thấy sự sáng tắt của các Led.


 
Bài 7: Viết chương trình để trên đèn số dùng Led 7 đoạn lần lượt xuất hiện các con số 0, 1, 2, 3...Thời gian thay đổi số là 0.2s.

Chú ý: Dùng loại đèn số Led 7 đoạn có Cathode chung, vậy Led sáng với mức 1.

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

Để hiện các số thập lúc phân trên đèn số 7 đoạn với chân cathode (K) mã các số sẽ như sau:

“0”    hay   3 FH
“1”    hay   06H
“2”    hay   5BH   
“3”    hay   4FH
“4”    hay   66H         
“5”     hay   6DH
“6”    hay   7DH
“7”    hay   07H
“8”    hay   7FH
“9”    hay    6FH           
“A”    hay    77H            
“b”    hay    7CH             
“C”    hay    39H         
“d”    hay    5EH            
“E”    hay   79H              
“F”    hay   71H    

Do vậy để tạo ra bảng hiển thị các số thập phân, chúng ta sẽ viết như sau:
TABLE DB 3FH,06H,5BH,4FH,66H,6DH,7DH,07H,7FH,6FH

ORG 0000h 
START:               MOV R1,#00H             ; Đặt trị khởi đầu 0 cho thanh ghi r1
NEXT:                 MOV A,R1                    ; Cho chuyển nội dung trong r1 vào a.
                            MOV DPTR,#TABLE   ; Đặt địa chỉ của bảng vào thanh ghi con trỏ dptr.
                            MOVC A,@A+DPTR   ; Lấy các mã dữ liệu trong bảng theo trị của a và dữ liệu cất vào a.
                            MOV P2,A                    ; Xuất dữ liệu trong a ra port 2 để cho hiện số.
                            LCALL DELAY             ; Cho gọi chương trình làm trễ, tên nhãn là delay.
                            INC R1                         ; Cho tăng trị trong r1 theo kiểu +1.
                            CJNE R1,#10,NEXT    ; So sánh trị trong r1, xem bằng 10 chưa? chưa, nhẩy về NEXT.
                            LJMP START               ; Lệnh nhảy không điều kiện về câu lệnh có tên nhãn là START.
DELAY:              MOV R5,#20                  ; Viết chương trình làm trễ. Bạn xem lại các phần thí dụ trên.
D2:                      MOV R6,#20 
D1:                      MOV R7,#248 
                            DJNZ R7,$ 
                            DJNZ R6,D1 
                            DJNZ R5,D2 
                            RET 
TABLE:              DB 3FH,06H,5BH,4FH,66H,6DH,7DH,07H,7FH,6FH 
 ; Bảng mã cho hiện các số thập phân.
END                                                            ; Dừng biên dịch.


Nói rõ hơn về loại đèn hiện số dùng Led 7 đoạn (Bạn xem hình):

Khi chân trên port 2 ở mức áp cao, thì Led tương ứng sẽ phát sáng. Vậy chúng ta có thể đặt mã để trên đèn Led 7 đoạn lần lượt hiện ra các con số thập phân.


Hình cho thấy các mã tương ứng với các con số thập phân hiện trên bảng đèn số dùng Led 7 đoạn.


Bài 8: Viết mạch đếm số hiển thi theo hệ cơ 2 với 4 Led trên các chân 1 (p1.0), 2 (p1.1), 3 (p1.2), 4 (p1.3). Mỗi lần nhấn khóa điện SP1 trên chân 17 (p3.7) thì sẽ tăng lên +1.

ORG   0000h 
START:                        MOV R1,#00H             ; Cho khởi đầu với trị 0 trong thanh ghi r1.                  
                                     MOV A,R1                   ; chuyển nội dung trong r1 vào a.                    
                                     CPL A                         ; Lấy bù 8 bit trong thanh ghi a.                       
                                     MOV P1,A                   ; Xuất nội dung trong a ra cảng port 1.                    
REL:                            JNB P3.7,REL             ; Chờ buôn phím nhấn ở chân p3.7.                    
                                     LCALL DELAY10MS   ; Gọi chương trình con làm trễ 10ms.       
                                     JNB P3.7,REL             ; Tránh ảnh hưởng của rung phím.                  
                                     INC R1                        ; Cho tăng trị trong thanh ghi r1                  
                                     MOV A,R1                   
; Cho chuyển nội dung trong r1 vào a.                 
                                     CPL A                         
 ; Lấy bù 8 bit trong thanh ghi a                 
                                     MOV P1,A                    
; Xuất nội dung trong a ra cảng port 1.              
                                     JNB P3.7,$                   ; Chở buông phím SP1                 
                                     SJMP REL                    ; Nhẩy không điều kiện về dòng lênh ở tên nhãn là REL                
DELAY10MS:             MOV R6,#20                   ; Viết chương trình làm trễ 10ms               
L1:                                MOV R7,#248 
                                     DJNZ R7,$ 
                                     DJNZ R6,L1 
                                     RET 
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:

Nội dung bài viết là cứ nhấn một lần phím SP1, mạch đếm số hệ cơ 2 sẽ nhẩy lên 1 số (Bạn xem hình).
Ở đây có 2 câu hỏi, tôi hỏi Bạn:

(1) Vấn đề rung phím là gì?
(2) Tại sao phải lấy bù a rồi mới cho xuất trên cảng port1?

Vấn đề rung phím là do phần tiếp xúc xấu, khi Bạn nhấn xuống, phím sẽ bị rung, nó ngắt mở nhiều lần và tạo ra kết quả sai. Do vậy Bạn phải viết đoạn chương trình chờ 10ms rồi mới xác lập trạng hái của phím, điều này sẽ tăng độ ổn định khi dùng loại phím cơ khí. Cách viết như sau:

REL:  JNB P3.7,REL             
; Khi bạn nhấn xuống, nếu phím tốt, nó sẽ ở bit 0 và sẽ ở trạng thái chờ buông phím. Nếu có rung phím, nó sẽ nhẩy xuống câu lệnh dưới là cho gọi chương trình trễ 10ms.                   

LCALL DELAY10MS   ; Gọi chương trình con làm trễ 10ms.       
; Sau chương trình trễ nó sẽ quay lại để lại kiểm tra phím với câu lệnh: JNB P3.7,REL 
Nếu nó ở bit 0 thì quay lại REL và lại chờ buông phím. Chỉ khi nó đã ở Bit 1 thì mới cho tăng trị trong r1.
                 
.....  
.              

JNB P3.7,$  
; Câu lệnh này là nhẩy tai chổ khi Bạn chưa bỏ phím nhấn SP1 ra.             

Trả lời câu hỏi thứ 2: Tại sao phải lấy bù a (cpl a) rồi mới cho xuất ra trên cảng port1.

Ở đây chúng ta kích Led bằng mức áp thấp, do đó khi tăng 1, nó sẽ là:

00000000b    --> 00000001b  Vậy phải lấy bù của nó sẽ là 11111110b Điều này sẽ chỉ có Led ở p1.0 sáng mà thôi nó ứng với 1 lần nhấn phím.

Nếu 2 lần nhấn phím kết quả là:

00000010b   --> lấy bù là 11111101b. Vậy Led ở p1.1 sẽ sáng. Bạn cứ lý luận tiếp tục sẽ thấy mạch  này dùng đếm hệ cơ 2kết quả cho hiển thị trên các Led của port 1.

và nếu Bạn thấy thích, Bạn có thể gắn đủ 8 Led trên port 1 và sẽ thấy hiện tượng tràng số. Thanh ghi 8 bit chỉ đếm được 256 nhịp sẽ trang số, quay về 0 và bắt đầu đếm tiếp...




Bài 9Viết chương trình để, mỗi lần nhấn khóa điện SP1 trên chân 17 (p3.7) thì Led D1  trên chân 1 (p1.0), nhấp nháy. Khi nhấn SP1 lần nữa đến Led D2 trên chân 2 nhấp nháy, nhấn SP1 lần nữa đến Led D3 trên chân 3 nhấp nháy và nhấn SP1 lần nữa thì đến Led D4 trên chân 4 nhấp nháy, và qui trình tiếp tục lập lại như trên.

 

ID                                 EQU 30H                   ; Lấy thanh nhớ có địa chỉ 30h định nghĩa là thanh ID.
K1                              BIT P3.7                    ; Chân p3.7 định nghĩa với tên là K1
L1                                 BIT P1.0                    ; Chân p1.0 định nghĩa với tên là L1.
L2                                 BIT P1.1                    
; Chân p1.1 định nghĩa với tên là L2.
L3                                 BIT P1.2                    ; Chân p1.2 định nghĩa với tên là L3.
L4                                 BIT P1.3                    ; Chân p1.3 định nghĩa với tên là L4.
ORG 0000h 
                                     MOV ID,#00H            ; Trị khởi đầu của ID là 0.
START:                        JB K1,REL                ; Chưa nhấn phím thì nhẩy đến tên nhãn REL.
                                     LCALL DELAY10MS ; Gọi chương trình làm trễ 10ms (tránh rung phím).
                                     JB K1,REL                ; Chưa nhấn phím thì nhẩy đến tên nhãn REL.
                                     INC ID                        ; Tăng trị trong ID.
                                     MOV A,ID                   ; Cho chuyển nội dung trong ID và thanh ghi a.
                                     CJNE A,#04,REL       ; Cho so sánh a với #04 để phát hiện số lần nhấn K1
                                     MOV ID,#00H             ; Trả trị trong ID về trị o.  
REL:                           JNB K1,$                      ; Chờ buông phím K1
                                     MOV A,ID                    
 ; Cho chuyển nội dung trong ID và thanh ghi a. 
                                     CJNE A,#00H,IS0        
; Cho so sánh a với #00 để phát hiện số lần nhấn K1
                                     CPL L1                        ; Lấy bù L1 để tắt/mở Led D1
                                     LCALL DELAY             ; Gọi chương trình làm trễ với tên nhãn là delay.
                                     SJMP START              ; Nhẩy không điều kiện về tên nhãn START
IS0:                               CJNE A,#01H,IS1       
; Cho so sánh a với #01 để phát hiện số lần nhấn K1
                                     CPL L2                        ; Lấy bù L2 để tắt/mở Led D2
                                     LCALL DELAY             ; Gọi chương trình làm trễ với tên nhãn là delay.
                                     SJMP START              ; Nhẩy không điều kiện về tên nhãn START
IS1:                               CJNE A,#02H,IS2        ; Cho so sánh a với #02 để phát hiện số lần nhấn K1
                                     CPL L3                         ; Lấy bù L3 để tắt/mở Led D3
                                     LCALL DELAY             ; Gọi chương trình làm trễ với tên nhãn là delay.
                                     SJMP START              ; Nhẩy không điều kiện về tên nhãn START                                        
IS2:                               CJNE A,#03H,IS3        ; Cho so sánh a với #03 để phát hiện số lần nhấn K1
                                     CPL L4                         ; Lấy bù L4 để tắt/mở Led D4
                                     LCALL DELAY             ; Gọi chương trình làm trễ với tên nhãn là delay.
                                     SJMP START               ; Nhẩy không điều kiện về tên nhãn START 
IS3:                               LJMP START                ; Nhẩy không điều kiện về tên nhãn START

DELAY10MS:              MOV R6,#20                  ; Chương trình làm trễ
LOOP1:                        MOV R7,#248 
                                     DJNZ R7,$ 
                                     DJNZ R6,LOOP1 
                                     RET 
DELAY:                        MOV R5,#20 
LOOP2:                        LCALL DELAY10MS 
                                     DJNZ R5,LOOP2 
                                     RET 
 END                                                                      ; Dừng biên dịch tại đây.

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

Bạn hãy chú ý đến lệnh so sánh có điều kiện, dùng để phát hiện các mã trùng nhau hay khác nhau và từ đó đưa ra hướng sử lý vấn đề. Thí dụ:

CJNE A,#00H,IS0       

; Cho so sánh a với số #00, nếu khác thì nhẩy đến tên nhãn IS0, nếu đúng thì xuống thi hành dòng lệnh bên dưới.

CPL L1                        ; Lấy bù L1 để tắt/mở Led D1.

LCALL DELAY             ; Gọi chương trình làm trễ với tên nhãn là delay.

SJMP START              ; Nhẩy không điều kiện về tên nhãn START.




Bài 10: Viết chương trình để mạch đếm số lần nhấn phím SP1 trên chân 17 (p3.7), kết quả hiển thị trên đèn số dùng Led 7 đoạn. Số đếm bắt đầu từ 00, 01, 02,...99.


Count                  EQU 30H                           ; Đặt tên thanh ghi 8 bit 30h là Count.
SP1                     BIT P3.7                            ; Đặt tên bit p3.7 là SP1.
ORG  0000h                                                  ; Bắt đầu từ thanh ghi Reset 0000h 
START:               MOV Count,#00H               ; Đặt Count về mức khởi đầu là số 0.
NEXT:                MOV A,Count                       ; Cho chuyển nội dung trong Count vào thanh ghi a.
                            MOV B,#10                          ; Đặt số 10 vào thanh ghi b.
                           DIV AB                                  ; Cho số trong a chia cho 10 (số trong b).
                            MOV DPTR,#TABLE          ; Đặt địa chỉ của bảng có tên là Table vào thanh ghi con trỏ.
                           MOVC A,@A+DPTR            ; Lấy số từ bảng theo trị có trong a và kết quả giữ trong a.
                            MOV P1,A                            ; Cho xuất nội dung trong a ra ở port 1. 
                            MOV A,B                              ; Bây giờ cho chuyển nội dung trong thanh ghi b vào a.
                           MOVC A,@A+DPTR            
; Lại lấy số từ bảng theo trị có trong a và kết quả giữ trong a.    
                            MOV P2,A                            
; Cho xuất nội dung trong a ra ở port 2. 
WT:                     JNB SP1,WT                        ; Chờ buông phím SP1. 
WAIT:                 JB SP1,WAIT                        ; Chờ nhấn phím SP1.
                            LCALL DELY10MS               ; Gọi chương trình trễ 10ms, tránh hiện tượng rung phím.
                           JB SP1,WAIT                         ; Kiểm tra buông phím
                            INC Count                             ; Tăng nội dung trong Count lên theo bước +1.
                            MOV A,Count                        ; Cho chuyển nội dung trong Count vào thanh ghi a.
                           CJNE A,#100,NEXT               ; So sánh trị trong a bằng 100 chưa? Nếu chưa thì tiếp tục. 
                            LJMP START                        ; Quay lại tù đầu.
DELY10MS:       MOV R6,#20                           ; Làm trễ 10ms để tránh ảnh hưởng của rung phím.
D1:                      MOV R7,#248 
                            DJNZ R7,$ 
                           DJNZ R6,D1 
                            RET 
TABLE:              DB 3FH,06H,5BH,4FH,66H,6DH,7DH,07H,7FH,6FH  ; Bảng mã số dùng cho Led 7 đoạn.
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:

Trong đoạn chương trình trên, chúng ta có dùng đến lệnh làm phép toán chia:div ab

Bạn lấy số có trong a chia cho b. Kết qua số chia có trong a và số dư có trong b. Để chia a cho 10, Bạn phải nạp vào thanh ghi b trị 10 với câu lệnh: mov b, #10.

Bạn chú ý đến trình làm trễ 10ms, ở đây dùng để tránh ảnh hưởng  đóc sai do rung phím, vì mỗi khi Bạn nhấn phím, trong khoảng thời gian ngắn phím bị rung và tạo ra sự ghi nhận sai.

Dùng câu lệnh so sánh (cjne: Compare Jump điều kiện Non-Zero) để kiểm tra trị trong thanh ghi a. Đây là một câu lệnh rất thường dùng.


Tạm kết:

Qua 10 bài thực hành cơ bản trên, Bạn thấy chúng ta có thể dùng các câu lệnh  (thuộc phạm vi phần mềm) để khai thác các phần cứng một cách dễ dàng, hiệu quả, đó là điểm đặc sắc của loại ic vi điều khiển. Ngày nay loại ic này có ứng dụng rất rộng rãi và rất đa dạng. Lần lượt trong chuyên mục "Trao đổi học tập" của cửa hàng Phúc_Lan-Shop, tôi sẽ giới thiệu đến Bạn nhiều ứng dụng cụ thể khác nữa, nhất là các ứng dụng có thể tạo ra sản phẩm và làm kinh tế được.Mong loạt bài viết này được Bạn hưởng ứng và giới thiệu cho nhiều Bạn cùng vào đọc. Đa tạ!


Nhắn bạn


Các linh kiện dùng cho các bài thực hành trên Bạn đều có thể tìm thấy ở cửa hàng Phúc Lan Shop. Ngoài ra  ở đây Bạn còn được tham vấn để tìm hiểu các chủ đề thực tế hơn, có hiệu quả kinh tế với Bạn hơn. 




Qua phần trình bày trên, chúng tôi mong Bạn đã hiểu cách dùng loại ic vi điều khiển để dùng nó chấp hành các mệnh lệnh do Bạn soạn ra, nó sẽ luôn trung thành với các câu lệnh mà Bạn đã "cấy" vào bộ nhớ của nó, nếu khi làm thực hành, Bạn gặp trở ngại gì hãy liên lạc với chúng tôi để được góp ý.

 

(1) Bạn có thể liên lạc trực thoại với chúng tôi, dùng phần mềm miễn phí Skype:

Skype name của chúng tôi là: wangqiyun1946, 

 

(2) hay e-mail trực tiếp về Vương Khánh Hưng:

dtth_vuongkhanhhung@yahoo.com

 

(3) hay, qua mục "Liên hệ" của trang Web Phúc-Lan-Shop:   

phuclanshop.com

 
  

Người soạn, giáo viên dạy nghề: Vương Khánh Hưng.


Không có nhận xét nào:

Đăng nhận xét