Vi xử lý 1

              Trong chương trình học ngành Công nghệ Kỹ thuật Điện, Điện tử, sinh viên sẽ được học 6 tín chỉ về Vi xử lý, bao gồm:
1. Vi xử lý 1
2. Vi xử lý 2
3. Thực hành Vi xử lý & Vi điều khiển
              Các học phần này được học sau học phần Kỹ thuật số. Không chỉ là học phần cơ sở ngành, Vi xử lý & Vi điều khiển còn có nhiều ứng dụng thực tế. Đồ án môn học 2, các cuộc thi sáng tạo kỹ thuật và Robocon do khoa tổ chức cũng gắn liền với môn học này. Có thể nói, đây là các học phần rất thú vị nhưng sinh viên cũng gặp nhiều khó khăn với nhiều khái niệm mới.
Vi xử lý 1:
Nội dung học phần Vi xử lý 1 bao gồm 2 phần chính:
- vi xử lý 80x86
- vi điều khiển 8051
            Phần đầu cung cấp cho các em các kiến thức cơ bản về kiến trúc hệ vi xử lý, cấu trúc và nguyên tắc hoạt động của CPU, tổ chức bộ nhớ và các thiết bị ngoại vi, cách mã hóa lệnh, các chế độ định địa chỉ, tập lệnh và cách viết chương trình cho 80x86, ngắt và truy nhập trực tiếp bộ nhớ DMA.
           Tiếp theo các em sẽ học về Vi điều khiển họ 8051. Đây là một họ vi điều khiển khá phổ biến và sinh viên dễ tiếp cận. Khi có kiến thức về họ vi điều khiển này, các em sẽ dễ dàng học về các họ vi điều khiển khác như PIC, AVR, v.v. Các em sẽ được học về cấu trúc, các chế độ định địa chỉ, tập lệnh, viết chương trình hợp ngữ cho vi điều khiển 8051. Ngắt và timer/counter cũng được giới thiệu cùng với một số bài tập ứng dụng.

             Để học tốt học phần này ngoài tài liệu, các em cần một số phần mềm hỗ trợ lập trình, mô phỏng như EMU8086, Pinnacle 52 (nên thay thế bằng Keil C để chạy tốt trên các bản Windows mới và được sử dụng nhiều trong thực tế) và Proteus.
Download EMU8086: download
Download Pinnacle 52: download
Phần mềm Proteus (để mô phỏng): trang chủ

             Các em cần cài đặt các phần mềm đã giới thiệu, học cách sử dụng chúng. Tài liệu hướng dẫn sử dụng phần mềm thầy đã gửi link ở phần dưới. Các em nên làm một số ví dụ mẫu để biết quy trình sử dụng, sau đó làm các bài tập, học cách mô phỏng từng bước chương trình để kiểm tra so sánh giữa ý hiểu và kết quả thực tế.

Một số vấn đề khi học phần vi xử lý 80x86

1. Cách mã hóa lệnh
            Qua cách mã hóa lệnh các em sẽ hiểu được cách thức một lệnh được viết dưới dạng mã nhị phân mà vi xử lý có thể hiểu được. Từ đó giúp các em hiểu rằng tất cả lệnh và dữ liệu trong hệ vi xử lý đều tồn tại dưới dạng nhị phân và tại sao khi đọc một chuỗi số nhị phân vi xử lý biết được phải làm gì.
Các em không phải nhớ một lệnh, ví dụ MUL, có mã nhị phân là bao nhiêu mà cần hiểu một lệnh được xây dựng từ các trường nào? ý nghĩa của mỗi trường ra sao? Từ đó em biết cách mã hóa một lệnh gợi nhớ bất kỳ.
Ví dụ, lệnh MOV AL, BL được mã hóa dưới dạng nhị phân thế nào?
            Tra trong tài liệu ta sẽ thấy lệnh MOV được mã hóa bởi một trường gồm 6 bit.
Tiếp theo để chuyển dữ liệu vào thanh ghi AL, vậy AL được xác định bằng các trường nào? Chúng ta thấy có các trường hướng D (D=1 dữ liệu đi tới thanh ghi, D=0 dữ liệu đi từ thanh ghi), trường W (W=0: toán hạng byte, W=1 toán hạng word), trường REG gồm 3 bit dùng để xác định thanh ghi.
Để xác định thanh ghi BL sẽ cần các trường MOD và R/M. Tra bảng ta sẽ thấy hai trường này kết hợp với nhau để tạo ra chế độ định địa chỉ thanh ghi để truy nhập đến BL.
Với việc xác định như vậy, các em sẽ lần lượt xác định được giá trị của các trường và bit tương ứng từ đó biết được mã lệnh của cả lệnh.
Sau khi mã hóa, cần gõ lệnh vào phần mềm, hợp dịch để kiểm tra mã nhị phân tương ứng của lệnh có đúng với cách tính toán không.

2. Học lệnh
            Vi xử lý 80x86 có tập lệnh rất lớn và các em không cần thiết phải học tất cả các lệnh. Điều các em cần học là học cách tra cứu và sử dụng một lệnh bất kỳ. Sau một quá trình làm các bài tập và ví dụ, các em sẽ tự nhớ một số lệnh hay được sử dụng.
            Trước tiên các em cần tổ chức các lệnh thành các nhóm lệnh cho dễ học, ví dụ nhóm lệnh di chuyển dữ liệu, nhóm lệnh số học, nhóm lệnh logic, nhóm lệnh rẽ nhánh chương trình, v.v. Với mỗi nhóm lệnh này cần liệt kê một vài lệnh.
           Với mỗi lệnh cần tìm hiểu cú pháp của lệnh bao gồm: mã lệnh, toán hạng (có bao nhiêu toán hạng, có thể sử dụng chế độ định địa chỉ nào), tác dụng của lệnh và ảnh hưởng lên các cờ thế nào. Với mỗi lệnh tài liệu đã giải thích rõ. Tuy nhiên, để thực sự hiểu và vận dụng được lệnh các em cần sử dụng phần mềm để kiểm chứng ý hiểu của mình.
Lấy ví dụ muốn biết lệnh DIV có ý nghĩa gì và cách sử dụng như thế nào?
Các em tra trong tài liệu sẽ thấy cú pháp của lệnh có dạng: DIV Toánhạng
Lệnh này thực hiện chia 2 toán hạng. 
- Trường hợp Toánhạng kiểu byte, lấy nội dung thanh ghi AX chia cho toán hạng. Kết quả phần dư lưu trên AH, phần nguyên lưu trên AL
- Trường hợp Toánhạng kiểu word, lấy nội dung thanh ghi DX AX chia cho toán hạng. Kết quả phần nguyên lưu trên thanh ghi AX, phần dư lưu trên DX.
           Để kiểm tra ý hiểu của mình có đúng không, các em cần làm một vài ví dụ nhỏ để kiểm tra kết quả trên phần mềm. Nếu kết quả trùng với suy đoán thì em đã hiểu hoạt động của lệnh. Ví dụ, trong trường hợp này, nếu ta nạp giá trị 102 vào thanh ghi AX và giá trị 100 vào thanh ghi BL thì kết quả phép chia DIV BL sẽ phải cho thanh ghi AH giá trị 2 và AL giá trị 1. Viết đoạn lệnh sau:

