Download as pdf or txt
Download as pdf or txt
You are on page 1of 152

Bài giảng KỸ THUẬT VI XỬ LÝ

CHƯƠNG 1: TỔNG QUAN VỀ VI XỬ LÝ – VI ĐIỀU KHIỂN


- Trình bày được cấu trúc và hoạt động các thành phần của Hệ thống vi xử lý tập lệnh của
VĐK
- Trình bày được các dạng dữ liểu biểu diễn thông tin trong Hệ thống vi xử lý
- Nhận dạng được thành phần của các hệ thống

Nhắc lại về Hệ thống số đếm:


Hệ nhị phân, hệ thập phân và hệ thập lục phân:
+ Hệ nhị phân, cơ số là 2, dùng hai số 0 và 1 để biểu diễn.
7 6 5 4 3 2 1 0
Thí dụ: 0B01001010 = 0x2 +1x2 +0x2 +0x2 +1x2 +0x2 +1x2 +0x2 = 64+8+2 = 74
+ Hệ thập phân, cơ số là 10 dùng các số 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 để biểu diễn.
2 1 0
Thí dụ: 125=1x10 +2x10 +5x10 = 100+20+5.
+ Hệ thập lục phân, cơ số là 16 dùng các số 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, A, B, C, D, E, F.
1 0
Thí dụ: 0x32 = 32H = 3x16 +2x16 = 48+2 = 50.
Bảng chuyển đổi giữa số nhị phân, thập phân và thập lục phân:
Hệ nhị phân (8 chữ số) Hệ thập phân (2 chữ số) Hệ thập lục phân (2 chữ số)
0B 00000000 00 00h; 0x00
0B 00000001 01 01h; 0x01
0B 00000010 02 02h; 0x02
0B 00000011 03 03h; 0x03
0B 00000100 04 04h; 0x04
0B 00000101 05 05h; 0x05
0B 00000110 06 06h; 0x06
0B 00000111 07 07h; 0x07
0B 00001000 08 08h; 0x08
0B 00001001 09 09h; 0x09
0B 00001010 10 0Ah; 0x0A
0B 00001011 11 0Bh; 0x0B
0B 00001100 12 0Ch; 0x0C
0B 00001101 13 0Dh; 0x0D
0B 00001110 14 0Eh; 0x0E
0B 00001111 15 0Fh; 0x0F

I. TỔNG QUAN VỀ HỆ THỐNG VI XỬ LÝ


1. Quá trình phát triển của máy vi tính (tham khảo thêm trên Internet)
- Máy vi tính bao gồm những máy tính dùng bộ vi xử lý (họ Intel, Motorola, AMD…) làm cốt lõi,
các vi điều khiển (microcontroller) hay máy vi tính trong một vi mạch (one-chip microcomputer).
GV: Ong Mẫu Dũng – Khoa CNĐT 1
Bài giảng KỸ THUẬT VI XỬ LÝ

2. Ứng dụng của vi xử lý (tham khảo thêm trên Internet)


3. Sơ đồ khối của Hệ thống vi xử lý

Address bus

Data bus

P Control bus

(CPU)
RAM ROM I/O Interface

Memory Input Output


Devices Devices

Peripheral Devices
Hình 1.1

P (Microprocessor): Vi xử lý
CPU (Central Processing Unit): Đơn vị xử lý trung tâm
Address bus: Bus địa chỉ
Data bus: Bus dữ liệu
Control bus: Bus điều khiển
RAM (Random Access Memory): Bộ nhớ truy xuất ngẫu nhiên
ROM (Read-Only Memory): Bộ nhớ chỉ đọc
I/O Interface: Khối giao tiếp nhập/xuất
Peripheral Devices: Thiết bị ngoại vi

3.1. Sơ đồ khối tiêu biểu của Hệ thống vi xử lý: (hệ thống vi xử lý có kiến trúc 3-bus)
3.2. Một Hệ thống vi xử lý gồm có các thành phần chính sau:
- P (microprocessor hay còn gọi là CPU): đọc mã lệnh từ bộ nhớ (được ghi dưới dạng các bit 0
và 1), sau đó giải mã và thực thi lệnh.
- Bộ nhớ (Memory): chứa các chương trình điều khiển hoạt động của toàn hệ và các dữ liệu,
kết quả trung gian. Có hai loại bộ nhớ: RAM (Random Access Memory) là loại bộ nhớ truy xuất
ngẫu nhiên và ROM (Read-Only Memory) là loại bộ nhớ chỉ đọc.
- Khối giao tiếp nhập/xuất (Input/Output - I/O): tạo ra khả năng giao tiếp giữa Hệ thống vi xử
lý với các thiết bị ngoại vi như bàn phím, chuột … (thiết bị nhập), màn hình, máy in, loa … (thiết
bị xuất), các ổ đĩa… (thiết bị xuất/nhập)

GV: Ong Mẫu Dũng – Khoa CNĐT 2


Bài giảng KỸ THUẬT VI XỬ LÝ

- Bus: ba khối chức năng trên liên hệ với nhau thông qua một tập các đường dây để truyền
thông tin gọi là bus. Trong hệ thống vi xử lý thường bao gồm 3 loại bus: bus địa chỉ, bus dữ liệu
và bus điều khiển.
3.3. Tổng kết lại các điểm quan trọng:
1. Hệ thống vi xử lý có 3 khối chính:
o Bộ nhớ
o CPU
o Phối ghép (giao tiếp) vào/ra (I/O)
2. CPU đọc thông tin từ bộ nhớ và ghi thông tin vào bộ nhớ
3. Các thiết bị đầu vào đưa thông tin từ bên ngoài vào Hệ thống vi xử lý
4. Các thiết bị đầu ra đưa thông tin từ CPU đến các đối tượng bên ngoài
5. Thông tin không chạy trực tiếp từ bộ nhớ đến các phối ghép vào/ra (I/O) và ngược lại,
trước tiên thông tin phải đi qua CPU
Có thể thấy rằng vi xử lý chỉ trao đổi thông tin với bộ nhớ và các phối ghép vào/ra I/O. Dù hệ
thống sau này phức tạp như thế nào hoặc chương trình có dài đến đâu thì vi xử lý chỉ làm
những việc sau:
1. Đọc từ bộ nhớ
2. Ghi vào bộ nhớ
3. Đọc từ các đầu vào
4. Ghi vào các đầu ra
5. Thực hiện các lệnh nội bộ như lệnh cộng (ADD), lệnh trừ (SUB) …
II. CÁC LOẠI BUS
1. Bus địa chỉ
- Có chức năng chuyển tải các thông tin về địa chỉ.
- Khi đọc/ghi bộ nhớ hay thiết bị I/O, P sẽ đưa ra các bit địa chỉ trên bus địa chỉ để chọn chính xác
một ngăn nhớ (word) hay một thiết bị I/O cụ thể nào đó sẽ được giao tiếp với nó.
- Số lượng địa chỉ mà P có thể quản lý phụ thuộc vào số bit (số đường dây) của bus địa chỉ (16,
20, 24, 32 … bit).
Ví dụ: Một P có số đường dây của bus địa chỉ là N = 16
→ có khả năng quản lý: 2N = 216 = 26.210 = 64.210 = 64 K = 65356 địa chỉ.
- Bus địa chỉ là loại bus một chiều (xuất phát từ P).
Đệm bus địa chỉ

GV: Ong Mẫu Dũng – Khoa CNĐT 3


Bài giảng KỸ THUẬT VI XỬ LÝ

Do tất cả các thiết bị ngoại vi và bộ nhớ đều được nối với bus địa chỉ nên về mặt điện có thể vượt
quá tính chịu tải (fan-out) của vi xử lý. Trong trường hợp các mạch nối vào bus địa chỉ tiêu thụ
dòng điện lớn hơn khả năng chịu tải của vi xử lý thì hệ thống sẽ không hoạt động hay hoạt động
không ổn định. Để giải quyết vấn đề này ta sử dụng các bộ đệm trung gian được gọi là bộ đệm địa
chỉ.
Ví dụ: Đệm địa chỉ cho CPU có bus địa chỉ 16-bit:

Hình 1.2
2. Bus dữ liệu
- Có chức năng chuyển tải các thông tin về dữ liệu đến/từ P.
- Số lượng đường dây của bus này quyết định số bit dữ liệu mà P có khả năng xử lý cùng một lúc
(8, 16, 32, 64 … bit).
- Bus dữ liệu là loại bus hai chiều.
Tuy nhiên tại một thời điểm nhất định thì dữ liệu chỉ được truyền theo một hướng duy nhất.

Hình 1.3 Dữ liệu di chuyển 2 chiều truyền bus dữ liệu


Lưu ý: Hoạt động của bus địa chỉ và bus dữ liệu hoàn toàn độc lập với nhau (hình 1.4).

GV: Ong Mẫu Dũng – Khoa CNĐT 4


Bài giảng KỸ THUẬT VI XỬ LÝ

Path1 ( Được chọn)


Address Bus

Data Bus

CPU
Path 2(Khoâ
ng chọn)

Hình 1.4
Đệm bus dữ liệu
- Tương tự như bus địa chỉ, bus dữ liệu cũng cần được đệm để tăng fan-out khi cần thiết. Lưu ý là
cần dùng kỹ thuật đệm 2 chiều (hình 1.5) (IC 74LS245).

Điều khiển hướng

Hình 1.5

Kỹ thuật đệm 2 chiều sử dụng


thêm một tín hiệu điều khiển,
BD0 đi vào tín hiệu này sẽ quy định chiều
D0 đến CPU hệ thống dữ liệu sẽ được đệm.
B

3. Bus điều khiển


- Gồm nhiều đường dây tín hiệu khác nhau ( WR , RD …), mỗi tín hiệu điều khiển có một chiều

nhất định. Khi hoạt động, P có thể đưa tín hiệu điều khiển đến các khối khác nhau trong hệ, đồng
thời nó cũng có thể nhận các tín hiệu từ các khối khác để phối hợp hoạt động của toàn hệ.
Lưu ý: Bus điều khiển ở khối I/O vẽ dạng 2 chiều để chỉ tính 2 chiều của cả nhóm tín hiệu, chứ
không phải của mỗi tín hiệu.
- Có 6 loại truyền thông tiêu biểu mà bus điều khiển phải xác đinh bằng tín hiệu điện:
(i) Đọc từ bộ nhớ
(ii) Ghi vo bộ nhớ
(iii) Đọc từ phối ghép đầu vào (Input)

GV: Ong Mẫu Dũng – Khoa CNĐT 5


Bài giảng KỸ THUẬT VI XỬ LÝ

(iv) Ghi vào phối ghép đầu ra (Output)


(v) Nhận biết yêu cầu ngắt (Interrupt acknowledge)
(vi) Nhận biết yêu cầu treo (Hold acknowledge, phục vụ DMA)
Giải thích về truyền thông trong cấu trúc 3-bus dựa vào sơ đồ khối hình 1.1: đọc và ghi.
III. VI XỬ LÝ (P – MICROPROCESSOR)
+ Sơ đồ khối của một P được cho trên hình 1.6.
+ Có ba khối chức năng chính: khối thực thi (Execution Unit), khối điều khiển tuần tự (Sequencer)
và khối giao tiếp bus (Bus Interface).

Execution Unit Sequencer

Control Instruction Register


Unit
Instruction Decoder
Registers
ALU
Program Counter
(data, address)

Internal bus

Data bus Control bus Address bus Bus


Interface
driver driver driver

Data bus Control bus Address bus

Hình 1.6
Execution Unit: Khối thực thi
Control Unit: Khối điều khiển
Registers: Các thanh ghi
ALU (Arithmetic & Logic Unit): Khối logic - số học
Sequencer: Bộ điều khiển tuần tự
Instruction Register: Thanh ghi lệnh
Instruction Decoder: Bộ giải mã lệnh
Program Counter: Bộ đếm chương trình
Internal bus: Bus nội
Bus interface: Giao tiếp bus
Data bus driver: Bộ điều khiển bus dữ liệu
Control bus driver: Bộ điều khiển bus điều khiển
Address bus driver: Bộ điều khiển bus địa chỉ

GV: Ong Mẫu Dũng – Khoa CNĐT 6


Bài giảng KỸ THUẬT VI XỬ LÝ

- Bộ điều khiển tuần tự (Sequencer): nhận lệnh từ bộ nhớ, sau đó giải mã lệnh và truyền lệnh đã
giải mã đến khối thực thi.
+ Bộ đếm chương trình (Proram Counter): là một thanh ghi lưu giữ địa chỉ của lệnh kế tiếp
sẽ được thực thi. Mỗi khi một lệnh được thực thi, bộ đếm chương trình sẽ được tăng lên 1 để chỉ
ra địa chỉ của lệnh kế tiếp sẽ được thực thi. Nội dung của bộ đếm chương trình được đặt lên bus
địa chỉ để tìm và nhận lệnh mong muốn. Như vậy, P thực hiện các lệnh của chương trình một
cách tuần tự, trừ khi gặp các lệnh chuyển điều khiển (lệnh nhảy, gọi chương trình con …) làm thay
đổi nội dung PC. Trong một số vi xử lý, bộ đếm chương trình còn được gọi là con trỏ lệnh IP
(Instruction Pointer).
+ Bộ giải mã lệnh (Instruction Decoder): thông dịch (diễn dịch) các lệnh được nhận vào P.
Có thể xem bộ giải mã lệnh như một từ điển lưu trữ nghĩa của mỗi lệnh và các bước mà P cần
thực hiện đối với mỗi lệnh được nhận vào. Giống như từ điển nếu có càng nhiều trang thì có thể
định nghĩa được nhiều từ hơn, một P có thể hiểu càng nhiều lệnh hơn nếu có bộ giải mã lệnh
càng lớn.
+ Thanh ghi lệnh (Instructin Register): lưu giữ mã nhị phân của lệnh đang được thực thi.
- Khối thực thi (Execution Unit): thực thi và ghi kết quả câu lệnh. Các toán hạng (operand) liên
quan có mặt ở các thanh ghi (registers) hoặc có từ bus nội (internal bus).
+ ALU (Arithmetic Logic Unit): là một mạch điện tử có khả năng thực hiện các phép toán số
học (+, -, *, / …) và logic (AND, OR, NOT, XOR…).
+ Thanh ghi (Register): là một bộ nhớ cực nhanh, có dung lượng hạn chế nằm bên trong P.
Các thanh ghi thường được dùng để lưu trữ các thông tin tạm thời. Mỗi thanh ghi có một địa chỉ
để truy xuất tới nó. Các thanh ghi được nối với nhau hoặc đến các phần tử khác của P hay nối với
bus ngoài nhờ bus nội. Độ rộng của các thanh ghi có thể là 8-bit, 16-bit, 32-bit hay 64-bit tùy thuộc
vào loại P. Thông tin có thể là 2 giá trị cần được xử lý hay địa chỉ chứa giá trị cần được xử lý nhận
từ bộ nhớ (hay I/O). P có càng nhiều thanh ghi và độ rộng càng lớn thì càng tốt vì lúc này chương
trình không phải thực hiện nhiều phép truyền thông tin giữa P và bộ nhớ do có thể truy xuất trực
tiếp từ thanh ghi, từ đó làm giảm thời gian truy xuất cũng như độ dài lệnh.
+ Khối điều khiển: tạo ra các tín hiệu điều khiển hoạt động của các bộ phận bên trong và
bên ngoài P (tùy theo mã lệnh).
- Giao tiếp bus (Bus Interface): gồm ba bộ điều khiển bus để giao tiếp với bus bên ngoài tương
ứng: bus dữ liệu, bus điều khiển và bus địa chỉ.

GV: Ong Mẫu Dũng – Khoa CNĐT 7


Bài giảng KỸ THUẬT VI XỬ LÝ

Việc tìm nạp lệnh từ bộ nhớ là một trong các thao tác cơ bản nhất mà P thực hiện, gồm các bước
như sau:
- Nội dung của PC được đặt lên bus địa chỉ.
- Tín hiệu điều khiển READ được xác lập (chuyển sang trạng thái tích cực).
- Mã lệnh được đọc từ bộ nhớ và đưa lên bus dữ liệu.
- Mã lệnh được chốt vào thanh ghi lệnh IR bên trong.
- PC được tăng lên để chuẩn bị tìm nạp lệnh kế từ bộ nhớ.
Hình 1.7 minh họa luồng thông tin cho việc tìm nạp lệnh.

Hình 1.7
IV. BỘ NHỚ (MEMORY)
❖ Nhắc lại các đơn vị bit, nibble, byte, word
o 1 nibble = 4 bit
o 1 byte = 8 bit
o Word là một nhóm gồm nhiều byte. Theo qui ước 1 word = 2 byte và 1 word dài = 4
byte (theo thế Hệ thống vi xử lý 16-bit, 32-bit …)
1. Phân loại
+ Bộ nhớ thường được chia làm hai loại: bộ nhớ cơ bản (hay bộ nhớ chính – main memory) và bộ
nhớ lưu trữ (storage memory).
- Bộ nhớ chính: ROM và RAM.
- Bộ nhớ lưu trữ: băng từ, đĩa mềm, đĩa cứng…
+ Thông thường bộ nhớ lưu trữ được xem như là thiết bị I/O.
a. Bộ nhớ chỉ đọc – ROM (Read-Only Memory)

GV: Ong Mẫu Dũng – Khoa CNĐT 8


Bài giảng KỸ THUẬT VI XỬ LÝ

- Là bộ nhớ chỉ đọc, không thể sửa đổi thông tin trong các hoạt động thông thường.
- Thông tin ghi trong ROM sẽ không bị mất đi khi mất nguồn cung cấp.
- ROM được ghi bằng thiết bị chuyên dụng.
- ROM thường được dùng để chứa các chương trình và dữ liệu cố định (chương trình khởi
động, dữ liệu tra bảng …)
- Các loại ROM:
o ROM: thông tin được ghi lúc chế tạo.
o PROM (Programable ROM): là ROM trắng, chỉ cho phép ghi thông tin một lần duy nhất.
o EPROM (Erasable ROM): có thể ghi và xóa thông tin nhiều lần. Loại này được xóa bằng
cách rọi tia cực tím vào cửa sổ thủy tinh trên bề mặt.
o EEPROM (Electrically EPROM): còn gọi là ROM điện, có thể ghi và xóa thông tin bằng
xung điện.
o Flash ROM: tương tự EEPROM.
b. Bộ nhớ truy xuất ngẫu nhiên – RAM (Random Access Memory)
- Cho phép đọc/ghi thông tin bất kỳ lúc nào trong quá trình làm việc mà không cần thiết bị
đặc biệt.
- Thông tin trong RAM sẽ bị mất khi mất nguồn cung cấp.
- Có hai loại RAM chính:
o RAM động – DRAM (Dynamic RAM): có cấu tạo từ các transistor MOSFET và tụ điện (1
phần tử nhớ), lưu trữ thông tin bằng điện tích trong tụ nên thông tin có thể mất đi (rò
rĩ hết) nếu không có biện pháp duy trì thích hợp. Do đó cần có quá trình làm tươi
(refresh) định kì để phục hồi nội dung của các ô nhớ trước khi nó mất đi (rò rĩ hết).
DRAM có thể tích hợp với dung lượng lớn.
o RAM tĩnh – SRAM (Static RAM): cấu tạo từ những Flipflop (FF) (1 phần tử nhớ), mỗi FF
lưu trữ một bit thông tin nên SRAM không cần quá trình làm tươi để duy trì nội dung.
Tuy nhiên, nó khó tích hợp với dung lượng lớn.
2. Cấu trúc bên trong tiêu biểu của bộ nhớ
- Bộ nhớ gồm các phần tử nhớ hay ô nhớ (memory cell) được tổ chức dưới dạng ma trận.
Mỗi ô nhớ chứa một bit thông tin.
- Mảng nhớ được phân chia thành một chuỗi các ngăn nhớ hay từ nhớ (word).
- Mỗi ngăn nhớ đều có một địa chỉ duy nhất.
- Một ngăn nhớ có thể có 4-bit, 8-bit, 16-bit …

GV: Ong Mẫu Dũng – Khoa CNĐT 9


Bài giảng KỸ THUẬT VI XỬ LÝ

- Ký hiệu: số ngăn nhớ x độ rộng mỗi ngăn nhớ


Ví dụ: bộ nhớ 1024 x 8 bao gồm 210 ngăn nhớ, mỗi ngăn nhớ có 8-bit.

- Cấu trúc bên trong tiêu biểu của bộ nhớ:

- Các tín hiệu tiêu biểu trên một chip nhớ:

+ CS (Chip Select): tín hiệu chọn chip (cho phép chip).

+ OE (Output Enable): tín hiệu cho phép xuất dữ liệu (nhận xung kích RD từ P).

+ WE (Write Enable): tín hiệu cho phép ghi dữ liệu (nhận xung kích WR từ P).
+ Address: các tín hiệu địa chỉ (từ bus địa chỉ) để chọn ngăn nhớ cần thao tác.
+ Data: các tín hiệu dữ liệu đọc ra (data output) hay ghi vào (data input), được nối với bus
dữ liệu.
3. Truy xuất bộ nhớ
* Các quy ước trên giản đồ thời gian: Hình 1.9

GV: Ong Mẫu Dũng – Khoa CNĐT 10


Bài giảng KỸ THUẬT VI XỬ LÝ

GV: Ong Mẫu Dũng – Khoa CNĐT 11


Bài giảng KỸ THUẬT VI XỬ LÝ

a. Truy xuất ROM


Giới thiệu EPROM 2764:
Đây là IC nhớ 28 chân 8K (8192 x 8) với 13 đường địa chỉ và 8 đường dữ liệu. Chú ý rằng
chân /PGM không được điều khiển bởi vi xử lý, chỉ dùng cho bộ nạp dữ liệu vào ROM. Điện áp VPP
chỉ sử dụng khi nạp ROM, còn điện áp VCC = 5V là điện áp hoạt động của ROM.

A0 – A12 Đường địa chỉ


D0 – D7 Đường dữ liệu
/CE Chọn chip
/OE Cho phép xuất
/PGM Lập trình

Quy trình đọc ROM:


1. Xác định địa chỉ của ngăn nhớ cần truy xuất. CPU sẽ đưa địa
chỉ này lên bus địa chỉ đến ROM.
2. Kích hoạt tín hiệu chọn chip cho phép dữ liệu được xuất ra

GV: Ong Mẫu Dũng – Khoa CNĐT 12


Bài giảng KỸ THUẬT VI XỬ LÝ

bus dữ liệu.
3. CPU đợi 1 khoảng thời gian ngắn gọi là thời gian truy cập để vi mạch nhớ giải mã địa chỉ
và xuất dữ liệu ra đường dữ liệu. CPU xuất xung nhịp nạp dữ liệu vào thanh ghi bên trong.
4. Tín hiệu chọn chip được đặt ở mức không tích cực và xóa dữ liệu từ ROM vào CPU.
Địa chỉ từ CPU đến ROM

CS
2

Bus dữ liệu

Dữ liệu không có giá trị 3 Dữ liệu không có giá trị

Dữ liệu của
ROM ở trên
bus dữ liệu

Hình 1.10
b. Truy xuất RAM
Giới thiệu RAM 6264
Đây là IC nhớ cho phép đọc ghi tùy ý, 28 chân 8K (8192 x 8) với 13 đường địa chỉ và 8
đường dữ liệu.
Quy trình đọc RAM: tương tự như đọc dữ liệu từ ROM.
A0 – A12 Đường địa chỉ
D0 – D7 Đường dữ liệu
/CE Chọn chip
/OE Cho phép xuất
/WE Cho phép ghi

Hình 1.11

GV: Ong Mẫu Dũng – Khoa CNĐT 13


Bài giảng KỸ THUẬT VI XỬ LÝ

Địa chỉ từ CPU đến RAM

Read/Write tín
hiệu logic để
truy cập RAM
Dữ liệu xuất ra có giá trị
Bus dữ liệu

TACC

Hình 1.12
Quy trình ghi RAM:
(i) Các đường địa chỉ được kết nối với RAM xác định ngăn nhớ nào trong RAM sẽ được kết nối.
(ii) Dữ liệu cần ghi vào RAM được xuất đến các đường dữ liệu vào của RAM.
(iii) Hệ thống phải đợi một khoảng thời gian nhỏ. Trong khoảng thời gian này RAM sẽ giải mã địa
chỉ và chọn ngăn nhớ mang địa chỉ nhận được. Khoảng thời gian này gọi là thời gian ghi vào
RAM.
(iv) Đường dẫn R/W sẽ được đặt ở mức logic tương ứng với thao tác ghi vào RAM. Tín hiệu này
cho phép dữ liệu được ghi vào RAM
(v) Chú ý rằng ở đây ta nói về các đường dẫn dữ liệu ra từ RAM và các đường dẫn dữ liệu vào
RAM. Trong thực tế vì rằng trong một khoảng khắc nhất định thì ta chỉ thực hiện một thao
tác l đọc hoặc ghi, nên cả hai loại đường dẫn trên được thực hiện bằng một đường dẫn hai
chiều chung.
Địa chỉ từ CPU đến RAM

Dữ liệu xuất ra RAM ổn định


Bus dữ liệu

Read/Write
xuống lên để
nạp dữ liệu
vàp RAM

Hình 1.13

GV: Ong Mẫu Dũng – Khoa CNĐT 14


Bài giảng KỸ THUẬT VI XỬ LÝ

4. Giải mã địa chỉ cho bộ nhớ


Trong một hệ thống vi xử lý, bộ nhớ có thể được tạo thành từ nhiều chip nhớ. Các chip này đều
dùng chung bus dữ liệu để trao đổi với P. Do đó để tránh xung đột trên bus, cần phải giải mã địa
chỉ để tại mỗi thời điểm chỉ cho phép một chip có thể kết nối với bus dữ liệu để trao đổi với P.
Kết nối mạch giải mã địa chỉ tổng quát:

Đến các chân địa chỉ của


Bus địa chỉ các chip nhớ

Đến các chân


chọn chip của
P Mạch giải mã
các chip nhớ
địa chỉ

Bảng bộ nhớ

MSB LSB
Các bit địa chỉ
2m
……

m bit n bit
vùng
đến bộ đến các
giải mã chip nhớ 2n
địa chỉ
địa chỉ
Hình 1.14 Quan hệ giữa giải mã địa chỉ và bảng bộ nhớ:
Ví dụ: P có 16 đường địa chỉ (A15 → A0) → có thể quản lý 216 = 26.210 = 64 K = 65536 địa chỉ: + 3
bit cao (A15 → A13) được đưa đến bộ giải mã (ở đây dùng IC 74LS138). + 13 bit thấp (A12 → A0)
được đưa đến các chip nhớ. → có 23 = 8 vùng, mỗi vùng có 213 = 23.210 = 8 K = 8192 địa chỉ.

GV: Ong Mẫu Dũng – Khoa CNĐT 15


Bài giảng KỸ THUẬT VI XỬ LÝ

0000 → 1FFF
2000 → 3FFF Đưa đến các
4000 → 5FFF chân chọn
6000 → 7FFF
8000 → 9FFF
chip của các
A000 → BFFF chip nhớ
C000 → DFFF
E000 → FFFF

Hình 1.16

V. NHẬP/XUẤT (I/O – INPUT/OUTPUT)


1. Phân loại
- Theo chiều trao đổi dữ liệu:
+ Thiết bị xuất
+ Thiết bị nhập
+ Thiết bị nhập/xuất
- Theo dạng truyền dữ liệu:
+ Nối tiếp: đồng bộ và bất đồng bộ (thêm bit start, stop)
+ Song song
2. Cấu trúc tiêu biểu của port I/O
- Các port nhập (I) và xuất (O) giao tiếp P với các thiết bị ngoài không thể nối trực tiếp đến
các bus.
- Về cơ bản, một port xuất chỉ là một thanh ghi. Khi P ghi ra địa chỉ được gán cho port, port
sẽ chứa dữ liệu có từ bus dữ liệu. Như vậy nó cung cấp ngõ ra có chốt cho các thiết bị ngoài.
- Một port nhập thông thường là một bộ đệm 3 trạng thái. Khi P đọc vào từ địa chỉ được
gán cho port, bộ đệm 3 trạng thái sẽ đưa dữ liệu từ các ngõ nhập ngoài vào bus dữ liệu rồi
P đọc dữ liệu từ bus.
3. Giải mã địa chỉ cho I/O
a. I/O trực tiếp (Định địa chỉ I/O theo kiểu trực tiếp)
- Các địa chỉ thiết bị I/O tách khỏi các địa chỉ bộ nhớ.

- P cung cấp hai đường điều khiển đọc và ghi riêng cho I/O: IOR và IOW .
- Giải mã địa chỉ cho I/O tương tự như giải mã địa chỉ cho bộ nhớ.

GV: Ong Mẫu Dũng – Khoa CNĐT 16


Bài giảng KỸ THUẬT VI XỬ LÝ

Hình 1.20 Định địa chỉ I/O theo kiểu trực tiếp
Lưu ý: Một số thiết bị I/O có thể không có các tín hiệu địa chỉ.
Ví dụ: Giải mã địa chỉ cho I/O:

Hình 1.20 Giải mã địa chỉ cho I/O


Khi P cần trao đổi dữ liệu với một thiết bị I/O nào đó, nó phát tín hiệu địa chỉ của thiết bị
lên bus địa chỉ. Một số trong các tín hiệu địa chỉ này được đặt vào mạch giải mã chọn thiết bị.
Mạch giải mã này sẽ kích hoạt chỉ một tín hiệu chọn chip tương ứng với thiết bị được chọn, do đó
chỉ có bộ đệm dữ liệu của thiết bị này được nối với bus dữ liệu để trao đổi với P. Trong quá trình
này, tín hiệu điều khiển đọc hay ghi cũng được phát trên bus điều khiển để xác định thao tác
tương ứng.
b. I/O được ánh xạ như bộ nhớ
- P xem các thiết bị I/O như các vị trí bộ nhớ. Các vị trí này không được trùng với các địa chỉ có
trong các thiết bị nhớ như ROM và RAM.
- P không có các tín hiệu điều khiển đọc và ghi riêng cho I/O.
Sau đây là hai ví dụ minh họa việc tạo ra các tín hiệu đọc/ghi I/O từ các đường điều khiển đọc/ghi
bộ nhớ:
GV: Ong Mẫu Dũng – Khoa CNĐT 17
Bài giảng KỸ THUẬT VI XỬ LÝ

