Giáo trình Vi điều khiển 8051 Assembly - Chương 3: Các lệnh nhảy, vòng lặp và lệnh gọi

Qúa trình lặp lại một chuỗi các lệnh với một số lần nhất định được gọi là vòng

lặp. Vòng lặp là một trong những hoạt động được sử dụng rộng rãi nhất mà bất kỳ bộ

vi sử lý nào đều thực hiện. Trong 8051 thì hoạt động vòng lặp được thực hiện bởi

lệnh “DJNZ thanh ghi, nhãn”. Trong lệnh này thanh ghi được giảm xuống, nếu nó

không bằng không thì nó nhảy đến địa chỉ đích được tham chiếu bởi nhãn. Trước khi

bắt đầu vòng lặp thì thanh ghi được nạp với bộ đếm cho số lần lặp lại. Lưu ý rằng,

trong lệnh này việc giảm thanh ghi và quyết định để nhảy được kết hợp vào trong

một lệnh đơn.

pdf12 trang | Chuyên mục: Kiến Trúc Máy Tính | Chia sẻ: dkS00TYs | Lượt xem: 8489 | Lượt tải: 2download
Tóm tắt nội dung Giáo trình Vi điều khiển 8051 Assembly - Chương 3: Các lệnh nhảy, vòng lặp và lệnh gọi, để xem tài liệu hoàn chỉnh bạn click vào nút "TẢI VỀ" ở trên
 trên đỉnh của ngăn xếp vào bộ đếm chương trình PC và tiếp 
tục thực hiện lệnh tại địa chỉ 07. Sơ đồ bên chỉ ra khung của ngăn xếp sau lần gọi 
LCALL đầu tiên. 
 0A 
09 00 
08 07 
SP = 09 
3.2.3 Sử dụng lệnh PUSH và POP trong các chương trình con. 
 Khi gọi một chương trình con thì ngăn xếp phải bám được vị trí mà CPU cần 
trở về. Sau khi kết thúc chương trình con vì lý do này chúng ta phải cẩn thận mỗi khi 
thao tác với các nội dung của ngăn xếp. Nguyên tắc là số lần đẩy vào (PUSH) và kéo 
ra (POP) luôn phải phù hợp trong bất kỳ chương trình con được gọi vào. Hay nói 
cách khác đối với mỗi lệnh PUSH thì phải có một lệnh POP. Xem ví dụ 3.10. 
3.2.4 Gọi các chương trình con. 
 Trong lập trình hợp ngữ thường có một chương trình chính và rất nhiều 
chương trình con mà chúng được gọi từ chương trình chính. Điều này cho phép ta tạo 
mới chương trình con trong một mô-đun riêng biệt. Mỗi mô-đun có thể được kiểm 
tra tách biệt và sau đó được kết hợp với nhau cùng với chương trình chính. Quan 
trọng hơn là trong một chương trình lớn thì các mô-đun có thể được phân cho các lập 
trình viên khác nhau nhằm rút ngắn thời gian phát triển. 
Ví dụ 3.10: 
 Phân tích ngăn xếp đối với lệnh LCALL đầu tiên trong đoạn mã. 
01 0000 ORG 0 
02 0000 7455 BACK: MOV A, #55H ; Nạp A với giá trị 55H 
03 0002 F590 MOV P1, A ; Gửi 55H ra cổng P1 
04 0004 7C99 MOV R4, #99H 
05 0006 7D67 MOV R5, #67H 
06 0008 120300 LCALL DELAY ; Tạo giữ chậm thời gian 
07 000B 74AA MOV A, #0AAH ; Nạp A với AAH 
08 000D F590 MOV P1, A ; Gửi AAH ra cổng P1 
09 000F 120300 LCALL DELAY 
10 0012 80EC SJMP BACK ; Tiếp tục thực hiện 
11 0014 ; ............ Đây là chương trình con DELAY 
12 0300 ORG 300H 
13 0300 C004 DELAY PUSH 4 ; Đẩy R4 vào ngăn xếp 
14 0302 C005 PUSH 5 ; Đẩy R5 vào ngăn xếp 
15 0304 7CFF MOV R4, 00FH ; Gán R4 = FFH 
16 0306 7DFF NEXT: MOV R5, #00FH ; Gán R5 = 255 
17 0308 DDFE AGAIN: DJNZ R5, AGAIN 
18 030A DCFA DJNZ R4, NEXT 
19 030C D005 POP 5 ; Kéo đỉnh ngăn xếp vào R5 
20 030E D004 POP 4 ; Kéo đỉnh ngăn xếp vào R4 
21 0310 22 RET ; Trở về nguồn gọi 
22 0311 END ; Kết thúc tệp tin hợp ngữ 
Lời giải: 
 Trước hết lưu ý rằng đối với các lệnh PUSH và POP ta phải xác định địa chỉ 