org 100h
mov ax,102
mov bl,100
div bl
Dịch và thực hiện lệnh từng bước. Sau khi thực hiện xong lệnh DIV, nếu thanh ghi AH và AL cho cùng giá trị như suy đoán thì ta đã hiểu đúng sự thực hiện của lệnh.

Một số vấn đề khi học vi điều khiển 8051

1. Sự khác biệt giữa Vi xử lý và Vi điều khiển?
            Vi xử lý (microprocessor) là một chip chứa thành phần trung tâm của một hệ vi xử lý: CPU. Để hệ vi xử lý có thể hoạt động được thì một mình chip vi xử lý là chưa đủ. Hệ thống cần bổ xung các thành phần khác như bộ nhớ, các thiết bị vào ra và mạch phụ trợ. Chính vì vậy mà việc thiết kế hệ thống rất linh hoạt, đáp ứng cho các hệ thống từ đơn giản đến phức tạp với dung lượng bộ nhớ thay đổi, số lượng thiết bị ngoại vi thay đổi. Các chương trình thường được lưu trữ trong bộ nhớ ngoài và được tải vào RAM để hoạt động. Các chương trình điều khiển các thành phần trong hệ thống có dung lượng nhỏ và thường ít thay đổi mới được lưu trong bộ nhớ ROM. Các hệ thống xây dựng dựa trên chip vi xử lý cũng thường có khả năng mở rộng  để thêm các tính năng mới phù hợp với người sử dụng. Việc xây dựng các hệ thống dựa trên chip vi xử lý thường khá phức tạp và thường là các hệ đa mục đích với khả năng tính toán, xử lý dữ liệu nhanh.
             Khác với vi xử lý, vi điều khiển (microcontroller) là một hệ thống trên chip (system on chip), nghĩa là bên trong một chip đã tổ hợp sẵn không chỉ bộ vi xử lý mà còn tích hợp cả bộ nhớ, mạch ngoại vi phụ trợ. Hệ thống xây dựng dựa trên chip vi điều khiển thường đơn giản hơn rất nhiều so với hệ thống xây dựng dựa trên vi xử lý. Hệ thống dựa trên vi điều khiển thường đáp ứng cho một nhiệm vụ cụ thể khi được xây dựng. Chúng thường là các hệ thống điều khiển có yêu cầu tính toán xử lý dữ liệu không đòi hỏi tốc độ và khối lượng lớn ví dụ như máy giặt, lò vi sóng, VCR, v.v. Hệ thống dựa trên vi điều khiển thường có kích thước nhỏ, tiêu tốn ít năng lượng và giá thành thấp hơn so với hệ thống dựa trên vi xử lý. Chương trình được lưu trữ trong bộ nhớ chương trình ROM.
             Đối với sinh viên ngành điện tử, việc tiếp cận với vi xử lý thông qua chip vi điều khiển thường dễ  dàng hơn trong việc tự xây dựng một ứng dụng thực tế hoàn chỉnh, giá thành thấp.

2.Tại sao học vi điều khiển 8051?
            Vi điều khiển 8051 được Intel thiết kế và sản xuất từ những năm cuối thập kỷ 80s. So với xu hướng thiết kế lõi vi xử lý  ngày nay dựa trên kiến trúc RISC thì 8051 thiết kế trên kiến trúc CISC với một số đặc trưng như tập lệnh lớn, thời gian thực hiện lệnh thay đổi, độ dài lệnh không cố định. Điều này gây khó khăn cho các trình biên dịch trong việc tối ưu mã, tốc độ thực hiện lệnh của vi xử lý chậm.
           Tuy nhiên, do là một vi điều khiển ra đời sớm, Intel đã cho phép các nhà sản xuất khác (Atmel, Siemens, Phillips v.v.) sản xuất vi điều khiển giữ nguyên lõi 8051, vi điều khiển 8051 trở nên phổ biến với số lượng và chủng loại đa dạng đáp ứng nhiều mục đích sử dụng và thiết kế. Việc thay đổi IC cùng họ của các nhà sản xuất khác nhau hầu như không phải viết lại chương trình. Bên cạnh đó số lượng nhà phát triển hỗ trợ phần mềm hợp dịch, biên dịch, mô phỏng và bộ nạp chương trình lớn. Tài liệu hướng dẫn phong phú cũng góp phần làm cho họ vi điều khiển 8051 trở nên phổ biến. Đây là lý do khiến việc tiếp cận với vi điều khiển trở nên dễ dàng hơn.
          Hiện nay có nhiều họ vi điều khiển đang phát triển mạnh mẽ và ngày càng chiếm được cảm tình của người thiết kế như PIC, AVR, ARM,v.v. . Chúng được thiết kế dựa trên kiến trúc RISC với khả năng hỗ trợ tốt ngôn ngữ lập trình bậc cao dẫn đến thời gian thiết kế và cho ra đời các sản phẩm nhanh hơn. Các họ vi điều khiển khác nhau có tập lệnh và cấu trúc khác nhau, việc học đồng thời tất cả các họ vi điều khiển là không thể. Tuy nhiên, việc nắm bắt tốt kiến trúc, cách thức thực hiện lệnh ở mức assembly, vẽ lưu đồ thuật toán và viết chương trình khi học vi điều khiển 8051 cũng tạo điều kiện dễ dàng cho sinh viên tiếp cận với họ vi điều khiển khác. Hơn nữa, với mỗi vi điều khiển của họ khác thì gần như kỹ sư thiết kế cũng có khả năng tìm được một vi điều khiển có tính năng tương đương thuộc họ 8051.

3. Tại sao học ngôn ngữ hợp ngữ (Assembly)?
           Lập trình cho vi điều khiển có thể viết bằng nhiều ngôn ngữ khác nhau như Assembly, C, Basic, Pascal, v.v. Tại sao chúng ta lại học ngôn ngữ Assembly trong chương trình? Nhiệm vụ của học phần vi xử lý 1 giải quyết hai nhiệm vụ: i) cung cấp cho các em các kiến thức cơ bản về tổ chức và hoạt động của hệ vi xử lý, ii) một số ứng dụng của vi xử lý, vi điều khiển trong thực tế.
           Để đáp ứng được nhiệm vụ thứ nhất thì việc học và lập trình bằng ngôn ngữ Assembly là thích hợp nhất. Qua việc hiểu cách thức mã hóa lệnh, quy trình thực hiện lệnh các em có được kiến thức về cấu trúc và nguyên tắc hoạt động cũng như chức năng của các thành phần trong hệ vi xử lý. Cách thức mà các lệnh được hệ vi xử lý mã hóa và giải mã dưới dạng nhị phân. Những chương trình dù phức tạp đến đâu để thực hiện được trên hệ vi xử lý đều phải chuyển đổi thành dạng mã nhị phân để máy có thể hiểu được. Chương trình viết bằng ngôn ngữ bậc cao để thực hiện được trên hệ vi xử lý cần phải biên dịch và hợp dịch để chuyển thành lệnh cơ bản của máy. Các em cũng hiểu được tại sao cần phải có trình biên dịch và hợp dịch. Tại sao chạy trên các hệ vi xử lý với các họ vi xử lý khác nhau thì cần phải có các trình biên dịch và hợp dịch phù hợp. Tại sao viết chương trình bằng ngôn ngữ Assembly thường cho khả năng tối ưu hơn về tốc độ và dung lượng. Rất nhiều khái niệm sẽ khó giải thích nếu các em không có được kiến thức cơ bản về hợp ngữ.
          Để đáp ứng được nhiệm vụ thứ hai thì có thể học và sử dụng các ngôn ngữ bậc thấp cũng như bậc cao. Tất nhiên, việc học và sử dụng ngôn ngữ bậc cao trong việc viết chương trình ứng dụng sẽ nhanh chóng và thuận tiện hơn.
          Để đáp ứng được cả hai nhiệm vụ này, trong chương trình chúng ta sử dụng ngôn ngữ Assembly để dạy và học. Điều này cũng gợi ý cho các em cần tiếp tục học hỏi để có thể viết chương trình ứng dụng bằng ngôn ngữ bậc cao. Trong học phần vi xử lý 2 chúng ta sẽ sử dụng ngôn ngữ bậc cao để học và viết chương trình.