Ví dụ 1: Giả sử P có 16 đường địa chỉ, tín hiệu đọc/ghi I/O tích cực mức 0:

Trong ví dụ này đường địa chỉ A15 được dùng như là bit chọn đọc/ghi bộ nhớ hay I/O. Nếu

A15 = 1, ngõ ra IOR và IOW luôn là mức 1 nên thao tác được chọn là đọc/ghi bộ nhớ. Ngược lại

khi A15 = 0, ngõ ra IOR hay IOW sẽ là mức 0 khi có tín hiệu RD hay WR tương ứng từ bộ xử
lý.
Ví dụ 2: Mức tích cực của các tín hiệu đọc/ghi I/O là mức 1:

CSx : tín hiệu chọn thiết bị I/O từ mạch giải mã địa chỉ.
3. Các phương pháp điều khiển I/O
Có 3 phương pháp cơ bản: hỏi vòng hay kiểm tra tuần tự (polling), điều khiển ngắt
(interrupt) và DMA (Direct Access Memory). Ngoài ra cũng có thể kết hợp các phương pháp trên.
a. Polling (Hỏi vòng)
- P lần lượt kiểm tra từng I/O xem có yêu cầu dịch vụ không thông qua các cờ (flag).
- Tất cả các việc chuyển dữ liệu đến và từ các thiết bị I/O được thực hiện bằng chương trình →
polling là cơ chế đồng bộ (synchronous) với việc thực thi chương trình.
- Kỹ thuật polling có các hạn chế:
+ Mất thời gian của P (do kiểm tra trạng thái của tất cả các ngoại vi thường xuyên).

GV: Ong Mẫu Dũng – Khoa CNĐT 18


Bài giảng KỸ THUẬT VI XỬ LÝ

+ Chậm trong các hệ thống thời gian thực (real-time), không thỏa mãn cho các thiết bị yêu
cầu tốc độ đáp ứng nhanh.
+ Người sử dụng có thể gặp khó khăn trong trong vấn đề lập trình vì phải luôn canh chừng
I/O.

- Lưu đồ hoạt động của polling:

b. Interrupt (Ngắt)
+ Ngắt là một quá trình xử lý thông tin của vi xử lý tương tự như con người xử lý thông tin.

GV: Ong Mẫu Dũng – Khoa CNĐT 19


Bài giảng KỸ THUẬT VI XỬ LÝ

Ví dụ khi bạn đang nói chuyện với một người. Người thứ ba đến và gọi tên bạn. Đây là dấu
hiệu rằng có một người khác yêu cầu sự quan tâm của bạn. Người thứ ba này có thể được coi như
là một yêu cầu ngắt bên ngoài (external interrupt request). Người này yêu cầu bạn ngắt cuộc nói
chuyện của mình. Bạn có thể xử lý yêu cầu nầy bằng các cách như sau:
1. Bạn có thể bỏ qua yêu cầu và coi như người thứ ba là không tồn tại.
2. Bạn có thể dừng một cách thích hợp đối thoại đang diễn ra, rồi bắt đầu quan tâm đến
người thứ ba. Lúc này bạn bắt đầu nói chuyện với người này chứ không nói chuyện với
người đầu tiên nữa.
3. Bạn tức khắc dừng nói chuyện với người thứ nhất và bắt đầu nói chuyện ngay với người
thứ ba.
Khi bạn nói chuyện xong với người thứ ba, bạn muốn quay lại tiếp tục cuộc đối thoại với
người thứ nhất tại điểm mà yêu cầu ngắt xuất hiện.
+ Quá trình này diễn ra tương tự với kỹ thuật ngắt trong hệ thống vi xử lý. Lúc này CPU
đóng vai trị của bạn. Người thứ nhất là chương trình chính đang được thực hiện. Người thứ ba là
một yêu cầu ngắt bên ngoài. Đây là một thiết bị phần cứng bên ngoài yêu cầu CPU quan tâm đến
nó. CPU phải xử lý yêu cầu ngắt nầy bằng cách nào đó. Có nhiều cách xử lý ngắt, các cách được
nêu ở ví dụ trên là các cách xử lý thơng dụng nhất.
+ Ví dụ như ta có một cảm biến báo cháy. Thông thường khi không có lửa thì cảm biến xuất
ra số 1, khi có lửa thì cảm biến xuất số 0 báo cho vi xử lý kích hoạt chương trình báo động. Vi xử lý
có thể luôn luôn đọc trạng thi của cảm biến bằng lệnh IN từ cổng nối với cảm biến. Sau đó vi xử lý
kiểm tra trạng thi cảm biến và gọi chương trình báo động khi trạng thi cảm biến là 0. Tuy vậy đây là
một thao tác lặp đi lặp lại nhiều lần một cách không hiệu quả, vì phần lớn thời gian cảm biến
không báo cháy. Một cách xử lý hiệu quả hơn là đưa tín hiệu của cảm biến vào yêu cầu ngắt của vi
xử lý. Chỉ khi nào yêu cầu ngắt này được kích hoạt thì vi xử lý mới gọi chương trình báo động.

GV: Ong Mẫu Dũng – Khoa CNĐT 20


Bài giảng KỸ THUẬT VI XỬ LÝ

Ngắt là cơ chế bất đồng bộ (asynchronous) với việc thực thi chương trình. Nó được dùng
với mục đích là tránh tối đa hoặc loại bỏ hẳn cơ chế hỏi vòng để kiểm tra trạng thái thiết bị.
- Mỗi thiết bị I/O hay bộ điều khiển của nó được nối với một đường interrupt.
- Khi I/O có yêu cầu trao đổi dữ liệu nó sẽ phát ra một tín hiệu báo cho P. Tín hiệu đó được gọi
là tín hiệu yêu cầu ngắt IRQ (interrupt request). Khi P nhận được yêu cầu ngắt đó, nếu đồng ý
trao đổi thông tin với I/O, nó sẽ trả lời với bộ điều khiển nhập/xuất bằng tín hiệu chấp nhận ngắt
INTA (interrupt acknownledge) đồng thời ngừng chương trình đang làm và gọi chương trình
phục vụ ngắt cho I/O. Sau khi phục vụ xong, nó quay về tiếp tục thực hiện chương trình đang
làm tại nơi bị ngắt.
- Khi có nhiều I/O yêu cầu ngắt đồng thời → cần có mạch điều khiển ưu tiên ngắt.
- Lưu đồ hoạt động của ngắt:

- Thủ tục interrupt về nguyên tắc tương tự với gọi chương trình con, ngoại trừ:
(i) Interrupt được khởi động từ 1 tín hiệu bên trong hoặc bên ngoài thay vì từ những thực thi
lệnh.
(ii) Địa chỉ của chương trình phục vụ interrupt được xác định bằng thủ tục hardware thay vì từ
vùng địa chỉ của lệnh. (bảng vector ngắt được xác định trước của từng loại vi xử lý).
(iii) Khi đáp ứng 1 interrupt cần lưu tất cả các thông tin định nghĩa trạng thái hiện hành của hệ
thống thay vì chỉ lưu trữ bộ đếm chương trình PC.
c. DMA (Direct Memory Access)
- Thông thường khi chương trình muốn chuyển một byte dữ liệu từ ngoại vi vào bộ nhớ, nó phải
thực hiện thông qua P gồm một thao tác nhập và sau đó là thao tác ghi bộ nhớ. Hoặc ngược lại,
khi muốn đưa thông tin từ bộ nhớ ra ngoại vi, P phải làm thao tác đọc bộ nhớ rồi xuất ra ngoại vi.

GV: Ong Mẫu Dũng – Khoa CNĐT 21


Bài giảng KỸ THUẬT VI XỬ LÝ

Trong trường hợp này, chức năng của P chỉ là chuyển dữ liệu mà không xử lý gì cả. Điều này lặp
đi lặp lại nhiều lần sẽ làm lãng phí việc sử dụng P vì chức năng chủ yếu của P là xử lý dữ liệu.

- DMA là cơ chế điều khiển cho phép truy xuất bộ nhớ trực tiếp, không thông qua P.
- Cơ chế DMA được thực hiện bởi một mạch phần cứng được gọi là bộ điều khiển DMA
(DMAC - DMA Controller).
- DMA giúp rút ngắn thời gian truy xuất giữa bộ nhớ và I/O. Cơ chế này rất tiện dụng cho
các thiết bị ngoại vi có khối lượng thông tin trao đổi lớn (trao đổi một khối dữ liệu lớn trong một
thời gian ngắn) ví dụ như card màn hình, đĩa cứng … trong máy tính.
- Quá trình DMA bắt đầu khi có tín hiệu yêu cầu DMA (DRQ) từ thiết bị I/O đến DMAC.
DMAC tiếp tục gởi tín hiệu yêu cầu P nhường bus (HRQ) đến chân HOLD của P để nó thực thi
việc trao đổi dữ liệu trực tiếp giữa bộ nhớ và I/O. Khi P đồng ý nhường bus, nó trả lời cho DMAC
bằng tín hiệu chấp nhận nhường bus (HLDA) đồng thời tạm ngưng mọi hoạt động, tự tách ra khỏi
hệ thống. Đến lượt DMAC gởi tín hiệu thông báo cho phép trao đổi dữ liệu theo kiểu DMA (DACK)
đến thiết bị I/O. Khi DMAC chuyển hết dữ liệu, nó trả quyền điều khiển các bus lại cho P, quá
trình DMA kết thúc.
- Trong thực tế, việc sử dụng cơ chế DMA khá phức tạp và qua nhiều công đoạn vì DMAC
không thi hành bất kì lệnh nào, chương trình nào (không thực thi phần mềm) để chuyển dữ liệu
mà nó thực hiện hoàn toàn bằng phần cứng nên cần phải có trước đầy đủ các thông tin về vị trí dữ
liệu của I/O, vị trí bộ nhớ chứa dữ liệu và số lượng byte cần chuyển để P nạp cho DMAC. Ngoài
ra, DMAC còn phải có khả năng tạo ra các tín hiệu điều khiển cần thiết giống như các tín hiệu của
P.

GV: Ong Mẫu Dũng – Khoa CNĐT 22


Bài giảng KỸ THUẬT VI XỬ LÝ

VI. VI XỬ LÝ VÀ VI ĐIỀU KHIỂN


- Về cấu trúc phần cứng:
+ Vi xử lý: là một CPU đơn chip (như trong sơ đồ khối ở trên).
+ Vi điều khiển: gồm CPU và một số thành phần khác như bộ nhớ ROM, RAM, các port I/O
và một số mạch chức năng như mạch định thời (timer), mạch điều khiển ngắt (interrupt
controller), mạch giao tiếp nối tiếp (serial interface)…
- Về ứng dụng:
+ Vi xử lý: thường dùng làm CPU trong các máy vi tính.
+ Vi điều khiển: thường dùng trong các thiết kế nhỏ, hướng điều khiển.
- Đặc trưng về tập lệnh:
+ Vi xử lý: mạnh về các kiểu định địa chỉ, số lệnh nhiều.
+ Vi điều khiển: có thể thao tác với từng bit đơn (định hướng bit).

***

GV: Ong Mẫu Dũng – Khoa CNĐT 23


Bài giảng KỸ THUẬT VI XỬ LÝ

CHƯƠNG 2: BỘ VI XỬ LÝ INTEL 80X86


2.1. Cấu trúc phần cứng của bộ vi xử lý 8086

+ Control Unit (CU) tạo ra tất cả các tín hiệu điều khiển trong CPU. Nó khởi tạo các thanh
ghi khi ở nguồn, tạo ra các tín hiệu để lấy lệnh cho ALU. Khối điều khiển có thể được thực hiện
hoàn toàn bởi phần cứng (điều khiển cứng, ví dụ như sử dụng một bộ đếm trạng thái và một mảng
logic khả lập triình) hay kết hợp giữa các lệnh phần mềm (vi lệnh được lưu trữ trong CPU) và phần
cứng (bộ điều khiển vi chương trình. Cả hai họ vi xử lý Intel 8086 và Motorola 68000 đều sử dụng
các bộ điều khiển vi chương trình.
+ Registers – là các bộ nhớ nhỏ, nhanh, thường được sử dụng để lưu dữ liệu và địa chỉ gắn
với (tương ứng với) các mã lệnh của chương trình.
+ ALU thực hiện các phép toán số học và logic
2.2. Cấu trúc bên trong và sự hoạt động
+ Trong sơ đồ khối, ta thấy trong CPU 8086 có hai khối chính: khối phối ghép bus (bus
interface unit, BIU) và khối thực hiện lệnh (execution unit, EU). Việc chia CPU thành hai phần
đồng thời có liên hệ với nhau qua đệm lệnh làm tăng đáng kể tốc độ xử lý của CPU. Các bus bên
trong CPU có nhiệm vụ chuyển tải tín hiệu của các khối khác. Trong số các bus có bus dữ liệu 16 bit
của ALU, bus các tín hiệu điều khiển ở EU và bus trong của hệ thống ở BIU. Trước khi đi ra bus
ngoài hoặc đi vào bus trong của bộ vi xử lý, các tín hiệu truyền trên bus thường được cho đi qua
các bộ đệm để nâng cao tính tương thích cho nối ghép hoặc nâng cao khả năng phối ghép.

GV: Ong Mẫu Dũng – Khoa CNĐT 24


Bài giảng KỸ THUẬT VI XỬ LÝ

+ BIU có nhiệm vụ đưa ra địa chỉ, đọc mã lệnh từ bộ nhớ, đọc/ghi dữ liệu từ/vào cổng hoặc
bộ nhớ. Bên trong BIU còn có bộ nhớ đệm lệnh (còn gọi là hàng đợi lệnh) dùng để chứa các lệnh
đã đọc được nằm sẵn chờ EU xử lý.
+ EU có nhiệm vụ cung cấp địa chỉ cho BIU để khối này đọc lệnh và dữ liệu, còn bản thân nó
thì giải mã lệnh và thực hiện lệnh. Mã lệnh đọc vào từ bộ nhớ được đưa đến đầu vào của bộ giải
mã (nằm trong khối điều khiển CU), các thông tin thu được từ đầu ra của bộ giải mã sẽ được đưa
đến mạch tạo xung điều khiển để tạo ra các dãy xung khác nhau (tùy từng lệnh) điều khiển hoạt
động của các bộ phận bên trong và bên ngoài CPU. Trong EU còn có khối tính toán số học và logic
ALU dùng để thực hiện các thao tác khác nhau với các toán hạng của lệnh.
2.3. Sơ đồ khối bên trong của 8086
+ Đơn vị giao tiếp Bus (BIU)
BIU bao gồm các thanh ghi đoạn (segment registers: CS, DS, SS, ES), con trỏ lệnh IP
(instruction pointer) và bộ điều khiển logic bus (bus control logic, BCL). Đơn vị giao diện BIU còn có
bộ nhớ đệm cho mã lệnh. Bộ nhớ này có chiều dài 4 byte (trong 8088) và 6 byte (trong 8086). Bộ
nhớ đệm mã lệnh được nối với khối điều khển CB (control block) của đơn vị thực hiện lệnh EU. Bộ
nhớ này lưu trữ tạm thời mã lệnh trong một dãy gọi là hàng đợi lệnh. Hàng đợi lệnh cho phép bộ
vi xử lý có khả năng xử lý xen kẽ liên tục dòng mã lệnh (pipelining). Hoạt động của bộ CPU được
chia làm ba giai đoạn: đọc mã lệnh (operation code fetching), giải mã lệnh (decording) và thực
hiện lệnh (execution).
BIU đưa ra địa chỉ, đọc mã lệnh từ bộ nhớ, đọc/ghi dữ liệu từ các cổng vào hoặc bộ nhớ.
Nói cách khác BIU chịu trách nhiệm đưa địa chỉ ra bus và trao đổi dữ liệu với bus.

GV: Ong Mẫu Dũng – Khoa CNĐT 25


Bài giảng KỸ THUẬT VI XỬ LÝ

+ Đơn vị xử lý lệnh (EU)


Trong EU có khối điều khiển (control unit, CU). Chính tại bên trong khối điều khiển này có
mạch giải mã lệnh. Mã lệnh đọc vào từ bộ nhớ được đưa đến đầu vào của bộ giải mã, các thông
tin thu được từ đầu ra của nó sẽ được đưa đến mạch tạo xung điều khiển, kết quả thu được là các
dãy xung khác nhau tuỳ theo mã lệnh, để điều khiển hoạt động của các bộ phận bên trong và bên
ngoài CPU.
Trong EU có khối số học và lôgic (arithmatic and logic unit, ALU) chuyên thực hiện các phép
tính số học và logic mã toán tử của nó nằm trong các thanh ghi đa năng. Kết quả thường được đặt
về thanh ghi AX.
Ngoài ra trong EU còn có các thanh ghi đa năng (registers: AX, BX, CX, DX, SP, BP, SI, DI),
thanh ghi cờ FR (flag register).
Tóm lại, khi CPU hoạt động EU sẽ cung cấp thông tin về địa chỉ cho BIU để khối này đọc lệnh và dữ
liệu, còn bản thân nó thì giải mã và thực hiện lệnh.
+ Nhóm các thanh ghi
Vi xử lý 8086 có tất cả 14 thanh ghi nội. Các thanh ghi này có thể phân nhóm như sau:
GV: Ong Mẫu Dũng – Khoa CNĐT 26
Bài giảng KỸ THUẬT VI XỬ LÝ

o Thanh ghi dữ liệu (data register)


o Thanh ghi chỉ số và con trỏ (index & pointer register)
o Thanh ghi đoạn (segment register)
o Thanh ghi cờ
a. Các thanh ghi dữ liệu
Các thanh ghi dữ liệu gồm có các thanh ghi 16 bit AX, BX, CX và DX trong đó nửa cao và nửa
thấp của mỗi thanh ghi có thể định địa chỉ một cách độc lập. Các nửa thanh ghi này (8 bit) có tên là
AH và AL, BH và BL, CH và CL, DH và DL. Các thanh ghi này được sử dụng trong các phép toán số
học và logic hay trong quá trình chuyển dữ liệu. Trong đó :
▪ AX (ACC – Accumulator):
▪ BX (Base): thanh ghi cơ sở
▪ CX (Count): đếm
▪ DX (Data): thanh ghi dữ liệu
b. Các thanh ghi chỉ số và con trỏ
Bao gồm các thanh ghi 16 bit SP, BP, SI và DI, thường chứa các giá trị offset (độ lệch) cho
các phần tử định địa chỉ trong một phân đoạn (segment). Chúng có thể được sử dụng trong các
phép toán số học và logic. Hai thanh ghi con trỏ (SP – Stack Pointer và BP – Base Pointer) cho phép
truy xuất dễ dàng đến các phần tử đang ở trong ngăn xếp (stack) hiện hành. Các thanh ghi chỉ số
(SI – Source Index và DI – Destination Index) được dùng để truy xuất các phần tử trong các đoạn
dữ liệu và đoạn thêm (extra segment). Thông thường các ghi con trỏ liên hệ đến đoạn stack hiện
hành và các thanh ghi chỉ số liên hệ đến doạn dữ liệu hiện hành. SI và DI dùng trong các phép toán
chuỗi.
c. Các thanh ghi đoạn
Bao gồm các thanh ghi 16 bit CS (Code segment), DS (Data segment), SS (stack segment)
và ES (extra segment), dùng để định địa chỉ vùng nhớ 1 MB bằng cách chia thành 16 đoạn 64 KB.
Tất cả các lệnh phải ở trong đoạn mã hiện hành, được định địa chỉ thông qua thanh ghi CS. Offset
(độ lệch) của mã được xác định bằng thanh ghi IP. Dữ liệu chương trình thường được đặt ở đoạn
dữ liệu, định vị thông qua thanh ghi DS. Stack định vị thông qua thanh ghi SS. Thanh ghi đoạn thêm
có thể sử dụng để định địa chỉ các toán hạng, dữ liệu, bộ nhớ và các phần tử khác ngoài đoạn dữ
liệu và stack hiện hành.
Do Bus địa chỉ của vi xử lý 8086 có kích thước là 20 bit, nhưng các thanh ghi con trỏ và
thanh ghi chỉ số chỉ rộng 16 bit nên không thể định địa chỉ cho toàn bộ nhớ vật lý của máy tính là

GV: Ong Mẫu Dũng – Khoa CNĐT 27


Bài giảng KỸ THUẬT VI XỬ LÝ

(220B = 1.048.576B = 1Mbyte). Vì vậy trong chế độ thực (real mode) bộ nhớ được chia làm nhiều
đoạn để một thanh ghi con trỏ 16 bit có thể quản lý được. Các thanh ghi đoạn 16 bit sẽ chỉ ra địa
chỉ đầu của 4 đoạn trong bộ nhớ, dung lượng lớn nhất của mỗi đoạn nhớ sẽ dài 216 = 64 Kbyte và
tại một thời điểm nhất định bộ vi xử lý chỉ làm việc được với 4 đoạn nhớ 64Kbyte này. Việc thay
đổi giá trị của các thanh ghi đoạn làm cho các đoạn có thể dịch chuyển linh hoạt trong không gian
1 Mbyte, vì vậy các đoạn có thể nằm cách nhau khi thông tin cần lưu trong chúng đòi hỏi dung
lượng đủ 64 Kbyte hoặc cũng có thể nằm chồng nhau do có những đoạn không dùng hết độ dài 64
Kbyte và vì thế các đoạn khác có thể bắt đầu nối tiếp ngay sau đó. Địa chỉ của ô nhớ nằm ở đầu
đoạn được ghi trong một thanh ghi đoạn 16 bit, địa chỉ này gọi là địa chỉ cơ sở. Mười sáu bit này
tương ứng với các đường dây địa chỉ từ A4 đến A20. Như vậy giá trị vật lý của địa chỉ đoạn là giá trị
trong thanh ghi đoạn dịch sang trái 4 vị trí. Điều này tương đương với phép nhân với 24 = 16. Địa
chỉ của các ô nhớ khác nằm trong đoạn tính được bằng cách cộng thêm vào địa chỉ cơ sở một giá
trị gọi là địa chỉ lệch hay độ lệch (offset), gọi như thế vì nó ứng với khoảng lệch của toạ độ một ô
nhớ cụ thể nào đó so với ô đầu đoạn. Độ lệch này được xác định bởi các thanh ghi 16 bit khác
đóng vai trò thanh ghi lệch (offset register).
d. Thanh ghi cờ
Các cờ chỉ thị tình trạng của bộ vi xử lý cũng như điều khiển sự hoạt động của chính nó.
Một thanh ghi cờ là 1 flip-flop mà nó chỉ thị một số tình trạng được tạo bởi việc thực thi 1 lệnh
hay các hoạt động điều khiển cụ thể của EU. Thanh ghi cờ 16-bit trong EU có 9 cờ.
o Các cờ điều kiện - conditional flags: Có 6 cờ được gọi là cờ điều kiện. Chúng được lập hay
xoá là bởi EU, dựa trên kết quả của các phép toán số học.
o Cờ điều khiển - control flags: 3 cờ còn lại trong thanh ghi cờ được sử dụng để điều khiển
một số hoạt động của vi xử lý. Chúng được gọi là các cờ điều khiển
a) Carry Flag (CF)- set by carry out of MSB.
b) Parity Flag (PF)- set if result has even parity.
c) Auxiliary carry Flag (AF)- for BCD
d) Zero Flag (ZF)- set if results = 0
e) Sign Flag (SF) = MSB of result
f) TF- single step trap flag
g) IF- interrupt enable flag
h) DF- string direction flag
i) Overflow Flag (OF)- overflow flag

GV: Ong Mẫu Dũng – Khoa CNĐT 28


Bài giảng KỸ THUẬT VI XỬ LÝ

+ Các cờ điều kiện


o Cờ nhớ - Carry flag (CF) – Cờ này được đặt lên 1 khi tính toán một số không dấu bị tràn. Ví
dụ khi cộng dạng byte: 255+1 (kết quả không nằm trong vùng 0..255). Khi không tràn, cờ
này đặt bằng 0
o Cờ chẵn lẻ - parity flag (PF) – Cờ PF=1 khi số lượng bit “1” trong kết quả là chẵn, PF=0 khi số
lượng bit “1” là lẻ.
o Cờ nhớ phụ - auxiliary carry flag (AF)- có ý nghĩa quan trọng đối với phép cộng và phép trừ
các số BCD; AF=1 khi nhóm 4 bit thấp (không dấu) tràn. Chỉ được sử dụng với lệnh thao tác
với số BCD.
o Cờ không - zero flag (ZF)- chỉ thị rằng kết qủa của phép toán số học hay logic là bằng 0.
o Cờ dấu - sign flag (SF) - chỉ thị dấu số học của kết quả sau 1 phép toán số học. Nếu số là âm
(MSB=1) thì SF=1 và ngược lại SF=0 khi MSB=0
o Cờ tràn - overflow flag (OF)- Cờ tràn OF=1 khi tính toán tràn số âm. Ví dụ khi tính bới 2 byte:
100+50 (kết quả ngoài khoảng -128..127)
+ Các cờ điều khiển
Các cờ điều khiển được lập hay xoá thông qua các lệnh đặc biệt trong chương trình người
dùng. Ba cờ điều khiển là:
o Cờ bẫy - trap flag (TF) – Khi cờ TF=1, CPU sẽ chờ ngắt từ thiết bị ngoài.
o Cờ ngắt - interrupt flag (IF) - được sử dụng để cho phép hay cấm ngắt của các chương trình;
o Cờ hướng - direction flag (DF) - được sử dụng với các lệnh chuỗi, mảng dữ liệu, nếu DF=0
thực thi theo hướng tiến, DF=1 thực thi theo hướng lùi.
o Không có lệnh riêng để lập cờ TF.
2.4. Mô tả chức năng các chân
+ Sơ đồ chân 8086/8088 là gần tương tự như nhau, chỉ khác ở chỗ 8088 có 8bit dữ liệu còn
8086 có 16 bit dữ liệu ngoài. Cả 2 bộ xử lý đều có:
o Độ rộng bus dữ liệu nội là 16 bit
o 20 đường địa chỉ (16 address/data + 4 address/status), cho phép địa chỉ hoá không
gian bộ nhớ tối đa là 1Mbyte ở chế độ dồn kênh address/data pins (8088 only
multiplexes 8 pins)
o 2 chế độ hoạt động (maximum và minimum mode)
o Cùng 1 tập lệnh
*** Sinh viên tham khảo them trên Internet. ***

GV: Ong Mẫu Dũng – Khoa CNĐT 29


Bài giảng KỸ THUẬT VI XỬ LÝ

CHƯƠNG 3: GIỚI THIỆU VĐK PIC 8 BIT HỌ 16F8XX


- Trình bày được chức năng của họ VĐK PIC và PIC 16F8xx.
- Trình bày được sơ đồ cấu trúc, cách tổ chức bộ nhớ thanh ghi và các modul thành phần,
tập lệnh của VĐK PIC
- Phân tích, lựa chọn loại VĐK cho mục đích thiết kế.
3.1 Đặc tính, cấu trúc, chức năng
3.1.1 Giới thiệu các VĐK , lịch sử phát triển của VĐK.
+ PIC viết tắt của “Programmable Intelligent Computer”, có thể dịch là máy tính thông minh
lập trình được, là một sản phẩm do hãng General Instruments đặt cho dòng sản phẩm đầu tiên của
họ PIC 1650.
+ PIC là một họ vi điều khiển RISC được sản xuất bởi công ty Microchip Technology. Dòng PIC
đầu tiên là PIC 1650 được phát triển bởi MicroElectronics Division thuộc General Instruments. Lúc
này PIC 1650 được dung để giao tiếp với các thiết bị ngoại vi cho máy chủ CP 1600. Hiện nay PIC
phát triển mạnh, có rất nhiều loại PIC ra đời.
▪ PIC 12 (độ dài mã lệnh 12 bit) như là dòng PIC 12Cxxx (thí dụ: PIC 12F50x, PIC 12F675), PIC
5x (16F54),
▪ PIC 14 như dòng PIC 16Fxxx (16F84, 16F818, 16F877A, 16F872),
▪ PIC 16 như dòng PIC 18Fxxx (PIC 18F4520, 18F2550).
3.1.2 Khảo sát VĐK 8 bit
o Cấu hình VĐK 8 bit.
+ PIC 16F877A là vi điều khiển PIC thông dụng, loại trung (mid- range) có đặc điểm:
- Đây là vi điều khiển thuộc họ PIC 16Fxxx với tập lệnh gồm 35 lệnh có độ dài 14 bit.
- Mỗi lệnh đều được thực thi trong một chu kì xung clock.
- Tốc độ hoạt động tối đa cho phép là 20 Mhz với một chu kì lệnh 20 ms.
- Bộ nhớ chương trình Flash là 8k x 14 words, bộ nhớ dữ liệu (RAM) là 368x8 byte, và bộ
nhớ EEPROM với dung lượng 256 x 8 byte.
- Số port I/O là 5 với 33 chân I/O.
+ Các đặc tính ngọai vi bao gồm các khối chức năng sau:
-Timer 0: bộ đếm 8 bit bộđếm với hệ số tỉ lệ trước.
-Timer 1: bộ đếm 16 bit, bộ đếm với hệ số tỉ lệ trước. Có thể được đếm thông qua xung
clock/ xung clock thạch anh ngoài ở chế độ phương thức cất giữ sleep.

GV: Ong Mẫu Dũng – Khoa CNĐT 30


Bài giảng KỸ THUẬT VI XỬ LÝ