trực tiếp của thanh ghi được đẩy vào, kéo ra từ ngăn xếp. Dưới đây là sơ đồ khung 
của ngăn xếp. 
Sau lệnh LCALL thứ nhất Sau lệnh PUSH 4 Sau lệnh POSH 5 
0B 0B 0B 67 R5 
0A 0A 99 R4 0A 09 R4 
09 00 PCH 09 00 PCH 09 00 PCL 
08 0B PCL 0B 0B PCL 08 0B PCL 
 Cần phải nhấn mạnh rằng trong việc sử dụng LCALL thì địa chỉ đích của các 
chương trình con có thể ở đâu đó trong phạm vi 64k byte không gian bộ nhớ của 
8051. Điều này không áp dụng cho tất cả mọi lệnh gọi CALL chẳng hạn như đối với 
ACALL dưới đây: 
 Hình 3.1: Chương trình chính hợp ngữ của 8051 có gọi các chương trình con. 
3.2.5 Lệnh gọi tuyệt đối ACALL (Absolute call). 
 Lệnh ACALL là lệnh 2 byte khác với lệnh LCALL dài 3 byte. Do ACALL chỉ 
có 2 byte nên địa chỉ đích của chương trình con phải nằm trong khoảng 2k byte địa 
chỉ vì chỉ có 11bit của 2 byte được sử dụng cho địa chỉ. Không có sự khác biệt nào 
giữa ACALL và LCALL trong khái niệm cất bộ đếm chương trình vào ngăn xếp hay 
trong chức năng của lệnh trở về RET. Sự khác nhau duy nhất là địa chỉ đích của lệnh 
LCALL có thể nằm bất cứ đâu trong phạm vi 64k byte không gian địa chỉ của 8051, 
còn trong khi đó địa chỉ của lệnh ACALL phải nằm trong khoảng 2 byte. Trong 
nhiều biến thế của 8051 do các hãng cung cấp thì ROM trên chíp chỉ có 1k byte.. 
Trong những trường hợp như vậy thì việc sử dụng ACALL thay cho LCALL có thể 
tiết kiệm được một số byte bộ nhớ của không gian ROM chương trình. 
Ví dụ 3.11: 
 Một nhà phát triển sử dụng chíp vi điều khiển Atmel AT89C1051 cho một sản 
phẩm. Chíp này chỉ có 1k byte ROM Flash trên chíp. Hỏi trong khi lệnh LCALL và 
ACALL thì lệnh nào hữu ích nhất trong lập trình cho chíp này. 
Lời giải: 
 Lệnh ACALL là hữu ích hơn vì nó là lệnh 2 byte. Nó tiết kiệm một byte mỗi 
lần gọi được sử dụng. 
 Tất nhiên, việc sử dụng các lệnh gọn nhẹ, chúng ta có thể lập trình hiệu quả 
bằng cách có một hiểu biết chi tiết về tất cả các lệnh được hỗ trợ bởi bộ vi xử lý đã 
cho và sử dụng chúng một cách khôn ngoan. Xét ví dụ 3.12 dưới đây. 
Ví dụ 3.12: 
 Hãy viết lại chương trình ở ví dụ 3.8 một cách hiệu quả mà bạn có thể: 
Lời giải: 
 ; MAIN program calling subroutines 
 ORG 0 
MAIN: LCALL SUBR-1 
 LCALL SUBR-2 
 LCALL SUBR-3 
 HERE: SJMP MAIN 
 ;----------------- end of MAIN 
 ; 
 SUBR-1l ... 
 ... 
 RET 
 ; ----------------- end of subroutinel 1 
 ; SUBR-1l ... 
 ... 
 RET 
 ; ----------------- end of subroutinel 2 
 ; SUBR-1l ... 
 ... 
 RET 
 ; ----------------- end of subroutinel 3 
 END ; end of the asm file 
 ORG 0 
 MOV A, #55H ; Nạp Avới giá trị 55H 
 BACK: MOV P1, A ; Xuất giá trị trong A ra cổng P1 
 ACALL DELAY ; Giữ chậm 
 CPL A ; Bù thành ghi A 
 SJMP BACK ; Tiếp tục thực hiện vô hạn 
 ; -------- Đây là chương trình con giữ chậm DELAY 
 DELAY: 