4. Làm thế nào để môn học trở nên thú vị hơn?
          Để môn học trở nên thú vị hơn, các em có thể làm các mạch đơn giản ứng dụng vi điều khiển ví dụ như mạch quang báo dùng led với các kiểu sáng khác nhau. Dù làm một mạch đơn giản nhưng các em sẽ tích lũy được nhiều kiến thức bổ ích từ thiết kế, thực hành điện tử cơ bản, lập trình, mô phỏng sửa lỗi, nạp chương trình. Tất nhiên, để làm được các mạch này các em cần có một số thiết bị và linh kiện cơ bản như:
+ Đồng hồ vạn năng
+ Board cắm
+ Mạch nạp chương trình
+ Vi điều khiển (thường dùng AT89S51, AT89S52 hoặc AT89C51, AT89C52)
+ Thạch anh (thường dùng 12Mhz hoặc 11,0592Mhz) , led phát quang, trở (220 Ohm, 4.7K, 10K), tụ (tụ gốm 33pF, tụ hóa 10uF), dây nối.
+ Nguồn 5V (có thể dùng Pin hoặc nguồn máy tính cũ)
Dưới đây là một mạch đơn giản thể hiện các điều kiện tối thiểu để một vi điều khiển hoạt động: điều khiển một led đơn nối với chân P1.0 sáng nhấp nháy.
Cần lưu ý: Chân 31(/EA/Vpp) nối với Vcc=5V. Tụ nối chân Reset là tụ hóa. Trở nối chân Reset có thể thay đổi trị số thành 4,7K hoặc 10K.

             Để mạch này có thể hoạt động được thì vi điều khiển cần được nạp một chương trình. Sau đây là một chương trình ví dụ để điều khiển led đơn nối với chân P1.0 nhấp nháy:

org 0
loop:
cpl P1.0
call delay
jmp loop
delay:
mov r6,#250
dl1:
mov r7,#250
djnz r7,$
djnz r6,dl1
ret
end

             Soạn thảo chương trình này trên Pinnacle 52, lưu vào ổ cứng với tên ví dụ là "nhapnhay.asm". Dịch và mô phỏng để kiểm tra hoạt động (xem tài liệu hướng dẫn sử dụng phần mềm Pinnacle 52 trong link bên dưới).
             Sau khi dịch chương trình, phần mềm sẽ tạo ra một file cùng tên có đuôi .hex, ví dụ "nhapnhay.hex". File này có thể sử dụng để nạp vào vi điều khiển. Trước tiên các em nên vẽ mạch trên phần mềm Proteus để mô phỏng hoạt động, sau đó lắp ráp mạch trên board cắm. Sử dụng bộ nạp (nếu chưa có bộ nạp thì nhờ thầy hoặc các bạn) nạp file "nhapnhay.hex" đã tạo ra ở bước trên vào vi điều khiển. Lắp ráp mạch, cấp nguồn và kiểm tra hoạt động của mạch thực tế.
            Như vậy các em đã hoàn thành một mạch đơn giản ứng dụng vi điều khiển. Qua công việc này, các em sẽ hiểu được quy trình làm việc với vi điều khiển và quan trọng hơn là thấy được sự thú vị của vi điều khiển.
            Để có hứng thú và trực quan hơn các em nên sử dụng thêm phần mềm Protues, đây là phần mềm cho phép mô phỏng các vi điều khiển khá trực quan.

5. Tổ chức bộ nhớ
           8051 có bộ nhớ tổ chức kiểu Harvard (có bộ nhớ chương trình tách biệt với bộ nhớ dữ liệu). 8051 có các bộ nhớ chính bao gồm:
          - bộ nhớ chương trình ROM (khả năng quản lý 64Kbyte, tích hợp sẵn 4Kbyte). Địa chỉ được đánh từ 0000H-0FFFFH, trong đó vùng ROM on-chip chiếm vùng địa chỉ thấp.
          - bộ nhớ dữ liệu RAM trong (128 byte). Địa chỉ được đánh từ 00H-7FH. Bộ nhớ RAM trong được chia thành 3 vùng: các banks thanh ghi, vùng nhớ bit, vùng RAM đa mục đích.
          - bộ nhớ RAM ngoài (khả năng quản lý 64Kybte). Địa chỉ được đánh từ 0000H-0FFFFH
          -các thanh ghi chức năng đặc biệt SFRs. Địa chỉ từ 80H-0FFH. SFRs có không gian nhớ 128 byte, tuy nhiên chỉ một phần trong số này được sử dụng. Các địa chỉ không sử dụng không được phép truy nhập.
Các vùng nhớ này được phân biệt với nhau bởi chức năng và cách thức truy nhập đến chúng.
           Đối với RAM trong có thể truy nhập theo các chế độ định địa chỉ: trực tiếp, gián tiếp và thanh ghi.
           ROM có chế độ định địa chỉ duy nhất là chỉ số thanh ghi
           SFRs được truy nhập bằng chế độ định địa chỉ trực tiếp

6. Các chế độ định địa chỉ (download slides: Cac_che_do_dinh_dia_chi_cua_8051.pdf)
          Để truy nhập đến các vùng nhớ khác nhau, 8051 có các chế độ định địa chỉ sau:
- Chế độ định địa chỉ tức thời.
         Ví dụ: MOV A, #10  ;di chuyển giá trị 10 vào thanh ghi A. Sau lệnh này thanh ghi A có giá trị bằng 10.
         Như vậy, trong chế độ định địa chỉ tức thời thì giá trị của toán hạng được chỉ ra và nằm sau mã lệnh.
- Chế độ định địa chỉ trực tiếp.
         Ví dụ: MOV A, 10   ;di chuyển nội dung ô nhớ có địa chỉ bằng 10 trong RAM trong vào thanh ghi A. Sau lệnh này thanh ghi A có giá trị bằng nội dung ô nhớ trong RAM trong có địa chỉ bằng 10.
        Trong chế độ định địa chỉ trực tiếp, địa chỉ của toán hạng được chỉ ra sau mã lệnh.
