Vi xử lý - Chương 3: Lập trình hợp ngữ họ mcs-51

Tài liệu Vi xử lý - Chương 3: Lập trình hợp ngữ họ mcs-51: Bài giảng VI XỬ LÝ Chương 3: Lập trình hợp ngữ họ MCS-51 1 CHƯƠNG 3: LẬP TRÌNH HỢP NGỮ HỌ MCS-51 Tại phần trước chúng ta đã chỉ ra cấu trúc 3-bus chung cho tất cả các họ vi xử lý. Với cấu trúc này, tất cả các họ vi xử lý khác nhau có thể thực hiện được mọi công việc mà ta có thể thấy trong cuộc sống, từ điều khiển các quá trình phức tạp, truyền thông, trò chơi điện tử Một câu hỏi đặt ra là: vậy thì cái gì đặc trưng cho bộ vi xử lý để nó có thể thực hiện chức năng riêng biệt của vi xử lý. Đó chính là phần mềm (software), hay chương trình. I. CÁC KHÁI NIỆM CƠ BẢN VỀ LẬP TRÌNH CHO VI XỬ LÝ VÀ VI ĐIỀU KHIỂN 1. Chương trình - Chương trình (program) là chuỗi các câu lệnh hay phát biểu được viết trong một dạng đặc thù (ngôn ngữ lập trình). Các lệnh này khi được thực hiện bởi vi xử lý sẽ thực hiện những thao tác nhất định với kết quả đo...