MOV R5, #0FFH ; Nạp R5 = 255 (hay FFH) làm cho bộ đếm 
 AGAIN: DJNZ R5, AGAIN ; Dừng ở đây cho đến khi R5 = 0 
 RET ; Trở về 
 END ; Kết thúc 
3.3 Tạo và tính toán thời gian giữ chậm. 
3.3.1 Chu kỳ máy: 
 Đối với CPU để thực hiện một lệnh thì mất một chu kỳ đồng hồ này được coi 
như các chu kỳ máy. Phụ lục AppendixA.2 cung cấp danh sách liệt kê các lệnh 8051 
và các chu kỳ máy của chúng. Để tính toán một độ trễ thời gian, ta sử dụng danh 
sách liệt kê này. Trong họ 8051 thì độ dài của chu kỳ máy phụ thuộc vào tần số của 
bộ dao động thạch anh được nối vào hệ thống 8051. Bộ dao động thạch anh cùng với 
mạch điện trên chip cung cấp xung đồng hồ cho CPU của 8051 (xem chương 4). Tần 
số của tinh thể thạch anh được nối tới họ 8051 dao động trong khoảng 4MHz đến 30 
MHz phụ thuộc vào tốc độ chíp và nhà sản xuất. Thường xuyên nhất là bộ dao động 
thạch anh tần số 10.0592MHz được sử dụng để làm cho hệ 8051 tương thích với 
cổng nối tiếp của PC IBM (xem chương 10). Trong 8051, một chu kỳ máy kéo dài 12 
chu kỳ dao động. Do vậy, để tính toán chu kỳ máy ta lấy 1/12 của tần số tinh thể 
thạch anh, sau đó lấy giá trị nghịch đảo như chỉ ra trong ví dụ 3.13. 
Ví dụ 3.13: 
 Đoạn mã dưới đây trình bày tần số thạch anh cho 3 hệ thống dựa trên 8051 
khác nhau. Hãy tìm chu kỳ máy của mỗi trường hợp: a) 11.0592MHz b) 16MHz và 
c) 20MHz. 
Lời giải: 
a) 11.0592/12 = 921.6kHz; Chu kỳ máy là 1/921.6kHz = 1.085ms (micro giây) 
b) 16MHz/12 = 1.333MHz; Chu kỳ máy MC = 1/1.333MHz = 0.75ms 
c) 20MHz/12 = 1.66MHz ị MC = 1/1.66MHz = 0.60ms 
Ví dụ 3.14: 
 Đối với một hệ thống 8051 có 11.0592MHz hãy tìm thời gian cần thiết để 
thực hiện các lệnh sau đây. 
a) MOV R3, #55 b) DEC R3 c) DJNZ R2 đích 
d) LJMP e) SJMP f) NOP g) MUL AB 
Lời giải: 
 Chu kỳ máy cho hệ thống 8051 có tần số đồng hồ là 11.0592MHz Là 1.085ms 
như đã tính ở ví dụ 3.13. Bảng A-1 trong phụ lục Appendix A trình bày số chu kỳ 
máy đối với các lệnh trên. Vậy ta có: 
Lệnh Chu kỳ máy Thời gian thực hiện 
(a) MOV R3, #55 1 1 ´ 1.085 ms = 1.085 ms 
(b) DEC R3 1 1 ´ 1.085 ms = 1.085 ms 
(c) DJNZ R2, target 2 2 ´ 1.085 ms = 2.17 ms 
(d) LJMP 2 2 ´ 1.085 ms = 2.17 ms 
(e) SJMP 2 2 ´ 1.085 ms = 2.17 ms 
(f) NOP 1 1 ´ 1.085 ms = 1.085 ms 
(g) MUL AB 4 4 ´ 1.085 ms = 4.34 ms 
3.3.2 Tính toán độ trễ. 
 Như đã trình bày ở trên đây, một chương trình con giữ chậm gồm có hai 