- Chế độ định địa chỉ thanh ghi
        Ví dụ: MOV A, R0  ; di chuyển nội dung thanh ghi R0 vào thanh ghi A. Sau lệnh này,  thanh ghi A có giá trị bằng nội dung thanh ghi R0.
       Trong chế độ định địa chỉ thanh ghi, toán hạng là một thanh ghi từ R0-R7.
- Chế độ định địa chỉ gián tiếp
       Ví dụ: MOV A, @R0 ; di chuyển nội dung ô nhớ trong RAM trong có địa chỉ là nội dung của thanh ghi R0 vào thanh ghi A.
       Trong chế độ định địa chỉ gián tiếp, địa chỉ của toán hạng được xác định gián tiếp thông qua một thanh ghi.Các thanh ghi được sử dụng để định địa chỉ gián tiếp bao gồm: R0, R1 và DPTR
- Chế độ định địa chỉ chỉ số thanh ghi:
       Ví dụ: MOVC A, @A+DPTR ;di chuyển nội dung ô nhớ trong ROM có địa chỉ xác định bởi tổng 2 thanh ghi A và DPTR vào thanh ghi A.
       Trong chế độ định địa chỉ chỉ số thanh ghi, địa chỉ của ô nhớ trong ROM được xác định thông qua nội dung hai thanh ghi A và DPTR (hoặc PC).
       Ngoài ra, có một chế độ định địa chỉ đặc biệt thanh ghi. Ví dụ hai lệnh MOV A, #10 và MOV Acc, #10 cho cùng kết quả là thanh ghi Acc có giá trị bằng 10 nhưng khi dịch ra mã máy thì khác nhau về dung lượng. Lệnh thứ nhất có dung lượng 2 byte trong khi lệnh thứ hai có dung lượng 3 byte. Trong ví dụ trên toán hạng A được gọi là định địa chỉ đặc biệt thanh ghi trong khi toán hạng Acc được định địa chỉ trực tiếp.
Các chế độ định địa chỉ được sử dụng để truy nhập đến các vùng nhớ khác nhau. Có thể tổng kết như sau:
- RAM trong có 3 chế độ định địa chỉ có thể truy nhập tới là: trực tiếp, thanh ghi và gián tiếp
- RAM ngoài có duy nhất chế độ định địa chỉ gián tiếp sử dụng lệnh MOVX
- ROM có chế độ định địa chỉ duy nhất là chỉ số thanh ghi, sử dụng lệnh MOVC A, @A+DPTR hoặc MOVC A, @A+PC
- SFRs có chế độ định địa chỉ trực tiếp
        Phân biệt giữa truy nhập giữa RAM trong và SFRs ở chế độ định địa chỉ trực tiếp là RAM trong có địa chỉ từ 0-7FH trong khi SFRs có địa chỉ từ 80H-0FFH

7. Tập lệnh
         Vi điều khiển 8051 thiết kế theo kiến trúc CISC là kiến trúc có tập lệnh phức tạp với số lượng lệnh lớn, độ dài và thời gian thực hiện lệnh thay đổi. Để nhớ các lệnh của vi điều khiển 8051 chúng ta chia thành 5 nhóm lệnh chính bao gồm:
- nhóm lệnh di chuyển dữ liệu (MOV, MOVX, MOVC, XCH, SWAP)
- nhóm lệnh logic (ANL, ORL, XRL, RR, RRC, RL, RLC, CLR, CPL)
- nhóm  lệnh số học (ADD, ADDC, INC, SUBB, DEC, MUL, DIV)
- nhóm lệnh rẽ nhánh chương trình: bao gồm lệnh rẽ nhánh có điều kiện và các lệnh rẽ nhánh không điều kiện
+ các lệnh rẽ nhánh không điều kiện (JMP, CALL, RET, RETI)
+ các lệnh rẽ nhánh có điều kiện (DJNZ, CJNE, JC, JNC, JB, JNB, JZ, JNZ)
- nhóm lệnh xử lý toán hạng bit (SETB, CLR, CPL)
          Với mỗi lệnh các em cần biết cú pháp (bao gồm số toán hạng, chế độ định địa chỉ tương ứng với từng toán hạng), ý nghĩa của lệnh, kết quả thực hiện lệnh lưu ở đâu, ảnh hưởng đến các cờ nào trong thanh ghi trạng thái chương trình PSW, thời gian thực hiện lệnh và độ dài lệnh.
Để hiểu cách thức thực hiện lệnh, cần lấy một vài ví dụ, mô phỏng từng bước và quan sát kết quả thực hiện lệnh để so sánh giữa ý hiểu và kết quả thực tế.

8. Phân biệt giữa lệnh nhảy JMP và lệnh gọi CALL
         Cả hai lệnh JMP và lệnh CALL cùng thực hiện rẽ nhánh chương trình không điều kiện, tức là cùng nhảy tới một địa chỉ được chỉ ra bởi nhãn. Tuy nhiên, hai lệnh này không được sử dụng thay thế cho nhau.
- Lệnh JMP rẽ nhánh chương trình đến địa chỉ được chỉ ra bởi nhãn
- Lệnh CALL cũng rẽ nhánh chương trình đến địa chỉ được chỉ ra bởi nhãn (tên chương trình con). Đồng thời với việc rẽ nhánh chương trình, lệnh CALL còn cất giữ nội dung con trỏ PC (địa chỉ quay trở về lên ngăn xếp) để khi gặp lệnh RET trong chương trình con thì lấy 2 byte trên đỉnh ngăn xếp đưa vào con trỏ PC để quay trở về thực hiện lệnh sau lệnh gọi CALL. Do đó nếu sử dụng lệnh JMP thay vì lệnh CALL để gọi chương trình con sẽ dẫn đến chương trình chạy sai khi gặp lệnh RET. Ngược lại khi sử dụng lệnh CALL thay vì lệnh JMP để nhảy đến chương trình con sẽ dẫn đến ngăn xếp bị thay đổi.

9. Phân biệt giữa lệnh RET và RETI
          Lệnh RET (RETURN) là lệnh trở về từ chương trình con. Lệnh RETI (RETURN FROM INTERRUPTS) là lệnh trở về từ chương trình phục vụ ngắt. Ngoài việc lấy 2 byte trên đỉnh ngăn xếp để nạp vào con trỏ PC để trở về vị trí bị gián đoạn, lệnh RETI còn thực hiện xóa cờ ngắt tương ứng.

10. Lệnh JMP với các dạng SJMP, AJMP và LJMP
         Khi dịch sang mã máy, lệnh JMP sẽ được dịch sang một trong 3 dạng là SJMP, AJMP hoặc LJMP. Mặc định các trình hợp dịch sẽ chuyển sang lệnh LJMP.