-Timer 2: bộ đếm 8 bit với thanh ghi chu kì 8 bit, bộ đếm8 bit của hệ số tỉ lệ trước, hệ số tỉ
lệ sau.
- Có hai bộ bắt giữ/so sánh/điều rộng xung.
- Các cổng giao tiếp nối tiếp đồng bộ (SSP) với SPI phương thức chủ và I2C (chủ/tớ).
- Bộ truyền nhận nối tiếp đồng bộ, không đồng bộ (UASRT/SCL) có khả năng phát hiện 9 bit
địa chỉ.
- Cổng phụ song song với 8 bit mở rộng, với các chân điều khiển RD, WR, CS.
- Các đặc tính analog:
▪ Bộ chuyển đổi tương tự-số 10 bit trên chip với 8 kênh vào.
▪ Hai bộ so sánh,
+ Bên cạnh đó là một vài đặc tính của vi điều khiển như:
- Bộ nhớ Flash với khả năng ghi xóa được 100000 lần.
- Bộ nhớ dữ liệu EEPROM với khả năng ghi xóa được 1000000 lần.
- Dữ liệu bộ nhớ EEPROM có thể lưu trữ được 40 năm.
- Khả năng tự nạp chương trình với sựđiều khiển của phần mềm.
- Nạp được chương trình ngay trên mạch điện ISP (in circuit programming) thông qua 2
chân.
- Bộ đếm xung thời gian (WDT-Watch dog timer) với dao động RC bên trong.
- Có mã chương trình bảo vệ (chức năng bảo mật mã chương trình).
- Có thể hoạt động hiều dạng dao động khác nhau.
- Chếđộ sleep (phương thức cất giữ) tiết kiệm năng lượng.
- Công nghệ CMOS Flash/ eeprom với nguồn mức thấp, tốc độ cao.
- Dãi điện thế hoạt động rộng: 2V -> 5,5 V.
- Công suất tiêu thụ thấp: <0,6 mA với 5V, 4Mhz. 20 μA với nguồn 3V, 32 Khz. <1 μA với
nguồn dự phòng.
- Khả năng ngắt: lên tới 14 nguồn ngắt trong và ngắt ngoài.
- Ngăn xếp được chia làm 8 mức.
- Truy cập bộ nhớ bằng địa chỉ trực tiếp hay gián tiếp.
- Nguồn khởi động lại (POR-Power on reset).
o Sơ đồ cấu trúc của VĐK PIC 16F8xx 8 bit

GV: Ong Mẫu Dũng – Khoa CNĐT 31


Bài giảng KỸ THUẬT VI XỬ LÝ

o Khảo sát sơ đồ chân, chức năng các chân, port của VĐK PIC 16F8xx 8 bit

GV: Ong Mẫu Dũng – Khoa CNĐT 32


Bài giảng KỸ THUẬT VI XỬ LÝ

+ Ý nghĩa các chân:


▪ OSC1/CLKI: chân ngõa vào mạch dao động, chân 13.
▪ OSC2/CLKO: chân ngõ ra của mạch dao động, chân 14.
▪ /MCLR/Vpp: chân số 1, chân reset, tích cực mức thấp và còn là xung lập trình cho ROM.
▪ RA0, RA1, RA2, RA3, RA4, RA5: chân 2-7, là các chân xuất nhập của PORTA.
▪ Chân 2-7, 8-10 còn là ngõ vào analog AN0, AN1, AN2, AN3, AN4, AN5, AN6, AN7.
▪ RA4/T0CKI: vừa là chân xuất nhập dữ liệu của port A, vừa là chân lấy xung cho thanh đếm
của timer 0 (timer 0 clock input).
▪ RE0, RE1, RE2: chân 8-10, là các chân xuất nhập của PORTE.
▪ RE0/RD: còn là xung cho phép đọc bộ nhớ (read), tích cực logic 0.
▪ RE1/WR: còn là xung cho phép ghi bộ nhớ (write), tích cực logic 0.
▪ RE2/CS: còn là xung chọn chip (chip select), tích cực logic 0.
▪ RC0, RC1, RC2, RC3: chân 15-18, và RC4, RC5, RC6, RC7: chân 23-26: là các chân xuất nhập
của port C.
▪ RC0/T1OSO/T1KCI: còn là chân lấy xung cho thanh đếm của timer 1, và là chân T1OSO.
▪ RC1/T1OSI: còn là chân T1OSI.
▪ RC2/CCP1, RC1/T1OSI/CCP2: còn là chân bắt (capture), so sánh (compare) và điều rộng
xung (PWM). Mođun CCP giao tiếp với timer 1 và timer 2.
▪ RB0, RB1, RB2, RB3, RB4, RB5, RB6, RB7: chân 33-40 là các chân xuất nhập của PORTB.
▪ RB0/INT: còn là chân phát động theo ngắt ngoài.

GV: Ong Mẫu Dũng – Khoa CNĐT 33


Bài giảng KỸ THUẬT VI XỬ LÝ

▪ RC6/TX/CK: nó có thể được lập trình để dung chân này phát xung nhịp (serial clock) dung
cho truyền bit dạng nối tiếp. Đây còn là chân phát TX (transmit data). Hai chân này dung
cho thu phát bất đồng bộ và đồng bộ (USART), có thể định địa chỉ.
▪ RC7/RX/DT: nó có thể được lập trình để dung chân này trao đổi dữ liệu (serial data). Đây
còn là chân thu dữ liệu (receive data).
▪ RA3/AN3/Vref+, RA2/AN2/Vref-/Cref: là các chân điện áp tham chiếu cho bộ chuyển đổi
tương tự-số (ADC) 10 bit.
▪ RC3/SCK/SCL: chân 18, còn là xung clock nối tiếp (Serial clock-SCK) cho SPI, và là chân clock
nối tiếp cho I2C.
▪ RC4/SDI/SDA: chân 23, còn là chân dữ liệu nối tiếp (serial data).
▪ RC5/SDO: chân 24, còn là chân xuất dữ liệu nối tiếp (serial data out).
▪ Môđun nối tiếp đồng bộ chủ (Master synchronous serial port-MSSP) có thể hoạt động ở hai
chếđộ: SPI và I2C
▪ SPI (serial peripheral interface): giao tiếp ngoại vi nối tiếp. SPI dùng 3 chân SDO, SDI, SCK.
▪ I2C: (inter-integrated circuit): mạch tích hợp lien kết, dung 2 chân: SCL, SDA, có thể ở chế
độ chủ hoàn toàn (full master mode) hay chế độ tớ (slave mode) (với gọi địa chỉ tổng quát).
▪ RD0, RD1, RD2, RD3: chân 19-22, và RD4, RD5, RD6, RD7: chân 27-30: là các chân xuất
nhập của PORT D.
▪ VDD: chân 11, 32: là nguồn dương Vcc từ 2V đến 6V (5,5 V).
▪ VSS: chân 12, 31, là chân đất (mass, GND, 0V).
3.2. Tổ chức bộ nhớ thanh ghi
3.2.1. Giới thiệu.
+ Thanh ghi là một bộ nhớ dung lượng nhỏ và rất nhanh, được sử dụng để tăng tốc độ xử lý
của các chương trình máy tính bằng cách cung cấp các truy cập trực tiếp đến các giá trị cần dùng.
Hầu hết, nhưng không phải tất cả, các máy tính hiện đại hoạt động theo nguyên lý chuyển dữ liệu
từ bộ nhớ chính vào các thanh ghi, tính toán trên chúng, sau đó chuyển kết quả vào bộ nhớ chính.
3.2.2. Các loại kiến trúc bộ nhớ.
+ Kiến trúc Harvard được dùng để chỉ những kiến trúc máy tính mà trong đó phân biệt rõ
ràng bộ nhớ dữ liệu và bộ nhớ chương trình, chúng có những đường truyền (bus) riêng để truy cập
vào bộ nhớ dữ liệu và bộ nhớ chương trình (ngược lại, kiến trúc von Neumann có bộ nhớ và bộ
nhớ chương trình chung).

GV: Ong Mẫu Dũng – Khoa CNĐT 34


Bài giảng KỸ THUẬT VI XỬ LÝ

+ Trong một máy tính sử dụng kiến trúc von Neumann, CPU có thể đọc một lệnh, hoặc
đọc/ghi dữ liệu từ bộ nhớ. Tuy vậy, cả hai quá trình tương tác với lệnh hoặc với dữ liệu, không thể
thực hiện cùng lúc, vì nó sử dụng chung một đường truyền và bộ nhớ. Trong một máy tính kiến
trúc Harvard, CPU có thể vừa đọc một lệnh, vừa truy cập dữ liệu từ bộ nhớ cùng lúc. Một máy tính
kiến trúc Harvard có thể chạy nhanh hơn, bởi vì nó có thể thực hiện ngay lệnh tiếp theo khi vừa
kết thúc lệnh trước đó. Tốc độ được tăng lên nhưng phải trả giá bằng sự thiết kế phần cứng phức
tạp hơn (cụ thể nhất mà chúng ta thấy, đó là việc phải thiết kế 2 bus khác nhau cho dữ liệu và
chương trình).
+ Những năm gần đây, tốc độ CPU tăng lên rất nhiều lần so với tốc độ truy cập vào bộ nhớ
chính. Người ta cần quan tâm đến việc giảm số lần truy cập vào bộ nhớ để đảm bảo tốc độ hoạt
động của CPU. Nếu, trong cùng một lúc, mỗi lệnh của CPU cần phải truy cập vào bộ nhớ 1 lần, vậy
thì việc tăng tốc độ CPU chẳng còn ý nghĩa gì nữa, bởi vì nó luôn luôn bị giới hạn bởi việc truy cập
vào bộ nhớ.
+ Bộ nhớ có thể được thiết kế để có tốc độ truy cập cao, nhưng nó đồng nghĩa với việc giá
sản xuất sẽ cao. Giải pháp là cung cấp một dung lượng nhỏ bộ nhớ đệm, với tốc độ truy cập rất
cao, và chúng ta gọi đó là cache (bộ nhớ đệm). Khi bộ nhớ CPU cần tương tác đang nằm trong
cache, vì việc tương tác vào đó tốn ít thời gian hơn rất nhiều lần so với khi cache phải thay đổi và
lấy dữ liệu từ bộ nhớ chính đưa vào. Việc điều chỉnh cache là một vấn đề quan trọng trong việc
thiết kế máy tính.
+ Những thiết kế chip CPU tốc độ cao ngày này thường kết hợp hai kiến trúc Harvard và
von Neumann. Bộ nhớ cache trên chip được phân thành cache chương trình và cache dữ liệu. Kiến
trúc Harvard được dùng khi CPU truy cập vào cache. Tuy nhiên, trong trường hợp không có cache,
dữ liệu được lấy từ bộ nhớ chính, mà bộ nhớ chính không được chia thành vùng nhớ chương trình
và vùng nhớ dữ liệu. Như vậy, kiến trúc von Neumann được dùng ở tầm vực truy cập bộ nhớ chính.
+ Kiến trúc Harvard cũng thường được dùng trong một số DSP chuyên dụng, thường dùng
trong các sản phẩm xử lý âm thanh, hình ảnh.

GV: Ong Mẫu Dũng – Khoa CNĐT 35


Bài giảng KỸ THUẬT VI XỬ LÝ