pdf22 trang | Chia sẻ: tranhong10 | Lượt xem: 2933 | Lượt tải: 2download
Bạn đang xem trước 20 trang mẫu tài liệu Vi xử lý - Chương 3: Lập trình hợp ngữ họ mcs-51, để tải tài liệu gốc về máy bạn click vào nút DOWNLOAD ở trên
Bài giảng VI XỬ LÝ Chương 3: Lập trình hợp ngữ họ MCS-51 1 CHƯƠNG 3: LẬP TRÌNH HỢP NGỮ HỌ MCS-51 Tại phần trước chúng ta đã chỉ ra cấu trúc 3-bus chung cho tất cả các họ vi xử lý. Với cấu trúc này, tất cả các họ vi xử lý khác nhau có thể thực hiện được mọi công việc mà ta có thể thấy trong cuộc sống, từ điều khiển các quá trình phức tạp, truyền thông, trò chơi điện tử Một câu hỏi đặt ra là: vậy thì cái gì đặc trưng cho bộ vi xử lý để nó có thể thực hiện chức năng riêng biệt của vi xử lý. Đó chính là phần mềm (software), hay chương trình. I. CÁC KHÁI NIỆM CƠ BẢN VỀ LẬP TRÌNH CHO VI XỬ LÝ VÀ VI ĐIỀU KHIỂN 1. Chương trình - Chương trình (program) là chuỗi các câu lệnh hay phát biểu được viết trong một dạng đặc thù (ngôn ngữ lập trình). Các lệnh này khi được thực hiện bởi vi xử lý sẽ thực hiện những thao tác nhất định với kết quả đoán trước được. - Có nhiều loại ngôn ngữ lập trình: + Ngôn ngữ máy (machine language) Mã nhị phân Mã bát phân hoặc thập lục phân + Hợp ngữ (assembly language) [cần có assembler – trình dịch hợp ngữ] Mã kí hiệu + Ngôn ngữ cấp cao [cần có compiler – trình biên dịch] Pascal, Fortran, Basic, C, C++, 2. Lưu đồ chương trình - Bước đầu tiên của việc lập trình là xác định rõ ràng mục đích của chương trình và trình tự cần thiết để đạt mục đích đó. Một trong những công cụ quan trọng trong việc phát triển chương trình là lưu đồ chương trình. - Lưu đồ chương trình là biểu diễn bằng hình ảnh thứ tự các thao tác cần làm để giải quyết một vấn để cụ thể. Lưu đồ chương trình không phụ thuộc ngôn ngữ lập trình hoặc loại vi xử lý cụ thể nào. Lưu đồ chương trình chỉ phụ thuộc vào công việc mà người lập trình muốn hoàn thành. - Các khối cơ bản dùng trong lưu đồ chương trình: Khối bắt đầu và kết thúc Khối thực hiện Khối quyết định (khối rẽ nhánh có điều kiện) Gọi chương trình con Khối nhập/xuất Đầu nối(khi qua trang mới) Chỗ nối chung Rất nhiều người lập trình khi mới bắt đầu với việc lập trình thường không thích sử dụng lưu đồ chương trình vì nghĩ rằng việc vẽ lưu đồ là tốn thời gian. Điều này chỉ đúng với các chương trình ngắn và đơn giản, nhưng trường hợp chương trình dài hơn thì nếu không có lưu đồ sẽ rất dễ bị rối rắm. Lưu đồ chương trình giúp sắp xếp các ý tưởng và lời giải của từng vấn đề riêng biệt. Sau khi hoàn thành lưu đồ, ta có thể trao đổi với người khác về ý tưởng Bài giảng VI XỬ LÝ Chương 3: Lập trình hợp ngữ họ MCS-51 2 của mình. Có lưu đồ chương trình thì dù sau một thời gian dài ta vẫn có thể quay lại với chương trình của mình một cách dễ dàng mà không bị “lạc” trong các dòng lệnh vốn rất chi tiết của chương trình hợp ngữ. 3. Khuôn dạng của chương trình hợp ngữ Một chương trình hợp ngữ có thể bao gồm: - Các lệnh (instruction) của vi xử lý/vi điều khiển - Các chỉ dẫn (directive) của trình dịch hợp ngữ - Các điều khiển (control) của trình dịch hợp ngữ - Các chú thích (comment) Các lệnh là các mã gợi nhớ quen thuộc và sẽ được dịch ra mã máy tương ứng với vi xử lý/vi điều khiển. Các chỉ dẫn của trình dịch hợp ngữ là các lệnh của trình dịch hợp ngữ dùng để định nghĩa cấu trúc chương trình, các ký hiệu, dữ liệu, các hằng số Các điều khiển của trình dịch hợp ngữ thiết lập các chế độ trình dịch hợp ngữ và các luồng hợp dịch trực tiếp. Các chú thích giúp cho chương trình dễ đọc bằng cách đưa ra các giải thích về mục đích và hoạt động của các chuỗi lệnh. Các dòng chứa các lệnh và các chỉ dẫn phải được viết theo các qui luật mà trình dịch hợp ngữ hiểu được. Mỗi dòng được chia thành các trường cách biệt nhau bởi khoảng trắng hay khoảng tab. Khuôn dạng tổng quát của mỗi dòng như sau: Tên (Nhãn) Mã gợi nhớ Các toán hạng Chú thích trong đó chỉ có trường mã gợi nhớ là bắt buộc. Với trình dịch hợp ngữ ASM51, trường mã gợi nhớ không cần ở trên cùng một dòng với trường nhãn. Tuy nhiên, trường toán hạng phải ở trên cùng một dòng với trường mã gợi nhớ. Có thể viết các dòng này bằng chữ hoa hay chữ thường và chúng sẽ được coi là tương đương vì trình dịch hợp ngữ không phân biệt kiểu chữ. a. Trường tên Trường này có thể chứa các nhãn, tên biến, hay tên chương trình con (thủ tục). Các tên và nhãn này sẽ được trình dịch hợp ngữ gán bằng các địa chỉ cụ thể của lệnh (hoặc dữ liệu) theo sau. Tên và nhãn có thể có độ dài từ 1 đến 31 ký tự, không chứa khoảng trắng, phải bắt đầu bằng ký tự chữ, dấu ‘?’ hay dấu ‘_’ và tiếp theo phải là các ký tự chữ, các ký số, dấu ‘?’ hay dấu ‘_’. Các tên và nhãn không được trùng với các từ khóa (các mã gợi nhớ, các chỉ dẫn, các toán tử hay các ký hiệu định nghĩa trước). Nói chung, ta cứ đặt các tên bình thường và có ý nghĩa là sẽ ít bị lỗi. Một nhãn được kết thúc bằng dấu ‘:’. b. Trường mã gợi nhớ Trường này chứa mã gợi nhớ (mnemonic) cho biết chức năng của lệnh (ví dụ như ADD, MOV, DIV, MUL, INC) hay chỉ dẫn của trình dịch hợp ngữ (ví dụ như ORG, END, EQU, DB). Các chỉ dẫn không được dịch ra mã máy. c. Trường toán hạng (operand) Trường này chứa địa chỉ hay dữ liệu mà lệnh sẽ sử dụng. Tùy theo từng loại lệnh mà có thể có 0, 1, 2 hay 3 toán hạng. Các toán hạng cách nhau bởi dấu phẩy. d. Trường chú thích (comment) Các chú thích để làm rõ chương trình được đặt trong trường chú thích ở cuối dòng lệnh. Điều này giúp cho người đọc chương trình dễ hiểu các thao tác của chương trình hơn. Các chú thích cần phải được bắt đầu bằng dấu ‘;’. Các chú thích có thể chiếm nhiều dòng riêng và cũng phải bắt đầu bằng dấu chấm ‘;’. Bài giảng VI XỬ LÝ Chương 3: Lập trình hợp ngữ họ MCS-51 3 Khi ta viết chương trình bằng kí tự của bảng chữ cái, ta gọi đây là dạng mnemonic (mã gợi nhớ). Vi xử lý/vi điều khiển không hiểu được các chữ cái này. Chúng đòi hỏi các lệnh phải được viết dưới dạng đặc biệt gọi là object code (mã đối tượng, mã lệnh). Mnemonic được dùng trong chương trình gốc dưới dạng source code (mã nguồn) do người lập trình viết bằng hợp ngữ hoặc (ngôn ngữ lập trình khác). Còn object code là ngôn ngữ chỉ bao gồm các số 1 và 0, đây là ngôn ngữ mà vi xử lý/vi điều khiển sẽ làm việc được. Vi xử lý/vi điều khiển đọc object code từ bộ nhớ dưới dạng các byte và biên dịch các dữ liệu thành lệnh cần thực thi. ™ Một số chỉ dẫn của trình dịch hợp ngữ thường dùng: • ORG Dạng: ORG bieuthuc Chỉ dẫn ORG thay đổi nội dung bộ đếm chương trình theo giá trị của bieuthuc để thiết lập nơi bắt đầu mới của chương trình cho các phát biểu theo sau nó. • END Dạng: END END là phát biểu cuối cùng của chương trình nguồn. Nhãn không được sử dụng trên dòng này. • EQU Dạng: kyhieu EQU bieuthuc Chỉ dẫn EQU gán giá trị của bieuthuc cho kyhieu. Kyhieu phải là tên hợp lệ. • DB Dạng: nhan: DB bieuthuc{, bieuthuc][] Chỉ dẫn DB thường được dùng để định nghĩa các giá trị byte tương ứng với các bieuthuc trong bộ nhớ chương trình bắt đầu từ địa chỉ tương ứng với nhan. 4. Biên dịch chương trình - Chương trình phải được chuyển sang thành dạng object code trước khi vi xử lý/vi điều khiển có thể thực hiện chương trình. Quá trình chuyển từ chương trình dạng source code sang object code gọi là biên dịch/hợp dịch (assembling). - Sau đó ta nạp object code này vào bộ nhớ vi xử lý/vi điều khiển và vi xử lý/vi điều khiển chạy chương trình. Việc chuyển đổi mnemonic sang object code thường thực hiện bằng máy tính. Trước hết ta dùng một chương trình gọi là editor để viết và lưu mã nguồn vào bộ nhớ. Ta có thể sử dụng editor quen thuộc của Window như Notepad hoặc trong môi trường DOS ta sử dụng lệnh edit trong Norton Commandor. Sau đó ta cho chạy chương trình biên dịch gọi là assembler, chương trình này sẽ lấy mã lệnh trong bộ nhớ và biên dịch sang tập tin dưới dạng object code. Cuối cùng, ta dùng một chương khác để nạp object code từ bộ nhớ của máy tính vào bộ nhớ của vi xử lý/vi điều khiển. 5. Nạp chương trình vào bộ nhớ Khi vi xử lý/vi điều khiển được cấp nguồn điện lần đầu hay được khởi động lại bằng cách kích hoạt vào chân RST thì vi xử lý/vi điều khiển thực hiện một số lệnh bên trong. Một trong các lệnh đó là xuất một địa chỉ đặc biệt lên bus địa chỉ và đọc opcode đầu tiên tại địa chỉ đó. Đối với Z80, 8080, 8085 và họ MCS-51 thì đó là địa chỉ 0000H. Do đó, opcode đầu tiên của chương trình cần thực hiện phải được đặt ở vị trí 0000H trong bộ nhớ chương trình và khi viết chương trình nên sử dụng chỉ dẫn ORG 0000H ở dòng đầu tiên của chương trình chính để báo cho trình dịch hợp ngữ biết chương trình được bắt đầu ở địa chỉ 0000H. Chương trình được nạp vào bộ nhớ thực chất chỉ là các số nhị phân hay hex. Trong các số này, có số sẽ là opcode, có số sẽ là dữ liệu được sử dụng bởi các lệnh. Việc nhầm lẫn thứ tự Bài giảng VI XỬ LÝ Chương 3: Lập trình hợp ngữ họ MCS-51 4 lệnh sẽ dẫn đến các kết quả không lường trước được. Phương pháp duy nhất để phân biệt giữa opcode và dữ liệu là cần phải biết địa chỉ chính xác của opcode đầu tiên tring chương trình và nạp chương trình đúng vị trí và theo thứ tự. II. CÁC KIỂU ĐỊNH ĐỊA CHỈ Các kiểu định địa chỉ là phần cần thiết cho toàn bộ tập lệnh của mỗi một bộ vi xử lý hay vi điều khiển. Các kiểu định địa chỉ cho phép xác định rõ nguồn và đích của dữ liệu theo nhiều cách khác nhau mà vi xử lý hay vi điều khiển sử dụng trong quá trình thực thi lệnh. Có 8 kiểu định địa chỉ đối với họ MCS-51: - Thanh ghi (register) - Trực tiếp (direct) - Gián tiếp (indirect) - Tức thời (immediate) - Tương đối (relative) - Tuyệt đối (absolute) - Dài (long) - Chỉ số (index) 1. Định địa chỉ thanh ghi - Trong lệnh truy xuất đến các thanh ghi R0 ÷ R7 của bank thanh ghi tích cực. Các lệnh này được mã hóa dài 1 byte, trong đó dùng 3 bit thấp nhất để chỉ thanh ghi được truy xuất. - Ngoài ra, trong lệnh cũng có thể truy xuất đến các thanh ghi đặc biệt như: thanh ghi tích lũy (ký hiệu A), con trỏ dữ liệu (ký hiệu DPTR), bộ đếm chương trình (ký hiệu PC), cờ nhớ (ký hiệu C) và cặp thanh ghi AB (ký hiệu AB). Các lệnh này không cần các bit địa chỉ, bản thân opcode của lệnh đã chỉ ra thanh ghi được dùng. Ví dụ: INC R1 ; tăng nội dung thanh ghi R1 lên 1 INC A ; tăng nội dung thanh ghi A lên 1 INC DPTR ; tăng nội dung thanh ghi DPTR lên 1 2. Định địa chỉ trực tiếp - Dùng để truy xuất các ô nhớ trong RAM nội (địa chỉ từ 00H ÷ 7FH) hay các thanh ghi chức năng đặc biệt (địa chỉ từ 80H ÷ FFH). Một byte được thêm vào tiếp theo opcode để xác định địa chỉ. - Trình dịch hợp ngữ cho phép sử dụng tên các thanh ghi chức năng đặc biệt (thay cho địa chỉ). Ví dụ: INC ACC ; tăng nội dung thanh ghi A lên 1 Lệnh này cùng chức năng với lệnh INC A ở trên nhưng khác kiểu định địa chỉ → các byte mã lệnh khác nhau. MOV P0,A ; chuyển nội dung của thanh ghi A vào Port 0 (≡ MOV 80H,A) INC 30H ; tăng nội dung ô nhớ 30H lên 1 Nội dung 30H ban đầu là 06H, sau lệnh trên (30H) = 07H 06H 30H Opcode n2 n1 n0 Opcode Địa chỉ trực tiếp Bài giảng VI XỬ LÝ Chương 3: Lập trình hợp ngữ họ MCS-51 5 3. Định địa chỉ gián tiếp - Trong lệnh dùng các thanh ghi R0 và R1 làm con trỏ để chỉ ra địa chỉ ô nhớ trong RAM nội mà lệnh tác động đến. Bit thấp nhất trong mã lệnh sẽ xác định thanh ghi nào được dùng. - Quy ước: dùng dấu @ trước R0 và R1 cho kiểu định địa chỉ này. Ví dụ: (R1) = 30H, (30H) = 52H INC @R1 ; tăng nội dung ô nhớ được trỏ bởi R1 → (R1) = 30H, (30H) = 53H - Kiểu định địa chỉ này thường dùng khi truy xuất tới một vùng nhớ liên tiếp. Ví dụ: Các bước sau được thực hiện để xóa 50 ô nhớ trong RAM nội bắt đầu từ địa chỉ 30H: 4. Định địa chỉ tức thời - Các dữ liệu tức thời được dùng trực tiếp trong lệnh có thể là một hằng số, một ký số, một biểu thức toán học Trình dịch hợp ngữ sẽ tự động tính toán và thay thế dữ liệu tức thời vào mã lệnh. - Quy ước: dùng dấu # trước các toán hạng tức thời. Ví dụ: MOV A,#7 ; nạp giá trị 7 vào thanh ghi A, (A) = 7H MOV A,#7+8 ; nạp giá trị 15 vào thanh ghi A, (A) = 0FH MOV A,#‘B’ ; nạp giá trị 66 (mã ASCII của ký tự B) vào thanh ghi A, (A) = 42H 5. Định địa chỉ tương đối - Được dùng trong các lệnh nhảy ngắn. 52H 30H 30H R1 → 53H 30H 30H R1 Opcode Dữ liệu tức thời Opcode i (R0) = 30H Đủ 50 byte ? - (@R0) = 0 - Tăng R0 N Y Tiếp tục Bài giảng VI XỬ LÝ Chương 3: Lập trình hợp ngữ họ MCS-51 6 - Một địa chỉ tương đối (hay còn gọi là offset) là một giá trị 8 bit có dấu (từ –128 đến +127) cho biết độ lệch từ vị trí lệnh theo ngay sau lệnh nhảy đến đích. Giá trị này được cộng thêm vào thanh ghi bộ đếm chương trình (PC) để tạo ra địa chỉ của lệnh tiếp theo cần được thực thi. Ví dụ: Tính offset cho kiểu định địa chỉ tương đối trong hai trường hợp nhảy tới và nhảy lùi. - Thông thường các đích nhảy được xác định bằng các nhãn và trình dịch hợp ngữ sẽ xác định offset tương đối tương ứng. Ví dụ: Nếu nhãn THERE được đặt ở địa chỉ 1040H và lệnh: SJMP THERE ở trong bộ nhớ chương trình tại địa chỉ 1000H và 1001H → địa chỉ của lệnh kế tiếp sẽ là 1000H + 02H = 1002H, nên offset tương đối sẽ là: offset = 1040H – 1002H = 3EH. Trình dịch hợp ngữ sẽ gán offset tương đối là 3EH cho byte 2 của lệnh SJMP THERE. - Có ưu điểm là không phụ thuộc vào vị trí nhưng bị giới hạn về tầm nhảy. 6. Định địa chỉ tuyệt đối - Chỉ dùng trong các lệnh AJMP và ACALL. - Cho phép rẽ nhánh chương trình trong trang 2K hiện hành của bộ nhớ chương trình (tức tầm nhảy của lệnh là trong trang 2K hiện hành của bộ nhớ chương trình). - 11 bit thấp của địa chỉ đích, trong đó 3 bit cao (A8 ÷ A10) được đưa vào cùng với opcode tạo thành byte thứ 1 của lệnh và 8 bit thấp (A0 ÷ A7) tạo thành byte thứ 2 của lệnh. 5 bit cao của địa chỉ đích là 5 bit cao hiện hành của bộ đếm chương trình (PC) → lệnh theo ngay sau lệnh rẽ nhánh và đích đến phải ở trong cùng 1 trang 2K. - Kiểu định địa chỉ này có tầm nhảy bị hạn chế và cung cấp mã phụ thuộc vị trí. 010A 0109 0108 0107 5 0106 4 0105 3 0104 2 0103 1 0102 0101 05 0100 80 00FF Code memory SJMP 0107H Offset tương đối từ địa chỉ 0102H là “5” (a) Nhảy ngắn tới 2043 2042 2041 F6 -1 2040 80 -2 203F -3 203E -4 203D -5 203C -6 203B -7 203A -8 2039 -9 2038 -10 Code memory SJMP 2038H Offset tương đối từ địa chỉ 2042H là “-10” (b) Nhảy ngắn lùi Hình 3.1 A10 A9 A8 Opcode A7 A0 Opcode Địa chỉ tương đối Bài giảng VI XỬ LÝ Chương 3: Lập trình hợp ngữ họ MCS-51 7 Ví dụ: Nếu nhãn THERE đặt tại địa chỉ 0F46H và lệnh: AJMP THERE ở trong bộ nhớ tại địa chỉ 0900H và 0901H → lệnh theo ngay sau lệnh nhảy bắt đầu ở địa chỉ 0902H sẽ có 5 bit cao địa chỉ trùng với địa chỉ nhãn THERE là 00001 (trang 1). → Mã hoá lệnh: 7. Định địa chỉ dài - Chỉ dùng trong các lệnh LCALL và LJMP. - Đây là các lệnh rẽ nhánh 3 byte, với 2 byte sau (byte 2 và byte 3) là địa chỉ đích của lệnh (16 bit). - Ưu điểm là có thể sử dụng toàn bộ vùng nhớ chương trình 64K, nhưng lệnh lại dài đến 3 byte và phụ thuộc vào vị trí. 8. Định địa chỉ chỉ số - Dùng một địa chỉ nền (chứa trong thanh ghi PC hay DPTR) và một offset (chứa trong thanh ghi A) để tạo địa chỉ được tác động cho các lệnh JMP hoặc MOVC. (Địa chỉ được tác động) = (PC) hoặc (DPTR) + (A) - Thường dùng khi truy xuất dữ liệu trong một bảng dữ liệu đã được định nghĩa trước. Khi đó, thanh ghi PC hay DPTR sẽ giữ địa chỉ đầu bảng và thanh ghi A giữ địa chỉ offset của dữ liệu cần truy xuất trong bảng. Ví dụ: Bảng các giá trị bình phương của số nguyên. Nếu DPTR chứa địa chỉ đầu bảng (tương ứng nhãn TABLE) và (A) = 3, thì sau khi thực hiện lệnh: MOVC A, @A+DPTR → (A) = 09H. 1 1 1 0 0 0 0 1 0 1 0 0 0 1 1 0 Hình 3.2 FFFF F800 2K trang 31 1800 . 17FF 1000 2K trang 2 0FFF 0800 2K trang 1 07FF 0000 2K trang 0 32 x 2K = 64K Trong một trang 2K bất kỳ, chỉ có 11 bit thấp thay đổi (a) Bộ nhớ được chia thành nhiều trang 2K A15 A10 A0 5 bit xác định trang 2K 11 bit xác định địa chỉ trong một trang 2K (b) Bên trong một trang 2K Địa chỉ A15 ÷ A8 Địa chỉ A7 ÷ A0 Opcode 10H 09H 04H 01H 00H TABLE 3 Bài giảng VI XỬ LÝ Chương 3: Lập trình hợp ngữ họ MCS-51 8 III. TẬP LỆNH (tham khảo thêm “Tóm tắt tập lệnh” và “Mô tả lệnh”) Tập lệnh của 8051 được chia làm 5 nhóm: - Nhóm lệnh số học - Nhóm lệnh logic - Nhóm lệnh chuyển dữ liệu - Nhóm lệnh rẽ nhánh (chuyển điều khiển) - Nhóm lệnh xử lý bit IV. CÁC KỸ THUẬT LẬP TRÌNH Lập trình cấu trúc (structured programming) là một kỹ thuật tổ chức và mã hóa các chương trình nhằm giảm sự phức tạp, dễ dàng gỡ rối và hiệu chỉnh chương trình. Lập trình cấu trúc nhấn mạnh đến các nhiệm vụ lập trình. Người lập trình phân tích một nhiệm vụ lớn thành nhiều công việc nhỏ hơn, sau đó dần dần chi tiết, cụ thể hóa để được các vấn đề đơn giản. Qua đó, tìm ra cách giải quyết vấn đề dưới dạng những thuật giải cụ thể rõ ràng, để có thể minh họa bằng ngôn ngữ giải thuật. Trong lập trình cấu trúc, các thuật giải này được gọi là các chương trình con. Cách thức phân tích và thiết kế như vậy ta gọi là nguyên lý lập trình từ trên xuống (top- down), để thể hiện quá trình suy diễn từ cái chung nhất cho đến cái cụ thể nhất. Tất cả các vấn đề lập trình đều có thể được giải quyết chỉ dựa trên 3 cấu trúc: * Các phát biểu * Các vòng lặp * Các lựa chọn 1. Các phát biểu - Các phát biểu là một cách thức cơ bản để thực hiện một công việc nào đó. - Các phát biểu còn bao gồm cả việc gán giá trị cho 1 biến hoặc gọi chương trình con. 2. Cấu trúc vòng lặp - Được sử dụng để thực hiện một hoặc một số công việc lặp đi lặp lại nhiều lần. - Có hai dạng vòng lặp cơ bản: a.WHILE/DO + Cú pháp: WHILE [điều kiện] DO [các phát biểu] + Lưu đồ: Statement Enter Condition true? Exit No Yes Ví dụ: Viết chương trình con SUM tính tổng của một chuỗi các số. Các thông số truyền vào chương trình con là chiều dài của chuỗi số (được chứa trong thanh ghi R7) và địa chỉ bắt đầu của chuỗi số đó trong RAM nội (được chứa trong thanh ghi R0). Kết quả trả về được chứa trong thanh ghi A. Bài giảng VI XỬ LÝ Chương 3: Lập trình hợp ngữ họ MCS-51 9 Giải Pseudo-code: [sum = 0] WHILE [length > 0] DO Begin [sum = sum + @pointer] [tăng pointer] [giảm length] End Lưu đồ: Cộng giá trị với sum Enter Length > 0 ? Exit No Yes Sum = 0 Tăng pointer Giảm length Mã 8051: SUM: CLR A LOOP: CJNE R7, #0, STATEMENT JMP EXIT STATEMENT: ADD A, @R0 INC R0 DEC R7 JMP LOOP EXIT: RET Hoặc: SUM: CLR A INC R7 MORE: DJNZ R7, SKIP RET SKIP: ADD A, @R0 INC R0 SJMP MORE b. REPEATUNTIL Cú pháp: REPEAT [các phát biểu] UNTIL [điều kiện] Bài giảng VI XỬ LÝ Chương 3: Lập trình hợp ngữ họ MCS-51 10 Lưu đồ: Statement Enter Condition true? Exit Yes No Ví dụ 1: Viết chương trình con để tìm một chuỗi được kết thúc bởi ký tự Null được trỏ bởi thanh ghi R0 và xác định xem trong chuỗi có ký tự Z hay không. Kết quả trả về ACC = Z nếu có ký tự Z ở trong chuỗi, nếu không thì ACC = 0. Giải: Pseudo-code: REPEAT [ACC = @pointer] [tăng pointer] Until [ACC == ‘Z’ or ACC == 0] Lưu đồ: Tăng pointer Enter Ký tự = “Z” ? Exit Yes Nhận một ký tự Ký tự = 0 ?No No Yes Mã 8051: STATEMENT: MOV A, @R0 INC R0 JZ EXIT CJNE A, #’Z’, STATEMENT EXIT: RET Bài giảng VI XỬ LÝ Chương 3: Lập trình hợp ngữ họ MCS-51 11 Ví dụ 2: Viết chương trình lấy 10 byte trong RAM nội, địa chỉ bắt đầu là 30H ghi ra RAM ngoài ở địa chỉ bắt đầu là 2000H. Giải: Cách 1: Dùng vòng lặp CJNE ORG 0000H MOV R0,#30H ; R0 trỏ tới địa chỉ 30H trong RAM nội MOV DPTR,#2000H ; DPTR trỏ tới địa chỉ ngoài 2000H LOOP:MOV A,@R0 ; ghi nội dung ô nhớ được trỏ bởi R0 vào A MOVX @DPTR, A ; ghi nội dung trong A ra địa chỉ được trỏ bởi DPTR INC R0 ; tăng chỉ số địa chỉ trong R0 INC DPTR ; tăng chỉ số địa chỉ trong DPTR CJNE R0,#3AH,LOOP ; đủ 10 byte chưa? END Cách 2: Dùng vòng lặp DJNZ ORG 0000H MOV R0,#30H ; R0 trỏ tới địa chỉ 30H trong RAM nội MOV DPTR,#2000H ; DPTR trỏ tới địa chỉ ngoài 2000H MOV R7,#10 ; R7 chứa số lần lặp là 10 LOOP:MOV A,@R0 ; ghi nội dung ô nhớ được trỏ bởi R0 vào A MOVX @DPTR, A ; ghi nội dung trong A ra địa chỉ được trỏ bởi DPTR INC R0 ; tăng chỉ số địa chỉ trong R0 INC DPTR ; tăng chỉ số địa chỉ trong DPTR DJNZ R7,LOOP ; đủ 10 byte chưa? END Ví dụ 3: Viết chương trình cộng một chuỗi số BCD không nén (unpacked – BCD) được cất trong RAM nội bắt đầu từ ô nhớ 31H. Chiều dài chuỗi chứa trong ô nhớ 30H. Kết quả (giả sử là 1 byte) cất vào ô nhớ 2FH. Giải: ORG 0000H MOV R0,#31H ; R0 trỏ tới địa chỉ 31H trong RAM nội CLR A ; ban đầu cho (A) = 0 LOOP:ADD A,@R0 ; cộng nội dung ô nhớ được trỏ bởi R0 vào A INC R0 ; tăng chỉ số địa chỉ trong R0 DJNZ 30H,LOOP ; hết chuỗi chưa? MOV 2FH,A ; cất kết quả sau khi cộng vào ô nhớ 2FH END Ví dụ 4: Viết chương trình đổi các ký tự chữ thường trong các ô nhớ từ 30H → 39H trong RAM nội sang chữ hoa. Biết: Ký tự Mã ASCII (Hex) Chữ hoa (‘A’ ÷ ‘Z’) 41H ÷ 5AH Chữ thường (‘a’ ÷ ‘z’) 61H ÷ 7AH Giải: Nhận xét: Để đổi chữ hoa sang chữ thường ta đặt bit 5 (hay cộng thêm 32) trong mã ASCII của chữ hoa. Ngược lại, để đổi chữ thường sang chữ hoa ta xóa bit 5 (hay trừ đi 32) trong mã ASCII của chữ thường. Bài giảng VI XỬ LÝ Chương 3: Lập trình hợp ngữ họ MCS-51 12 ORG 0000H MOV R0,#30H ; R0 trỏ tới địa chỉ 30H trong RAM nội LOOP:XCH A,@R0 ; hoán đổi nội dung A và ô nhớ được trỏ bởi R0 ANL A,#11011111B ; xóa bit 5 trong mã ASCII, các bit khác giữ nguyên XCH A,@R0 ; cất kết quả trở lại ô nhớ được trỏ bởi R0 INC R0 ; tăng chỉ số địa chỉ trong R0 CJNE R0,#3AH,LOOP ; xử lý xong ô nhớ 39H chưa? END 3. Cấu trúc lựa chọn a. IFTHENELSE Cú pháp: IF [điều kiện] THEN [phát biểu 1] ELSE [phát biểu 2] Lưu đồ: Statement 1 Enter Condition true? Exit Statement 2 Yes No Ví dụ 1: viết một đoạn chương trình nhập một ký tự từ RAM ngoài có địa chỉ là 2000H và kiểm tra ký tự đó. Nếu ký tự nhận được là loại mã ASCII hiển thị được (có giá trị trong khoảng 20H → 7EH) thì xuất lại nó, nếu không thì xuất lại ký tự ‘.’ ra RAM ngoài ở địa chỉ 2001H. Lưu đồ: Xuất lại ký tự đó ra RAM ngoài 2001H Enter Ký tự hiển thị được ? Exit Xuất ký tự ‘.’ ra RAM ngoài 2001H Yes No Nhập ký tự từ RAM ngoài 2000H Bài giảng VI XỬ LÝ Chương 3: Lập trình hợp ngữ họ MCS-51 13 Pseudo-code: [nhập ký tự] IF [ký tự == graphic] THEN [xuất lại ký tự] ELSE [xuất ký tự ‘.’] Mã 8051: ENTER: ACALL INCH ACALL ISGRPH JNC STMENT2 STMENT1: ACALL OUTCH JMP EXIT STMENT2: MOV A, #’.’ ACALL OUTCH EXIT: (tiếp tục) Hay ACALL INCH ACALL ISGRPH JC SKIP MOV A, #’.’ SKIP: ACALL OUTCH (tiếp tục) Ví dụ 2: Viết chương trình kiểm tra một khối dữ liệu trong RAM ngoài có chiều dài 100 byte bắt đầu từ địa chỉ 1000H xem có bao nhiêu giá trị chẵn và lẻ. Số giá trị chẵn và lẻ được lưu tương ứng trong 2 ô nhớ 30H và 31H. Giải: Cách 1: ORG 0000H MOV DPTR,#1000H ; DPTR trỏ tới địa chỉ ngoài 1000H MOV R7,#100 ; R7 chứa số lần lặp là 100 LOOP: MOVX A,@DPTR ; đọc ô nhớ được trỏ bởi DPTR vào A để kiểm tra JB ACC.0,ODD ; (ACC.0) = 1 → số lẻ INC 30H ; (ACC.0) = 0 → số chẳn SJMP CONT ; xét byte kế tiếp ODD: INC 31H CONT: INC DPTR ; tăng chỉ số địa chỉ trong DPTR DJNZ R7,LOOP ; đủ 100 byte chưa? END Cách 2: Có thể thay dòng lệnh JB ACC.0, ODD bằng: ANL A,#01H JNZ ODD Ví dụ 3: Viết chương trình con tên COMPARE_8 so sánh số nhị phân 8 bit trong thanh ghi A với giá trị chuẩn trong ô nhớ RAM nội có địa chỉ 30H. Kết quả trả về: + Nếu (A) > (30H) thì xóa P1.0 + Nếu (A) = (30H) thì xóa P1.1 + Nếu (A) < (30H) thì xóa P1.2 Giải: Bài giảng VI XỬ LÝ Chương 3: Lập trình hợp ngữ họ MCS-51 14 Hướng dẫn: Sử dụng lệnh so sánh CJNE: CJNE arg1, arg2, arg3 Nếu arg1 ≥ arg2 thì C = 0 Nếu arg1 < arg2 thì C = 1 Giải thuật: Chương trình: COMPARE_8: CJNE A,30H,NOT_EQUAL ; (A) # (30H) CLR P1.1 ; (A) = (30H) SJMP EXIT NOT_EQUAL: JNC GREATER ; (C) = 0 → (A) > (30H) CLR P1.2 ; (C) = 1 → (A) < (30H) SJMP EXIT GREATER: CLR P1.0 EXIT: RET b. CASE Cú pháp: CASE [biểu thức] OF 0: [phát biểu 0] 1: [phát biểu 1] 2: [phát biểu 2] . . . n: [phát biểu n] [phát biểu mặc định] END_CASE Lưu đồ: N N Y Y COMPARE_8 (A) = (30H) Xóa P1.1 Xóa P1.0 Xóa P1.2 (C) = 0 RET Bài giảng VI XỬ LÝ Chương 3: Lập trình hợp ngữ họ MCS-51 15 Phát biểu 0 Enter Biểu thức 0 ? Exit Phát biểu 1 Biểu thức 1 ?No Biểu thức 2 ? Biểu thức n ?No Phát biểu 2 Phát biểu n Phát biểu mặc định No Yes Yes Yes Yes No Ví dụ: Một chương trình yêu cầu các đáp ứng 0, 1, 2, hoặc 3 của một user để chọn một trong bốn hành động. Viết đoạn chương trình nhập một ký tự từ bàn phím và nhảy đến ACT0, ACT1, ACT2 hoặc ACT3, phụ thuộc vào đáp ứng của user. Bỏ qua việc kiểm tra lỗi. Pseudo-code: [nhập một ký tự] CASE [ký tự] OF ‘0’: [hành động 0] ‘1’: [hành động 1] ‘2’: [hành động 2] ‘3’: [hành động 3] END_CASE Lưu đồ: Hành động 0 Enter Ký tự = ‘0’ ? Exit Hành động 1 Ký tự = ‘1’ ?No Ký tự = ‘2’ ? Ký tự = ‘3’ ?No Hành động 2 Hành động 3 No Yes Yes Yes Yes No Nhập ký tự Mã 8051 CALL INCH CJNE A, #’0’, SKIP1 ACT0: . . . SKIP1: CJNE A, #’1’, SKIP2 Bài giảng VI XỬ LÝ Chương 3: Lập trình hợp ngữ họ MCS-51 16 ACT1: . . . SKIP2: CJNE A, #’2’, SKIP3 ACT2: . . . SKIP3: CJNE A, #’3’, EXIT ACT2: . . . EXIT: (tiếp tục) Hay CALL INCH ANL A, #3 RL A MOV DPTR, #TABLE JMP @A+DPTR TABLE: AJMP ACT0 AJMP ACT1 AJMP ACT2 ACT3: . . . JMP EXIT ACT0: . . . JMP EXIT ACT1: . . . JMP EXIT ACT2: . . . EXIT: (tiếp tục) 4. Kỹ thuật tạo trễ Ví dụ 1: Viết chương trình con tên DELAY_100 để tạo trễ (trì hoãn) 100 μs. Giả sử dùng thạch anh 12 MHz (fOSC = 12 MHz). Giải: Hướng dẫn: Dùng thời gian thực thi lệnh để tính thời gian tạo trễ cần thiết. fOSC = 12 MHz → fM = fOSC / 12 = 1 MHz → TM = 1 μs Cách 1: Dùng các lệnh NOP DELAY_100: ; dùng 98 lệnh NOP → 98 μs Bài giảng VI XỬ LÝ Chương 3: Lập trình hợp ngữ họ MCS-51 17 NOP NOP NOP RET ; 2 μs → 98 + 2 = 100 μs Cách 2: Dùng vòng lặp để chương trình ngắn gọn hơn. DELAY_100: MOV R7,#49 ; 1 μs LOOP: DJNZ R7,LOOP ; 2 μs / 1 lệnh → 2 x 49 = 98 μs RET ; 2 μs Tổng quát: DELAY_T: MOV R7,#N ; 1 TM, N ≤ 255 LOOP: DJNZ R7,LOOP ; 2 TM / 1 lệnh → (2 x N) TM RET ; 2 TM → tổng thời gian tạo trễ: T = [(1 + 2 x N + 2)TM] ≅ [(2 x N) TM] μs Chú ý: Lệnh LOOP: DJNZ R7, LOOP tương đương với lệnh DJNZ R7,$. Dấu $ là một ký hiệu đặc biệt của trình dịch hợp ngữ ASM51 để tham chiếu vị trí của lệnh hiện hành. Ví dụ 2: Viết chương trình con tên DELAY_10ms để tạo trễ 10 ms. Giả sử dùng thạch anh 12 MHz (fOSC = 12 MHz). Giải: Thời gian cần tạo trễ: T = 10 ms = 10000 μs = 10000 TM. Nếu dùng vòng lặp như ví dụ 8 thì thời gian tạo trễ tối đa khoảng ≅ 2 x 255 = 510μs < 10000μs. Như vậy cần dùng 2 vòng lặp lồng nhau. Chương trình: DELAY_10ms: MOV R7,#20 ; 1 μs LOOP: MOV R6,#250 ; 1 μs DJNZ R6,$ ; 2 μs / 1 lệnh DJNZ R7,LOOP ; 2 μs / 1 lệnh RET ; 2 μs → tổng thời gian tạo trễ: T = 1 + 20(1 + 2 x 250 + 2) + 2 = 10063 μs ≅ 10000 μs Tổng quát: DELAY_T: MOV R7,#M ; 1 TM LOOP: MOV R6,#N ; 1 TM DJNZ R6,$ ; 2 TM / 1 lệnh DJNZ R7,LOOP ; 2 TM / 1 lệnh RET ; 2 TM → tổng thời gian tạo trễ: T = [1 + M(1 + 2 x N + 2) + 2]TM ≅ [(2 x M x N)TM] μs Ví dụ 3: Viết chương trình tạo sóng vuông tuần hoàn đối xứng tại chân P1.0 có tần số là f= 10 KHz. Giả sử fOSC = 12 MHz. Giải: fOSC = 12 MHz → fM = fOSC / 12 = 1 MHz → TM = 1 μs Bài giảng VI XỬ LÝ Chương 3: Lập trình hợp ngữ họ MCS-51 18 f = 10 KHz → T = 0,1 ms = 100 μs Sóng vuông đối xứng → tH = tL = 50 μs = 50TM Chương trình: ORG 0000H LOOP: CPL P1.0 ; 1 μs MOV R7,#23 ; 1 μs DJNZ R7,$ ; 2 x 23 = 46 μs SJMP LOOP ; 2 μs END T tH tL Bài giảng VI XỬ LÝ Chương 3: Lập trình hợp ngữ họ MCS-51 19 CÂU HỎI VÀ BÀI TẬP CHƯƠNG 3 3.1. Hãy cho biết cách định địa chỉ của mỗi lệnh sau: a.MOV R1,A b.MOV A,#12H c.MOV A,@R1 d.PUSH B e.MOV A,12H f.SJMP LOOP g.ACALL SUB1 h.LJMP 0567H 3.2. Để nạp vào R4 giá trị 56H thì có cần dấu ‘#’ trong lệnh: MOV R4,#56H không? 3.3. Sự khác biệt giữa 2 lệnh sau là gì? INC A INC ACC 3.4. Hãy xác định offset tương đối cho lệnh: SJMP AHEAD Biết lệnh đặt tại địa chỉ 0400H và 0401H, nhãn AHEAD đặt tại địa chỉ 041FH. 3.5. Hãy xác định offset tương đối cho lệnh: SJMP BACK Biết lệnh đặt tại địa chỉ A050H và A051H, nhãn BACK đặt tại địa chỉ 9FE0H. 3.6. Giả sử lệnh: AJMP THERE trong bộ nhớ chương trình ở địa chỉ 2FF0H và 2FF1H, nhãn THERE ở địa chỉ 2F96H. Hãy xác định các byte mã máy của lệnh trên? 3.7. Giả sử thanh ghi A chứa 5AH. Hãy cho biết giá trị trong thanh ghi A sau khi thực hiện lệnh sau: XRL A,#0FFH Hãy tìm một lệnh khác tương đương với lệnh trên? 3.8. Giả sử thanh ghi A chứa 50H và thanh ghi PSW chứa 0CH. Hãy cho biết giá trị trong thanh ghi A sau khi thực hiện lệnh sau: RLC A 3.9. Hãy xác định nội dung của thanh ghi A sau khi thực hiện các chuỗi lệnh sau: a. MOV A,#25 MOV R7,#18H ADD A,R7 b. MOV A,#7FH MOV 50H,#29H MOV R0,#50H XCHD A,@R0 3.10. Cho biết giá trị của cờ CY sau khi thực hiện các đoạn mã sau: a. CLR C b. MOV A,#54H c. MOV A,#250 CPL C ADD A,#0C4H ADD A,#05 3.11. Các lệnh nào sau đây là không hợp lệ: 1.MOV R7,#500 2.MOV A,50H 3.ADD A,R5 4.ADD R3,A 5.MOV R1,#50 6.MOV A,#F5H 7.ADD A,#50H 8.MOV @R1,R7 9.PUSH A 10.MOV A,@R3 11.MOV R7,#00 12.MOV R6,R7 3.12. Cho nội dung của các ô nhớ và thanh ghi: (30H) = 12H; (B) = 34H; (A) = 05H. Hãy xác định nội dung của ô nhớ 30H, thanh ghi A và B sau khi thực thi đoạn chương trình sau: MOV R1,#30H XCH A,B XCHD A,@R1 SWAP A XCHD A,@R1 SWAP A 3.13. Xét đoạn chương trình sau: Bài giảng VI XỬ LÝ Chương 3: Lập trình hợp ngữ họ MCS-51 20 MOV R0,#20H MOV R1,#30H MOV R2,#2 ; * CLR C NEXT: MOV A,@R0 ADDC A,@R1 MOV @R0,A INC R0 INC R1 DJNZ R2,NEXT a. Sau khi thực hiện lệnh thứ 3 (có chú thích *), nội dung của R0, R1 và R2 là bao nhiêu? b. Lệnh có nhãn NEXT được thực thi bao nhiêu lần? c. Sau khi hoàn tất chương trình trên thì nội dung của R0, R1 và R2 là bao nhiêu? d. Cho nội dung của các ô nhớ ban đầu là: (20H) = 23H, (21H) = 45H, (30H) = 67H, (31H) = 89H: • Cho biết nội dung của các ô nhớ trên sau khi thực thi xong chương trình trên? • Chức năng của chương trình trên? 3.14. Xét chương trình sau: ORG 0000H MOV R0,#05H MOV R1,#40H MOV R2,#0 ; * MOV @R1,#0 AGAIN: MOV DPTR,#TABLE MOV A,R2 MOVC A,@A+DPTR ADD A,@R1 MOV @R1,A INC R2 DJNZ R0,AGAIN AJMP EXIT TABLE: DB 10H,11H,12H,13H,14H EXIT: NOP END a. Sau khi thực hiện lệnh có chú thích *, nội dung của R0, R1 và R2 là bao nhiêu? b. Lệnh có nhãn AGAIN được thực thi bao nhiêu lần? c. Sau khi hoàn tất chương trình trên thì nội dung của R0, R1 và R2 là bao nhiêu? d. Nội dung của ô nhớ 40H sau khi thực thi xong chương trình trên? e. Chức năng của chương trình trên? f. Nếu kết quả của chương trình trên được cất vào ô nhớ 50H thì lệnh nào cần sửa đổi? 3.15. Viết 1 đoạn chương trình xóa 20 byte ô nhớ RAM nội bắt đầu từ địa chỉ 30H. 3.16. Viết 1 đoạn chương trình xóa 100 byte ô nhớ RAM ngoài bắt đầu từ địa chỉ 1000H. 3.17. Viết 1 đoạn chương trình đọc 20 byte ô nhớ RAM ngoài bắt đầu từ địa chỉ 2000H và ghi vào RAM nội bắt đầu từ địa chỉ 30H. 3.18. Viết chương trình con TINHTB_3SO tính giá trị trung bình của 3 số nguyên dương chứa trong 3 ô nhớ 30H, 31H và 32H. Kết quả (phần nguyên) chứa trong thanh ghi R7. Giả sử tổng của 3 số đó không lớn hơn 255. Bài giảng VI XỬ LÝ Chương 3: Lập trình hợp ngữ họ MCS-51 21 3.19. Viết 1 chương trình con cộng 2 số 16 bit không dấu, số hạng 1 cất trong R7_A (R7: byte cao, A: byte thấp), số hạng 2 cất trong ô nhớ 31H_30H (31H: byte cao, 30H: byte thấp). Kết quả trả về cất trong R7_A. 3.20. Viết 1 chương trình con trừ 2 số 16 bit không dấu, số bị trừ cất trong R7_A (R7: byte cao, A: byte thấp), số trừ cất trong ô nhớ 31H_30H (31H: byte cao, 30H: byte thấp). Kết quả trả về cất trong R7_A. 3.21. * Viết 1 chương trình con nhân số 16 bit cất trong R7_A (R7: byte cao, A: byte thấp) với số 8 bit cất trong B. Kết quả trả về 24 bit cất trong R7_B_A. 3.22. * Viết 1 chương trình con chia số 16 bit cất trong R7_A (R7: byte cao, A: byte thấp) cho số 8 bit cất trong B. Kết quả: thương số cất trong R7_A, dư số cất trong B. 3.23. Viết 1 chương trình con lấy bù 2 của số 16 bit cất trong R7_A (R7: byte cao, A: byte thấp). Kết quả trả về cất trong R7_A. 3.24. Viết chương trình con BINTOBCD chuyển số nhị phân trong A sang số BCD 3 digit (ký số) cất trong các ô nhớ 32H, 31H và 30H (32H: trăm, 31H: chục, 30H: đơn vị). 3.25. Viết chương trình con BCDTOBIN chuyển số BCD không nén (2 ký số) trong A sang số nhị phân cất trong ô nhớ 30H. 3.26. * Viết chương trình con BCDTOBIN16 chuyển số nhị phân 16 bit trong R7_A (R7: byte cao, A: byte thấp) sang số BCD 5 digit cất trong các ô nhớ theo thứ tự từ chục ngàn đến đơn vị là: 34H_33H_32H_31H_30H. 3.27. Viết chương trình đổi các ký tự chữ hoa trong các ô nhớ 30H → 3FH trong RAM nội sang chữ thường. 3.28. Viết chương trình đổi các ký tự chữ hoa trong các ô nhớ 30H → 3FH trong RAM nội sang chữ thường và ngược lại. 3.29. Viết chương trình con SOSANH16 so sánh số 16 bit không dấu cất trong R7_A (R7: byte cao, A: byte thấp) với số 16 bit không dấu làm giá trị chuẩn cất trong ô nhớ 31H_30H (31H: byte cao, 30H: byte thấp). Kết quả trả về: - (C) = 1 nếu (R7_A) < (31H_30H) - (C) = 0 nếu (R7_A) ≥ (31H_30H) Lưu ý: phải bảo toàn nội dung của các thanh ghi và ô nhớ ở trên. 3.30. Viết chương trình kiểm tra một khối dữ liệu trong RAM ngoài có chiều dài 200 byte bắt đầu từ địa chỉ 1000H xem có bao nhiêu byte có giá trị là 0. Kết quả (số byte có giá trị là 0) được lưu vào ô nhớ có địa chỉ là 0FFFH trong RAM ngoài. 3.31. Viết chương trình kiểm tra một khối dữ liệu trong RAM ngoài có chiều dài 50 byte bắt đầu từ địa chỉ 2000H xem có bao nhiêu byte có giá trị là 0, dương và âm. Kết quả được lưu vào các ô nhớ trong RAM nội như sau: - Ô nhớ 30H: chứa số byte bằng 0. - Ô nhớ 31H: chứa số byte dương. - Ô nhớ 32H: chứa số byte âm. 3.32. Viết 1 chương trình con tên DELAY_500 tạo trễ 500μs, biết fOSC = 12 MHz. 3.33. Viết 1 chương trình con tên DELAY_20ms tạo trễ 20ms, biết fOSC = 12 MHz. 3.34. Viết 1 chương trình con tên DELAY_1s tạo trễ 1s, biết fOSC = 12 MHz. 3.35. Viết chương trình xuất chuỗi xung vuông đối xứng có tần số f = 1KHz ra chân P1.0. 3.36. Viết chương trình xuất chuỗi xung vuông ra chân P1.0 với tần số f = 10KHz, duty cycle = 30% (thời gian mức cao = 30% thời gian của chu kì xung). Bài giảng VI XỬ LÝ Chương 3: Lập trình hợp ngữ họ MCS-51 22 3.37. Viết chương trình điều khiển đèn giao thông tại ngã tư đường (đèn xanh sáng 4s, đèn vàng sáng 1s, đèn đỏ sáng 5s). Dùng port 1 để điều khiển các đèn với quy định nếu xuất ra mức logic 0 là đèn sáng: Chân Đèn đường 1 Chân Đèn đường 2 P1.0 Xanh P1.3 Xanh P1.1 Vàng P1.4 Vàng P1.2 Đỏ P1.5 Đỏ 3.38. Cho mạch kết nối như sau: a. Hãy viết chương trình để sáng từng LED theo chiều D1 → D8 và lặp lại, thời gian sáng của mỗi LED là 0,2s. b. Tương tự câu a nhưng theo chiều D8 → D1. c. Kết hợp câu a và b: sáng theo chiều D1 → D8 rồi D8 → D1 và lặp lại. d. Hãy viết chương trình để các LED sáng lan tỏa theo chiều D1 → D8 rồi tắt dần theo chiều D1 → D8 và lặp lại, thời gian cách nhau giữa 2 LED là 0,2s. e. Tương tự câu d nhưng theo chiều từ D8 → D1. 3.39. Cho mạch kết nối như sau: Hãy viết chương trình để xuất giá trị BCD trong ô nhớ 30H ra LED 7 đoạn. P1.0 P1.3 P1.4 P1.5 P1.6 P1.1 P1.2 P1.7 8051 D1 D3 D7 74HC373 1 11 2 5 6 9 12 15 16 19 3 4 7 8 13 14 17 18 OE LE Q1 Q2 Q3 Q4 Q5 Q6 Q7 Q8 D1 D2 D3 D4 D5 D6 D7 D8 D5 330 x 8 +5V D6 D8 D2 +5V D4 +5V P1.0 P1.3 P1.4 P1.5 P1.6 P1.1 P1.2 P1.7 8051 f 74HC373 1 11 2 5 6 9 12 15 16 19 3 4 7 8 13 14 17 18 OE LE Q1 Q2 Q3 Q4 Q5 Q6 Q7 Q8 D1 D2 D3 D4 D5 D6 D7 D8 b d +5V c e a g 330x8

Các file đính kèm theo tài liệu này:

  • pdfCh3.pdf