Cả 3 biến thể này đều có tác dụng nhảy đến một nhãn được chỉ ra sau lệnh. Tuy nhiên có sự khác biệt về dung lượng và vị trí của địa chỉ cần nhảy tới so với lệnh.
- Lệnh SJMP nhảy trong phạm vi địa chỉ cách 127 byte về phía trước và 128 byte về phía sau so với vị trí của lệnh SJMP. Lệnh này có độ lớn 2 byte.
- Lệnh AJMP nhảy tới địa chỉ bất kỳ nằm trong phạm vi 2KByte địa chỉ đầu tiên từ 0000H-7FFH. Lệnh này có độ lớn 2 byte.
- Lệnh LJMP là lệnh nhảy dài có thể nhảy đến vị trí bất kỳ trong bộ nhớ dung lượng 64Kbyte. Lệnh này có độ lớn 3 byte.
Khi lập trình, nên lựa chọn sử dụng 1 trong 3 dạng trên để có dung lượng chương trình tối ưu.
Tương tự lệnh CALL có 2 biến thể là ACALL và LCALL.

11. Timer/counter
           8051 có 2 bộ timer/counter 16 bit đặt tên lần lượt là timer/counter0 và timer/counter1. Timer/counter thực chất  là một bộ đếm 16 bit. Các bộ timer/counter của 8051 là các bộ đếm lên.
           Timer/counter hoạt động với chức năng timer khi nguồn xung là dao động bên trong. Số đếm của timer tăng 1 đơn vị tương ứng với 1 chu kỳ máy của vi điều khiển (12 chu kỳ xung nhịp). Như vậy số đếm của timer tăng liên tục, thời gian giữa các số đếm là bằng nhau.
          Timer/counter hoạt động với chức năng counter khi nguồn xung đưa tới bộ đếm từ bên ngoài (đưa tới chân P3.4 đối với timer/counter0 và P3.5 đối với timer/counter1). Số đếm của counter tăng 1 đơn vị khi có xung đưa tới đầu vào counter. Như vậy số đếm của counter chỉ tăng lên khi có xung tác động tới các chân đầu vào.
           Để điều khiển hoạt động của timer/counter cần tác động lên các thanh ghi TMOD, TCON, TLx và THx (x=0, 1 tương ứng với timer/counter 0 và timer/counter 1).
          TMOD là thanh ghi 8 bit, cho phép truy nhập ở mức byte, trong đó 4 bit cao (từ bit 3 đến bit 7) là các bit điều khiển timer/counter1 và 4 bit thấp (từ bit 0 đến bit 3) là các bit điều khiển timer/counter0. Do hai bộ timer/counter counter hoạt động giống nhau nên các bit điều khiển có chức năng giống nhau.
          Timer/counter có 4 mode hoạt động tương ứng với trạng thái của hai bit M1 và M0 trong thanh ghi TMOD. 4 mode này xác lập số đếm lớn nhất mà bộ đếm có thể đếm được.
          Để lựa chọn chức năng timer hay counter cần tác động lên bit C/T. Nếu C/T=0, timer/counter làm chức năng timer. Nếu C/T=1, timer/counter làm chức năng counter.
         GATE là bit lựa chọn điều khiển hoạt động của timer/counter bằng phần cứng hay phần mềm. Nếu GATE=0, điều khiển hoạt động của timer/counter bằng phần mềm, nghĩa là chỉ cần TRx=1 là timer/counter hoạt động. Nếu GATE=1, để timer/counter hoạt động (đếm) cần thêm điều kiện có chân P3.2 ( đối với timer/counter0) hoặc P3.3 (đối với timer/counter1) phải ở mức cao.
         TCON là thanh ghi 8 bit cho phép truy nhập ở mức bit. Bit TRx là bit cho phép timer/counter hoạt động hay dừng. Nếu TRx=0, timer/counter dừng hoạt động. Nếu TRx=1, timer/counter hoạt động hay dừng còn phụ thuộc vào trạng thái của bit GATE như trình bày ở phía trên.
         Bit TFx trong thanh ghi TCON là cờ tràn. TFx được tự động đặt lên 1 khi timer/counterx đếm tràn. Cờ TFx được xóa về 0 bằng phần mềm hoặc gặp lệnh RETI khi trở về từ chương trình phục vụ ngắt tương ứng. Nghĩa là TF0 được tự động xóa về 0 khi gặp lệnh RETI của chương trình phục vụ ngắt timer/counter0 và TF1 được tự động xóa về 0 khi gặp lệnh RETI của chương trình phục vụ ngắt timer/counter1.
         Các thanh ghi THx và TLx kết hợp thành các bộ đếm 16 bit, 13 bit hay 8 bit auto-reload phụ thuộc vào mode hoạt động được xác lập bởi các bit M1 và M0. Trong đó THx chứa các bit cao, TLx chứa các bit thấp.
         Hoạt động ở mode 0 (13 bit) và mode 1 (16 bit), khi timer/counter đếm tràn sẽ trở về đếm từ 0.  Mode 2 (8 bit) có chức năng auto-reload, nghĩa là khi timer/counter đếm đến giá trị lớn nhất (255), khi đếm thêm một số đếm nữa thì timer/counter đếm tràn  và trở về giá trị được đặt trước trong thanh ghi THx.
         Khi lập trình sử dụng timer/counter cần biết phải sử dụng bộ timer/counter nào. Khi sử dụng với chức năng timer thì thông thường có thể tùy chọn 1 trong 2 bộ timer. Tuy nhiên, khi sử dụng timer/counter với chức năng counter thì việc lựa chọn bộ counter0 hay counter1 là do tín hiệu đưa tới chân nào. Nếu tín hiệu đưa tới chân P3.4(T0) thì phải sử dụng bộ counter0, nếu tín hiệu đưa tới  chân P3.5(T1) thì phải sử dụng bộ counter1. Khi sử dụng trong truyền thông nối tiếp để tạo tốc độ baud, timer0 được sử dụng.
Ví dụ: chương trình tạo xung vuông có chu kỳ T=0.1 giây, độ rỗng 50% tại chân P1.0. Biết thạch anh sử dụng có tần số 12Mhz.
         Với yêu cầu này ta có thể sử dụng timer/counter0 hay timer/counter1 đều được với chức năng timer. Tần số thạch anh 12Mhz, như vậy trong 1 giây sẽ có 12.10^6/12 =10^6 chu kỳ máy. Vậy để đếm được 1 giây timer cần đếm được 10^6 số đếm (vì số đếm của timer tăng 1 đơn vị tương ứng với 1 chu kỳ máy).
Xung vuông có chu kỳ T=0.1 giây, độ rỗng 50% vậy xung sẽ có 0.05 giây ở mức cao và 0.05 giây ở mức thấp. Để tạo được thời gian 0.05 giây, timer cần đếm được 0.05*(10^6)=50.000 số đếm.
Ta có thể lựa chọn timer hoạt động ở mode 1 (số đếm lớn nhất là 2^16-1=65.535). Số đếm ban đầu của timer sẽ là: 65.536-50.000=15.536. Vậy khi timer đếm bắt đầu từ 15.536 trở lên đến khi đếm tràn sẽ đếm được 50.000 số đếm tương ứng với 0.05 giây.
Với các phân tích ở trên ta có thể thiết lập timer như sau:
- Sử dụng timer0 (có thể sử dụng timer1)
- Mode hoạt động 1: M1=0, M0=0
- Chức năng timer: C/T=0
- Điều khiển bằng phần mềm: Gate=0
- Số đếm ban đầu của timer: 15.536=3CB0H, như vậy TH0=3CH, TL0 = B0H
- Cờ tràn TF0 được xóa
Chương trình có thể viết như sau:
org 0
loop:
       cpl P1.0
       call delay_0_05s
       jmp loop