+ Thêm vào đó, hầu hết các vi điều khiển thông dụng được dùng trong các ứng dụng điện
tử như là PIC được sản xuất bởi Microchip Technology Inc và AVR của hãng Atmel Corporation,
được phát triển dựa trên kiến trúc Harvard. Những vi xử lý này có đặc tính là có lượng bộ nhớ dữ
liệu và bộ nhớ chương trình nhỏ, rất phù hợp với kiến trúc Harvard và tập lệnh RISC để đảm bảo
hầu hết các lệnh được thực hiện trong 1 chu kỳ máy. Việc phân chia bộ nhớ ra thành bộ nhớ
chương trình và bộ nhớ dữ liệu có thể làm cho bus dữ liệu và bus chương trình có kích thước băng
truyền khác nhau. Ví dụ như các vi điều khiển PIC có bus dữ liệu 8-bit (phụ thuộc vào dòng PIC),
nhưng bus chương trình có thể là 12-bit, 14-bit hoặc 16-bit word. Điều này cho phép mỗi một
lệnh đơn có đủ chỗ chứa cho một giá trị hằng. Những CPU RISC khác, ví dụ như ARM, thường cần
ít nhất 2 lệnh để load một hằng số đủ kích thước.
3.2.3. Tổ chức bộ nhớ của VĐK PIC 16F8xx 8 bit
o Tổ chức bộ nhớ.
+ Cấu trúc bộ nhớ của vi điều khiển PIC16F877A bao gồm bộ nhớ chương trình (Program
Memory) và bộ nhớ dữ liệu (Data Memory).
o Khảo sát bộ nhớ chương trình.
- Bộ nhớ chương trình của vi điều khiển PIC16F877A là bộ nhớ flash, dung lượng bộ nhớ 8K
word (1 word = 14 bit) và được phân thành nhiều trang (từ page0 đến page 3). Như vậy bộ nhớ
chương trình có khả năng chứa được 8*1024 = 8192 lệnh (vì một lệnh sau khi mã hóa sẽ có dung
lượng 1 word (14 bit).
- Để mã hóa được địa chỉ của 8K word bộ nhớ chương trình, bộ đếm chương trình có dung
lượng 13 bit (PC<12:0>).
- Khi vi điều khiển được reset, bộ đếm chương trình sẽ chỉ đến địa chỉ 0000h (Reset vector).
- Khi có ngắt xảy ra, bộ đếm chương trình sẽ chỉ đến địa chỉ 0004h (Interrupt vector).
- Bộ nhớ chương trình không bao gồm bộ nhớ stack và không được địa chỉ hóa bởi bộ đếm
chương trình. Bộ nhớ stack sẽ được đề cập cụ thể trong phần sau.

GV: Ong Mẫu Dũng – Khoa CNĐT 36


Bài giảng KỸ THUẬT VI XỬ LÝ

o Khảo sát bộ nhớ dữ liệu


- Bộ nhớ dữ liệu của PIC là bộ nhớ EEPROM được chia ra làm nhiều bank.
- Đối với PIC16F877A bộ nhớ dữ liệu được chia ra làm 4 bank. Mỗi bank có dung lượng 128
byte, bao gồm các thanh ghi có chức năng đặc biệt SFG (Special Function Register) nằm ở các vùng
địa chỉ thấp và các thanh ghi mục đích chung GPR (General Purpose Register) nằm ở vùng địa chỉ
còn lại trong bank.
- Các thanh ghi SFR thường xuyên được sử dụng (ví dụ như thanh ghi STATUS) sẽ được đặt ở
tất cà các bank của bộ nhớ dữ liệu giúp thuận tiện trong quá trình truy xuất và làm giảm bớt lệnh
của chương trình.
- Sơ đồ cụ thể của bộ nhớ dữ liệu PIC16F877A như sau:

GV: Ong Mẫu Dũng – Khoa CNĐT 37


Bài giảng KỸ THUẬT VI XỬ LÝ

GV: Ong Mẫu Dũng – Khoa CNĐT 38


Bài giảng KỸ THUẬT VI XỬ LÝ

o Khảo sát các thanh ghi đặc biệt


+ Đây là các thanh ghi được sử dụng bởi CPU hoặc được dùng để thiết lập và điều khiển các
khối chức năng được tích hợp bên trong vi điều khiển.
+ Có thể phân thanh ghi SFR làm hai lọai: thanh ghi SFR liên quan đến các chức năng bên trong
(CPU) và thanh ghi SRF dùng để thiết lập và điều khiển các khối chức năng bên ngoài (ví dụ như
ADC, PWM, …). Phần này sẽ đề cập đến các thanh ghi liên quan đến các chức năng bên trong. Các
thanh ghi dùng để thiết lập và điều khiển các khối chức năng sẽ được nhắc đến khi ta đề cập đến
các khối chức năng đó.
+ Chi tiết về các thanh ghi SFR sẽ được liệt kê cụ thể trong bảng phụ lục. Chúng ta liệt kê các
SFR đặc biệt quan trong sau:
▪ Thanh ghi STATUS (03h, 83h, 103h, 183h): thanh ghi chứa kết quả thực hiện phép toán của
khối ALU, trạng thái reset và các bit chọn bank cần truy xuất trong bộ nhớ dữ liệu.

▪ Thanh ghi OPTION_REG (81h, 181h): thanh ghi này cho phép đọc và ghi, cho phép điều
khiển chức năng pull-up của các chân trong PORTB, xác lập các tham số về xung tác động,
cạnh tác động của ngắt ngoại vi và bộ đếm Timer0.

▪ Thanh ghi INTCON (0Bh, 8Bh,10Bh, 18Bh): thanh ghi cho phép đọc và ghi, chứa các bit điều
khiển và các bit cờ hiệu khi timer0 bị tràn, ngắt ngoại vi RB0/INT và ngắt interrputon-
change tại các chân của PORTB.

▪ Thanh ghi PIE1 (8Ch): chứa các bit điều khiển chi tiết các ngắt của các khối chức năng ngoại
vi.

GV: Ong Mẫu Dũng – Khoa CNĐT 39


Bài giảng KỸ THUẬT VI XỬ LÝ

▪ Thanh ghi PIR1 (0Ch) chứa cờ ngắt của các khối chức năng ngoại vi, các ngắt này được cho
phép bởi các bit điều khiển chứa trong thanh ghi PIE1.

▪ Thanh ghi PIE2 (8Dh): chứa các bit điều khiển các ngắt của các khối chức năng CCP2, SSP
bus, ngắt của bộ so sánh và ngắt ghi vào bộ nhớ EEPROM.

▪ Thanh ghi PIR2 (0Dh): chứa các cờ ngắt của các khối chức năng ngoại vi, các ngắt này được
cho phép bởi các bit điều khiển chứa trong thanh ghi PIE2.

▪ Thanh ghi PCON (8Eh): chứa các cờ hiệu cho biết trạng thái các chế độ reset của vi điều
khiển.

▪ Thanh ghi mục đích chung GPR: Các thanh ghi này có thể được truy xuất trực tiếp hoặc gián
tiếp thông qua thanh ghi FSG (File Select Register). Đây là các thanh ghi dữ liệu thông
thường, người sử dụng có thể tùy theo mục đích chương trình mà có thể dùng các thanh
ghi này để chứa các biến số, hằng số, kết quả hoặc các tham số phục vụ cho chương trình.
▪ Thanh ghi PC (13 bit): bao gồm 2 thanh ghi PCL và PCH, trong đó PCH không truy cập được
trực tiếp mà truy cập gián tiếp thông qua 5 bit thấp trong thanh ghi PCLATH. Có 2 kiểu truy
cập đến PC (chỉ tác động đến PCL; chọn BANK 2K trong ROM rồi dùng lệnh GOTO, CALL)

GV: Ong Mẫu Dũng – Khoa CNĐT 40


Bài giảng KỸ THUẬT VI XỬ LÝ

*** Stack không nằm trong bộ nhớ chương trình hay bộ nhớ dữ liệu mà là một vùng nhớ đặc
biệt không cho phép đọc hay ghi. Khi lệnh CALL được thực hiện hay khi một ngắt xảy ra làm
chương trình bị rẽ nhánh, giá trị của bộ đếm chương trình PC tự động được vi điều khiển cất vào
trong stack. Khi một trong các lệnh RETURN, RETLW hat RETFIE được thực thi, giá trị PC sẽ tự động
được lấy ra từ trong stack, vi điều khiển sẽ thực hiện tiếp chương trình theo đúng qui trình định
trước. Bộ nhớ Stack trong vi điều khiển PIC họ 16F87xA có khả năng chứa được 8 địa chỉ và hoạt
động theo cơ chế xoay vòng. Nghĩa là giá trị cất vào bộ nhớ Stack lần thứ 9 sẽ ghi đè lên giá trị cất
vào Stack lần đầu tiên và giá trị cất vào bộ nhớ Stack lần thứ 10 sẽ ghi đè lên giá trị cất vào Stack
lần thứ 2. Cần chú ý là không có cờ hiệu nào cho biết trạng thái stack, do đó ta không biết được khi
nào stack tràn. Bên cạnh đó tập lệnh của vi điều khiển dòng PIC cũng không có lệnh POP hay PUSH,
các thao tác với bộ nhớ stack sẽ hoàn toàn được điều khiển bởi CPU.
3.3. Lệnh hợp ngữ
3.3.1 Giới thiệu.

Chương trình Thông dịch Ngôn ngữ


CPU Hành động
Mã nguồn Biên dịch Máy

- Chương trình: là chuỗi các câu lệnh báo cho máy phải làm gì, làm như thế nào và khi nào phải làm.
- Ngôn ngữ máy: là chuỗi các số 0/1 mà CPU thực hiện. Ngôn ngữ máy được giải quyết trực tiếp
bởi mạch điện tử
GV: Ong Mẫu Dũng – Khoa CNĐT 41
Bài giảng KỸ THUẬT VI XỬ LÝ

- Ngôn ngữ cấp cao: gồm có các ngôn ngữ sau.


▪ Ngôn ngữ lập trình hướng đối tượng: C++ .
▪ Ngôn ngữ lập trình cấp cao: C, Pascal, QBasic .
▪ Ngôn ngữ lập trình logic: prolog .
▪ Ngôn ngữ lập trình hàm: lisp.
▪ Thiết kế giao diện : Visual Basic, Borland Delphi và C++ Builder/Visual C++
- Bộ phận biên dịch: là những chương trình dịch mã nguồn sang mã máy
- Ngôn ngữ assembly: dung hòa ngôn ngữ cấp cao và ngôn ngữ máy, ta dùng ngôn ngữ assembly.
Chương trình sẽ dùng mã gợi nhớ và dùng các lệnh của CPU

Chương trình
Ngôn ngữ
Trình biên dịch hướng đối
Assembly
tượng

3.3.2 Lệnh hợp ngữ của VĐK PIC 16F8xx 8 bit


o Giới thiệu
+ Phần mềm MPLAB MPASM.EXE: dịch mã nguồn thành mã máy, chạy ở MS-DOS. Trong môi
rường Windows, các tập tin cần có trên đĩa là: MPASMWIN.exe, MPLINK.exe, và MPLIB.exe. Tạo ra
dự án dùng MPLAB:

* Qui trình xây dựng chương trình:


▪ Nhìn và nghe: vấn đề gì cần giải quyết, cái gì đã cho, cái gì cần tìm, sau đó thực hiện lưu đồ
giải thuật (flow chart) để diễn tả chương trình hoạt động như thế nào.

GV: Ong Mẫu Dũng – Khoa CNĐT 42


Bài giảng KỸ THUẬT VI XỬ LÝ

▪ Viết chương trình theo ngôn ngữ assembly (hợp ngữ) sử dụng các điều đã cho để giải
quyết bài toán theo yêu cầu đầu ra.
▪ Nhập chương trình vào máy tính.
▪ Chuyển mã ngữ cho chương trình (assembling-biên dịch).
▪ Cho chạy chương trình.
▪ Đánh giá kết quả.
▪ Bảo trì.
Ví dụ: Vẽ lưu đồ giải thuật nhập một số và in ra trị số tuyệt đối của số đó:

Một lệnh trong ngôn ngữ assembly (hợp ngữ) trong chương trình gồm có 4 khu vực sau:
Nhãn Mã lệnh Các toán hạng Ghi chú

GV: Ong Mẫu Dũng – Khoa CNĐT 43


Bài giảng KỸ THUẬT VI XỬ LÝ

▪ Nhãn (label field): là một tên, dùng các chữ cái (a-z), số (0-9) và dấu gạch dưới. Nhãn dùng
cho tham khảo, làm địa chỉ, gọi chương trình con.
▪ Mã lệnh (Op-code): là những chữ viết tắt, dễ gợi nhớ được dùng đối với lệnh của PIC
16F877A. Ví dụ: movf, movlw, addwf, subwf vv…
▪ Toán hạng (operand): lệnh có thể là một toán hạng hoặc hai toán hạng. Trường hợp 2 toán
hạng thì toán hạng thứ 2 gọi là toán hạng đến (destination operand) và toán hạng thứ 1 gọi
là toán hạng nguồn (source operand)
▪ Ghi chú (comment): là những lời chú thích cho cho lệnh đó bắt đầu bằng dấu (;). Chương
trình sẽ bỏ qua
❖ Các kiểu định địa chỉ của VĐK PIC 16F8xx 8 bit
- Địa chỉ số lập tức (tức thời): Số thao tác và số lập tức, có thể nhận được trực tiếp từ trong mã
lệnh. Thí dụ: MOVLW <CONSTANT>

- Địa chỉ trực tiếp: Có thể phỏng vấn truy cập tìm kiếm địa chỉ trực tiếp với bất kì bộ nhớ nào, tức
là trong mã lệnh đã bao gồm địa chỉ của bộ nhớ bị truy cập. Thí dụ: ADDWF <DATA_ADDRESS>,<D>

- Gián tiếp bộ nhớ: Phương thức tìm loại này thực hiện thong qua INDF bộ nhớ và FSR. Địa chỉ
thực tế trước tiên đặt vào trong FSR thông qua việc truy cập INDF để thực hiện gián tiếp đọc và
viết số liệu bộ nhớ. Phương pháp tìm địa chỉ gián tiếp chủ yếu dùng để viết các chương trình các
“bảng tra” hoặc là bảng trị số thực hết sức tiện lợi. Thí dụ: ADDWF INDF,<D>

- Địa chỉ byte/bit: Có thể trực tiếp truy cập tìm kiếm một bit bất kì nào trong bộ nhớ bất kì tức là
trong mã lệnh đã bao gồm địa chỉ của bộ nhớ bị truy cập đồng thời bao gồm địa chỉ hằng số trong
bộ nhớ đó. Thí dụ: SETB PORTB,<CONSTANT>.

❖ Khảo sát chi tiết tập lệnh của VĐK PIC 16F8xx 8 bit
+ Tập lệnh của PIC bao gồm 35 lệnh. Một lệnh thực thi trong 1 chu kì máy, trừ các lệnh nhảy
là 2 chu kì máy. Nhiều nhất (đa số) trong các lệnh bao gồm việc sử dụng thanh ghi làm việc
(working register) hay W. Thanh ghi W là ở trung tâm (trái tim) của vi điều khiển PIC. Để di chuyển
dữ liệu từ ô nhớ A (file A) sang ô nhớ B, bạn phải di chuyển nó từ ô nhớ A sang W và sau đó từ W
sang ô nhớ B, khá giống hệ thống điện thoại dẫn hướng một cuộc gọi tới nơi khác thông qua tổng
đài.Thanh ghi W cũng vận hành phép toán logic và số học trên dữ liệu.
+ Để liên lạc (giao tiếp) với vi điều khiển PIC bạn phải học cách lập trình nó sử dụng tập lệnh
của PIC. PIC 16F877A có 8kx14 bit word bộ nhớ chương trình Flash, 368x8 bit thanh ghi đa năng và
35 lệnh làm nên ba nhóm lệnh: bit, byte và tác vụ điều khiển và số.
+ Lệnh bit: Dạng tổng quát của lệnh: Tác vụ thanh ghi file hướng bit

GV: Ong Mẫu Dũng – Khoa CNĐT 44


Bài giảng KỸ THUẬT VI XỬ LÝ

- Lệnh bit tác động trên bit cụ thể trong một ô nhớ, vì vậy lệnh có thể được theo sau bởi dữ
liệu mà chỉ ra số ô nhớ và số bit. Thí dụ BSF 6,3. Mã này không có nhiều thong tin để chúng ta có
thể sử dụng điều gì đó giống như BSF PORTB,BUZZER trong đó PORTB là ô nhớ 6 và BUZZER được
nối với bit 3 của port ngõ ra. Trong phần tương đương chúng ta sẽ thấy PORTB equ 6 và BUZZER
equ 3.
+ Lệnh byte:

- Lệnh byte làm việc trên tất cả 8 bit trong ô nhớ. Vì vậy một lệnh byte sẽđược theo sau bởi
số ô nhớ phù hợp. Thí dụ: DECF 0Ch; lệnh này không có nhiều thông tin để chúng ta sẽ chỉ ra tên
của ô nhớ như là DECF COUNT. Dĩ nhiên chúng ta sẽ cần khai báo phần tương đương mà COUNT là
ô nhớ 0Ch bằng lệnh COUNT equ 0Ch.
+ Lệnh tác vụ điều khiển và số:
- Tác vụ số và điều khiển vận hành dữ liệu và thực hiện nhảy (rẽ nhánh) chương trình.
Những lệnh này làm việc chủ yếu trên 2 thanh ghi 8 bit-thanh ghi làm việc W và ô nhớ F mà có thể
là một trong 15 thanh ghi đặc biệt của 368-byte RAM của 16F877A. Vi điều khiển PIC là thiết bị 8
bit-điều này có nghĩa là số cực đại mà có thể lưu trữ trong bất kì vị trí nhớ là 255.

GV: Ong Mẫu Dũng – Khoa CNĐT 45


Bài giảng KỸ THUẬT VI XỬ LÝ

3.3.3 Cấu trúc của một chương trình điều khiển


+ Một chương trình Assembly bao gồm nhiều thành phần như chương trình chính, chương
trình ngắt, chương trình con, Ở đây chỉ trình bày cấu trúc một chương trình đơn giản nhất khi mới
bắt đầu làm quen với việc lập trình cho vi điều khiển PIC.
;**********************************************************************
; This file is a basic code template for assembly code generation *
; on the PIC16F877A. This file contains the basic code *
; building blocks to build upon. *
;**********************************************************************

list p=16f877A ; list directive to define processor


#include <p16f877A.inc> ; processor specific variable definitions

__CONFIG _CP_OFF & _WDT_OFF & _BODEN_OFF & _PWRTE_OFF & _HS_OSC &
_WRT_OFF & _LVP_OFF & _CPD_OFF

; '__CONFIG' directive is used to embed configuration data within .asm file.


; The lables following the directive are located in the respective .inc file.
; See respective data sheet for additional information on configuration word.

;***** VARIABLE DEFINITIONS


w_temp EQU 0x7D ; variable used for context saving
status_temp EQU 0x7E ; variable used for context saving
pclath_temp EQU 0x7F ; variable used for context saving

COUNT1 EQU 0x20


COUNT2 EQU 0x21
COUNT3 EQU 0x22

;**********************************************************************
ORG 0x000 ; processor reset vector

nop ; nop required for icd


goto START ; go to beginning of program

ORG 0x004 ; interrupt vector location

movwf w_temp ; save off current W register contents


movf STATUS,w ; move status register into W register
movwf status_temp ; save off contents of STATUS register
movf PCLATH,w ; move pclath register into w register
movwf pclath_temp ; save off contents of PCLATH register

; isr code can go here or be located as a call subroutine elsewhere

GV: Ong Mẫu Dũng – Khoa CNĐT 46


Bài giảng KỸ THUẬT VI XỬ LÝ

movf pclath_temp,w ; retrieve copy of PCLATH register


movwf PCLATH ; restore pre-isr PCLATH register contents
movf status_temp,w ; retrieve copy of STATUS register
movwf STATUS ; restore pre-isr STATUS register contents
swapf w_temp,f
swapf w_temp,w ; restore pre-isr W register contents
retfie ; return from interrupt

; remaining code goes here


START

BANKSEL TRISB
CLRF TRISB
BANKSEL PORTB
CLRF PORTB

END ; directive 'end of program'

+ Ta nhận thấy rằng không có sự khác biệt lớn trong cấu trúc của một chương trình
Assembly viết cho vi điều khiển PIC so với vi điều khiển khác, chỉ có sự khác biệt về các lệnh sử
dụng trong chương trình. Dấu “;” được dùng để đưa một ghi chú vào chương trình và chỉ có hiệu
lực trên một hàng của chương trình. Hình trên là ví dụ về một chương trình đơn giản với các bước
khởi tạo cơ bản ban đầu, ngoài ra nếu cần thiết ta vẫn có thể khai báo thêm các biến, hằng và các
tham số khác trước chương trình chính (label “Main”).
+ Trong trường hợp cần sử dụng đến chương trình ngắt, ta cần một cấu trúc chương trình
phức tạp hơn với nhiều bước khởi tạo phức tạp và phải tuân theo một thứ tự lệnh nhất định. Tuy
nhiên nếu sử dụng trình biên dịch MPLAB, cấu trúc của chương trình dành cho một vi điều khiển
PIC nhất định đã được viết sẵn, ta chỉ việc viết đoạn chương trình điều khiển vào các vị trí thích
hợp trên mẫu chương trình được viết trước đó. Đây là một lợi thế rất lớn khi sử dụng MPLAB để
soạn thảo các chương trình viết cho vi điều khiển PIC.

***

GV: Ong Mẫu Dũng – Khoa CNĐT 47


Bài giảng KỸ THUẬT VI XỬ LÝ

CHƯƠNG 4: NGÔN NGỮ LẬP TRÌNH


- Nắm bắt được lý thuyết về từ khóa, cách đặt tên và khai báo biến, các kiểu dữ liệu trong
ngôn ngữ lập trình (ASM, Hi_techC)
- Trình bày được lý thuyết về cú pháp của các cấu trúc chương trình (ASM, Hi_techC)
- Trình bày được cấu trúc của một chương trình .ASM và .C
- Sử dụng thành thạo phần mềm lập trình MPLAB và Hi_tech C
- Xây dựng được lưu đồ giải thuật cho bài toán.
- Có khả năng lập trình sử dụng ngôn ngữ lập trình phù hợp cho các bài toán.

4.1. Lập trình Assemly


4.1.1. Giới thiệu.
+ Như đã trình bày ở chương 3, PIC là vi điều khiển có tập lệnh rút gọn RISC (Reduced
Instruction Set Computer), bao gồm 35 lệnh và có thể được phân ra thành 3 nhóm cơ bản:
• Nhóm lệnh thao tác trên bit.
• Nhóm lệnh thao tác trên byte.
• Nhóm lệnh điều khiển.
+ Đối với dòng vi điều khiển PIC16Fxxx, mỗi lệnh được mã hóa thành 14-bit word, bao gồm các
bit opcode (dùng để xác định lệnh nào được mã hóa) và các bit mô tả một hay vài tham số của
lệnh.
+ Đối với nhóm lệnh thao tác trên byte, ta có 2 tham số f (xác định địa chỉ byte cần thao tác)
và d (xác định nơi chứa kết quả thực thi lệnh). Nếu d = 0, kết quả sẽ được đưa vào thanh ghi W.
Nếu d = 1, kết quả được đưa vào thanh ghi được mô tả bởi tham số f.
+ Đối với nhóm lệnh thao tác trên bit, ta có hai tham số b (xác định bit cần thao tác) và f (xác
định địa chỉ byte dữ liệu cần thao tác).
+ Đối với nhóm lệnh điều khiển chỉ có một tham số duy nhất là k (k có thể là 8 bit trong trường
hợp các lệnh bình thường hay 11 bit trong trường hợp là lệnh CALL và lệnh GOTO) dùng để mô
tả đối tượng tác động của vi điều khiển (một label, một hằng số nào đó).
+ Mỗi lệnh sẽ được vi điều khiển thực thi xong trong vòng một chu kì lệnh, ngoại trừ các lệnh
làm thay đổi giá trị bộ đếm chương trình PC cần 2 chu kì lệnh. Một chu kì lệnh gồm 4 xung clock
của oscillator, do bên trong vdk có bộ chia tần số cho 4. Ví dụ ta sử dụng oscillator có tần số 4 MHz
thì tần số thực thi lệnh sẽ là 4MHz/4 = 1 MHz, như vậy một chu kì lệnh có thời gian 1 uS.

GV: Ong Mẫu Dũng – Khoa CNĐT 48


Bài giảng KỸ THUẬT VI XỬ LÝ

+ Các lệnh thao tác trên một thanh ghi bất kì đều thực hiện cơ chế Read-Modify-Write, tức là
thanh ghi sẽ được đọc, dữ liệu được thao tác và kết quả được đưa vào thanh ghi chứa kết quả (nơi
chứa kết quả tùy thuộc vào lệnh thực thi và tham số d). Ví dụ như khi thực thi lệnh “CLRF PORTB”,
vi điều khiển sẽ đọc giá trị thanh ghi PORTB, xóa tất cả các bit và ghi kết quả trở lại thanh ghi
PORTB.
4.1.2. Các thành phần cơ bản
a. Các kiểu dữ liệu của biến
b. Các toán tử
c. Các lệnh cơ bản (bao gồm cả kiểu dữ liệu và các toán tử)
Lệnh ADDLW
Cú pháp: ADDLW k (0 ≤ k≤255)
Tác dụng: cộng giá trị k vào thanh ghi W, kết quả được chứa trong thanh W
Lệnh ADDWF
Cú pháp: ADDWF f,d (0≤f≤255, d∈¸[0,1]).
Tác dụng: cộng giá trị hai thanh ghi W và thanh ghi f. Kết quả được chứa trong thanh ghi W
nếu d = 0 hoặc thanh ghi f nếu d =1.
Bit trạng thái: C, DC, Z
Lệnh ANDLW
Cú pháp: ANDLW k (0≤k≤255)
Tác dụng: thực hiện phép toán AND giữa thanh ghi W và giá trị k, kết quả được chứa trong
thanh ghi W.
Bit trạng thái: Z
Lệnh ANDWF
Cú pháp: ANDWF f,d (0≤f≤127, d ∈¸[0,1]).
Tác dụng: thực hiện phép toán AND giữa các giá trị chứa trong hai thanh ghi W và f. Kết
quả được đưa vào thanh ghi W nếu d=0 hoặc thanh ghi f nếu d = 1.
Bit trạng thái: Z
Lệnh BCF
Cú pháp: BCF f,b (0≤f≤127, 0≤b≤7)
Tác dụng: xóa bit b trong thanh ghi f về giá trị 0.
Bit trạng thái: không có.
Lệnh BSF

GV: Ong Mẫu Dũng – Khoa CNĐT 49


Bài giảng KỸ THUẬT VI XỬ LÝ

Cú pháp: BSF f,b (0≤f≤127, 0≤b≤7)


Tác dụng: set bit b trong trnh ghi f.
Bit trạng thái: không có
Lệnh BTFSS
Cú pháp: BTFSS f,b (0≤f≤127, 0≤b≤7)
Tác dụng: kiểm tra bit b trong thanh ghi f. Nếu bit b bằng 0, lệnh tiếp theo được thực thi.
Nếu bit b bằng 1, lệnh tiếp theo được bỏ qua và thay vào đó là lệnh NOP.
Bit trạng thái: không có
Lệnh BTFSC
Cú pháp: BTFSC f,b (0≤f≤127, 0≤b≤7)
Tác dụng: kiểm tra bit b trong thanh ghi f. Nếu bit b bằng 1, lệnh tiếp theo được thựcthi.
Nếu bit b bằng 0, lệnh tiếp theo được bỏ qua và thay vào đó là lệnh NOP.
Bit trạng thái: không có
Lệnh CALL
Cú pháp: CALL k (0≤k≤2047)
Tác dụng: gọi một chương trình con. Trước hết địa chỉ quay trở về từ chương trình con
(PC+1) được cất vào trong Stack, giá trị địa chỉ mới được đưa vào bộ đếm gồm 11 bit của
biến k và 2 bit PCLATH<4:3>.
Bit trạng thái: không có
Lệnh CLRF
Cú pháp CLRF f (0≤f≤127)
Tác dụng: xóa thanh ghi f và bit Z được set.
Bit trạng thái: Z
Lệnh CLRW
Cú pháp CLRW
Tác dụng: xóa thanh ghi W và bit Z được set.
Bit trạng thái: Z
Lệnh CLRWDT
Cú pháp: CLRWDT
Tác dụng: reset Watchdog Timer, đồng thời prescaler cũng được reset, các bit \PD và \TO
được set lên 1.
Bit trạng thái: \PD, \TO.

GV: Ong Mẫu Dũng – Khoa CNĐT 50


Bài giảng KỸ THUẬT VI XỬ LÝ

Lệnh COMF
Cú pháp: COMF f,d (0≤f≤127, d∈¸[0,1]).
Tác dụng: đảo các bit trong thanh ghi f. Kết quả được đưa vào thanh ghi W nếu d=0 hoặc
thanh ghi f nếu d=1.
Bit trạng thái: Z
Lệnh DECF
Cú pháp: DECF f,d (0≤f≤127, d∈¸[0,1]).
Tác dụng: giá trị thanh ghi f được giảm đi 1 đơn vị. Kết quả được đưa vào thanh ghi W nếu
d = 0 hoặc thanh ghi f nếu d = 1.
Bit trạng thái: Z
Lệnh DECFSZ
Cú pháp: DECFSZ f,d (0≤f≤127, d∈¸[0,1])
Tác dụng: gía trị thanh ghi f được giảm 1 đơn vị. Nếu kết quả sau khi giảm khác 0, lệnh tiếp
theo được thực thi, nếu kết quả bằng 0, lệnh tiếp theo không được thực thi và thay vào đó
là lệnh NOP. Kết quả được đưa vào thanh ghi W nếu d = 0 hoặc thanh ghi f nếu d = 1.
Bit trạng thái: không có
Lệnh GOTO
Cú pháp: GOTO k (0≤k≤2047)
Tác dụng: nhảy tới một label được định nghĩa bởi tham số k và 2 bit PCLATH<4:3>.
Bit trạng thái: không có.
Lệnh INCF
Cú pháp: INCF f,d (0≤f≤127, d ∈¸[0,1])
Tác dụng: tăng giá trị thanh ghi f lên 1 đơn vị. Kết quả được đưa vào thanh ghi W nếu d = 0
hoặc thanh ghi f nếu d = 1.
Bit trạng thái: Z
Lệnh INCFSZ
Cú pháp: INCFSZ f,d (0≤f≤127, d∈¸[0,1])
Tác dụng: tăng giá trị thanh ghi f lên 1 đơn vị. Nếu kết quả khác 0, lệnh tiếp theo được thực
thi, nếu kết quả bằng 0, lệnh tiếp theo được thay bằng lệnh NOP. Kết quả sẽ được đưa vào
thanh ghi f nếu d=1 hoặc thanh ghi W nếu d = 0.
Bit trạng thái: không có.
Lệnh IORLW

GV: Ong Mẫu Dũng – Khoa CNĐT 51


Bài giảng KỸ THUẬT VI XỬ LÝ

Cú pháp: IORLW k (0≤k≤255)


Tác dụng: thực hiện phép toán OR giữa thanh ghi W và giá trị k. Kết quả được chứa trong
thanh ghi W.
Bit trạng thái: Z
Lệnh IORWF
Cú pháp: IORWF f,d (0≤f≤127, d∈¸[0,1])
Tác dụng: thực hiện phép toán OR giữa hai thanh ghi W và f. Kết quả được đưa vào thanh
ghi W nếu d=0 hoặc thanh ghi f nếu d=1.
Bit trạng thái: Z
Lệnh RLF
Cú pháp: RLF f,d (0≤f≤127, d∈¸[0,1])
Tác dụng: dịch trái các bit trong thanh ghi f qua cờ carry. Kết quả được lưu trong thanh ghi
W nếu d=0 hoặc thanh ghi f nếu d=1.
Bit trạng thái: C
Lệnh RETURN
Cú pháp: RETURN
Tác dụng: quay trở về chương trình chính từ một chương trình con
Bit trạng thái: không có
Lệnh RRF
Cú pháp: RRF f,d (0≤f≤127, d∈¸[0,1])
Tác dụng: dịch phải các bit trong thanh ghi f qua cờ carry. Kết quả được lưu trong thanh ghi
W nếu d=0 hoặc thanh ghi f nếu d=1.
Bit trạng thái: C
Lệnh SLEEP
Cú pháp: SLEEP
Tác dụng: đưa vi điều khiển về chế độ sleep. Khi đó WDT bị xóa về 0, bit \PD được xóa về 0,
bit \TO được set lên 1 và oscillator không được cho phép hoạt động.
Bit trạng thái: \PD, \TO.
Lệnh SUBLW
Cú pháp: SUBLW k
Tác dụng: lấy giá trị k trừ giá trị trong thanh ghi W. Kết quả được chứa trong thanh ghi W.
Bit trạng thái: C, DC, Z

GV: Ong Mẫu Dũng – Khoa CNĐT 52


Bài giảng KỸ THUẬT VI XỬ LÝ

Lệnh SUBWF
Cú pháp: SUBWF f,d (0≤f≤127, d∈¸[0,1])
Tác dụng: lấy giá trị trong thanh ghi f đemtrừ cho thanh ghi W. Kết quả được lưu trong
thanh ghiaW nếu d=0 hoặc thanh ghi f nếu d=1.
Bit trạng thái: C, DC, Z
Lệnh SWAP
Cú pháp: SWAP f,d (0≤f≤127, d∈¸[0,1])
Tác dụng: đảo 4 bit thấp với 4 bit cao trong thanh ghi f. Kết quả được chứa trong thanh ghi
W nếu d=0 hoặc thanh ghi f nếu d=1.
Bit trạng thái: không có
Lệnh XORLW
Cú pháp: XORLW k (0≤k≤255)
Tác dụng: thực hiện phép toán XOR giữa giá trị k và giá trị trong thanh ghi W. Kết quả được
lưu trong thanh ghi W.
Bit trạng thái: Z
Lệnh XORWF
Cú pháp: XORWF f,d
Tác dụng: thực hiện phép toán XOR giữa hai giá trị chứa trong thanh ghi W và thanh ghi f.
Kết quả được lưu vào trong thanh ghi W nếu d=0 hoặc thanh ghi f nếu d=1.
Bit trạng thái: Z
Ngoài các lệnh trên còn có một số lệnh dùng trong chương trình như:
Lệnh #DIFINE
Cú pháp: #DEFINE <text1> <text2>
Tác dụng: thay thế một chuỗi kí tự này bằng một chuỗi kí tự khác, có nghĩa là mỗi khi chuỗi
kí tự text1 xuất hiện trong chương trình, trình biên dịch sẽ tự động thay thế chuỗi kí tự đó
bằng chuỗi kí tự <text2>.
Lệnh INCLUDE
Cú pháp: #INCLUDE <filename> hoặc #INCLUDE “filename”
Tác dụng: đính kèm một file khác vào chương trình, tương tự như việc ta copy file đó vào vị
trí xuất hiện lệnh INCLUDE. Nếu dùng cú pháp <filename> thì file đình kèm là file hệ thống
(system file), nếu dùng cú pháp “filename” thì file đính kèm là file của người sử dụng.
Thông thường chương trình được đính kèm theo một “header file” chứa các thông tin định

GV: Ong Mẫu Dũng – Khoa CNĐT 53


Bài giảng KỸ THUẬT VI XỬ LÝ

nghịa các biến (thanh ghi W, thanh ghi F,..) và các địa chỉ cảu các thanh ghi chức năng đặc
biệt trong bộ nhớ dữ liệu. Nếu không có header file, chương trình sẽ khó đọc và khó hiểu
hơn.
Lệnh CONSTANT
Cú pháp: CONSTANT <name>=<value>
Tác dụng: khai báo một hằng số, có nghĩa là khi phát hiện chuỗi kí tự “name” trong chương
trình, trình biên dịch sẽ tự động thay bằng chuỗi kí tự bằng giá trị “value” đã được định
nghĩa trước đó.
Lệnh VARIABLE
Cú pháp: VARIABLE <name>=<value>
Tác dụng: tương tự như lệnh CONSTANT, chỉ có điểm khác biệt duy nhất là giá trị “value”
khi dùng lệnh VARIABLE có thể thay đổi được trong quá trình thưc thi chương trình còn
lệnh CONSTANT thì không.
Lệnh SET
Cú pháp: <name variable> SET <value>
Tác dụng: gán giá trị cho một tên biến. Tên của biến có thể thay đổi được trong quá trình
thực thi chương trình.
Lệnh EQU
Cú pháp: <name constant> EQU <value>
Tác dụng: gán giá trị cho tên của tên của hằng số. Tên của hằng số không thay đổi trong
quá trình thực thi chương trình.
Lệnh ORG
Cú pháp: ORG <value>
Tác dụng: định nghĩa một địa chỉ chứa chương trình trong bộ nhớ chương trình của vi điều
khiển.
Lệnh END
Cú pháp: END
Tác dụng: đánh dấu kết thúc chương trình.
Lệnh __CONFIG
Cú pháp: __CONFIG “0xxxxx”
Tác dụng: thiết lập các bit điều khiển các khối chức năng của vi điều khiển được chứa trong
bộ nhớ chương trình (Configuration bit).

GV: Ong Mẫu Dũng – Khoa CNĐT 54


Bài giảng KỸ THUẬT VI XỬ LÝ

Lệnh PROCESSOR
Cú pháp: PROCESSOR <processor type>
Tác dụng: định nghĩa vi điều khiển nào sử dụng chương trình.
4.2. Lập trình Hi_tech C (SV tự ôn tập các lệnh trong ngôn ngữ C)
4.2.1. Giới thiệu.
4.2.2. Các thành phần cơ bản của ngôn ngữ lập trình Hi_tech C
4.3. Phần mềm MPLAP, MPLABX (xem file hướng dẫn phần phụ lục).
4.3.1. Cách cài đặt.
4.3.2. Sử dụng cho các ứng dụng
Hitech C template:
#define _XTAL_FREQ 4000000 //Khai báo dùng Thạch anh 4 MHz

#include <htc.h> //Khai báo dùng trình biên dịch Hitech C

__CONFIG(0x3FFA); //Khai báo các bit cấu hình vi điều khiển

unsigned char variable1 = 1; //Khai báo biến toàn cục kiểu char số dương(8bit)
signed char variable2 = 1; //Khai báo biến toàn cục kiểu char số nguyên(8bit)
unsigned int variable3 = 1; //Khai báo biến toàn cục kiểu int số dương (16bit)
unsigned long variable4 = 1; //Khai báo biến toàn cục kiểu long số dương (32bit)

unsigned char chuong_trinh_con(void); //Khai báo cho chương trình con

void main(void) //Bắt đầu chương trình chính


{
// code viết cho chương trình //
while(1) //Chạy vòng lặp
{
// code viết cho chương trình //
}
} //Kết thúc chương trình chính

unsigned char chuong_trinh_con(void) //Bắt đầu chương trình con


{
// code viết cho chương trình //
return 0x01; // Kết thúc bằng việc trả về giá trị
}

void interrupt isr(void) //Chương trình con xử lý Ngắt (Interrupt)


{ // code viết cho chương trình // }

GV: Ong Mẫu Dũng – Khoa CNĐT 55


Bài giảng KỸ THUẬT VI XỬ LÝ

CHƯƠNG 5: PORT XUẤT NHẬP CỦA VĐK PIC 16F8XX 8 BIT


- Trình bày được cấu trúc và tập lệnh của VĐK PIC và các thanh ghi lien quan đến các PORT.
- Trình bày được qui trình phân tích, thiết kế các hệ mạch ứng dụng hệ VĐK với ngoại vi qua
các PORT.
- Phân tích, thiết kế các hệ mạch ứng dụng hệ VĐK với ngoại vi qua các port.
- Thiết kế lưu đồ giải thuật và lập trình ứng dụng cho các mạch điều khiển xuất nhập cơ bản
sử dụng (LED đơn, LED 7 đoạn, LED ma trận, LCD,…).
- Vẽ được sơ đồ nguyên lý mạch điều khiển xuất nhập cơ bản sử dụng (LED đơn, LED 7 đoạn,
LED ma trận, LCD,…).

5.1. Giới thiệu


+ Vi điều khiển là một chip rất linh hoạt và có thể được lập trình để hoạt động trong một số
cấu hình khác nhau. PIC 16F877A có 33 đường I/O.
+ Cụ thể: 16F877A có 5 port: port A là port 6 bit nó có 6 đường I/O, port B có 8 đường I/O,
port C có 8 đường I/O, port D có 8 đường I/O, và port E có 3 đường I/O.
5.2. Chức năng
+ PortA là port 2 chiều, 6 bit. Thanh ghi định hướng dữ liệu tương ứng và TRISA. Bật các bit
TRISA (=1) sẽ làm cho các chân portA tương ứng là ngõ vào (input) (nghĩa là đặt bộ điều khiển
(driver) ngõ tương ứng trong chế độ tổng trở cao Hi-Z). Xóa bit TRISA (=0) sẽ làm cho chân portA
tương ứng là ngõ ra (output) (nghĩa là đặt nội dung của mạch cài ngõ ra trên chân được chọn).
+ Tương tự, PortB là port 2 chiều, 8 bit. Thanh ghi định hướng dữ liệu tương ứng là TRISB.
+ Tương tự, PortC là port 2 chiều, 8 bit. Thanh ghi định hướng dữ liệu tương ứng là TRISC.
+ PortD là port 8 bit với đệm ngõ vào Schmitt-trigger. Thanh ghi định hướng dữ liệu tương
ứng là TRISD.
+ PortE có 3 chân (RE0/RD/AN5, RE1/WR/AN6, RE2/CS/AN7) mà có thể được cấu hình riêng
biệt như là ngõ vào hay ngõ ra. Thanh ghi định hướng dữ liệu tương ứng là TRISE. Chú ý thêm đối
với PORTE, đảm bảo rằng thanh ghi ADCON được cấu hình cho I/O số. Trong chế độ này, bộ đệm
ngõ vào là TTL.

5.3 Tập các thanh ghi liên quan


+ Trong Chương nhập/xuất các PORT, ta chỉ quan tâm đến chức năng các port là digital I/O.
Các chức năng đặc biệt khác sẽ trình bày tuần tự trong các phần kế tiếp.

GV: Ong Mẫu Dũng – Khoa CNĐT 56


Bài giảng KỸ THUẬT VI XỬ LÝ

+ Để điều khiển I/O, sử dụng thanh ghi tên TRIS tương ứng với Port cần dùng (đã trình bày
ở 5.2). Như vậy, có các cặp thanh ghi tương ứng: PORTA-TRISA; PORTB-TRISB; PORTC-TRISC;
PORTD-TRISD và PORTE-TRISE.
5.4. Lập trình điều khiển các chức năng xuất nhập
+ Thanh ghi PIC gồm có 4 BANK độc lập. Khi sử dụng thanh ghi nào, trước hết ta cần chọn
BANK chứa thanh ghi tương ứng. Trong ngôn ngữ ASM, câu lệnh BANKSEL <tên thanh ghi> cần
được thực hiện trước khi dùng thanh ghi. Tuy nhiên trong ngôn ngữ Hitech-C, người lập trình
không cần quan tâm đến các BANK thanh ghi, nó sẽ được thực hiện tự động.
+ Có 2 trường hợp đưa dữ liệu vào/ra Port: theo từng bit và theo 1 Byte.
5.5 Ứng dụng ghép nối với ngoại vi
+ Do những ưu điểm vượt bậc của ngôn ngữ C so với ASM, tác giả chỉ chú trọng sử dụng
ngôn ngữ C cho tất cả các ví dụ trong bài giảng.
Ví dụ 1:
Thực hiện điều khiển đồng thời tắt, mở các led ở PORTB theo Ton=Toff=500 ms.

#define _XTAL_FREQ 4000000


#include <htc.h>

void delay_for_500ms(void); // Khai báo chương trình con

__CONFIG(0x3FFA);

void main(void)
{
TRISB = 0x00; // PORTB là Output
PORTB = 0x00; // Cho 8 chân PORTB xuống mức 0 – các Led OFF
GV: Ong Mẫu Dũng – Khoa CNĐT 57
Bài giảng KỸ THUẬT VI XỬ LÝ

while(1) // Chạy vòng lặp mãi mãi


{
PORTB = 0xFF; // Cho 8 chân PORTB xuống mức 0 – các Led ON
delay_for_500ms(); // Gọi chương trình con tạo trễ 500ms
PORTB = 0x00; // Cho 8 chân PORTB xuống mức 0 – các Led OFF
delay_for_500ms(); // Gọi chương trình con tạo trễ 500ms
}
}

void interrupt isr(void) // Chương trình con ngắt – không dùng tới
{ }

void delay_for_500ms(void) // Chương trình con tạo trễ 500ms


{
unsigned char count1, count2, i;

for (count2=10; count2>0; count2--)


{
for (count1=50; count1>0; count1--)
{
for (i=0; i<100; i++)
{
} // chú ý: tạo trễ dạng này không được chính xác
}
}
}

Ví dụ 2:
Thực hiện điều khiển tắt, mở các led ở PORTB từ chân PORTB.0 đến PORTB.7 theo chu kỳ lặp lại
với Ton=Toff=500 ms.
#define _XTAL_FREQ 4000000
#include <htc.h>

__CONFIG(0x3FFA);
void main(void)
{
TRISB = 0x00; // PORTB là Output
PORTB = 0b00000001; // Led ON tại chân PORTB.0

while(1)
{ __delay_ms(500); // Tạo trễ chính xác 500ms, dùng thư viện của Hitech-C
PORTB = PORTB<<1; // Dịch các bit của PORTB sang trái 1 đơn vị
if (PORTB == 0x00) // Kiểm tra đã dịch trái 8 đơn vị hay không
{PORTB = 0b00000001;} //nếu đúng thì gán lại giá trị cho PORTB
}
}

GV: Ong Mẫu Dũng – Khoa CNĐT 58


Bài giảng KỸ THUẬT VI XỬ LÝ

Ví dụ 3:
Thực hiện hiển thị Led 7 đoạn anode chung các số từ 0 đến 9. Thời gian hiển thị mõi số là 1s.

Dựa vào kết nối từ sơ đố mạch, ta xây dựng bảng mã cho Led 7 đoạn. Chú ý, Led 7 đoạn
cực dương chung, và segment-a nối với chân trọng số thấp nhất (PORTB.0), segment-dp nối với
chân trọng số cao nhất (PORTB.7).

#define _XTAL_FREQ 4000000

#define uchar unsigned char


#define uint unsigned int
#define ulong unsigned long

#include <htc.h>

__CONFIG(0x3FFA);

const uchar seg7led[]={0xC0, 0xF9, 0xA4, 0xB0, 0x99, 0x92, 0x82, 0xF8, 0x80, 0x90};
uchar val=0;
//*************** main ********************

GV: Ong Mẫu Dũng – Khoa CNĐT 59


Bài giảng KỸ THUẬT VI XỬ LÝ

void main(void)
{
TRISB=0x00;
PORTB=0xFF;
while(1)
{
if (val==10) { val=0; }
else
{
PORTB = seg7led[val];
__delay_ms(1000);
val ++;
}
}
}

Ví dụ 4:
Thực hiện hiển thị đồng thời 2 Led 7 đoạn anode chung các số từ 00 đến 59. Thời gian hiển thị
mỗi số là 1s. Tần số lưu ảnh của mắt: 25 hình/s → với 2 led thì mỗi led sẽ sáng trong 20ms.

#define _XTAL_FREQ 4000000

#define uchar unsigned char


#define uint unsigned int
#define ulong unsigned long

#include <htc.h>

__CONFIG(0x3FFA);

const uchar seg7led[]={ 0xC0, 0xF9, 0xA4, 0xB0, 0x99, 0x92, 0x82, 0xF8, 0x80, 0x90 };
uchar val1=0;
uchar val2=0;
//*************** main ********************
void main(void)
{
TRISB=0x00;
PORTB=0xFF;

TRISC1 = 0;
TRISC2 = 0;

while(1)
{
for (val1=0 ; val1<6 ; val1++)
{
for (val2=0 ; val2<10 ; val2++)
GV: Ong Mẫu Dũng – Khoa CNĐT 60
Bài giảng KỸ THUẬT VI XỬ LÝ

{
for (uchar count=25; count>0; count--)
{
PORTB = seg7led[val1];
RC1 = 0;
RC2 = 1;
__delay_ms(20);
RC1 = 1;
RC2 = 1;
PORTB = seg7led[val2];
RC1 = 1;
RC2 = 0;
__delay_ms(20);
RC1 = 1;
RC2 = 1;
}
}
}
}
}

Ví dụ 5:
Thực hiện lại ví dụ 3 khi Led 7 đoạn dùng thêm IC chốt song song (74LS373; 74LS374)

Do có IC chốt song song, dữ liệu từng Led 7 đoạn sẽ được chốt vào từng Led tương ứng mà
không cần phải quét các led theo chu kỳ để lưu ảnh. Phương pháp dùng IC chốt có ưu điểm cho
Led sáng không nhấp nhấy, ổn định và lập trình cho vi điều khiển nhẹ nhàng hơn.
Chúng ta chỉ thay đổi một chút cho đoạn code trong ví dụ 4 như sau:
for (val1=0 ; val1<6 ; val1++)

GV: Ong Mẫu Dũng – Khoa CNĐT 61


Bài giảng KỸ THUẬT VI XỬ LÝ

{
for (val2=0 ; val2<10 ; val2++)
{
PORTB = seg7led[val1];
RC1 = 1;
RC1 = 0; // Chốt giá trị val1 cho Led 1

PORTB = seg7led[val2];
RC2 = 1;
RC2 = 0; // Chốt giá trị val2 cho Led 2

__delay_ms(1000);
}
}

Ví dụ 6:
Hiển thị ký tự A lên Led ma trận.

+ Trước hết, chúng ta phải xem xét kết nối port anode và port cathode của Led ma trận với
vi điều khiển. Port anode (dương chung) kết nối đến port C, Port cathode (âm chung) kết nối đến
port B. Như vậy, Port C dùng để xuất tuần tự dữ liệu cột, và Port B dùng cho việc chọn cột dữ liệu
đồng bộ với dữ liệu của Port C.
+ Trong ví dụ này chúng ta cần tạo bảng mã hiển thị ký tự ‘A’ theo dạng ma trận 8x8.

GV: Ong Mẫu Dũng – Khoa CNĐT 62


Bài giảng KỸ THUẬT VI XỬ LÝ

#define _XTAL_FREQ 4000000


#define uchar unsigned char
#define uint unsigned int
#define ulong unsigned long
#include <htc.h>
__CONFIG(0x3FFA);
const uchar seg7led[]={ 0xC0, 0xF9, 0xA4, 0xB0, 0x99, 0x92, 0x82, 0xF8, 0x80, 0x90 };

const uchar A[8][8]={ {0,0,0,1,1,0,0,0},


{0,0,1,0,0,1,0,0},
{0,1,0,0,0,0,1,0},
{1,0,0,0,0,0,0,1},
{1,1,1,1,1,1,1,1},
{1,0,0,0,0,0,0,1},
{1,0,0,0,0,0,0,1},
{1,0,0,0,0,0,0,1} };

//*************** main ********************


void main(void)
{
// Configure PORTC as OUTPUT
TRISC=0x00;
PORTC=0x00;
// Configure PORTB as OUTPUT
TRISB=0x00;
PORTB=0x00;
while(1)
{
PORTB=0b01111111; // Cột được tích cực mức 0 sẽ sáng
for (uchar i=0; i<8; i++)
{
GV: Ong Mẫu Dũng – Khoa CNĐT 63
Bài giảng KỸ THUẬT VI XỬ LÝ

RC0=A[0][i];
RC1=A[1][i];
RC2=A[2][i];
RC3=A[3][i];
RC4=A[4][i];
RC5=A[5][i];
RC6=A[6][i];
RC7=A[7][i];
__delay_ms(5);

PORTB = (PORTB >>1) + 0b10000000;


// Dịch mức tích cực 0 sang phải 1 đơn vị,
// đồng thời cho cột ngoài cùng bên trái lên mức 1 vì PORTB là số không dấu nên số 0 được chèn
vào trong phép dịch (còn gọi là phép dịch số học)
}
}
}

Ví dụ 7:
Hiển thị các ký tự lên màn hình LCD16x2 sử dụng giao tiếp mode 4 bit.

GV: Ong Mẫu Dũng – Khoa CNĐT 64


Bài giảng KỸ THUẬT VI XỬ LÝ

+ Cấu tạo và nguyên lý làm việc của LCD:


Khi sản xuất LCD, nhà sản xuất đã tích hợp chíp điều khiển (HD44780) bên trong lớp vỏ và chỉ đưa
các chân giao tiếp cần thiết. Các chân này được đánh số thứ tự và đặt tên như hình trên.
Chân Ký Mô tả
hiệu
1 Vss Chân nối đất cho LCD, nối chân này với GND của mạch điều khiển
2 VDD Chân cấp nguồn cho LCD, nối chân này với VCC=5V của mạch điều khiển
3 VEE Điều chỉnh độ tương phản của LCD.
4 RS Chân chọn thanh ghi (Register Select).
+ Logic “0”: Bus DB0-DB7 sẽ nối với thanh ghi lệnh IR của LCD (ở chế độ “ghi” -
write) hoặc nối với bộ đếm địa chỉ của LCD (ở chế độ “đọc” - read)
+ Logic “1”: Bus DB0-DB7 sẽ nối với thanh ghi dữ liệu DR bên trong LCD.
5 R/W Chân chọn chế độ đọc/ghi (Read/Write). Nối chân R/W với logic “0” để LCD hoạt
động ở chế độ ghi, hoặc nối với logic “1” để LCD ở chế độ đọc.
6 E Chân cho phép (Enable). Sau khi các tín hiệu được đặt lên bus DB0-DB7, các lệnh
chỉ được chấp nhận khi có 1 xung cho phép của chân E.
+ Ở chế độ ghi: Dữ liệu ở bus sẽ được LCD chuyển vào (chấp nhận) thanh ghi bên
trong nó khi phát hiện một xung (high-to-low transition) của tín hiệu chân E.
+ Ở chế độ đọc: Dữ liệu sẽ được LCD xuất ra DB0-DB7 khi phát hiện cạnh lên
(low-to-high transition) ở chân E và được LCD giữ ở bus đến khi nào chân E
xuống mức thấp.
7 - 14 DB0 - Tám đường của bus dữ liệu dùng để trao đổi thông tin với MPU. Có 2 chế độ sử
DB7 dụng 8 đường bus này :
+ Chế độ 8 bit: Dữ liệu được truyền trên cả 8 đường, với bit MSB là bit DB7.
+ Chế độ 4 bit: Dữ liệu được truyền trên 4 đường từ DB4 tới DB7, bit MSB là DB7
15 - Nguồn dương cho đèn nền
16 - GND cho đèn nền

+Các thanh ghi : HD44780 có 2 thanh ghi 8 bit quan trọng : Thanh ghi lệnh IR (Instructor Register)
và thanh ghi dữ liệu DR (Data Register)
- Thanh ghi IR : Để điều khiển LCD, người dùng phải “ra lệnh” thông qua tám đường bus
DB0-DB7. Mỗi lệnh được nhà sản xuất LCD đánh địa chỉ rõ ràng. Người dùng chỉ việc cung cấp địa
chỉ lệnh bằng cách nạp vào thanh ghi IR. Nghĩa là, khi ta nạp vào thanh ghi IR một chuỗi 8 bit, chíp
HD44780 sẽ tra bảng mã lệnh tại địa chỉ mà IR cung cấp và thực hiện lệnh đó.
- Thanh ghi DR : Thanh ghi DR dùng để chứa dữ liệu 8 bit để ghi vào vùng RAM DDRAM
hoặc CGRAM (ở chế độ ghi) hoặc dùng để chứa dữ liệu từ 2 vùng RAM này gởi ra cho MPU (ở chế
độ đọc). Nghĩa là, khi MPU ghi thông tin vào DR, mạch nội bên trong chíp sẽ tự động ghi thông tin
này vào DDRAM hoặc CGRAM. Hoặc khi thông tin về địa chỉ được ghi vào IR, dữ liệu ở địa chỉ này
trong vùng RAM nội của HD44780 sẽ được chuyển ra DR để truyền cho MPU.

GV: Ong Mẫu Dũng – Khoa CNĐT 65


Bài giảng KỸ THUẬT VI XỬ LÝ

=> Bằng cách điều khiển chân RS và R/W chúng ta có thể chuyển qua lại giữ 2 thanh ghi này
khi giao tiếp với MPU. Bảng sau đây tóm tắt lại các thiết lập đối với hai chân RS và R/W theo mục
đích giao tiếp.
RS R/W Chức năng
0 0 Ghi vào thanh ghi IR để ra lệnh cho LCD
0 1 Đọc cờ bận ở DB7 và giá trị của bộ đếm địa chỉ ở DB0-DB6
1 0 Ghi vào thanh ghi DR
1 1 Đọc dữ liệu từ DR

+ Cờ báo bận BF: (Busy Flag) Khi thực hiện các hoạt động bên trong chíp, mạch nội bên trong cần
một khoảng thời gian để hoàn tất. Khi đang thực thi các hoạt động bên trong chip như thế, LCD bỏ
qua mọi giao tiếp với bên ngoài và bật cờ BF (thông qua chân DB7 khi có thiết lập RS=0, R/W=1)
lên để báo cho MPU biết nó đang “bận”. Dĩ nhiên, khi xong việc, nó sẽ đặt cờ BF lại mức 0.
+ Vùng RAM hiển thị DDRAM : (Display Data RAM) Đây là vùng RAM dùng để hiển thị, nghĩa là ứng
với một địa chỉ của RAM là một ô kí tự trên màn hình và khi bạn ghi vào vùng RAM này một mã 8
bit, LCD sẽ hiển thị tại vị trí tương ứng trên màn hình một kí tự có mã 8 bit mà bạn đã cung cấp.
Hình sau đây sẽ trình bày rõ hơn mối liên hệ này :

+ Vùng ROM chứa kí tự CGROM: Character Generator ROM: Vùng ROM này dùng để chứa các
mẫu kí tự loại 5x8 hoặc 5x10 điểm ảnh/kí tự, và định địa chỉ bằng 8 bit. Tuy nhiên, nó chỉ có 208
mẫu kí tự 5x8 và 32 mẫu kí tự kiểu 5x10 (tổng cộng là 240 thay vì 2^8 = 256 mẫu kí tự). Người
dùng không thể thay đổi vùng ROM này.

GV: Ong Mẫu Dũng – Khoa CNĐT 66


Bài giảng KỸ THUẬT VI XỬ LÝ

+ Vùng RAM chứa kí tự đồ họa CGRAM : (Character Generator RAM) : Như trên bảng mã kí tự, nhà
sản xuất dành vùng có địa chỉ byte cao là 0000 để người dùng có thể tạo các mẫu kí tự đồ họa
riêng. Tuy nhiên dung lượng vùng này rất hạn chế: Ta chỉ có thể tạo 8 kí tự loại 5x8 điểm ảnh, hoặc
4 kí tự loại 5x10 điểm ảnh.
+ Tập lệnh điều khiển LCD:
Tên lệnh Hoạt động

Clear Mã lệnh: DBx = DB7 DB6 DB5 DB4 DB3 DB2 DB1 DB0

Display DBx = 0 0 0 0 0 0 0 1

Lệnh Clear Display (xóa hiển thị) sẽ ghi một khoảng trống-blank (mã hiện kí tự
GV: Ong Mẫu Dũng – Khoa CNĐT 67
Bài giảng KỸ THUẬT VI XỬ LÝ

20H) vào tất cả ô nhớ trong DDRAM, sau đó trả bộ đếm địa AC=0, trả lại kiểu
hiển thị gốc nếu nó bị thay đổi. Nghĩa là : Tắt hiển thị, con trỏ dời về góc trái
(hàng đầu tiên), chế độ tăng AC.

Return Mã lệnh : DBx = DB7 DB6 DB5 DB4 DB3 DB2 DB1 DB0

home DBx = 0 0 0 0 0 0 1 *

Lệnh Return home trả bộ đếm địa chỉ AC về 0, trả lại kiểu hiển thị gốc nếu nó bị
thay đổi. Nội dung của DDRAM không thay đổi.

Entry Mã lệnh : DBx = DB7 DB6 DB5 DB4 DB3 DB2 DB1 DB0

mode DBx = 0 0 0 0 0 1 [I/D] [S]


set
I/D : Tăng (I/D=1) hoặc giảm (I/D=0) bộ đếm địa chỉ hiển thị AC 1 đơn vị mỗi khi
có hành động ghi hoặc đọc vùng DDRAM. Vị trí con trỏ cũng di chuyển theo sự
tăng giảm này.

S : Khi S=1 toàn bộ nội dung hiển thị bị dịch sang phải (I/D=0) hoặc sang trái
(I/D=1) mỗi khi có hành động ghi vùng DDRAM. Khi S=0: không dịch nội dung
hiển thị. Nội dung hiển thị không dịch khi đọc DDRAM hoặc đọc/ghi vùng
CGRAM.

Display Mã lệnh : DBx = DB7 DB6 DB5 DB4 DB3 DB2 DB1 DB0

on/off DBx = 0 0 0 0 1 [D] [C] [B]

control D: Hiển thị màn hình khi D=1 và ngược lại. Khi tắt hiển thị, nội dung DDRAM
không thay đổi.

C: Hiển thị con trỏ khi C=1 và ngược lại.

B: Nhấp nháy kí tự tại vị trí con trỏ khi B=1 và ngược lại.

Chu kì nhấp nháy khoảng 409,6ms khi mạch dao động nội LCD là 250kHz.

Cursor Mã lệnh : DBx = DB7 DB6 DB5 DB4 DB3 DB2 DB1 DB0

or DBx = 0 0 0 1 [S/C] [R/L] * *

display Lệnh Cursor or display shift dịch chuyển con trỏ hay dữ liệu hiển thị sang trái mà
không cần hành động ghi/đọc dữ liệu. Khi hiển thị kiểu 2 dòng, con trỏ sẽ nhảy
shift xuống dòng dưới khi dịch qua vị trí thứ 40 của hàng đầu tiên. Dữ liệu hàng đầu
và hàng 2 dịch cùng một lúc. Chi tiết sử dụng xem bảng bên dưới:

GV: Ong Mẫu Dũng – Khoa CNĐT 68


Bài giảng KỸ THUẬT VI XỬ LÝ

S/C R/L Hoạt động

0 0 Dịch vị trí con trỏ sang trái (Nghĩa là giảm AC một đơn vị).

0 1 Dịch vị trí con trỏ sang phải (Tăng AC lên 1 đơn vị).

1 0 Dịch toàn bộ nội dung hiển thị sang trái, con trỏ cũng dịch theo.

1 1 Dịch toàn bộ nội dung hiển thị sang phải, con trỏ cũng dịch
theo.

Function Mã lệnh : DBx = DB7 DB6 DB5 DB4 DB3 DB2 DB1 DB0

set DBx = 0 0 1 [DL] [N] [F] * *

DL: Khi DL=1, LCD giao tiếp với MPU bằng giao thức 8 bit (từ bit DB7 đến DB0).
Ngược lại, giao thức giao tiếp là 4 bit (từ bit DB7 đến bit DB0). Khi chọn giao thức
4 bit, dữ liệu được truyền/nhận 2 lần liên tiếp. với 4 bit cao gởi/nhận trước, 4 bit
thấp gởi/nhận sau.

N : Thiết lập số hàng hiển thị. Khi N=0 : hiển thị 1 hàng, N=1: hiển thị 2 hàng.

F : Thiết lập kiểu kí tự. Khi F=0: kiểu kí tự 5x8 điểm ảnh, F=1: kiểu kí tự 5x10 điểm
ảnh.

Set Mã lệnh : DBx = DB7 DB6 DB5 DB4 DB3 DB2 DB1 DB0

CGRAM DBx = 0 1 [ACG][ACG][ACG][ACG][ACG][ACG]

address Lệnh này ghi vào AC địa chỉ của CGRAM. Kí hiệu [ACG] chỉ 1 bit của chuỗi dữ liệu
6 bit. Ngay sau lệnh này là lệnh đọc/ghi dữ liệu từ CGRAM tại địa chỉ đã được chỉ
định.

Set Mã lệnh : DBx = DB7 DB6 DB5 DB4 DB3 DB2 DB1 DB0

DDRAM DBx = 1 [AD] [AD] [AD] [AD] [AD] [AD] [AD]

address Lệnh này ghi vào AC địa chỉ của DDRAM, dùng khi cần thiết lập tọa độ hiển thị

mong muốn. Ngay sau lệnh này là lệnh đọc/ghi dữ liệu từ DDRAM tại địa chỉ đã
được chỉ định.

Khi ở chế độ hiển thị 1 hàng: địa chỉ có thể từ 00H đến 4FH. Khi ở chế độ hiển thị
2 hàng, địa chỉ từ 00h đến 27H cho hàng thứ nhất, và từ 40h đến 67h cho hàng
thứ 2.

GV: Ong Mẫu Dũng – Khoa CNĐT 69


Bài giảng KỸ THUẬT VI XỬ LÝ

Read BF Mã lệnh : DBx = DB7 DB6 DB5 DB4 DB3 DB2 DB1 DB0

and DBx =[BF] [AC] [AC] [AC] [AC] [AC] [AC] [AC] (RS=0,R/W=1)

address Như đã đề cập trước đây, khi cờ BF bật, LCD đang làm việc và lệnh tiếp theo (nếu
có) sẽ bị bỏ qua nếu cờ BF chưa về mức thấp. Cho nên, khi lập trình điều khiển,
phải kiểm tra cờ BF trước khi ghi dữ liệu vào LCD.

Khi đọc cờ BF, giá trị của AC cũng được xuất ra các bit [AC]. Nó là địa chỉ của

CG hay DDRAM là tùy thuộc vào lệnh trước đó.

Write Mã lệnh : DBx = DB7 DB6 DB5 DB4 DB3 DB2 DB1 DB0

data to DBx = [Write data] (RS=1, R/W=0)

CG or Khi thiết lập RS=1, R/W=0, dữ liệu cần ghi được đưa vào các chân DBx từ mạch

DDRAM ngoài sẽ được LCD chuyển vào trong LCD tại địa chỉ được xác định từ lệnh ghi địa
chỉ trước đó (lệnh ghi địa chỉ cũng xác định luôn vùng RAM cần ghi)

Sau khi ghi, bộ đếm địa chỉ AC tự động tăng/giảm 1 tùy theo thiết lập Entry
mode.

Read Mã lệnh : DBx = DB7 DB6 DB5 DB4 DB3 DB2 DB1 DB0

data DBx = [Read data] (RS=1, R/W=1)

from CG Khi thiết lập RS=1, R/W=1,dữ liệu từ CG/DDRAM được chuyển ra MPU thông qua
or các chân DBx (địa chỉ và vùng RAM đã được xác định bằng lệnh ghi địa chỉ trước
đó).
DDRAM
Sau khi đọc, AC tự động tăng/giảm 1 tùy theo thiết lập Entry mode, tuy nhiên nội
dung hiển thị không bị dịch bất chấp chế độ Entry mode.

#define _XTAL_FREQ 4000000


#define uchar unsigned char
#define uint unsigned int
#define ulong unsigned long

#define dport PORTB


#define dport_in TRISB=0xFF
#define dport_out TRISB=0x00

#define rs RB0
#define rw RB1
GV: Ong Mẫu Dũng – Khoa CNĐT 70
Bài giảng KỸ THUẬT VI XỬ LÝ

#define en RB2

void lcd1602_write_dat(uchar lcd_dat);


void lcd1602_write_string(const uchar *cy);
void lcd1602_write_com(uchar lcd_com);

#include <htc.h>
__CONFIG(0x3FFA);
//*************** main ********************
void main(void)
{
dport_out ;
lcd1602_write_com(0x28);
//DL=0 (Data Line 4bit mode);N=1 (Number of display line=2);F=0 (Char font 5x7)

lcd1602_write_com(0x0F);
//D=1 (Display on);C=1 (Cursor on);B=1 (Blink on);

lcd1602_write_com(0x80);
lcd1602_write_string("DH CN TP.HCM");
lcd1602_write_com(0xC0);
lcd1602_write_string("Khoa CNDT- DTMT");
__delay_ms(3000);

lcd1602_write_com(0x01);
//clear lcd creen

lcd1602_write_com(0x80);
lcd1602_write_string("Ky thuat VXL");
lcd1602_write_com(0xC0);
lcd1602_write_string("PIC 17F877A");
__delay_ms(3000);

while(1)
{

}
}

void lcd1602_write_dat(uchar lcd_dat)


{
__delay_ms(50);
// Instead of checking LCD busy flag, we use the fixed delay.
uchar temp;

temp = lcd_dat & 0xF0 ;


dport=temp;
rs=1;

GV: Ong Mẫu Dũng – Khoa CNĐT 71


Bài giảng KỸ THUẬT VI XỬ LÝ

rw=0;
en=1;
en=0;

__delay_us(10);
// Make some delay for LCD ready for the next nibble bit, otherwise it will loose data
temp = (lcd_dat << 4) & 0xF0 ;
dport=temp;
rs=1;
rw=0;
en=1;
en=0;
}

void lcd1602_write_string(const uchar *cy)


{
while(*cy)
{
__delay_ms(50);

uchar temp;
temp = *cy & 0xF0;
dport=temp;
rs=1;
rw=0;
en=1;
en=0;
__delay_us(10);

temp = (*cy << 4) & 0xF0;


dport=temp;
rs=1;
rw=0;
en=1;
en=0;

cy++; //Get the next char until end of string (will get 0 at that time)
}
__delay_ms(50);
}

void lcd1602_write_com(uchar lcd_com)


{
__delay_ms(50);

uchar temp;

temp = lcd_com & 0xF0 ;

GV: Ong Mẫu Dũng – Khoa CNĐT 72


Bài giảng KỸ THUẬT VI XỬ LÝ

dport=temp;
rs=0;
rw=0;
en=1;

en=0;

__delay_us(10);

temp = (lcd_com << 4) & 0xF0 ;


dport=temp;
rs=0;
rw=0;
en=1;
en=0;
}

Ví dụ 9:
Nút bấm đơn và nút bấm ma trận

GV: Ong Mẫu Dũng – Khoa CNĐT 73


Bài giảng KỸ THUẬT VI XỬ LÝ

+ Nút bấm đơn: ở trạng thái nút hở, chân vđk được cấp mức logic-1 thông qua điện trở kéo lên
nguồn 5V, trong khi ở trạng thái nút ấn, chân vđk là mức logic-0 do nối xuống GND thông qua nút
được ấn.

+ Khi ấn nút phát sinh tình trạng gai xung do nút nhấn vật lý không có chống rung.

+ Chúng ta sẽ thêm vào những đoạn mã giúp MCU bỏ qua những tín hiệu không mong muốn
bằng cách thêm vào những khoảng thời gian Delay sau khi nhấn phím, hệ thống sẽ chờ đến khi
tín hiệu ổn định rồi mới lấy và xử lý tín hiệu.
+ Có một vài cách thêm vào như sau:
if(Button_pressed?)
{
Delay(TimeDebounce); //This value about (ms)
Pressed_State;
}
else Not_Pressed;

Giải thích: Sau khi kiểm tra có tín hiệu nhấn phím, chúng ta để cho hệ thống Delay 1 khoảng thời
gian (Tạm dừng chưa lấy tín hiệu). Khoảng thời gian này khá lớn (Cỡ vài chục ms).
Đặc điểm: Khi bạn nhấn phím lâu hơn thời gian Delay thì hệ thống sẽ lại thực thi 1 hoặc nhiều lần
nữa. Khiến cho hàm trong mệnh đề IF sẽ được thực hiện hơn 1 lần.Chúng ta có thể ứng dụng việc
này vào việc tăng hoặc giảm giá trị nào đó chẳng hạn….

GV: Ong Mẫu Dũng – Khoa CNĐT 74


Bài giảng KỸ THUẬT VI XỬ LÝ

if(Button_pressed?)
{
While(Button_pressed?) Delay(TimeDebounce); //This value about (ns)
Pressed;
}
else Not_Pressed;

Giải thích: Sau khi hệ thống kiểm tra có tín hiệu nhấn phím hay không, nếu có thì hệ thống sẽ
nhảy vào trong mệnh đề IF, tại đây hệ thống sẽ kiểm tra tiếp xem phím có đang được nhấn hay
không tại mệnh đề WHILE, nếu có thì sẽ Delay 1 khoảng thời gian. (Giá trị Delay này bạn có thể
đặt cỡ vài chục ns – Ít hơn nhiều so với cách phía trên)
Đặc điểm: phương pháp này sẽ Delay liên tục cho đến khi phím được nhả ra thì mới thực thi
chương trình xử lý. Tiết kiệm thời gian hơn so với phương pháp trước.
#define _XTAL_FREQ 4000000
#define uchar unsigned char
#define uint unsigned int
#define ulong unsigned long

#define dport PORTB


#define dport_in TRISB=0xFF
#define dport_out TRISB=0x00

#define rs RB0
#define rw RB1
#define en RB2

void lcd1602_write_dat(uchar lcd_dat);


void lcd1602_write_string(const uchar *cy);
void lcd1602_write_com(uchar lcd_com);

unsigned char read_PORTE(void);


unsigned char read_PORTC(void);

unsigned char idx_to_str[]="0123456789";

#include <htc.h>
#include "matrix_PIC16F877A.h"

__CONFIG(0x3FFA);
//*************** main ********************
void main(void)
{
dport_out ;
lcd1602_write_com(0x28);
lcd1602_write_com(0x0F);
GV: Ong Mẫu Dũng – Khoa CNĐT 75
Bài giảng KỸ THUẬT VI XỬ LÝ

lcd1602_write_com(0x01);

// Cofigure PORTE as general I/O


PCFG3=1;
PCFG2=1;
TRISE0=1;
TRISE1=1;
TRISE2=1;

// Configure PORTC as INPUT


TRISC=0xFF;

while(1)
{
uchar key;
key = read_matrixkey();
if (key!=0)
{
lcd1602_write_dat(key);
__delay_ms(20);
}

key = read_PORTE();
if (key==1)
{
lcd1602_write_com(0x18);
__delay_ms(20);
}
else if (key ==2)
{
lcd1602_write_com(0x1C);
__delay_ms(20);
}
else if (key ==3)
{
lcd1602_write_com(0x01);
__delay_ms(20);
}

key = read_PORTC();
if (key!=0)
{
lcd1602_write_dat(idx_to_str[key]);
__delay_ms(20);
}

}
}

GV: Ong Mẫu Dũng – Khoa CNĐT 76


Bài giảng KỸ THUẬT VI XỬ LÝ

void lcd1602_write_dat(uchar lcd_dat)


{
……(như ví dụ trên)
}

void lcd1602_write_string(const uchar *cy)


{
……(như ví dụ trên)
}

void lcd1602_write_com(uchar lcd_com)


{
……(như ví dụ trên)
}

unsigned char read_PORTE(void)


{
uchar key = PORTE & 0B00000111;
if (key != 0B00000111) // found key pressed
{
__delay_ms(100); // debound key by delay
key = PORTE & 0B00000111;
if (key != 0B00000111) // check key still pressed again
{
switch (key) // Read key
{
case 0B00000110:
{ return 1; break; }
case 0B00000101:
{return 2; break; }
case 0B00000011:
{return 3; break; }
default:
{return 0; break; }
}
}
else return 0;
}
return 0;
}

unsigned char read_PORTC(void)


{
uchar key = PORTC & 0xFF;
if (key != 0xFF)
{

GV: Ong Mẫu Dũng – Khoa CNĐT 77


Bài giảng KỸ THUẬT VI XỬ LÝ

__delay_ms(100);
key = PORTC & 0xFF;
if (key != 0xFF)
{
switch (key)
{
case 0B11111110:
{return 1;break;}
case 0B11111101:
{return 2;break;}
case 0B11111011:
{return 3;break;}
case 0B11110111:
{return 4;break;}
case 0B11101111:
{return 5;break;}
case 0B11011111:
{return 6;break;}
case 0B10111111:
{return 7;break;}
case 0B01111111:
{return 8;break;}
default:
{return 0;break;}
}
}
else return 0;
}
return 0;
}

GV: Ong Mẫu Dũng – Khoa CNĐT 78


Bài giảng KỸ THUẬT VI XỬ LÝ

Chương 6: Moodul Timer –ngăt


- Trình bày được cấu trúc và tập lệnh của VĐK PIC và các thanh ghi lien quan đến các Modul
Timer và modul ngắt của VĐK PIC
- Trình bày được nguyên lý hoạt động và điều khiển Modul Timer và modul ngắt cơ bản của
VĐK PIC.
- Xây dựng mô hình, phân tích và thiết kế, vẽ lưu đồ và lập trình ứng dụng được Modul
Timer và modul ngắt cho các ứng dụng

6.1 Timer-Counter
6.1.1 Giới thiệu
Tất cả vi điều khiển có mạch định thời trên chip; một số có 4 timer khác nhau. Vi điều khiển
16F8xx gồm 3 Timers (0,1,2). Các timer này chạy ở tốc độ 1/4 của xung đồng hồ hệ thống (fosc).
Như vậy nếu chúng ta sử dụng thạch anh 32,768 Khz, các timer bên trong sẽ chạy ở ở tần số 8192
Hz. Nếu chúng ta muốn bật led sáng trong 1 giây chẳng hạn thì chúng ta cần đếm 8192 xung. Đây
là rất nhiều xung. Thật là may mắn bên trong vi điều khiển có 1 thanh ghi gọi là thanh ghi OPTION,
mà cho phép chúng ta làm giảm (chậm) những xung này bằng các hệ số chia: 2, 4, 8, 16, 32, 128 và
256. Thanh ghi OPTION được thảo luận trong phần tập lệnh dùng cho Timer0. Thiết lập bộ tỉ lệ
trước , ví dụ như nó được gọi để chia 256 trong thanh ghi OPTION nghĩa là xung định thì của
chúng ta bây giờ là 8192/256=32 Hz, nghĩa là 32 xung trong 1 giây. Như vậy để bật led sáng trong 1
giây, chúng ta chỉ cần đếm 32 xung trong các timer hay 16 xung cho 0,5 giây, hay 160 xung cho 50
mili-giây (ms),v.v...
6.1.2 Timer/counter của VĐK PIC 16f8xx
a. Khảo sát các timer
+ Timer 0 có các đặc điểm sau:
o Là bộ đếm 8 bit (thanh ghi đếm TMR0: chạy từ 0x00 đến 0xFF)
o Có thể đọc/ghi thanh ghi đếm TMR0
o Có bộ chia trước tỉ lệ (prescale) 4bit
o Cho phép lựa chọn nguồn xung clock từ bên trong (xung clock hệ thống) hoặc từ bên
ngoài (thông qua chân T0CKI)
o Có thể phát sinh ngắt khi báo tràn (0xFF về 0x00), đồng thời cờ tràn được set
o Bộ đếm tự khởi động chạy khi vđk được cấp nguồn

GV: Ong Mẫu Dũng – Khoa CNĐT 79


Bài giảng KỸ THUẬT VI XỬ LÝ

GV: Ong Mẫu Dũng – Khoa CNĐT 80


Bài giảng KỸ THUẬT VI XỬ LÝ

+ Timer 1 có các đặc điểm sau:


o Là bộ đếm 16 bit (2 thanh ghi đếm TMR1H:TMR1L chạy từ 0x0000 đến 0xFFFF)
o Có thể đọc/ghi thanh ghi đếm TMR1H:TMR1L
o Có bộ chia trước tỉ lệ (prescale) 2bit
o Cho phép lựa chọn nguồn xung clock từ bên trong (xung clock hệ thống) hoặc từ bên
ngoài (thông qua chân T1CKI)
o Có thể phát sinh ngắt khi báo tràn (0xFFFF về 0x0000), đồng thời cờ tràn được set
o Timer1 được bật và tắt thông qua cờ TMR1ON.
o Ngoài chức năng timer/counter, được dùng cho module Capture và Compare

+ Timer 2 có các đặc điểm sau:


o Là bộ đếm 8 bit (thanh ghi đếm TMR0: chạy từ 0x00 đến 0xFF)
o Có thể đọc/ghi thanh ghi đếm TMR2
o Có 2 bộ chia trước tỉ lệ (prescale – 2bit và postscale – 4bit)
o Chỉ dùng nguồn xung clock từ bên trong (xung clock hệ thống)
o Có thể phát sinh ngắt khi báo tràn (giá trị của thanh ghi PR2 về 0x00), đồng thời cờ tràn
được set
o Timer2 được bật và tắt thông qua cờ TMR2ON.
o Ngoài chức năng timer/counter, được dùng cho module PWM.

GV: Ong Mẫu Dũng – Khoa CNĐT 81


Bài giảng KỸ THUẬT VI XỬ LÝ

b. Cách truy xuất các thành phần của timer


+ Truy xuất Timer0:

GV: Ong Mẫu Dũng – Khoa CNĐT 82


Bài giảng KỸ THUẬT VI XỬ LÝ

+ Truy xuất Timer1:

GV: Ong Mẫu Dũng – Khoa CNĐT 83


Bài giảng KỸ THUẬT VI XỬ LÝ

+ Truy xuất Timer2:

GV: Ong Mẫu Dũng – Khoa CNĐT 84


Bài giảng KỸ THUẬT VI XỬ LÝ

6.1.3 Ứng dụng timer/counter của VĐK PIC 16f8xx.


a. Ứng dụng định thời dùng timer.
b. Ứng dụng đếm xung ngoại counter.
* Phần a. và b. sẽ trình bày cụ thể song song với ứng dụng ngắt PORTB và các TIMERs. Lý do là
việc so sánh 2 chương trình xử lý tràn bộ đếm theo polling và theo interrupt rõ ràng hơn.

6.2. Ngắt
6.2.1 Tổng quan về ngắt của VĐK PIC 16f8xx
+ Có 2 phương pháp nhận ngắt: thứ nhất khi chúng ta liên tục kiểm tra gọi là ngắt bằng
phần mềm (hỏi vòng-polling), thứ hai khi chuông reo gọi là tương đương ngắt phần cứng
(interrupt). Khi xảy ra ngắt chúng ta cần nhớ nội dung của file là gì, nghĩa là thanh ghi trạng thái
STATUS, thanh tích lũy W, Timers và thiết lập PORT v.v., để mà khi trở về từ ngắt, các thiết lập
được lưu trở lại (restored). Chúng ta cần lưu lại các thiết lập, các giá trị trước khi bị ngắt, bởi vì
ngắt các nội dung thanh ghi có thể thay đổi trong chương trình phục vụ ngắt.

GV: Ong Mẫu Dũng – Khoa CNĐT 85


Bài giảng KỸ THUẬT VI XỬ LÝ

6.2.2 Ngắt của VĐK PIC 16f8xx


a. Các nguồn ngắt của VĐK.
▪ 16F877A có 15 nguồn ngắt (xem hình dưới).
▪ Thay đổi cạnh lên hay cạnh xuống của PORTB,0.
▪ TMR0 tràn từ FFh về 00h.
▪ TMR1 tràn từ FFFFh về 0000h.
▪ TMR2 tràn từ PR2 về 00h.
▪ PORTB bit 4-7 thay đổi.
▪ Ngắt điều chế độ rộng xung, bắt giữ và so sánh.
▪ Chuyển đổi A/D hoàn thành.
▪ Ghi dữ liệu EEPROM hoàn thành
▪ Ngắt port nối tiếp đồng bộ/ bất đồng bộ.
Những ngắt này có thể được cho phép (enable) hay cấm theo yêu cầu bởi bit cho phép/cấm
ngắt. Các bit này có thể được tìm thấy trong thanh ghi điều khiển ngắt INTCON cho 16F877A.
▪ GIE: Global Interrut Enable
▪ PEIE: PEripheral Interrupt Enable
▪ xxxIE và xxxIF: bit cho phép modul ngắt và bit cờ (flag) báo hiệu cho modul tương ứng

GV: Ong Mẫu Dũng – Khoa CNĐT 86


Bài giảng KỸ THUẬT VI XỬ LÝ

b. Các thanh ghi liên quan đến ngắt.


Trong mục này, chúng ta tìm hiểu về các ngắt liên quan đến PORTB và các Timers. Các loại ngắt
khác sẽ trình bày cụ thể trong các modul chức năng ở các chương kế tiếp
+ Ngắt ngoài tại chân RB0 , ngắt do thay đổi PORTB (các chân RB4,5,6,7), và ngắt do Timer0: 3 loại
ngắt này thuộc về 3 loại ngắt trong, cụ thể như sau:
▪ Ngắt ngoài tại chân RB0: INTF; INTE và GIE
▪ Ngắt do thay đổi PORTB: RBIF; RBIE và GIE
▪ Ngắt do Timer0: TMR0IF; TMR0IE và GIE
+ Thanh ghi INTCON dùng cho việc cấu hình và sử dụng 3 loại ngắt trên.

c. Khai báo ngắt trong ngôn ngữ lập trình


Phần này đã được minh học cụ thể trong phần “lập trình cho vđk bằng ngôn ngữ ASM và Hitech-C”.

GV: Ong Mẫu Dũng – Khoa CNĐT 87


Bài giảng KỸ THUẬT VI XỬ LÝ

6.2.3 Các ứng dụng dùng ngắt của VĐK PIC 16f8xx
INTERUPT AT PIN RB0 AND PORTB(PINS RB4,5,6,7)

#define _XTAL_FREQ 4000000 //4MHz void interrupt isr(void) // INT Subroutine


{
#include <htc.h> // belong to INT PORTB CHANGES
if ((RBIF==1) && (INTF==0))
__CONFIG(0x3FFA); {
unsigned char data;
void main(void)
{ // clear the current state of PORTB and update new
RBIE = 1; status.
GIE = 1; data = PORTB;
RBIF = 0; // INT PORTB changes.
RBIF=0;
INTE = 1;
INTF = 0; // INT RB0 changes. PORTD = 0B00001111;
}
TRISD = 0x00; // belong to INT RB0 CHANGES
PORTD = 0xFF; else if (!RBIF && INTF)
{
while(1) // loop forever INTF=0;
{
PORTD = 0B11110000;
} }
} }

GV: Ong Mẫu Dũng – Khoa CNĐT 88


Bài giảng KỸ THUẬT VI XỬ LÝ

TIMER0 OPERATES AS TIMER

/* INTERUPT method */ /* POLLING method */

#define _XTAL_FREQ 4000000 #define _XTAL_FREQ 4000000


#define uchar unsigned char #define uchar unsigned char
#define uint unsigned int #define uint unsigned int
#define ulong unsigned long #define ulong unsigned long

#include <htc.h> #include <htc.h>


__CONFIG(0x3FFA); __CONFIG(0x3FFA);

void main(void) void main(void)


{ {
// pre-scale for TMR0 // pre-scale for TMR0
PSA=0; PSA=0;

// pre-scale with 256 times // pre-scale with 256 times


PS2=1; PS2=1;
PS1=1; PS1=1;
PS0=1; PS0=1;

T0CS=0; // internal CLK T0CS=0; // internal CLK


TMR0=0; // cycle 256 TMR0= (256-250); // cycle 250

T0IF=0; T0IF=0;

GIE=1; TRISD=0;
T0IE=1; PORTD=0x00;

TRISD=0; while(1)
PORTD=0x00; {
while (!TMR0IF) ;
while(1)
{ TMR0IF = 0;

} TMR0= (256-250); // cycle 250


}
PORTD=~PORTD;
}
void interrupt isr(void) }
{
if(T0IE&&T0IF) // Timer = 250 cycle * 256 prescaler
{
T0IF=0;
PORTD=~PORTD;
}
}

GV: Ong Mẫu Dũng – Khoa CNĐT 89


Bài giảng KỸ THUẬT VI XỬ LÝ

/* TIMER0 OPERATES AS COUNTER EXTERNAL /* TIMER0 COMBINES WITH REGISTER */


PULSES*/

#define _XTAL_FREQ 4000000 #define _XTAL_FREQ 4000000


#define uchar unsigned char #define uchar unsigned char
#define uint unsigned int #define uint unsigned int
#define ulong unsigned long #define ulong unsigned long

#include <htc.h> #include <htc.h>


__CONFIG(0x3FFA); __CONFIG(0x3FFA);

void main(void) void main(void)


{ {
// prescaler NOT for TMR0, for WDT // Prescaler Assigmet Bit (1 for WDT)
PSA=1; PSA=1;

// prescaler with 256 times (not use in this case) // Internal Clock Source
// PS2=1; PS1=1; PS0=1; T0CS=0;

// External CLK from pin T0CKI // Predefine value for TMR0


T0CS=1; TMR0=(256-100);

// Predefine value for TMR0 T0IF=0 ;


TMR0= (256-10); // cycle 10
TRISD=0;
T0IF=0 ; PORTD=0x00;

TRISD=0; uint tmr0_count=1 ;


PORTD=0x00;
while(1)
while(1) {
{ while(!T0IF); // loop this while T0IF=0
while (!TMR0IF) ;
TMR0=(256-100); // Predefine value for TMR0
TMR0IF = 0;
T0IF=0 ;
TMR0= (256-10); // cycle 10
if (++tmr0_count >= 5000)
PORTD=PORTD+1; {
// Counter every 10 external pulses tmr0_count=1;
} PORTD=~PORTD;
} }
// 5000 loop * TMR0 cycle
}
}

GV: Ong Mẫu Dũng – Khoa CNĐT 90


Bài giảng KỸ THUẬT VI XỬ LÝ

TIMER1 WORKS AS INTERNAL TIMER 16 BIT

/*/* INTERUPT method */ */ /*/* POLLING method */ */

#define _XTAL_FREQ 4000000 #define _XTAL_FREQ 4000000


#define uchar unsigned char #define uchar unsigned char
#define uint unsigned int #define uint unsigned int
#define ulong unsigned long #define ulong unsigned long

#include <htc.h> #include <htc.h>


__CONFIG(0x3FFA); __CONFIG(0x3FFA);

void main(void) void main(void)


{ {
T1CKPS0=1; T1CKPS0=1;
T1CKPS1=1; // scale 1:8 T1CKPS1=1; // scale 1:8

TMR1CS=0; // internal clock TMR1CS=0; // internal clock

// initial value with 12500 // initial value with 12500


TMR1L=(65536-12500)%256; TMR1L=(65536-12500)%256;
TMR1H=(65536-12500)/256; TMR1H=(65536-12500)/256;

GIE=1; TMR1IF=0;
PEIE=1; TMR1ON=1; // start TMR1
TMR1IE=1;
TRISD=0;
TMR1IF=0; PORTD=0x00;
TMR1ON=1; // start TMR1
while(1)
TRISD=0; {
PORTD=0x00; while(!TMR1IF) ;

while(1) TMR1IF=0;
{
TMR1L=(65536-12500)%256;
} TMR1H=(65536-12500)/256;
}
PORTD=PORTD+1;
void interrupt isr(void) // Timer1 = 12500 cycle * 8 prescaler
{ }
if(TMR1IE&&TMR1IF) }
{
TMR1IF=0;
TMR1L=(65536-12500)%256;
TMR1H=(65536-12500)/256;

PORTD=PORTD+1;
}
}

GV: Ong Mẫu Dũng – Khoa CNĐT 91


Bài giảng KỸ THUẬT VI XỬ LÝ

TIMER1 OPERATES AS COUNTER EXTERNAL PULSES

#define _XTAL_FREQ 4000000


#define uchar unsigned char
#define uint unsigned int
#define ulong unsigned long

#include <htc.h>
__CONFIG(0x3FFA);

void main(void)
{
TRISD=0x00;
PORTD=0x00;

// no prescaler
T1CKPS0=0;
T1CKPS1=0;

// Initial value = 10
TMR1L=(65536-10)%256;
TMR1H=(65536-10)/256;

// Synchronous clock enable


T1SYNC=0;

// Select External Counter (from R-C osc or from T1CKI pin)


TMR1CS=1;

// Select External Counter from T1CKI pin


T1OSCEN=0;

TMR1IF=0;
TMR1ON=1; // start counter

while(1)
{
while (!TMR1IF);
TMR1IF=0;

TMR1ON=0; // stop counter


TMR1L=(65536-10)%256;
TMR1H=(65536-10)/256;
TMR1ON=1; // start counter

PORTD=~PORTD;
// Count up 1 times after received 10 pulse from T1CKI pin
}
}

GV: Ong Mẫu Dũng – Khoa CNĐT 92


Bài giảng KỸ THUẬT VI XỬ LÝ

TIMER2 OPERATES AS COUNTER EXTERNAL PULSES

#define _XTAL_FREQ 4000000 #define _XTAL_FREQ 4000000


#define uchar unsigned char #define uchar unsigned char
#define uint unsigned int #define uint unsigned int
#define ulong unsigned long #define ulong unsigned long
#include <htc.h> #include <htc.h>
__CONFIG(0x3FFA); __CONFIG(0x3FFA);

void main(void) void main(void)


{ {
T2CKPS0=1; T2CKPS0=1;
T2CKPS1=0; // pre-scale 1:4 T2CKPS1=0; // pre-scale 1:4

TOUTPS3=0; TOUTPS3=0;
TOUTPS2=1; TOUTPS2=1;
TOUTPS1=0; TOUTPS1=0;
TOUTPS0=0; // post-scale 1:6 TOUTPS0=0; // post-scale 1:6

// TMR2 begins from 0 // TMR2 begins from 0


TMR2=0; TMR2=0;

// TMR2 ends to PR2 (250 cycle in this case) // TMR2 ends to PR2 (250 cycle in this case)
PR2=250-1; PR2=250-1;

GIE=1; TMR2IF=0;
PEIE=1; TMR2ON=1; // TMR2 starts
TMR2IE=1;
TRISD=0;
TMR2IF=0; PORTD=0x00;
TMR2ON=1; // TMR2 starts
uchar count=1;
TRISD=0;
PORTD=0x00; while(1)
{
while(1) while (!TMR2IF) ;
{
} TMR2IF=0;
}
void interrupt isr(void) PR2=250-1;
{ // TMR2 ends to PR2 (250 cycle in this case)
uchar count=1;
if(++count>=25)
if(TMR2IF&&TMR2IE) { count=1;
{ PORTD=PORTD+1; }
TMR2IF=0;
if(++count>=25) }
{ count=1; }
PORTD=PORTD+1; } // total timer = TMR2 * count * precsaler *
} postscaler
} // = 250*25*4*6=150 ms
// total timer = TMR2 * count * precsaler * postscaler

GV: Ong Mẫu Dũng – Khoa CNĐT 93


Bài giảng KỸ THUẬT VI XỬ LÝ

CHƯƠNG 7: CCP – ADC

- Trình bày được cấu trúc và tập lệnh của VĐK PIC và các thanh ghi lien quan đến các Modul CCP
của VĐK PIC

- Trình bày được nguyên lý hoạt động và điều khiển Modul CCP ở các chế độ cơ bản của VĐK PIC.

- Xây dựng mô hình, phân tích và thiết kế, vẽ lưu đồ và lập trình ứng dụng được được Modul CCP
cho các ứng dụng

7.1 CCP

7.1.1. Giới thiệu Modul CCP

+ Mỗi Module Bắt giữ/So sánh/PWM (CCP -Capture/Compare/PWM) chứa một thanh ghi 16 bit
mà có thể hoạt động như:

▪ Thanh ghi bắt giữ 16 bit.


▪ Thanh ghi so sánh 16 bit.

+ Cả hai Module CCP1 và CCP2 là giống nhau về hoạt động. Riêng Module PWM hoạt động dựa
trên Timer2.

Chế độ CCP Nguồn timer


Bắt giữ Timer 1
So sánh Timer 1
Điều rộng xung (PWM) Timer 2

+ Module CCP1: Thanh ghi bắt giữ/So sánh/Điều rộng xung (PWM) thứ 1 (CCPR1) gồm hai thanh
ghi 8 bit: CCPR1L (byte thấp) và CCP1RH (byte cao). Thanh ghi CCP1CON điều khiển hoạt động của
CCP1. Trigger sự kiện đặc biệt có thể được cấu hình để tạo bởi bộ khớp so sánh và sẽ reset timer 1
và bắt đầu chuyển đổi A/D (nếu môđun A/D được cho phép).

+ Tương tự, Module CCP2: Thanh ghi bắt giữ/so sánh/PWM số 2 (CCPR2) gồm có 2 thanh ghi 8 bit:
CCPR2L (byte thấp) và CCPR2H (byte cao). Thanh ghi CCP2CON điều khiển hoạt động của CCP2.

GV: Ong Mẫu Dũng – Khoa CNĐT 94


Bài giảng KỸ THUẬT VI XỬ LÝ

7.1.2. Khảo sát chế độ Capture

Chế độ bắt giữ (Capture) được dùng cho chức năng lặp thời gian hay xác định độ dài của xung
PWM. Khi đo thời gian xung PWM, clock TMR1 phải đủ nhanh để lấy giá trị có ý nghĩa với độ phân
giải đủ cao mà có sự thể hiện chính xác của định thời.

a. Tập các thanh ghi liên quan

CCPxM3:CCPxM0: CCPx Mode Select bits trong thanh ghi CCPxCON được sử dụng:

▪ 0100 = Capture mode, every falling edge


▪ 0101 = Capture mode, every rising edge
▪ 0110 = Capture mode, every 4th rising edge
▪ 0111 = Capture mode, every 16th rising edge

Ngoài ra, Capture sử dụng Timer1 nên tất cả các thanh ghi lien quan đến Timer1 cũng dùng cho
việc thực hiện chế độ Capture.

GV: Ong Mẫu Dũng – Khoa CNĐT 95


Bài giảng KỸ THUẬT VI XỬ LÝ

b. Hoạt động nguyên lý

+ Tín hiệu capture được đưa vào chân CCPx của vđk sau khi đã chuẩn hóa tín hiệu theo mức logic-
0 và logic-1. Chú ý, chân CCPx của vđk phải được cấu hình là INPUT.

+ Tùy theo cấu hình CCPx Mode Select bits, tín hiệu capture được phát hiện sau khi qua bộ chia tỉ
lệ và bộ phát hiện cạnh. Timer 1 được bật chạy để đếm số lượng xung hệ thống.

+ Sau khi capture, vđk thực hiện 2 tác vụ: bật cờ báo CCPxIF và lưu giá trị Timer1 vào thanh ghi
16bit của CCPx là CCPRxH:CCPRxL. Như vậy, người lập trình cần chú trọng đến giới hạn số xung
đếm của Timer1. Trong trường hợp độ rộng xung cần capture quá dài, có thể kết hợp Timer1 với
bộ chia tỉ lệ trước (prescale) hoặc kết hợp với thanh ghi lưu lại số lần Timer1 đếm tràn.

+ Người lập trình dựa vào cờ báo CCPxIF hoặc dựa vào ngắt do CCP để thực hiện các bước tiếp
theo (ví dụ tính toán độ rộng xung …)

GV: Ong Mẫu Dũng – Khoa CNĐT 96


Bài giảng KỸ THUẬT VI XỬ LÝ

c. Khai báo và lập trình chức năng

Ví dụ 1:

Sử dụng nút bấm tạo xung tác động vào chân RC2 (CCP1). Vđk thực hiện chức năng Capture từ
chân CCP1 và đánh dấu kết quả capture được ra PORTD thông qua Led.

#define _XTAL_FREQ 4000000


#include <htc.h>

__CONFIG(0x3FFA);

void main(void)
{
// Configure Capture mode for Timer 1
// 0100 [every falling edge] 0101 [every rising edge]
// 0110 [every 4 rising edge] 0111 [every 16 rising edge]
CCP1M3 = 0 ;
CCP1M2 = 1 ;
CCP1M1 = 1 ;
CCP1M0 = 0 ;

// Clear the flag


CCP1IF = 0 ;

// Configure Capture pin as INPUT mode


TRISC2 = 1 ;

TMR1H = 0;
TMR1L = 0;

GV: Ong Mẫu Dũng – Khoa CNĐT 97


Bài giảng KỸ THUẬT VI XỬ LÝ

TMR1ON = 1;

// Configure PORTD to out led


TRISD = 0x00;
PORTD = 0x00;

while(1)
{
while (!CCP1IF);

CCP1IF = 0;

PORTD = PORTD+1;

TMR1H = 0;
TMR1L = 0;
}
}

void interrupt isr(void) // CCP2 INT Subrouting


{

7.1.3 Khảo sát chế độ Compare

+ Chế độ so sánh (Compare) được dùng cho chức năng lặp thời gian. Chế độ so sánh thay đổi trạng
thái của chân CCPx của vi điều khiển PIC khi nội dung của TMR1 khớp giá trị trong các thanh ghi
CCPRxH và CCPRxL. Chế độ này được dùng kích khởi hay điều khiển phần cứng bên ngoài sau một
trì hoãn cụ thể. Hoặc là dùng để kích hoạt (trigger) một sự kiện đặc biệt bên trong vi điều khiển
(Timer1 và ADC).

a. Tập các thanh ghi liên quan

CCPxM3:CCPxM0: CCPx Mode Select bits trong thanh ghi CCPxCON được sử dụng:

▪ 1000 = compare mode, when a match occurs, the RC2/CCP1 pin is driven HIGH and CCPxIF =1.
▪ 1001 = compare mode, when a match occurs, the RC2/CCP1 pin is driven LOW and CCPxIF =1.
▪ 1010 = compare mode, when a match occurs, the RC2/CCP1 pin remains unchanged, and
CCPxIF =1, and generate software interrupt.
▪ 1011 = compare mode, when a match occurs, the RC2/CCP1 pin remains unchanged, and
CCPxIF =1 and ADC convers (if ADC was enable).

Ngoài ra, Compare sử dụng Timer1 nên tất cả các thanh ghi liên quan đến Timer1 cũng dùng cho
việc thực hiện chế độ Capture.

GV: Ong Mẫu Dũng – Khoa CNĐT 98


Bài giảng KỸ THUẬT VI XỬ LÝ

b. Hoạt động nguyên lý

+ Giá trị cần so sánh với Timer1 được ghi vào thanh ghi 16 bit: CCPR1H:CCPR1L. Chú ý, chân CCPx
của vđk phải được cấu hình là OUTPUT. Timer 1 được bật chạy để bắt đầu so sánh.

+ Tùy theo cấu hình CCPx Mode Select bits, sau khi compare bằng nhau, vđk có thể báo hiệu thông
qua thay đổi chân CCPx hoặc thông qua các sự kiện đặc biệt. Trong tất cả trường hợp, cờ CCPxIF
luôn được set.

+ Người lập trình dựa vào cờ báo CCPxIF hoặc dựa vào ngắt do CCP để thực hiện các bước tiếp
theo (ví dụ: thực hiện ADC, kích hoạt thiết bị khác, …)

c. Khai báo và lập trình chức năng


GV: Ong Mẫu Dũng – Khoa CNĐT 99
Bài giảng KỸ THUẬT VI XỬ LÝ

Ví dụ 2:

Dùng chức năng so sánh của CCP, tạo ra xung tuần hoàn có Ton=Toff=60 ms trên 1 chân VĐK. Biết
rằng, vđk thực hiện chương trình ngắt (Interrupt) khi phát hiện compare bằng nhau.

#define _XTAL_FREQ 4000000


#include <htc.h>
__CONFIG(0x3FFA);
void main(void)
{
// Configure Compare mode for Timer 1
// 1000 [CCP pin default Low, match forces High]
// 1001 [CCP pin default High, match forces Low]
CCP2M3 = 1 ; CCP2M2 = 0 ; CCP2M1 = 0 ; CCP2M0 = 1 ;

// Clear the flag


CCP2IF = 0 ;

// Configure Compare pin as OUTPUT mode


TRISC1 = 0 ;

// Configure Compare value with Timer 1


CCPR2H = 60000/256;
CCPR2L = 60000%256;

// CCP2 interrupt enable


CCP2IE = 1;
PEIE = 1;
GIE = 1;

// Configure Timer 1 as internal timer


T1CON = 0x00 ;
TMR1ON = 1;

// Configure PORTD to out led


TRISD = 0x00;
PORTD = 0x00;
}

void interrupt isr(void) // CCP2 INT Subrouting


{
CCP2IF = 0;
PORTD = PORTD + 1;

TMR1H = 0;
TMR1L = 1;
}

GV: Ong Mẫu Dũng – Khoa CNĐT 100


Bài giảng KỸ THUẬT VI XỬ LÝ

7.1.4. Khảo sát chế độ PWM

+ Chế độ PWM là chế độ chiều chế độ rộng xung (Pulse Width Modulator) sử dụng Timer2.
Phương pháp điều xung là phương pháp điều chỉnh điện áp ra tải, hay nói cách khác, là phương
pháp điều chế dựa trên sự thay đổi độ rộng của chuỗi xung vuông, dẫn đến sự thay đổi điện áp ra.
Các PWM khi biến đổi thì có cùng 1 tần số và khác nhau về độ rộng của sườn dương hay sườn âm.

+ PWM được ứng dụng nhiều trong điều khiển. Điển hình nhất mà chúng ta thường hay
gặp là điều khiển động cơ và các bộ xung áp, điều áp... Sử dụng PWM điều khiển độ nhanh chậm
của động cơ hay cao hơn nữa, nó còn được dùng để điều khiển sự ổn định tốc độ động cơ. + Ngoài
lĩnh vực điều khiển hay ổn định tải thì PWM còn tham gia và điều chế các mạch nguồn như: boot,
buck, nghịch lưu 1 pha và 3 pha... + PWM còn gặp nhiều trong thực tế ở các mạch điện điều khiển.
Điều đặc biệt là PWM chuyên dùng để điều khiển các phần tử điện tử công suất có đường đặc tính
là tuyến tính khi có sẵn 1 nguồn 1 chiều cố định. Như vậy PWM được ứng dụng rất nhiều trong các
thiết bị điện- điện tử.

a. Tập các thanh ghi liên quan

GV: Ong Mẫu Dũng – Khoa CNĐT 101


Bài giảng KỸ THUẬT VI XỬ LÝ

+ CCPxM3: CCPxM0 = 11xx : dùng cho chế độ PWM.

+ Dạng sóng PWM ngõ ra chân CCPx:

+Chu kỳ PWM (Period): được xác định bởi độ lớn của Timer2 kết hợp với 2 bit prescale.

PWM_Period = (PR2+1)*4*Tosc*Timer2_prescale_value

Thông thường, với Thạch anh 4 Mhz, ta có: PWM_period = (PR2+1)* Timer2_prescale_value (uS)

+ Chu kỳ nhiệm vụ (Duty Cycle) : là chu kỳ Ton của PWM, được xác định bởi 10 bit, trong đó 8bit
trọng số cao là thanh ghi CCPR1L, 2bit trọng số thấp còn lại là CCP1CON<5:4>.

PWM_Duty_Cycle = (CCPR1L:CCP1CON<5:4>)*Tosc* Timer2_prescale_value

Thông thường, với Thạch anh 4 Mhz, ta có:

GV: Ong Mẫu Dũng – Khoa CNĐT 102


Bài giảng KỸ THUẬT VI XỬ LÝ

PWM_Duty_Cycle = (CCPR1L:CCP1CON<5:4>)* Timer2_prescale_value/4 (uS)

+ Phần trăm chu kỳ nhiệm vụ: D = (Ton_của_PWM / PWM_Period)*100%

+ Độ phân giải (Resolution): là số lượng bit có thể dùng cho việc tạo ra tín hiệu PWM

b. Hoạt động nguyên lý

▪ Cài đặt PWM_Period bằng cách ghi giá trị tương ứng vào thanh ghi PR2
▪ Cài đặt PWM_Duty_Period bằng cách ghi giá trị tương ứng vào thanh ghi CCPR1L và 2 bit
CCP1CON<5:4> (còn có tên gọi là <CCP1X: CCP1Y>)
▪ Cài đặt chân CCP1 là OUTPUT thông qua bit TRISC<2>.
▪ Cài đặt giá trị cho TMR2-Prescale và cho phép TMR2 đếm (TMR2ON)
▪ Cài đặt chế độ PWM cho module CCP.

c. Khai báo và lập trình chức năng

Ví dụ 3:

Hãy tạo xung PWM trên ngõ ra CCP2, biết rằng PWM có tần số xung 5000 Hz và chu kỳ nhiệm vụ
là 5% chu kỳ xung.

#define _XTAL_FREQ 4000000


#include <htc.h>

__CONFIG(0x3FFA);

void main(void)
{
//Define PWM_period and PWM_duty
unsigned int PWM_freq = 5000 ;
unsigned int PWM_period = 1000000/PWM_freq ;
unsigned char PWM_duty = 5 ;
unsigned int PWM_ON = (PWM_period*PWM_duty)/100 ;

// Configure the CCPxCON for PWM operation


CCP2M3 = 1 ; CCP2M2 = 1 ; CCP2M1 = 1 ; CCP2M0 = 1 ;

// Establish the PWM period by writing to the PR2 register


// PWM period = [(PR2) + 1] • 4 • TOSC • (TMR2 prescale value)
// PWM period = [(PR2) + 1] • (TMR2 prescale value) us with 4Mhz crystal
// Choose TMR2 prescale value=1:1, we have:
PR2 = (char)(PWM_period)-1 ;

// Establish the PWM_ON by writing to the DCxB9:DCxB0 bits


GV: Ong Mẫu Dũng – Khoa CNĐT 103
Bài giảng KỸ THUẬT VI XỬ LÝ

// PWM_ON = (DCxB9:DCxB0 bits value) • Tosc • (TMR2 prescale value)


// because (Tosc =1/4) and (TMR2 prescale value =1),
// PWM_ON = (DCxB9:DCxB0 bits value)/4
// CCPRxL = DCxB9:DCxB2 >> 2 = PWM_ON
// and DCxB1:DCxB0 = CCPxCON<5:4> = <CCP1X: CCP1Y> = PWM_ON % 4 ;
CCPR2L=(char)PWM_ON ;

unsigned char CCPR2L_remain = (char) PWM_ON%4;

switch (CCPR2L_remain)
{
case (0b00):
{
CCP2X=0; // bit CCPxCON<5>
CCP2Y=0; // bit CCPxCON<4>
break;
}
case (0b01):
{
CCP2X=0;
CCP2Y=1;
break;
}
case (0b10):
{
CCP2X=1;
CCP2Y=0;
break;
}
case (0b11):
{
CCP2X=1;
CCP2Y=1;
break;
}
}
// Make the CCPx pin an output by clearing the appropriate TRIS bit
TRISC1=0;
// Establish the TMR2 prescale value and enable Timer2 by writing to T2CON.
T2CKPS1 =0 ;
T2CKPS0 =0 ; // pre-csale 1:1
TMR2ON = 1; // start Timer2 (means PWM)

while(1)
{

}
}

GV: Ong Mẫu Dũng – Khoa CNĐT 104


Bài giảng KỸ THUẬT VI XỬ LÝ

Ví dụ 4:

Hãy tạo xung PWM trên ngõ ra CCP2, biết rằng PWM có tần số xung 5000 Hz và chu kỳ nhiệm vụ
là xx% chu kỳ xung. Với giá trị xx thay đổi được bằng 2 nút ấn trong khoãng 1% đến 99%.

#define _XTAL_FREQ 4000000


#include <htc.h>
__CONFIG(0x3FFA);
unsigned char read_PORTB(void);

void main(void)
{
// Define PWM_period and PWM_duty
unsigned int PWM_freq = 5000 ;
unsigned int PWM_period = 1000000/PWM_freq ;
unsigned char PWM_duty = 5 ;
unsigned int PWM_ON = (PWM_period*PWM_duty)/100 ;

// Configure the CCPxCON for PWM operation


CCP2M3 = 1 ; CCP2M2 = 1 ; CCP2M1 = 1 ; CCP2M0 = 1 ;

// Establish the PWM period by writing to the PR2 register


// PWM period = [(PR2) + 1] • 4 • TOSC • (TMR2 prescale value)
// PWM period = [(PR2) + 1] • (TMR2 prescale value) us with 4Mhz crystal
PR2 = (char)(PWM_period)-1 ;

label_setupPWM:
// Establish the PWM_ON by writing to the DCxB9:DCxB0 bits
// PWM_ON = (DCxB9:DCxB0 bits value) • Tosc • (TMR2 prescale value)
// because (Tosc =1/4) and (TMR2 prescale value =1),
// PWM_ON = (DCxB9:DCxB0 bits value)/4
// CCPRxL = DCxB9:DCxB2 >> 2 = PWM_ON
// and DCxB1:DCxB0 = CCPxCON<5:4> = <CCP1X: CCP1Y> = PWM_ON % 4 ;
CCPR2L=(char)PWM_ON ;

unsigned char CCPR2L_remain = (char) PWM_ON%4;

switch (CCPR2L_remain)
{
case (0b00):
{
CCP2X=0; // bit CCPxCON<5>
CCP2Y=0; // bit CCPxCON<4>
break;
}
case (0b01):
{CCP2X=0; CCP2Y=1; break;}
case (0b10):

GV: Ong Mẫu Dũng – Khoa CNĐT 105


Bài giảng KỸ THUẬT VI XỬ LÝ

{CCP2X=1; CCP2Y=0; break;}


case (0b11):
{CCP2X=1; CCP2Y=1; break;}
}

// Make the CCPx pin an output by clearing the appropriate TRIS bit
TRISC1=0;

// Establish the TMR2 prescale value and enable Timer2 by writing to T2CON.
T2CKPS1 =0 ;
T2CKPS0 =0 ; // TMR2 pre-scale 1:1
TMR2ON = 1; // start Timer2 (means PWM)

while(1)
{
unsigned char key =read_PORTB();
if (key ==8)
{
PWM_duty ++;
if (PWM_duty >=99)
PWM_duty=99;

PWM_ON = (PWM_period*PWM_duty)/100 ;
goto label_setupPWM;
}
else if (key ==7)
{
PWM_duty --;
if (PWM_duty <= 1)
PWM_duty=1;

PWM_ON = (PWM_period*PWM_duty)/100 ;
goto label_setupPWM;
}
}
}

unsigned char read_PORTB(void)


{
TRISB=0xFF;
TRISD=0x00;

unsigned char key = PORTB & 0B11000000;

if (key != 0B11000000)
{
__delay_ms(50);
key = PORTB & 0B11000000;

GV: Ong Mẫu Dũng – Khoa CNĐT 106


Bài giảng KỸ THUẬT VI XỬ LÝ

if (key != 0B11000000)
{
switch (key)
{
case 0B10000000:
{PORTD = 7; return 7; break; }

case 0B01000000:
{PORTD = 8; return 8; break; }

default:
{return 0; break; }
}
}
else return 0;
}
return 0;
}

7.2 ADC

7.2.1. Khảo sát chuyển đổi ADC

+ Để thực hiện đo lường analog thì ta phải cấu hình PIC16F877A thay đổi để làm cho 8 ngõ
I/O số trở thành Analog INPUT từ PORT A và PORT E, để hiển thị giá trị trên led hoặc LCD ta cần
cấu hình 1 PORT B hoặc PORTD là OUTPUT.

+ Độ phân giải lớn nhất của bộ ADC là 10bit. Giả sử rằng ta sử dụng Vref+ Vref- là 5V thì độ
phân giải của ADC là: 4,88 mV.

7.2.2. Tập các thanh ghi liên quan

+ Để cấu hình 16F877A cho đo lường A/D, 3 thanh ghi cần được thiết lập:

▪ ADCON0.
▪ ADCON1.
▪ ADRESH và ADRESL

+ Thanh ghi điều khiển A/D: ADCON0, địa chỉ 1FH, ADCON0 có các chức năng sau:

▪ Bật lên chuyển đổi A/D với ADCON0, bit 0 (ADON). Bit này bật chuyển đổi A/D khi nó được
bật lên 1 và tắt A/D khi nó bị xóa về 0. Khi A/D được bật, nó có thể được để ON (bật) suốt
thời gian nhưng nó lái dòng 90μA, so sánh với phần còn lại của vi điều khiển mà lái dòng
15μA.
▪ Ra lệnh vi điều khiển thực thi chuyển đổi bằng cách bật bit GO/DONE, bit 2. Khi bit
GO/DONE=’1’ thì vi điều khiển thực hiện chuyển đổi A/D. Khi chuyển đổi hoàn thành, phần

GV: Ong Mẫu Dũng – Khoa CNĐT 107


Bài giảng KỸ THUẬT VI XỬ LÝ

cứng xóa bit GO/DONE. Bit này có thể được đọc dùng để chỉ thị kết quả chuyển đổi đã sẵn
sàng để vđk lấy giá trị.
▪ Thiết lập kênh cụ thể (ngõ vào) để thực hiện đo lường. Điều này được thực hiện với 3 bit
chọn kênh CHS0, CHS1 và CHS2, bit 3,4, và 5.
▪ Bit 7 và 6, ADCS1 và ADCS0: 2 bit này được kết hợp thêm với bit ADCS2 trong thanh ghi
ADCON1 dùng cho việc chọn tốc độ clock chuyển đổi A/D.

+ Thanh ghi điều khiển A/D 1: ADCON1, địa chỉ 9FH. Trong ADCON1 có các chức năng sau:

▪ Các bit 0,1,2, và 3 được dùng cấu hình port. <PCFG0, PCFG1, PCFG2 và PCFG3> xác định
chân nào của port A sẽ là ngõ vào analog và chân nào là I/O.
GV: Ong Mẫu Dũng – Khoa CNĐT 108
Bài giảng KỸ THUẬT VI XỬ LÝ

▪ Bit 7, ADFM : bit chọn khuôn dạng kết quả A/D. ADFM =1 kết quả chỉnh phải, 6 bit trong số
cao nhất của ADRESH là đọc là ‘0’. ADFM =0 kết quả chỉnh trái, 6 bit trọng số thấp nhất của
ADRESH là đọc là ‘0’.
▪ Bit 6, ADCS2: bit kết hợp vớ ADCS1, ADCS0 trong ADCON0 dùng chọn clock chuyển đổi A/D.

GV: Ong Mẫu Dũng – Khoa CNĐT 109


Bài giảng KỸ THUẬT VI XỬ LÝ

+ ADRES, thanh ghi kết quả A/D. Đây là các ô nhớ mà kết quả chuyển đổi A/D được lưu trữ. Nếu
nhiều đo lường yêu cầu lưu trữ thì số trong ADRES cần được chuyển tới ô nhớ người dùng trước
khi nó bị đè bởi đo lường kế tiếp. PIC 16F877A có A/D 10 bit, với 8 bit cao được lưu trong ADRESH
và 2 bit thấp hơn được lưu trong ADRESL. Chú ý, bit 7, ADFM trong thanh ghi ADCON1 cấu hình
định dạng kết quả định trái hoặc định phải.

GV: Ong Mẫu Dũng – Khoa CNĐT 110


Bài giảng KỸ THUẬT VI XỬ LÝ

7.2.3 Khai báo và lập trình chức năng

(1) Lựa chọn xung Clock cho quá trình A/D thông qua ADCS2:ADCS1:ADCS0

(2) Cấu hình chân Analog ngõ vào: chọn chân analog INPUT và sử dụng Vref+, Vref- bên trong hay
bên ngoài vđk thông qua PCFG3:PCFG0

(3) Set bit GO\DONE để kích hoạt quá trình chuyển đổi A/D

(4) Đợi 1 khoãng thời gian để quá trình chuyển đổi hoàn thành

(5) Đọc kết quả chuyển đổi

GV: Ong Mẫu Dũng – Khoa CNĐT 111


Bài giảng KỸ THUẬT VI XỬ LÝ

7.3 Ứng dụng của ADC

Ví dụ 5:
Giả thiết có 2 nguồn tín hiệu analog (sóng SIN) đưa vào 2 chân AN1 và AN2.
Hãy dùng module ADC chuyển đổi và hiển thị giá trị mV lên LCD.

#define _XTAL_FREQ 4000000


#define uchar unsigned char
#define uint unsigned int
#define ulong unsigned long
GV: Ong Mẫu Dũng – Khoa CNĐT 112
Bài giảng KỸ THUẬT VI XỬ LÝ

#define dport PORTB


#define dport_in TRISB=0xFF
#define dport_out TRISB=0x00

#define rs RB0
#define rw RB1
#define en RB2

void lcd1602_write_dat(uchar lcd_dat);


void lcd1602_write_string(const uchar *cy);
void lcd1602_write_com(uchar lcd_com);

void adc_init(void);
void adc_channel(uchar channel);
uint adc_converter(void);
void decimal_bcd_16bit(uint cnt);

uchar num_to_char[10]="0123456789";

uchar disbuf[4];
uint count=0;

#include <htc.h>

__CONFIG(0x3FFA);

//*************** main ********************


void main(void)
{
dport_out ;
//DL=0 (Data Line 4bit);N=1 (Number of display line=2);F=0 (Char font 5x7)
lcd1602_write_com(0x28);
//D=1 (Display on);C=1 (Cursor on);B=1 (Blink on);
lcd1602_write_com(0x0F);

lcd1602_write_com(0x80);
lcd1602_write_string("AN1 value: xxxx mV");
lcd1602_write_com(0xC0);
lcd1602_write_string("AN1 value: xxxx mV ");
__delay_ms(3000);

while(1)
{
lcd1602_write_com(0x01); //clear lcd creen

//Display Channel 1
lcd1602_write_com(0x80);

GV: Ong Mẫu Dũng – Khoa CNĐT 113


Bài giảng KỸ THUẬT VI XỬ LÝ

adc_init();
adc_channel(1);
count = adc_converter();
decimal_bcd_16bit(count);

uchar index;
index = disbuf[0];
lcd1602_write_dat(num_to_char[index]);
index = disbuf[1];
lcd1602_write_dat(num_to_char[index]);
index = disbuf[2];
lcd1602_write_dat(num_to_char[index]);
index = disbuf[3];
lcd1602_write_dat(num_to_char[index]);

//Display Channel 2
lcd1602_write_com(0xC0);

adc_init();
adc_channel(2);
count = adc_converter();
decimal_bcd_16bit(count);

index = disbuf[0];
lcd1602_write_dat(num_to_char[index]);
index = disbuf[1];
lcd1602_write_dat(num_to_char[index]);
index = disbuf[2];
lcd1602_write_dat(num_to_char[index]);
index = disbuf[3];
lcd1602_write_dat(num_to_char[index]);
}
}

void lcd1602_write_dat(uchar lcd_dat)


{ // Đã trình bày trong Chương I/O
}
void lcd1602_write_string(const uchar *cy)
{ // Đã trình bày trong Chương I/O
}
void lcd1602_write_com(uchar lcd_com)
{ // Đã trình bày trong Chương I/O
}

void adc_init(void)
{
//AD configure analog INPUT and Vref+, Vref-
PCFG3=0; PCFG2=0; PCFG1=0; PCFG0=0;

GV: Ong Mẫu Dũng – Khoa CNĐT 114


Bài giảng KỸ THUẬT VI XỬ LÝ

// PCF<3..0>: AN7 AN6 AN5 AN4 AN3 AN2 AN1 AN0 VERF+ VREF-
// 0 1 0 0 : A A A A A A A A VDD VSS

TRISA=0b00111111; // config PORTA as INPUT

ADCS2=0;
ADCS1=0;
ADCS0=0; //AD Clock Source --> 1.25 MHz
ADFM=1; //AD result mode: Right Justify [[ADRESH:9,8+ADRESL:7..0]]

ADON=1; //ADC Enable


}

void adc_channel(uchar channel) // Select INPUT 0..7


{
CHS0 = 0; // Clear CHS2:CHS1:CHS0 before use
CHS1 = 0;
CHS2 = 0;
ADCON0|=((channel&0x07)<<3); // using 3 bits CHS2:CHS1:CHS0 = bit5:bit4:bit3
__delay_ms(1); // for stability sampling voltage (Cin)
}

uint adc_converter(void) // Start AD and Convert AD result


{
ulong adc_result; // ADC result with 10bits long

GO_DONE=1; // Force AD starts


while(GO_DONE==1); // Polling GO_DONE, check AD convert complete
ADIF=0; // AD completed, clear the flag

adc_result=ADRESH<<8;
adc_result|=ADRESL; // Combine ADRESH and ADRESL together to adc_result

// Conver adc_result into Voltage value with 5000 mV, 10bit resolution
adc_result=(adc_result*5000)>>10

return(adc_result); // echo result back


}
void decimal_bcd_16bit(uint cnt) // example cnt = abcd
{
disbuf[0]=(cnt/1000)%10; // [0] is a
cnt=cnt%1000; // cnt = bcd
disbuf[1]=(cnt/100)%10; // [1] is b
cnt=cnt%100; // cnt = cd
disbuf[2]=cnt/10; // [2] = c
disbuf[3]=cnt%10; // [3] = d
}

GV: Ong Mẫu Dũng – Khoa CNĐT 115


Bài giảng KỸ THUẬT VI XỬ LÝ

CHƯƠNG 8: TRUYỀN DỮ LIỆU


- Trình bày được cấu trúc và tập lệnh của VĐK PIC và các thanh ghi liên quan đến các Modul
UART, Modul MSSP của VĐK PIC
- Trình bày được nguyên lý hoạt động và điều khiển Modul UART, Modul MSSP của VĐK PIC
ở các chế độ cơ bản của VĐK PIC.
- Xây dựng được mô hình, phân tích và thiết kế, vẽ lưu đồ và lập trình ứng dụng Modul
UART, Modul MSSP của VĐK PIC cho các ứng dụng

8.1 Tổng quan về các kiểu truyền dữ liệu


+ Truyền dữ liệu đồng bộ và không đồng bộ:
USART viết tắt cho Universal Synchronous Asynchronous Receiver Transmitter (Bộ thu phát
đồng bộ/ bất đồng bộ) và cho phép vi điều khiển PIC giao tiếp với một tầm rộng các thiết bị khác
từ chip nhớ riêng biệt và LCD hiển thị tinh thể lỏng, tới máy tính! Điều này bao gồm gửi hay nhận
gói dữ liệu 8 bit hay 9 bit (nghĩa là 1 byte hay 1 byte cộng thêm bit kiểm tra chẵn/lẻ). Bit chẵn lẻ là
bit phụ gửi kèm với dữ liệu mà giúp kiểm tra lỗi. Nếu có 1 số lẻ số 1 trong byte dữ liệu (thí dụ
b’00110100’), bit parity sẽ là 1 và nếu có một số chẵn số 1 (thí dụ b’00110011’) thì bit parity sẽ là 0.
Trong bài giảng này, nếu có lỗi (ví dụ lật bit) diễn ra đâu đó trong giữa lúc gửi 1 byte và nhận nó bit
parity sẽ không còn khớp loại dữ liệu. Bên nhận sẽ biết rằng có gì đó sai sót và nó yêu cầu gửi lại
byte. Nếu có 2 bit lỗi xảy ra trong một việc truyền, bit parity sẽ xuất hiện đúng, tuy nhiên có thể
hai lỗi diễn ra đồng thời là nhỏ hơn, và vì vậy điều này thường bị bỏ qua.
+ Chế độ USART có 2 chế độ (mode) chính: hoạt động đồng bộ và bất đồng bộ. Trong hoạt
động bất đồng bộ, chân phát (TX-transmitter) từ 1 thiết bị được nối với chân thu (RX-Receiver)
của thiết bị kia và dữ liệu được hoán đổi (được gọi là song công-full duplex). Trong chế độ đồng bộ,
xung clock (CK) và đường dữ liệu (DT) là chia sẻ giữa một số thiết bị (một là chủ (master) và một
hay nhiều tớ (Slaves)). Chủ chịu trách nhiệm tạo ra xung clock đồng bộ. Trong cả hai trường hợp,
tốc độ tại đó dữ liệu được gửi bởi bộ phát (và mong đợi bởi bộ thu) được biết đến như là tốc độ
baud.
+ Master Synchronous Serial Port (MSSP) Module: Môđun port nối tiếp đồng bộ chủ là giao
tiếp nối tiếp, có ích cho truyền thông với thiết bị vi điều khiển hay ngoại vi khác. Những thiết bị
ngoại vi này có thể là EEPROM nối tiếp, thanh ghi dịch, bộ hiển thị, bộ chuyển đổi A/D,vv… Mô đun
MSSP có thể hoạt động trong hai chếđộ: Giao tiếp ngọai vi nối tiếp (Serial Peripheral Interface - SPI)
và Mạch tích hợp liên kết (Inter-Integrated Circuit - I2C) .

GV: Ong Mẫu Dũng – Khoa CNĐT 116


Bài giảng KỸ THUẬT VI XỬ LÝ

8.2 Modul UART của VĐK PIC


a. Khảo sát các thanh ghi của truyền dữ liệu UART
+ Có hai thanh ghi để cấu hình/kiểm soát việc nhận và phát dữ liệu: RCSTA và TXSTA. Dữ
liệu mà được đọc thành công được lưu vào thanh ghi RCREG, và dữ liệu mà được gửi đi nên được
đặt trong thanh ghi TXREG. Tốc độ baud được đặt sử dụng thanh ghi SPBRG.
+ Trong chế độ bất đồng bộ, USART lấy kí tự 8 bit hay 9 bit để gửi, và thêm 1 bit bắt đầu
(start bit -bit 0) ở đầu, và bit dừng (stop bit - 1 bit) vào cuối để tạo nên chuỗi 10 hay 11 bit. Điều
này được chuyển vào thanh ghi dịch mà quay bit vào chân phát (TX) . Môđun nhận sẽ liên tục kiểm
tra trạng thái của chân thu RX, mà sẽ bình thường là mức cao. Nếu nó dò thấy chân RX xuống
mức thấp (bit start – bit 0), nó sẽ lấy thêm 3 mẫu trong giữa bit (cho phép lên và xuống chậm các
lần) và lấy giá trị chính của ba . Nếu giá trị chính là 0, nó khẳng định đây thực sự là bit bắt đầu và
tiến hành lấy mẫu các bit tuần tự với 3 mẫu ở giữa mỗi bit. Thời gian của mẫu này được chỉ ra bởi
tốc độ baud. Khi nó đạt đến cái là bit dừng, nó phải đọc bit 1, ngược lại nó sẽ khẳng định kí tự thu
được bị lỗi. Nhớ rằng với thiết lập phù hợp trong TXSTA và RCSTA, tất cả điều này được thực hiện
tự động cho bạn bởi môđun USART.
+ Bạn có thể dùng chế độ bất đồng bộ để giao tiếp với port nối tiếp RS232 trên máy tính PC.
Cách đơn giản để gửi byte thông qua port nối tiếp của PC là sử dụng chương trình đi kèm
Microsoft Windows được gọi là Hyper Terminal. Bạn có thể tạo ra một kết nối với cổng nối tiếp (ví
dụ COM 1), chọn tốc độ baud, số bit, thiết lập parity. Khi Hyper Terminal kết nối với port nối tiếp,
bất kì kí tự mà bạn gõ sẽ được gửi (như là mã ASCII) thông qua port nối tiếp. Kí tự mà được nhận
được hiển thị lên màn hình. Cả hai chế độ đồng bộ và bất đồng bộ hỗ trợ đặc tính được biết như là
dò tìm địa chỉ mà cho phép một số thiết bị được kết nối. Khi gửi dữ liệu, một byte địa chỉ phải
được gửi đi đầu tiên để nhận diện nơi nhận dự định.
+ Bộ tạo tốc độ baud hỗ trợ cả chế độ bất đồng bộ và đồng bộ của USART. Nó là bộ tạo tốc
độ baud 8 bit. Thanh ghi SPBRG (địa chỉ 99H) điều khiển chu kì của bộ định thì 8 bit chạy tự do.
Trong chế độ bất đồng bộ bit BRGH (TXSTA<2>) cũng kiểm soát tốc độ baud. Trong chế độ đồng bộ,
bit BRGH bị bỏ qua. Công thức tính tốc độ baud như sau:

GV: Ong Mẫu Dũng – Khoa CNĐT 117


Bài giảng KỸ THUẬT VI XỬ LÝ

GV: Ong Mẫu Dũng – Khoa CNĐT 118


Bài giảng KỸ THUẬT VI XỬ LÝ

GV: Ong Mẫu Dũng – Khoa CNĐT 119


Bài giảng KỸ THUẬT VI XỬ LÝ

b. Các kiểu truyền dữ liệu UART của VĐK


+ Trong mode kiểu truyền dữ liệu không đồng bộ (UART), USART sử dung dạng NRZ (Non-Return
–to-Zero) chuẩn (một bit bắt đầu(start), 8 hay 9 bit dữ liệu, và một bit dừng(stop)). Dạng dữ liệu
thông dụng nhất là 8 bit. Một bộ tạo tốc độ baud 8 bit có sẵn trên chip có thể được dùng để tạo
tần số tốc độ baud chuẩn từ tần số thạch anh của hệ thống. USART phát và nhận bit LSB trước tiên.
Bộ phát và thu là độc lập chức năng nhưng sử dụng chung dạng dữ liệu và tốc độ baud. Bộ tạo tốc
độ baud tạo ra xung clock, hoặc là x16 hay x64 của tốc độ dịch bit phụ thuộc vào bit BRGH

GV: Ong Mẫu Dũng – Khoa CNĐT 120


Bài giảng KỸ THUẬT VI XỬ LÝ

(TXSTA<2>). Chẵn lẻ (parity) không được hỗ trợ bởi phần cứng nhưng có thể hiện thực bằng phần
mềm (và được lưu như là bit dữ liệu thứ 9). Mode bất đồng bộ bị dừng trong khi Sleep. Mode bất
đồng bộ được chọn bằng cách xóa bit SYNC (TXSTA<4>). Môđun bất đồng bộ USART gồm có các
phần tử quan trọng sau đây:
▪ Bộ tạo tốc độ baud.
▪ Mạch lấy mẫu.
▪ Bộ phát bất đồng bộ .
▪ Bộ thu bất đồng bộ.

+ Khi thiết lập sự phát bất đồng bộ, bạn theo các bước sau:
▪ Khởi động thanh ghi SPBRG cho tốc độ baud phù hợp. Nếu tốc độ baud tốc độ cao là
mong muốn thì ta bật (lên 1) bit BRGH.
▪ Cho phép port nối tiếp bất đồng bộ bằng cách xóa bit SYNC và bật bit SPEN.
▪ Nếu ngắt là mong muốn, thì ta bật bit cho phép TXIE.
▪ Nếu sự truyền 9 bit là mong muốn, thì ta bật bit truyền TX9.
▪ Cho phép truyền bằng cách bật bit TXEN mà sẽ bật bit TXIF.

GV: Ong Mẫu Dũng – Khoa CNĐT 121


Bài giảng KỸ THUẬT VI XỬ LÝ

▪ Nếu sự truyền 9 bit được chọn, bit thứ 9 sẽ được nạp vào bit TX9D.
▪ Kiểm tra bộ nhớ đệm (thanh ghi dịch – bit TRMT)đang trống trước khi nạp dữ liệu truyền
▪ Nạp dữ liệu vào thanh ghi TXREG (bắt đầu truyền).
▪ Nếu dùng ngắt, đảm bảo rằng GIE và PEIE (bit 7 và 6) của thanh ghi INTCON được bật.
+ Các thanh ghi được dùng trong phát bất đồng bộ USART:

+ Dữ liệu được nhận trên chân RC7/RX/DT và đến khối phục hồi dữ liệu. Khối khôi phục dữ liệu
thực chất là bộ dịch tốc độ cao, hoạt động ở 16x tốc độ baud, trong khi bộ dịch nối tiếp thu chính
hoạt động ở tốc độ bit hay Fosc.
+ Khi thiết lập sự thu bất đồng bộ, bạn theo các bước sau:
▪ Khởi động thanh ghi SPBRG cho tốc độ baud phù hợp. Nếu tốc độ baud tốc độ cao được
chọn, thì ta bật bit BRGH.
▪ Cho phép port nối tiếp bất đồng bộ bằng cách xóa bit SYNC và bật bit SPEN.
▪ Nếu ngắt là mong muốn, thì ta bật bit cho phép RCIE.
▪ Nếu sự nhận 9 bit là mong muốn, thì ta bật bit RX9.
▪ Cho phép nhận bằng cách bật bit CREN.
▪ Bit cờ RCIF được bật (=1) khi sự nhận hoàn thành và ngắt sẽ tạo ra nếu bit cho phép RCIE
được bật.
▪ Đọc thanh ghi RCSTA để nhận bit thứ 9 (nếu cho phép) và xác định xem có lỗi nào xảy ra
trong quá trình nhận (thu).
▪ Đọc dữ liệu nhận 8 bit bằng cách đọc thanh ghi CRREG.
▪ Nếu có lỗi xảy ra, xoá lỗi bằng cách xóa bit cho phép CREN.
▪ Nếu dùng ngắt, đảm bảo rằng GIE và PEIE (bit 7 và 6) của thanh ghi INTCON được bật.

GV: Ong Mẫu Dũng – Khoa CNĐT 122


Bài giảng KỸ THUẬT VI XỬ LÝ

+ Các thanh ghi được dung trong phát bất đồng bộ USART:

GV: Ong Mẫu Dũng – Khoa CNĐT 123


Bài giảng KỸ THUẬT VI XỬ LÝ

c. Ứng dụng truyền dữ liệu UART


Ví dụ 1:
Viết chương trình cho vđk phát một chuỗi ký tự dùng kiểu truyền bất đồng bộ 8 bit (UART). Khi vđk
nhận 1 ký tự (dùng phương pháp ngắt) thì sẽ hồi âm (feedback/echo) chính ký tự vừa nhận được.

#define _XTAL_FREQ 4000000

#define uchar unsigned char


#define uint unsigned int
#define ulong unsigned long

#include <htc.h>
__CONFIG(0x3FFA);

void senddata_uart(uchar cdd);


void sendstring_uart(const uchar *dd);

//*************** main ********************


void main(void)
{
SYNC=0; // uart mode
BRGH=1; // hi-speed mode
SPBRG=25; // 9600 baud with 4Mhz crytal
SPEN=1; // Enable serial port
TRISC7=1; // Rx - Input
TRISC6=0; // Tx - Output
TXEN=1; // Enable Tx
CREN=1; // Enable Continue Receive
GIE=1; // Enable Interrupt Receive
PEIE=1;
RCIE=1;

GV: Ong Mẫu Dũng – Khoa CNĐT 124


Bài giảng KỸ THUẬT VI XỬ LÝ

sendstring_uart("***string 1****\r\n");
sendstring_uart("***STRING 2****\r\n");
sendstring_uart("***STRING 3****\r\n");
sendstring_uart("\r\n"); // \r\n means new lines

while(1)
{

}
}

//********************* INTTERUPT *****************


void interrupt isr(void)
{
uchar cd;

if(RCIE&&RCIF) // map with Rx UART Int


{
cd=RCREG; // read byte to cd

while(!TRMT); // wait until reading complete


TXREG= cd; // echo read byte back to UART sender

TRISD = 0;
PORTD = cd; // display received byte to 8 led
}
}

//****************** UART send Subroutin *******************


void senddata_uart(uchar cdd)
{
while(!TRMT); // wait for free buffer
TXREG=cdd;
}

//************************UART send one string**************


void sendstring_uart(const uchar *dd)
{
while((*dd)!=0)
{
senddata_uart(*dd);
dd++;
}
}

d. Giao tiếp truyền dữ liệu giữa máy tính và VĐK theo kiểu truyền UART.
+ Sử dụng lại chương trình truyền/nhận ký tự như trên để giao tiếp UART với máy tính.

GV: Ong Mẫu Dũng – Khoa CNĐT 125


Bài giảng KỸ THUẬT VI XỬ LÝ

e. Kiểu truyền dữ liệu đồng bộ USRT:


+ Trong mode chủ đồng bộ, dữ liệu được truyền theo cách bán song công (half-
duplex)(nghĩa là phát và thu không diễn ra cùng một thời điểm). Khi phát dữ liệu, sự nhận (thu) bị
cấm và ngược lại. Mode đồng bộ đưa vào bằng cách bật bit, SYNC(TXSTA<4>). Hơn nữa, bit cho
phép SPEN (RCSTA<7>) được bật (=1) để cấu hình chân RC6/TX/CK và RC7/RX/DT tới đường CK
(clock) và DT (dữ liệu-data) tương ứng. Mode chủ chỉ ra rằng bộ xử lí phát clock chủ trên đường CK.
Mode chủ được đưa vào bằng cách bật bit CSRC (TXSTA<7>).
+ Việc thu phát đồng bộ giống như thu phát không đồng bộ.

8.3 Modul MSSP


8.3.1 SPI
a. Truyền dữ liệu SPI.
+ Giao tiếp SPI được hãng motorola giới thiệp ở giữa năm 1980 và được sử dụng trong các
dòng vi điều khiển của họ. Ngày nay giao tiếp SPI được sử dụng phổ biến để giao tiếp với các vi
điều khiển, eeprom, IC thời gian thực...
+ SPI là giao thức nối tiếp đồng bộ đa mục đích (general-purpose synchronous serial
interface), trong khi thực hiện giao tiếp SPI dữ liệu truyền và nhận được diễn ra một các đồng thời.
Một xung clock đồng bộ (Synchronous Clock – SCK) dùng để dịch và lấy mẫu thông tin trên hai
đường dữ liệu. Thiết bị giao tiếp SPI sử dụng mối quan hệ master- slaver (chủ-tớ), do thiết bị tớ
không được định địa chỉ nên khi giao tiếp một master với nhiều slaver ta cần đường chọn chíp CS,
để chọn slave nào cần truyền nhận dữ liệu. Vậy số bus cho giao tiếp này là 3 + (1....n) dây.
+ Chế độ SPI cho phép 8 bit dữ liệu được phát đồng bộ và nhận đồng thời. Tất cả 4 chế độ
của SPI được hỗ trợ. Để hoàn thành truyền thông, ba chân tiêu biểu được dùng:
▪ Dữ liệu ra nối tiếp (Serial Data Output -SDO)-RC5/SDO.
▪ Dữ liệu vào nối tiếp (Serial Data Input -SDI)-RC4/SDI/SDA.
▪ Clock nối tiếp (Synchronous Clock -SCK)-RC3/SCK/SCL.
▪ Trong trường hợp vđk hoạt động ở chế độ Slave, Slave Select (SS) – RA5/AN4/SS/C2OUT
cần thêm vào để sử dụng cho việc chọn thiết bị Slave.
+ Sơ đồ khối của môđun MSSP khi hoạt động ở chế độ SPI:

GV: Ong Mẫu Dũng – Khoa CNĐT 126


Bài giảng KỸ THUẬT VI XỬ LÝ

b. Khảo sát các thanh ghi của truyền dữ liệu SPI.


+ Có 4 thanh ghi được sử dụng cho SPI:
▪ MSSP Control Register (SSPCON)
▪ MSSP Status Register (SSPSTAT)
▪ Serial Receive/Transmit Buffer Register (SSPBUF)
▪ MSSP Shift Register (SSPSR) – Not directly accessible
+ Các bước thực hiện cho việc truyền/ nhận dữ liệu SPI
▪ Master mode (SCK is the clock output)
▪ Slave mode (SCK is the clock input)
▪ Clock Polarity (Idle state of SCK)
▪ Data Input Sample Phase (middle or end of data output time)
▪ Clock Edge (output data on rising/falling edge of SCK)
▪ Clock Rate (Master mode only)
▪ Slave Select mode (Slave mode only)
+ Chú ý, việc cấu hình các thông số phải đồng bộ giữa master và các slave: ví dụ như: Clock
Polarity, Clock Edge, Clock Rate…

GV: Ong Mẫu Dũng – Khoa CNĐT 127


Bài giảng KỸ THUẬT VI XỬ LÝ

+ Như đã giới thiệu, Module MSSP của PIC có 2 thanh ghi chức năng Truyền/Nhận là Thanh
ghi-dịch SSPSR và thanh ghi đệm SSPBUF. SSPSR sẽ dịch chuyển data vào hoặc ra khỏi thiết bj, bit
MSB trước. SSPBUF sẽ giữ dữ liệu mà dữ liệu này đã được ghi vào SSPSR cho đến khi nhận được
byte dữ liệu kế tiếp. Nếu SSPBUF đã nhận đủ 8 bit dữ liệu thì bit BF (Buffer Full detect bit) và SSPIF
(Interrupt Flag bit) của thanh ghi SSPSTAT được set. Bất cứ việc ghi/đọc dữ liệu trong thanh ghi
SSPBUF trong qua trình truyền/nhận đều bị cấm và bit WCOL sẽ được set lên 1. Bit này cần được
xóa để nếu dữ liệu tiếp theo được ghi vào SSPBUF hoàn tất thành công.
+ Cần phải đọc dữ liệu trong SSPBUF ngay sau khi nhận về để cho phép các dữ liệu tiếp
theo được ghi vào. Bit BF sẽ cho biết khi nào SSPBUF đầy dữ liệu (quá trình truyền hoàn tất). Khi ta
đọc giá trị trong thanh ghi SSPBUF, bit BF sẽ được xóa.
+ Một cách tổng quát, Ngắt của Module MSSP thường dùng để xét xem quá trình truyền/
nhận xong hay chưa. Nếu bit SSPIF = 1 thì chứng tỏ quá trình truyền nhận đã hoàn tất. Ngược lại,
nếu bit SSPIF = 0 thì quá trình chưa hoàn thành.
* Tập hợp các thanh ghi liên quan đến module SPI:

GV: Ong Mẫu Dũng – Khoa CNĐT 128


Bài giảng KỸ THUẬT VI XỬ LÝ

GV: Ong Mẫu Dũng – Khoa CNĐT 129


Bài giảng KỸ THUẬT VI XỬ LÝ

+ Cực tính của xung SCK được chọn bằng cách thao tác lên bit CKP (SSPCON1). Dạng sóng của giao
tiếp SPI được biểu diễn như hình bên dưới với bit MSB được truyền đi trước. Ở Master Mode, tốc
độ xung SCK của giao tiếp SPI được chọn một trong số 4 tùy chọn sau:
▪ Fosc/4 ( hoặc Tcy)
▪ Fosc/16 (hoặc 4 - Tcy)
▪ Fosc/64 (hoặc 16 – Tcy)
▪ Timer2 output/2
+ Hình sau cho thấy dạng sóng của SPI Master Mode.
GV: Ong Mẫu Dũng – Khoa CNĐT 130
Bài giảng KỸ THUẬT VI XỬ LÝ

+ PIC ở mode slave spi:


- Ở chế độ Slave, dữ liệu chỉ được truyền đi hay nhận về khi có xung SCK. Khi bit cuối cùng đã
được chốt, cờ ngắt SSPIF sẽ được set.
- Trước khi cho phép PIC hoạt động ở Slave Mode ta cần phải chú ý đến xung SCK. Xung clock
phải khớp với trạng thái nghỉ của xung SCK. Trạng thái nghỉ được lựa chọn bằng việc thao
tác lên bit CKP.
- Trong khi đang ở SPI Slave Mode, xung clock cần thiết cho việc trao đổi dữ liệu được lấy từ
chân SCK. PIC có thể truyền/ nhận trong lúc đang sleep (trạng thái tiết kiệm năng lượng).
Nếu có 1 byte dữ liệu được nhận thì PIC sẽ wake-up (trạng thái hoạt động).
+ Thiết bị slave tự động lựa chọn sự đồng bộ hóa:
- Chân Slave Select (SS) cho phép đồng bộ hóa ở chế độ SPI Slave. Do đó, nếu đặt cấu hình
hoạt động ở chế độ Slave thì ta nên cho phép chân SS để điều khiển (đặt các bit SSPCON1 =

GV: Ong Mẫu Dũng – Khoa CNĐT 131


Bài giảng KỸ THUẬT VI XỬ LÝ

0x04). Khi chân SS được đưa xuống mức thấp, sự truyền/ nhận dữ liệu được cho phép và
chân SDO sẽ được thúc để tải dữ liệu. Khi chân SS được đưa lên mức cao, chân SDO sẽ
không được thúc nữa, dữ liệu sẽ không được lưu thông.
- Nếu SPI Slave Mode có chân SS điều khiển được kích hoạt, thì mô-đun SPI sẽ reset khi chân
SS được đưa lên Vdd. Lúc này bit counter bị xóa về ‘0’. Ta cũng có thể xóa bit counter bằng
cách xóa bit SSPEN.
- Cần phải sử dụng chân SS nếu như SPI Slave Mode được dùng với bit CKE được set.

GV: Ong Mẫu Dũng – Khoa CNĐT 132


Bài giảng KỸ THUẬT VI XỬ LÝ

d. Ứng dụng truyền dữ liệu SPI,


Ví dụ 2:
Sử dụng Module SPI như là công cụ mở rộng Port I/O cho vđk bằng cách giao tiếp SPI out với IC
thanh ghi dịch chốt 74LS595.
GV: Ong Mẫu Dũng – Khoa CNĐT 133
Bài giảng KỸ THUẬT VI XỬ LÝ

#define _XTAL_FREQ 4000000


#define uchar unsigned char
#define uint unsigned int
#define ulong unsigned long
#include <htc.h>
__CONFIG(0x3FFA);

uchar byte_send = 0;
void spi_send_byte(uchar dd);
//*************** main ********************
void main(void)
{
SSPM3=0;
SSPM2=0;
SSPM1=0;
SSPM0=0; // SPI rate = Fosc/4

CKP=0; // rising edge with Low state


CKE=1;

SMP=0; // sampling data at the middle bit

TRISC3=0; // RC3/SCK
TRISC4=1; // RC4/SDI
TRISC5=0; // RC5/SDO

TRISC0=0; //RC0 control latch (L to H) data output 74595


RC0=0;

SSPEN=1; // enable SPI operation


WCOL = 0 ; // Init no SSPBUF collision at the begining

while(1)
GV: Ong Mẫu Dũng – Khoa CNĐT 134
Bài giảng KỸ THUẬT VI XỬ LÝ

{
spi_send_byte(byte_send);
byte_send ++;
__delay_ms(500);
}
}

//********************* INTTERUPT *****************


void interrupt isr(void)
{
}

void spi_send_byte(uchar dd)


{
while (WCOL) ; //Check the SSPBUF collision
SSPBUF = dd;
while(!SSPIF);
SSPIF = 0;

RC0=0; // Latch data to output for 74595


RC0=1;
}

Chú ý: Việc thiết lập các thông số SPI cho vđk phụ thuộc vào giản đồ xung 74LS595 như sau:

GV: Ong Mẫu Dũng – Khoa CNĐT 135


Bài giảng KỸ THUẬT VI XỬ LÝ

Ví dụ 3:
Gửi ký tự từ PIC SPI master đến PIC SPI slave, ký tự Slave thu được sẽ truyền đi qua kênh truyền
UART để hiển thị (ví dụ UART monitor)

#define _XTAL_FREQ 4000000


#define uchar unsigned char
#define uint unsigned int
#define ulong unsigned long
#include <htc.h>
__CONFIG(0x3FFA);

void senddata_uart(uchar cdd);


void sendstring_uart(const uchar *dd);

void spi_send_byte(uchar dd);


uchar byte_send = '0';
uchar recv_byte ;
//*************** main ********************
void main(void)
{
SYNC=0; // uart mode
BRGH=1; // hi-speed mode
SPBRG=25; // 9600 bps with 4Mhz crytal
SPEN=1; // Enable serial port
TRISC7=1; // Rx - Input
TRISC6=0; // Tx - Output
TXEN=1; // Enable Tx
CREN=1; // Enable Continue Receive

SSPM3=0; SSPM2=1; SSPM1=0; SSPM0=0; // SPI slave mode


SSPIE=1; // Enable received Interrupt
GV: Ong Mẫu Dũng – Khoa CNĐT 136
Bài giảng KỸ THUẬT VI XỬ LÝ

CKP=0; // rising edge with Low state


CKE=1;

SMP=0; // sampling data at the middle bit

TRISC3=1; // RC3/SCK
TRISC4=1; // RC4/SDI
TRISC5=0; // RC5/SDO

SSPEN=1; // enable SPI operation


WCOL = 0 ; // Init no SSPBUF collision at the begining

while(1)
{ }
}
//********************* INTTERUPT *****************
void interrupt isr(void)
{
if(SSPIE&&SSPIF) // map with SSP Int
{
SSPIF=0;
recv_byte = SSPBUF;
senddata_uart (recv_byte);
}
}
//****************** UART send Subroutin *******************
void senddata_uart(uchar cdd)
{
while(!TRMT); // wait until writing complete
TXREG=cdd;
}
//************************UART send one string**************
void sendstring_uart(const uchar *dd)
{
while((*dd)!=0)
{
senddata_uart(*dd);
dd++;
}
}
//****************** SPI send Subroutin *******************
void spi_send_byte(uchar dd)
{
while (WCOL) ; //Check the SSPBUF collision
SSPBUF=dd;
}
8.3.2. I2C

GV: Ong Mẫu Dũng – Khoa CNĐT 137


Bài giảng KỸ THUẬT VI XỬ LÝ

a. Giới thiệu.
+ Viết tắt của Inter-Intergrated Circuit – là một bus nối tiếp do Philip phát triển. Trước đây
I2C chủ yếu được dùng trong việc chế tạo các hệ thống điện tử sử dụng chip của Philip. Ngày nay
I2C được sử dụng rộng rãi trong việc kết nối các thiết bị ngoại vi tốc độ thấp vào các mạch tích hợp.
b. Tổng quan về truyền dữ liệu I2C.
+ I2C sử dụng 2 đường truyền tín hiệu 2 chiều (một đường clock và một đường data), sử dụng
hiệu điện thế 5V và cùng được kéo lên cao (pull-ups) bằng điện trở. Hai chân được dung cho
truyền dữ liệu:
▪ Clock nối tiếp (SCL)-RC3/SCK/SCL.
▪ Dữ liệu nối tiếp (SDA)-RC4/SDI/SDA.
+ I2C hoạt động theo nhiều mode: mode chuẩn (standard mode) hoạt động ở tốc độ 100kbit/s,
mode tốc độ thấp (low-speed mode) hoạt động ở tốc độ 10kbit/s. Tần số clock có thể cho xuống 0.
+ I2C có sử dụng 7 bit để định địa chỉ, do đó trên một bus có thể có 112 nút (16 địa chỉ được sử
dụng vào mục đích riêng).
+ Điểm mạnh của I2C là ở chỗ, một vi điều khiển có thể dùng để điều khiển cả một mạng thiết
bị mà chỉ tốn 2 chân của vi điều khiển. Chính vì nguyên nhân đó mà I2C và SPI là hai chuẩn giao
tiếp được sử dụng nhiều nhất trong các IC đặc biệt là các VĐK 8 bít.
+ Giao tiếp I2C hỗ trợ các chế độ sau trong phần cứng:
▪ Chế độ chủ (master mode).
▪ Chế độ đa (nhiều) chủ (multi master mode).
▪ Chế độ tớ (slave mode).
c. Quy trình truyền dữ liệu I2C.
+ Để truyền và nhận dữ trong I2C tạo thành khối, người ta dùng các bít Stop, Start, Restart,
ACK, NACK.
+ Quá trình hoạt động các bit này khá giống nhau đẻ bắt đầu phát đi: ta phải set bit tưong
ứng trong thanh ghi đó đi (VD: muốn gửi bít Stop đi ta chỉ cần PEN =1), tương tự với các bit còn lại
và khi đã truyền xong rồi thì các bit đó sẽ tự động chuyển về 0 ( thông qua Hardware).
+ Lưu ý, quá trình hoạt động này chỉ có tác dụng khi mà I2C đã hoàn thành xong nhiệm vụ
trước đó. Như vậy ta cần phải biết được lúc nào chương trình đã hoàn thành xong nhiệm vụ và
đây chính là vai trò của cờ SSPIF trong thanh ghi PIR1, SSPIF báo cho vđk biết là hoạt động đã kết
thúc bằng cách Set từ 0 lên 1 và ta phải xoá cờ này băng phần mềm cho các hoạt động tiếp theo.

GV: Ong Mẫu Dũng – Khoa CNĐT 138


Bài giảng KỸ THUẬT VI XỬ LÝ

Do yêu cầu I2C là: khi hoạt động này kết thúc, thì mới cho phép hoạt động kia bắt đầu chính yêu
cầu này đặt ra chúng ta phải có một chương trình con báo hiệu khi kết thúc một hoạt động.
+ Quá trình truyền một byte dữ liệu từ Master qua slave ( transmit), để truyền một byte dữ
liệu gồm có các bước cơ bản:
▪ Gửi bít Start từ Master tới slave, đợi cho đến khi truyền xong.
▪ Gửi địa chỉ của slave lên đường truyền. Dùng để chọn Slave nào hoạt động. Đợi cho đến khi
truyền xong.
▪ Gửi địa chỉ cần lưu dữ liệu tới, đợi cho đên khi truyền xong.
▪ Gửi dữ liệu cần truyền tới Slave, đợi cho đến khi truyền xong.
▪ Tiếp tục gửi dữ liệu ......
▪ Khi muốn kết thúc gửi bít Stop lên đường truyền.
+ Quá trình nhận dữ liệu từ slave phải tuân thủ theo các bước sau:
▪ Gửi bít Start từ Master tới slave. Đợi cho đến khi truyền xong
▪ Gửi địa chỉ của slave (chú ý: bit 0 = 0 ) lên đường truyền. Dùng để chọn Slave nào hoạt
động, Đợi cho đến khi truyền xong
▪ Gửi địa chỉ của dữ liệu cần nhận Đợi cho đên khi truyền xong
▪ Gửi bit Restart, Đợi cho đến khi truyền xong
▪ Gửi địa chỉ của slave lên đường truyền ( chú ý, bit 0 =1 báo rằng hoạt động sắp tới là read).
Đợi cho đến khi truyền xong
▪ Đọc dữ liệu từ Slave . Đợi cho đên khi đọc xong
▪ Phát bít ACK báo tiếp tục nhận dữ liệu . Đợi cho đến khi truyền xong
▪ Đọc dữ liệu từ Slave . Đợi cho đên khi đọc xong
▪ Phát bít ACK báo tiếp tục nhận dữ liệu . Đợi cho đên khi truyền xong
▪ ........(Lập lại đến khi đủ dữ liệu cần đọc)...........
▪ Đọc dữ liệu từ Slave . Đợi cho đên khi đọc xong
▪ Phát bít NACK báo rằng qua trình nhận dữ liệu đã kết thúc . Đợi cho đên khi truyền xong
▪ Phát bít Stop để kết thúc
d. Khảo sát dạng sóng truyền dữ liệu I2C.

GV: Ong Mẫu Dũng – Khoa CNĐT 139


Bài giảng KỸ THUẬT VI XỬ LÝ

GV: Ong Mẫu Dũng – Khoa CNĐT 140


Bài giảng KỸ THUẬT VI XỬ LÝ

GV: Ong Mẫu Dũng – Khoa CNĐT 141


Bài giảng KỸ THUẬT VI XỬ LÝ

GV: Ong Mẫu Dũng – Khoa CNĐT 142


Bài giảng KỸ THUẬT VI XỬ LÝ

e. Khảo sát các thanh ghi của truyền dữ liệu.


+ Trong Pic 16F87x có 3 thanh ghi điều khiẻn quá trình truyền và nhận dữ liệu: đó là
SSPSTAT ( 94h bank 1), SSPCON1 ( 14H bank 0) và SSPCON2 ( 91H bank 1 ). Trong đó thì:

▪ SMP chọn Speed chuẩn (SMP =1: 100kHz, 1MHz; SMP =0: 400KHz)
▪ R/W báo rằng quá trình truyền vẫn đang diễn ra
▪ BF báo rằng SSPBUF vẫn đang đầy ( trong cả hai trường hợp Transmit, Receive )

▪ WCOL: báo rằng có sự xếp chông dữ liệu


▪ SSPEN: enable chế độ I2C
▪ SSPM3:SSPM0: chọn chế độ với chế độ I2C master: là '1000'

▪ ACKSTAT: Bít ACK được nhận từ Slave ( =0, chỉ dùng trong Transmit )
▪ ACKDT, ACKEN: dùng để phát bít ACK hay NACK từ Master ( trong chế độ Receive ACKDT =0
là ACK, ACKDT =1 là NACK )
▪ RCEN : tín hiêu báo hiệu quá trình nhân ( chỉ dùng trong Receive: khi RCEN = 1, Master
nhận tín hiệu từ Slave )
▪ PEN, RSEN, SEN: bit khởi tạo quá trình truyền Stop, Restart, Start
+ Để điều khiển tốc độ baud của chế độ, người ta sử dụng thanh ghi SSPADD. I2C làm việc ở 3
chế độ chuẩn ( tất nhiên chỉ tương đối ) : 100Kb, 400Kb, 1Mb. Nếu ta dùng thạch anh 4M, và cần
sử dụng tốc độ 100Kb ta phải nạp giá trị vào thanh ghi SSPADD là: 28H với tốc độ 400Kb ta cần giá
trị là 0AH. Còn để lưu và nhận dữ liệu người ta dùng thanh ghi SSPBUF.
+ Như vây tổng cộng có cả thẩy 5 thanh ghi được dùng đến : SSPSTAT, SSPCON1, SSPCON2
( chọn chế độ và đỉều khiển đường truyền ) SSPADD ( khởi tạo tốc độ Baud ) và SSPBUF dùng để
lưu dữ liệu trong hai quá trình Receive, và Transmister.
GV: Ong Mẫu Dũng – Khoa CNĐT 143
Bài giảng KỸ THUẬT VI XỬ LÝ

f. Khảo sát các thiết bị ngoại vi dùng chuẩn truyền I2C.


Ví dụ 4:
Giao tiếp I2C giữa PIC với EEROM 24c02. PIC thực hiện Write ký tự lên ROM, sau đó Read ký tự vừa
Write lên ROM.

GV: Ong Mẫu Dũng – Khoa CNĐT 144


Bài giảng KỸ THUẬT VI XỬ LÝ

#define _XTAL_FREQ 4000000


#define uchar unsigned char
#define uint unsigned int
#define ulong unsigned long
#include <htc.h>
__CONFIG(0x3FFA);

void senddata_uart(uchar cdd);


void sendstring_uart(const uchar *dd);

void WaitMSSP(void);
void STARTBit(void);
void RESTARTBit(void);
void STOPBit(void);
void ACKBit(void);
void NACKBit(void);

GV: Ong Mẫu Dũng – Khoa CNĐT 145


Bài giảng KỸ THUẬT VI XỬ LÝ

uchar write_iic_24c02(uchar address,uchar ddt);


uchar read_iic_24c02(uchar address);

uchar LC01CTRLIN=0xA0 ; // I2C value for CONTROL BYTE when Writing 24c02
uchar LC01CTRLOUT=0xA1 ; // I2C value for CONTROL BYTE when Reading 24c02
uchar LC01ADDR=0x00 ; // Sample value for ADDRESS BYTE
uchar LC01DATA=0x10 ; // Sample data to write to EEPROM

uchar write_iic_return;
uchar read_iic_return;
//*************** main ********************
void main(void)
{
SYNC=0; // uart mode
BRGH=1; // hi-speed mode
SPBRG=25; // 9600 bps with 4Mhz crytal
SPEN=1; // Enable serial port
TRISC7=1; // Rx - Input
TRISC6=0; // Tx - Output
TXEN=1; // Enable Tx
CREN=1; // Enable Continue Receive
GIE=1;
PEIE=1;
RCIE=1;

__delay_ms(1000);

sendstring_uart("Debug and Display results:\r\n");


sendstring_uart("\r\n");

// *** Setup Registers for I2C ***//


// Configure MSSP module for Master Mode
TRISC3=1; // RC3(SCL)
TRISC4=1; // RC4(SDA)
SSPCON=0B00101000; //I2C Master mode with bit_rate=Fosc/(4*(SSPADD+1))
// and I2C enable
SMP=1; //slew rate control, using bit_rate at 100 kbps
SSPADD=0x0A;

while(1)
{
write_iic_return = write_iic_24c02(LC01ADDR,LC01DATA);

if (write_iic_return == 0)
sendstring_uart("Write IIC pass \r\n");
else if (write_iic_return == 1)
sendstring_uart("Write IIC fail at Write_command \r\n");
else if (write_iic_return == 2)

GV: Ong Mẫu Dũng – Khoa CNĐT 146


Bài giảng KỸ THUẬT VI XỬ LÝ

sendstring_uart("Write IIC fail at WORD_ADDR \r\n");


else if (write_iic_return == 3)
sendstring_uart("Write IIC fail at DATA TX \r\n");

read_iic_return = read_iic_24c02(LC01ADDR);

if (read_iic_return > 10)


sendstring_uart("Read IIC pass \r\n");
else if (read_iic_return == 1)
sendstring_uart("Read IIC fail at Write_command \r\n");
else if (read_iic_return == 2)
sendstring_uart("Read IIC fail at WORD_ADDR \r\n");
else if (read_iic_return == 3)
sendstring_uart("Read IIC fail at READ_command \r\n");
else if (read_iic_return == 4)
sendstring_uart("Read IIC fail at DATA RX \r\n");

LC01ADDR ++;
LC01DATA ++;

if (LC01ADDR == 0xFF)
{
sendstring_uart("Write and Read all data to IIC ...\r\n");
while (1);
}
}
}

//********************* INTTERUPT *****************


void interrupt isr(void)
{
uchar cd;

if(RCIE&&RCIF) // map with Rx UART Int


{
cd=RCREG; // read byte to cd

while(!TRMT); // wait until reading complete


TXREG= cd; // echo read byte back
}
}

//****************** UART send Subroutin *******************


void senddata_uart(uchar cdd)
{
while(!TRMT); // wait until writing complete
TXREG=cdd;
}

GV: Ong Mẫu Dũng – Khoa CNĐT 147


Bài giảng KỸ THUẬT VI XỬ LÝ

//************************UART send one string**************


void sendstring_uart(const uchar *dd)
{
while((*dd)!=0)
{
senddata_uart(*dd);
dd++;
}
}

//**************I2C with 24C02 EEROM condition**************


void WaitMSSP(void)
{
while (!SSPIF) ;
SSPIF = 0 ;
}

void STARTBit(void)
{
SEN = 1 ;
WaitMSSP ();
}

void RESTARTBit(void)
{
RSEN = 1 ;
WaitMSSP ();
}

void STOPBit(void)
{
PEN = 1 ;
WaitMSSP ();
}

void ACKBit(void)
{
ACKDT = 0 ;
ACKEN = 1 ;
WaitMSSP ();
}

void NACKBit(void)
{
ACKDT = 1;
ACKEN = 1;
WaitMSSP ();
}

GV: Ong Mẫu Dũng – Khoa CNĐT 148


Bài giảng KỸ THUẬT VI XỬ LÝ

//****************************I2C write to EEROM 24C02************************


uchar write_iic_24c02(uchar address,uchar ddt)
{
STARTBit (); // Always with Start condition

SSPBUF=LC01CTRLIN; // WRITE command


WaitMSSP ();
if (ACKSTAT==1) return 1;
SSPBUF=address; // ROM Address wanna to write to
WaitMSSP ();
if (ACKSTAT==1) return 2;
SSPBUF=ddt; // Value wanna to write to
WaitMSSP ();
if (ACKSTAT==1) return 3;

STOPBit (); // Always end with Stop condition


return 0;
}

//***************************I2C read from EEROM24c02************************


uchar read_iic_24c02(uchar address)
{
uchar ddt;

RESTARTBit (); // Always with Start or Restart condition

SSPBUF=LC01CTRLIN; // WRITE command


WaitMSSP ();
if (ACKSTAT==1) return 1;
SSPBUF=address; // ROM Address wanna to read from
WaitMSSP ();
if (ACKSTAT==1) return 2;

RESTARTBit (); // Always with Restart condition

SSPBUF=LC01CTRLOUT; // READ command


WaitMSSP ();
if (ACKSTAT==1) return 3;
RCEN = 1; // Enable Reading and waiting to complete
WaitMSSP ();
if (ACKSTAT==1) return 4;

NACKBit (); // Always with NACK condition before STOP codition


STOPBit (); // Always end with Stop condition

ddt = SSPBUF;
return ddt;
}

GV: Ong Mẫu Dũng – Khoa CNĐT 149


Bài giảng KỸ THUẬT VI XỬ LÝ

Chương 9: Thiết kế Hệ thống vi xử lý – VĐK cho ứng dụng


- Trình bày qui trình phương pháp thiết kế Hệ thống vi xử lý cho ứng dụng
- Xây dựng được mô hình, phân tích và thiết kế, vẽ lưu đồ và lập trình giao tiếp và lập trình
điều khiển ngoại vi cho Hệ thống vi xử lý theo ứng dụng.
- Sử dụng thành thạo các phần mềm: soạn thảo, biên dịch, mô phỏng và lập trình cho VĐK .
- Tính toán và thiết kế Hệ thống vi xử lý – VĐK PIC cho ứng dụng .
- Vẽ được sơ đồ nguyên lý Hệ thống vi xử lý – vi diều khiển
- Thiết kế được lưu đồ, viết được các chương trình điều khiển hoạt động cho hệ theo chức
năng ứng dụng.
- Cải tiến, nâng cấp giải thuật điều khiển.

9.1. Thiết kế kit VĐK


a. Ví dụ thiết kế VĐK dùng cho ĐAMH 1:

GV: Ong Mẫu Dũng – Khoa CNĐT 150


Bài giảng KỸ THUẬT VI XỬ LÝ

b. Ví dụ thiết kế KIT VĐK dùng cho thực hành lập trình:


+ Khối PIC16F887
+ IC EEROM with SPI interface
+ IC temperature with I2C interface

+ 5V Power Supply
+ LCD1602 with 4bit mode interface
+ RS232 interface
+ IC Driver motor interface
+ Single button and single Led interface
9.2. Tiểu luận
….

GV: Ong Mẫu Dũng – Khoa CNĐT 151


Bài giảng KỸ THUẬT VI XỬ LÝ

GV: Ong Mẫu Dũng – Khoa CNĐT 152

You might also like