phần: (1) thiết lập bộ đếm và (2) một vòng lặp. Hầu hết thời gian giữ chậm được thực 
hiện bởi thân vòng lặp như trình bày ở ví dụ 3.15. 
Ví dụ 3.15: 
 Hãy tìm kích thước của thời gian giữ chậm trong chương trình sau, nếu tần số 
giao động thach anh là 11.0592MHz. 
 MOV A, #55H 
 AGAIN: MOV P1, A 
 ACALL DELAY 
 CPL A 
 SJMP AGAIN 
 ; -------- Time delay 
 DELAY: MOV R3, #200 
 HERE : DJNZ R3, HERE 
 RET 
Lời giải: 
 Từ bảng A-1 của phụ lục Appendix A ta có các chu kỳ máy sao cho các lệnh 
của chương trình con giữ chậm là: 
 DELAY: MOV R3, #200 1 
 HERE : DJNZ R3, HERE 2 
 RET 1 
 Do vậy tổng thời gian giữ chậm là [(200 ´ 2) + 1 + 1] ´ 1.085 = 436.17ms. 
 Thông thường ta tính thời gian giữ chậm dựa trên các lệnh bên trong vòng lặp 
và bỏ qua các chu kỳ đồng hồ liên quan với các lệnh ở ngoài vòng lặp. 
 Trong ví dụ 3.15 giá trị lớn nhất mà R3 có thể chứa là 255, do vậy một cách 
tăng độ trễ là sử dụng lệnh UOP (không làm gì) trong vòng lặp để tiêu tốn thời gian 
một cách đơn giản. Điều này được chỉ ra trong ví dụ 3.16 dưới đây. 
Ví dụ 3.16: 
 Hãy tìm độ trễ thời gian cho chương trình con sau. Giả thiết tần số dao động 
thạch anh là 11.0592MHz. 
 Số chu kỳ máy 
 DELAY: MOV R3, #250 1 
 HERE : NOP 1 
 NOP 1 
 NOP 1 
 NOP 1 
 DJNZ R3, HERE 2 
 RET 1 
Lời giải: 
 Thời gian trễ bên trong vòng lặp HERE là [250 (1 + 1 + 1 + 1 + 1 + 2)] ´ 
1.0851ms = 1627.5ms. Cộng thêm hai lệnh ngoài vòng lặp ta có 1627.5ms ´ 1.085ms 
= 1629.67ms. 
3.3.3 Độ trễ thời gian của vòng lặp trong vòng lặp. 
 Một cách khác để nhận được giá trị từ độ trễ lớn là sử dụng một vòng lặp bên 
trong vòng lặp và cũng được gọi là vòng lặp lồng nhau. Xem ví dụ 3.17 dưới đây. 
Ví dụ 3.17: 
 Đối với một chu kỳ máy 1.085ms hãy tính thời gian giữ chậm trong chương 
trình con sau: 
 DELAY: chu kỳ máy 
 MOV R2, #200 1 
 AGAIN: MOV R3, #250 1 
 HERE: NOP 1 
 NOP 1 
 DJNZ R3, HERE 2 
 DJNZ R2, AGAIN 2 
 RET 1 
Lời giải: 
 Đối với vòng lặp HERE ta có (4 ´ 250) ´ 1.085ms = 1085ms. Vòng lặp 
AGAIN lặp vòng lặp HERE 200 lần, do vậy thời gian trễ là 200 ´ 1085ms 217000ms, 
nên ta không tính tổng phí. Tuy nhiên, các lệnh “MOV R3, #250” và “DJNZ R2, 
AGAIN” ở đầu và cuối vòng lặp AGAIN cộng (3 ´ 200 ´ 1.085ms) = 651ms vào thời 
gian trễ và kết quả ta có 217000 + 651 = 217651ms = 217.651 miligiây cho tổng thời 
gian trễ liên quan đến chương trình con giữ chậm DELAY nói trên. Lưu ý rằng, 
trong trường hợp vòng lặp lồng nhau cũng như trong mọi vòng lặp giữ chậm khác 
thời gian xấp xỉ gần dúng vì ta bỏ qua các lệnh đầu và cuối trong chương trình con. 

File đính kèm:

  • pdfVi_dieu_khien_8051_ Assembly_03_CaCLenhNhay.pdf
Tài liệu liên quan