delay_0_05s:
       mov TMOD,#00000001B;timer0, mode 1, timer, gate=0
       mov TH0,#high(15536)   ;phần mềm sẽ tự động lấy byte cao của số 15.536 đưa vào thanh ghi TH0
       mov TL0,#low(15536)    ;phần mềm lấy byte thấp của 15.536 đưa vào thanh ghi TL0
      clr TF0                             ; xóa cờ tràn TF0
       setb TR0                         ; cho phép timer bắt đầu hoạt động
      jnb TF0,$                         ;khi TF0 bằng 1 nghĩa là timer0 đếm đủ 50000 số đếm
      ret
end
Tất nhiên chương trình này chưa hoàn toàn chính xác do còn một số lệnh tiêu tốn thời gian nhưng không được tính, ta hoàn toàn có thể chỉnh sửa bằng cách thay đổi lại giá trị ban đầu nạp vào TH0 và TL0.

12. Ngắt
        Ngắt là cơ chế đặc biệt trong các hệ vi xử lý. Khi có một sự kiện xảy ra tại thiết bị ngoại vi (ví dụ như timer/counter đếm tràn hay truyền/nhận xong một ký tự) sẽ yêu cầu CPU tạm dừng công việc hiện tại để đáp ứng sự kiện này. Sự kiện ngắt thường không biết trước thời gian xảy ra, nhưng khi sự kiện xảy ra lại yêu cầu CPU phải đáp ứng nhanh nhất có thể.
        8051 có 6 nguồn ngắt tương ứng với 5 vector ngắt. 6 nguồn ngắt bao gồm 2 ngắt ngoài INT0 (P3.2) và INT1 (P3.3), 2 ngắt timer/counter đếm tràn và 2 ngắt của cổng nối tiếp (ngắt truyền và ngắt nhận). Vector ngắt là địa chỉ bắt đầu của chương trình phục vụ ngắt trong bộ nhớ chương trình. Ứng với mỗi một sự kiện ngắt, CPU tạm thời dừng công việc hiện tại để thực hiện chương trình phục vụ ngắt tương ứng nằm tại các vị trí xác định trong bộ nhớ. Cụ thể:
Ngắt        Vector ngắt
INT0           03H
T0               0BH
INT1           13H
T1               1BH
Serial           23H
Nghĩa là nếu có xung đưa tới chân P3.2(INT0) và sự kiện này được xác lập là một sự kiện ngắt, CPU sẽ tạm dừng công việc hiện tại để thực hiện lệnh bắt đầu tại địa chỉ 03H.
         Mặc định CPU cấm tất cả các ngắt. Để xác lập một sự kiện là ngắt, thiết lập mức ưu tiên ngắt chúng ta phải tác động lên các bit trong các thanh ghi cho phép ngắt IE (Interrupts Enable), thanh ghi ưu tiên ngắt IP (Interrupts Priority). Khi lập trình bằng assembly, chúng ta phải nhớ tên và chức năng của từng bit trong các thanh ghi này.
          Thanh ghi IE là thanh ghi 8 bit, cho phép truy nhập ở mức bit. Trong thanh ghi này chứa các bit cho phép ngắt chung EA, các bit cho phép ngắt tương ứng với các nguồn ngắt cụ thể: EX0, ET0, EX1, ET1, ES.
Để cho phép một ngắt ta phải cho EA=1 và bit cho phép ngắt tương ứng bằng 1. Ví dụ, để cho phép sự kiện  timer/counter0 đếm tràn là một ngắt ta phải cho EA=1 và ET0=1.
           Khi 2 hoặc nhiều ngắt xảy ra sẽ nảy sinh vấn đề ngắt nào được CPU ưu tiên thực hiện trước. Về nguyên tắc, CPU chỉ thực hiện được 1 lệnh tại một thời điểm. 8051 có thanh ghi IP xác lập chế độ ưu tiên ngắt. Trong IP có các bit tương ứng với các ngắt là PX0, PT0, PX1, PT1 và PS. Khi các bit này ở mức cao thì ngắt tương ứng sẽ có mức ưu tiên cao và ngược lại.
          Ví dụ, đoạn chương trình sau sẽ xác lập cho phép 2 sự kiện được coi là ngắt là xung ngoài đưa tới chân P3.2 (INT0) và timer/counter1 đếm tràn. Trong đó ngắt timer/counter1 có mức ưu tiên cao (tức là được ưu tiên phục vụ trước).
      SETB P3.2 ; xác lập P3.2 là chân đầu vào
      SETB EA  ;cho phép ngắt chung
      SETB EX0; cho phép ngắt ngoài INT0
      SETB PT1  ;ưu tiên timer/counter1 ở mức cao
      CLR PX0  ;ưu tiên ngắt ngoài INT0 ở mức thấp
Với việc xác lập như trên, khi chương trình phục vụ ngắt INT0 đang được phục vụ mà timer/counter1 đếm tràn thì ngắt INT0 tạm thời bị dừng lại để phục vụ ngắt timer/counter1. Sau khi chương trình phục vụ ngắt timer/counter thực hiện xong mới quay trở lại thực hiện tiếp chương trình phục vụ ngắt ngoài INT0.
          Trong trường hợp bit PX0 trong ví dụ trên cũng được đặt bằng 1 (nghĩa là ngắt ngoài INT0 cũng có mức ưu tiên cao) thì khi 2 ngắt xảy ra đồng thời thì CPU sẽ phục vụ ngắt nào? Việc căn cứ vào thanh ghi IP là không thể xác định được ngắt nào sẽ được phục vụ trước. Trong trường hợp này, CPU sẽ căn cứ vào thứ tự ưu tiên ngắt mặc định. 8051 quy định mức ưu tiên mặc định từ cao xuống thấp như sau: INT0->T0->INT1->T1->Serial. Mặc định, ngắt INT0 sẽ có mức ưu tiên cao hơn ngắt timer/counter1. Như vậy, ngắt INT0 trong trường hợp này sẽ được ưu tiên phục vụ trước.
           Cấu trúc chương trình phục vụ ngắt: khác với chương trình con có thể nằm tại vị trí bất kỳ trong bộ nhớ chương trình, chương trình phục vụ ngắt ứng với mỗi sự kiện ngắt nằm tại một vị trí xác định trong bộ nhớ. Do đó, cấu trúc chương trình phục vụ ngắt có sự khác biệt với chương trình con. Cụ thể, cấu trúc chung của chương trình phục vụ ngắt là:
       ORG  Vector_ngắt
          Thân chương trình
       RETI
            Ví dụ, với chương trình phục vụ ngắt ngoài INT0 thì vector_ngắt sẽ được thay bằng địa chỉ 03H. Thân chương trình là tập hợp các lệnh của 8051 nhằm thực hiện công việc tương ứng với sự kiện ngắt.
           Ví dụ: chương trình đếm xung ngoài đưa tới chân P3.2(INT0), hiển thị số đếm từ 0-200 trên các led đơn nối với cổng P1.
biendem   equ 70h
org 0
        jmp start
org 03h                            ;địa chỉ của chương trình phục vụ ngắt ngoài INT0
        inc biendem            ;tăng biến đếm 1 đơn vị mỗi khi có một ngắt (xung tác động tại sườn xuống)
        reti
start:
        setb P3.2                   ;xác lập cho chân P3.2 là đầu vào
        mov biendem,#0
        mov IE,#10000001B; cho phép ngắt ngoài INT0
        setb IT0                  ;ngắt tích cực ở sườn xuống
loop:
        mov a,biendem
        mov P1,a
        cjne a,#201,loop
        mov biendem,#0  ;xóa biến đếm khi số đếm bằng 201
        jmp loop
end
Thông thường, các thanh ghi quan trọng được sử dụng nhiều như PSW, Acc được cất giữ để trạng thái của chúng không bị thay đổi khi thực hiện xong chương trình phục vụ ngắt so với trước khi thực hiện chương trình phục vụ ngắt. Để cất giữ các thanh ghi này ta sử dụng lệnh PUSH, để lấy lại nội dung của thanh ghi ta sử dụng lệnh POP. Một số lỗi rất khó phát hiện do nguyên nhân không cất giữ các thanh ghi này trong chương trình phục vụ ngắt.

13. Giao tiếp nối tiếp UART
            Vi điều khiển 8051 tích hợp một cổng giao tiếp nối tiếp bất đồng bộ UART cho phép các vi điều khiển có thể liên lạc với nhau, với máy tính hoặc các thiết bị khác.
            Để có thể giao tiếp qua UART cần thiết lập tốc độ truyền, khung dữ liệu, bit chẵn lẻ. Việc thiết lập này thông qua trạng thái của các bit trong thanh ghi SCON.
           SCON là thanh ghi 8 bit. Trong đó hai bit SM0 và SM1 tổ hợp thành 4 trạng thái tương ứng với 4 chế độ xác lập truyền: 8 bit hay 9 bit, tốc độ truyền bằng bao nhiêu. Khi hoạt động ở mode 0 và mode 2, tốc độ truyền là cố định dựa trên tần số thạch anh. Mode 1 và mode 3 tốc độ truyền thay đổi dựa trên tốc độ tràn của timer 1.
          Bit SM2 sử dụng trong chế độ truyền đa vi xử lý. Bình thường, khi nhận đủ 1 byte, cờ RI (cờ ngắt nhận) sẽ tự động được đặt lên mức 1 để báo cho chương trình biết đã nhận đủ 1 byte. Tuy  nhiên khi bit SM2 được đặt, cờ RI chỉ được bật lên mức 1 nếu bit thứ 9 nhận được có giá trị bằng 1.
          Bit REN là bit cho phép nhận. Nếu bit này được đặt bằng 1, dữ liệu có thể được nhận qua cổng nối tiếp, ngược lại sẽ không cho phép nhận dữ liệu. Như vậy, để có thể nhận được dữ liệu qua cổng nối tiếp bit REN phải được đặt bằng 1.
          Bit TB8 được sử dụng trong các mode 2 và 3. Trong hai mode này dữ liệu truyền gồm 9 bit. TB8 chứa bit thứ 9 được truyền. Sau khi 8 bit trong thanh ghi SBUF được truyền xong, bit thứ 9 được truyền là nội dung của bit TB8. TB8 thường được sử dụng để truyền bit chẵn lẻ.
          Bit RB8 cũng hoạt động trong các mode 2 và 3 và có chức năng nhận bit dữ liệu thứ 9.
          TI là cờ ngắt nhận. Khi dữ cổng nối tiếp truyền xong một byte dữ liệu, bit TI sẽ được tự động đặt lên mức 1 để báo đã truyền xong 1 byte và sẵn sàng truyền byte tiếp theo.
          Ví dụ: Lệnh xác lập UART hoạt động ở mode 1 (8 bit dữ liệu, tốc độ truyền do tốc độ tràn timer1 quyết định):
          MOV SCON,#01010000B
           Thanh ghi SBUF là thanh ghi đệm truyền và đệm nhận. Mặc dù chỉ có một tên nhưng thực chất đây là 2 thanh ghi, một thanh ghi đệm truyền và một thanh ghi đệm nhận. Khi ghi đến SBUF là truy nhập đến thanh ghi đệm truyền. Khi đọc từ thanh ghi SBUF là đọc từ thanh ghi đệm nhận.
           Dữ liệu truyền các bit có trọng số thấp trước, bit trọng số cao sau.
Xác lập tốc độ baud:
          - Khi hoạt động ở mode 0 và mode 2, tốc độ baud được xác định dựa trên tần số thạch anh sử dụng. Trong mode 0, tốc độ baud luôn luôn bằng tần số dao động thạch anh chia 12. Điều này có nghĩa là nếu tần số thạch anh là 11,0592Mhz, khi hoạt động ở mode 0 tốc độ baud sẽ là 921.600 baud. Khi hoạt động ở mode 2, tốc độ baud luôn bằng tần số thạch anh chia 64. Ví dụ nếu sử dụng thạch anh tần số 11.0592Mhz, tốc độ baud sẽ là 11,0592*10^6/64=172.800.
          - Khi hoạt động ở mode 1 và mode 3, tốc độ baud được xác lập dựa trên tốc độ tràn của timer1. Tốc độ tràn của timer1 càng lớn thì tốc độ baud càng lớn. Thông thường timer1 được hoạt động ở chế độ auto-reload để tạo tốc độ baud trong đó thanh ghi TH1 sẽ chứa giá trị tái nạp cho TL1. Cũng cần lưu ý rằng khi sử dụng cổng nối tiếp thạch anh thường được sử dụng có tần số là 11,0592Mhz. Tần số này tạo ra các tốc độ truyền với sai số nhỏ. Ví dụ đoạn chương trình sau xác lập timer1 tạo tốc độ baud 9600 cho cổng nối tiếp UART, tần số thạch anh sử dụng là 11,0592Mhz.

            MOV TMOD,#20h    ;Timer 1 hoạt động trong chế độ auto-reload
            MOV TH1,#0FDh     ;Giá trị tái nạp cho timer1 khi đếm tràn
            MOV TL1,#0FDh     ;giá trị đếm ban đầu của timer1
            SETB TR1                 ; Cho phép timer1 hoạt động

           Lưu ý, bit SMOD trong thanh ghi PCON nếu được đặt bằng 1 sẽ nhân đôi tốc độ baud của UART nếu timer1 được sử dụng để tạo tốc độ baud. Mặc định SMOD bị xóa về 0.
14. Điều chế độ rộng xung PWM
Một số vi điều khiển 8051 như AT89C51RD2 hỗ trợ khối PCA hoạt động ở chế độ điều chế độ rộng xung. Điều chế độ rộng xung có thể được sử dụng trong điều khiển tốc độ động cơ một chiều.
Sơ đồ khối của bộ PCA hoạt động ở chế độ PWM như sau:
Quan sát sơ đồ khối ta thấy rằng CCAPnH là thanh ghi đệm chứa giá trị độ rỗng của xung. CL là thanh ghi chứa số đếm của bộ PCA Counter/Timer. CCAPnL là thanh ghi chứa giá trị độ rỗng được lấy từ CCAPnH. Giá trị của CL và CCAPnL luôn được kiểm tra bởi bộ so sánh 8 bit. Khi CL<CCAPnL, đầu ra CEXn=0. Khi CL đếm tới giá trị lớn nhất (chuyển từ 0FFH về 0) nội dung của CCAPnH được nạp vào CCAPnL.
Để bộ so sánh hoạt động các bit ECOMn và PWMn phải đặt bằng 1.
Có thể viết lệnh như sau (ví dụ viết với bộ CCP0):
MOV A, CCAPM0
ORL A,#01000010B
MOV CCAPM0,A
Nguồn xung cho CL của PCA Counter/Timer có thể được xác lập như sau:
Quan sát sơ đồ khối của khối PCA Timer, 2 bit CPS0 và CPS1 xác định nguồn xung cho bộ đếm.
Ví dụ: để cho phép PCA Timer hoạt động với nguồn xung bằng 1/6 tần số dao động ngoài có thể thiết lập như sau:

MOV A, CMOD
CLR ACC.1
CLR ACC.2 ;cho nguon xung Fclk/6 (CPS1=0,CPS1=0)
MOV CMOD,A

CLR CCON.7        ; cho phep timer hoat dong (CIDL=0)
SETB CCON.6      ; CR=1

Mô phỏng tương tác kết hợp Keil C và Proteus
         Keil C là phần mềm phục vụ soạn thảo, dịch và mô phỏng cho các vi điều khiển 8051 và ARM. Phần mềm hỗ trợ viết chương trình bằng ngôn ngữ Assembly và C. Keil C được sử dụng phổ biến với số lượng IC hỗ trợ lớn.
         Proteus là phần mềm thiết kế mạch nguyên lý và mạch in. Một điểm mạnh của Proteus làm cho phần mềm này được sử dụng rộng rãi trong những năm gần đây là khả năng mô phỏng các họ vi điều khiển như 8051, PIC, AVR v.v. Không chỉ mô phỏng trực quan, Proteus còn có khả năng kết hợp với các phần mềm để mô phỏng ở mức lệnh.
         Để mô phỏng ở mức lệnh kết hợp giữa Keil C và Proteus làm theo các bước sau:
         - Bước 1: Cài đặt Proteus VSM Keil Driver (đường link download tại: http://www.labcenter.com/support/vdmkeil.cfm)
        - Bước 2: Thiết lập mô phỏng trong Keil C. Trong menu Project, chọn Options for target 'target1'.... Một cửa sổ hiện ra, chọn tab Debug, lựa chọn "Use: Proteus VSM Simulator".

         - Bước 3: Khởi động Proteus, mở file nguyên lý. Nháy chuột phải vào IC vi điều khiển, chọn file .hex Keil C đã tạo ra.
         - Bước 4: Trong menu Debug của Proteus, chọn Use Remote Debug Monitor


        - Bước 5: Mô phỏng từng bước trong Keil C, các lệnh sẽ chạy tương ứng trong Protues
Video tạo một dự án mới cho vi điều khiển 8051 trong Keil C (viết bằng ngôn ngữ C): xem
Một số trang web gợi ý một số dự án và hướng dẫn:
http://www.8051projects.info/projects.asp
http://8052.com/
http://www.mikroe.com/eng/products/view/267/architecture-and-programming-of-8051-mcu-s/
http://www.kmitl.ac.th/~kswichit/

Diễn đàn điện tử để trao đổi, tham khảo:
http://www.dientuvietnam.net/forums/

Tài liệu tham khảo chính của môn học:
[1]. Văn Thế Minh. Kỹ thuật Vi xử lý. NXB Giáo Dục. 1997
[2]. Nguyễn Tăng Cường, Phan Quốc Thắng. Cấu trúc và lập trình họ vi điều khiển 8051. NXB KHKT. 2003
Ngân hàng câu hỏi (download): Ngân hàng câu hỏi tham khảo
Hướng dẫn sử dụng phần mềm EMU8086 (download): Hướng dẫn sử dụng phần mềm EMU8086
Hướng dẫn sử dụng phần mềm Pinnacle 52 (download): Hướng dẫn sử dụng Pinnacle 52
Hướng dẫn tạo một dự án với Keil uVision(download): Su_dung_keil_C.pdf


Tài liệu tiếng Anh tham khảo thêm:
[1]. B.Brey, B. The Intel Microprocessors, 8086/8088, 80186/80188, 80286, 80386, 80486, Pentium and Pentium Pro Processor Architecture, Programming, and Interfacing. Prentice-Hall, Inc, 1997
[2]. Ayala, K. J. The 8051 Microcontroller: Architecture, Programming, and Applications. West Publishing Company, 1991
[3].8052 Tutorial and Reference download

Ví dụ bài tập cho 8086:
1. Viết chương trình tính tổng 2 số từ 0-9 nhập vào từ bàn phím. Hiển thị kết quả (download): Congso0_9
2. Viết chương trình tính tổng 2 số từ 0-99 nhập vào từ bàn phím. Hiển thị kết quả (download) Congso0_99

Ví dụ bài tập cho 8051:(Các bài tập viết và dịch bằng phần mềm Pinnacle 52)
1. Viết chương trình điều khiển các led đơn nối với cổng P1 và P2 sáng dần từ giữa ra 5 lần sau đó tắt dần 10 lần: sangdan_tatdan
2. Chương trình điều khiển led 7 nối với cổng P0 hiển thị số từ 0-9 (led 7 anode chung): hienthiso0_9
3. Chương trình đếm xung ngoài đưa tới chân P3.2(INT0) sử dụng ngắt ngoài: dem_xung_P3_2
4. Chương trình đếm xung ngoài đưa tới chân P3.4 (T0) sử dụng timer/counter với chức năng counter: counter0
5. Chương trình đếm xung ngoài đưa tới chân P3.4(T0) sử dụng timer/counter0 với chức năng counter. Hiển thị số đếm từ 0-45 trên 2 led 7 đoạn nối song song với cổng P0. Các led 7 đoạn loại anode chung. Hai chân P2.0 và P2.1 lần lượt điều khiển đóng ngắt hai transistor nối với chân anode của led hàng đơn vị và hàng chục:download
6. Chương trình tạo xung vuông có chu kỳ 0,1 giây. Thạch anh tần số 12Mhz. Sử dụng timer/counter0 với chức năng timer: xung vuong
7. Chương trình đếm giây từ 0-59, hiển thị giây trên 2 led 7 đoạn nối song song với cổng P0. Các led 7 đoạn loại anode chung. Hai chân P2.0 và P2.1 lần lượt điều khiển đóng ngắt hai transistor nối với chân anode của led hàng đơn vị và led hàng chục. Thạch anh tần số 12Mhz: demgiay
8. Chương trình truyền nhận dữ liệu nối tiếp: Truyen_nhan_noi_tiep

Video hướng dẫn sử dụng phần mềm Proteus:
Video hướng dẫn tạo dự án trên Keil C viết bằng C (viết bằng ngôn ngữ Assembly thao tác tương tự):