Tải bản đầy đủ (.pdf) (155 trang)

giáo trình học vi điều khiển

Bạn đang xem bản rút gọn của tài liệu. Xem và tải ngay bản đầy đủ của tài liệu tại đây (2.11 MB, 155 trang )

CHƢƠNG 1: GIỚI THIỆU HỆ THỐNG VI XỬ LÝ VÀ VI ĐIỀU KHIỂN
1.1 Lịch sử phát triển vi xử lý và vi điểu khiển
Vi xử lý (viết tắt là µP hay uP), đôi khi còn đƣợc gọi là bộ vi xử lý, là một linh kiện
điện tử đƣợc chế tạo từ các tranzito thu nhỏ tích hợp lên trên một vi mạch tích hợp
đơn. Khối xử lý trung tâm (CPU) là một bộ vi xử lý đƣợc nhiều ngƣời biết đến nhƣng
ngoài ra nhiều thành phần khác trong máy tính cũng có bộ vi xử lý riêng của nó, ví dụ
trên card màn hình (video card) chúng ta cũng có một bộ vi xử lý. Trƣớc khi xuất
hiện các bộ vi xử lý, các CPU đƣợc xây dựng từ các mạch tích hợp cỡ nhỏ riêng biệt,
mỗi mạch tích hợp chỉ chứa khoảng vào chục tranzito. Do đó, một CPU có thể là một
bảng mạch gồm hàng ngàn hay hàng triệu vi mạch tích hợp. Ngày nay, công nghệ tích
hợp đã phát triển, một CPU có thể tích hợp lên một hoặc vài vi mạch tích hợp cỡ lớn,
mỗi vi mạch tích hợp cỡ lớn chứa hàng ngàn hoặc hàng triệu tranzito. Nhờ đó công
suất tiêu thụ và giá thành của bộ vi xử lý đã giảm đáng kể.
Vi điều khiển (viết tắt là µC hay uC), là một máy tính đƣợc tích hợp trên một chíp,
nó thƣờng đƣợc sử dụng để điều khiển các thiết bị điện tử. Vi điều khiển, thực chất, là
một hệ thống bao gồm một vi xử lý có hiệu suất đủ dùng và giá thành thấp (khác với
các bộ vi xử lý đa năng dùng trong máy tính) kết hợp với các khối ngoại vi nhƣ bộ
nhớ, các mô đun vào/ra, các mô đun biến đổi số sang tƣơng tự và tƣơng tự sang số,...
Ở máy tính thì các mô đun thƣờng đƣợc xây dựng bởi các chíp và mạch ngoài. Vi
điều khiển thƣờng đƣợc dùng để xây dựng các hệ thống nhúng. Nó xuất hiện khá
nhiều trong các dụng cụ điện tử, thiết bị điện, máy giặt, lò vi sóng, điện thoại, đầu đọc
DVD, thiết bị đa phƣơng tiện, dây chuyền tự động, v.v. Hầu hết các vi điều khiển
ngày nay đƣợc xây dựng dựa trên kiến trúc Harvard, kiến trúc này định nghĩa bốn
thành phần cần thiết của một hệ thống nhúng. Những thành phần này là lõi CPU, bộ
nhớ chƣơng trình (thông thƣờng là ROM hoặc bộ nhớ Flash), bộ nhớ dữ liệu (RAM),
một hoặc vài bộ định thời và các cổng vào/ra để giao tiếp với các thiết bị ngoại vi và
các môi trƣờng bên ngoài - tất cả các khối này đƣợc thiết kế trong một vi mạch tích
hợp. Vi điều khiển khác với các bộ vi xử lý đa năng ở chỗ là nó có thể hoạt động chỉ
với vài vi mạch hỗ trợ bên ngoài.
1



1.2 Một số dòng vi xử lý và vi điều khiển hiện đại
- Thế hệ 1 (1971 - 1973): vi xử lý 4 bit, đại diện là 4004, 4040, 8080 (Intel) hay IPM16 (National Semiconductor).
+ Độ dài word thƣờng là 4 bit (có thể lớn hơn).
+ Tốc độ 10 - 60 μs / lệnh với tần số xung nhịp 0.1 - 0.8 MHz.
+ Tập lệnh đơn giản và phải cần nhiều vi mạch phụ trợ.
- Thế hệ 2 (1974 - 1977): vi xử lý 8 bit, đại diện là 8080, 8085 (Intel) hay Z80 .
+ Tập lệnh phong phú hơn.
+ Địa chỉ có thể đến 64 KB. Một số bộ vi xử lý có thể phân biệt 256 địa chỉ cho
thiết bị ngoại vi. + Sử dụng công nghệ NMOS hay CMOS.
+ Tốc độ 1 - 8 μs / lệnh với tần số xung nhịp 1 - 5 MHz - Thế hệ 3 (1978 - 1982):
vi xử lý 16 bit, đại diện là 68000/68010 (Motorola) hay 8086/ 80286/ 80386 (Intel)
+ Tập lệnh đa dạng với các lệnh nhân, chia và xử lý chuỗi.
+ Địa chỉ bộ nhớ có thể từ 1 - 16 MB và có thể phân biệt tới 64KB địa chỉ cho
ngoại vi
+ Sử dụng công nghệ HMOS. + Tốc độ 0.1 - 1 μs / lệnh với tần số xung nhịp 5 10 MHz.
- Thế hệ 4: vi xử lý 32 bit 68020/68030/68040/68060 (Motorola) hay 80386/80486
(Intel) và vi xử lý 32 bit Pentium (Intel)
+ Bus địa chỉ 32 bit, phân biệt 4 GB bộ nhớ.
+ Có thể dùng thêm các bộ đồng xử lý (coprocessor).
+ Có khả năng làm việc với bộ nhớ ảo.
+ Có các cơ chế pipeline, bộ nhớ cache.
+ Sử dụng công nghệ HCMOS. - Thế hệ 5: vi xử lý 64 bit
1.3 Vi điều khiển Pic
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à PIC1650 đƣợc phát triển bởi Microelectronics Division
thuộc General Instrument.

2



PIC bắt nguồn là chữ viết tắt của "Programmable Intelligent Computer" (Máy tính
khả trình thông minh) là một sản phẩm của hãng General Instrument đặt cho dòng sản
phẩm đầu tiên của họ là PIC1650. Lúc này, PIC1650 đƣợc dùng để giao tiếp với các
thiết bị ngoại vi cho máy chủ 16bit CP1600, vì vậy, ngƣời ta cũng gọi PIC với cái tên
"Peripheral Interface Controller" (Bộ điều khiển giao tiếp ngoại vi). CP1600 là một
CPU tốt, nhƣng lại kém về các hoạt động xuất nhập, và vì vậy PIC 8-bit đƣợc phát
triển vào khoảng năm 1975 để hỗ trợ hoạt động xuất nhập cho CP1600. PIC sử dụng
microcode đơn giản đặt trong ROM, và mặc dù, cụm từ RISC chƣa đƣợc sử dụng thời
bây giờ, nhƣng PIC thực sự là một vi điều khiển với kiến trúc RISC, chạy một lệnh
một chu kỳ máy (4 chu kỳ của bộ dao động).
Năm 1985 General Instrument bán bộ phận vi điện tử của họ, và chủ sở hữu mới hủy
bỏ hầu hết các dự án - lúc đó đã quá lỗi thời. Tuy nhiên PIC đƣợc bổ sung EEPROM
để tạo thành 1 bộ điều khiển vào ra khả trình. Ngày nay rất nhiều dòng PIC đƣợc xuất
xƣởng với hàng loạt các module ngoại vi tích hợp sẵn (nhƣ USART, PWM, ADC...),
với bộ nhớ chƣơng trình từ 512 Word đến 32K Word.
Hiện nay, tại Việt Nam, đã có một cộng đồng nghiên cứu và phát triển PIC, dsPIC
và PIC32.
1.4 Xu hƣớng ứng dụng của các hệ vi điều khiển
Vi xử lý, chính là chip của các loại máy tính ngày nay, nên hẳn các bạn đã biết rất rõ
nó có những ứng dụng gì. Ở đây, tôi chỉ nói đên ứng dụng của vi điều khiển.
Vi điều khiển có thể dùng trong thiết kế các loại máy tính nhúng. Máy tính nhúng có
trong hầu hết các thiết bị tự động, thông minh ngày nay.
Chúng ta có thể dùng vi điều khiển để thiết kế bộ điều khiển cho các sản phẩm nhƣ:
 Trong các sản phẩm dân dụng:
o Nhà thông minh: ƒ
 Cửa tự động
 Khóa số
 Tự động điều tiết ánh sáng thông minh (bật/tắt đèn theo thời
gian, theo cƣờng độ ánh sáng,...)

3


 Điều khiển các thiết bị từ xa (qua điều khiển, qua tiếng vỗ tay,...)
 Điều tiết hơi ẩm, điều tiết nhiệt độ, điều tiết không khí, gió
 Hệ thống vệ sinh thông minh,...
o Trong quảng cáo: ƒ
 Các loại biển quảng cáo nháy chữ
 Quảng cáo ma trận LED (một màu, 3 màu, đa màu)
 Điều khiển máy cuốn bạt quảng cáo,...
o Các máy móc dân dụng
 Máy điều tiết độ ẩm cho vƣờn cây
 Buồng ấp trứng gà/vịt ƒ


Đồng hồ số, đồng hồ số có điều khiển theo thời gian

o Các sản phẩm giải trí
 Máy nghe nhạc ƒ
 Máy chơi game ƒ
 Đầu thu kỹ thuật số, đầu thu set-top-box,... ™
 Trong các thiết bị y tế:
o Máy móc thiết bị hỗ trợ:
 Máy đo nhịp tim, máy đo đƣờng huyết, máy đo huyết áp, điện
tim đồ, điện não đồ,…
 Máy cắt/mài kính o Máy chụp chiếu (city, X-quang,...) ™
 Các sản phẩm công nghiệp:
o Điều khiển động cơ o Điều khiển số (PID, mờ,...)
o Đo lƣờng (đo điện áp, đo dòng điện, áp suất, nhiệt độ,...)
o Cân băng tải, cân toa xe, cân ô tô,...

o Máy cán thép: điều khiển động cơ máy cán, điều khiển máy quấn thép,..
o Làm bộ điều khiển trung tâm cho RoBot o Ổn định tốc độ động cơ
o Đếm sản phẩm của 1 nhà máy, xí nghiệp,…
o Máy vận hành tự động (dạng CNC)

4


CHƢƠNG 2: CẤU TRÚC VI ĐIỀU KHIỂN PIC
2.1 Cấu trúc bên trong vi điều khiển PIC

Hình 2.1: Cấu trúc chung của vi điều khiển
Cấu tạo của vi điều khiển có thể chia làm 2 phần cơ bản nhƣ sau:
-

Phần lõi: gồm bộ điều khiển trung tâm có chức năng chạy chƣơng trình (gồm các
câu lệnh) đã đƣợc nạp vào trong bộ nhớ chƣơng trình (program memory) trƣớc đó.

-

Phần ngoại vi: gồm có các timer, bộ biến đổi tƣơng tự số ADC và các modun khác

Phần lõi của vi điều khiển chịu trách nhiệm chạy chƣơng trình trong vi điều khiển và
quản lý toàn bộ các hoạt động khác bao gồm hoạt động của ngoại vi.
5


Vi điều khiển chạy chƣơng trình gồm các lệnh trong bộ nhớ chƣơng trình, địa chỉ của
lệnh nằm trong thanh ghi bộ đếm chƣơng trình PC, lúc khởi động PC=0, sau khi thực
hiện một lệnh PC=PC+1 do đó vi điều khiển chạy lệnh kế tiếp trong chƣơng trình. Lệnh

vi điều khiển trong bộ nhớ thực ra đã đƣợc mã hóa mỗi lệnh thành 14 bit. Quá trình thực
hiện một lệnh gồm các bƣớc:
- Lệnh trong bộ nhớ chƣơng trình đƣợc đƣa vào thanh ghi lệnh (địa chỉ của lệnh nằm
trong thanh ghi PC). Sau đó lệnh đƣa vào bộ giải mã và điều khiển để giải mã lệnh. Trên
cơ sở đó, vi điều khiển biết lệnh đó là lệnh gì, thao tác với dữ liệu nào, phép thao tác
v.v.v Trên cơ sở đó, nếu lệnh thao tác với dữ liệu chứa trong các thanh ghi trong RAM,
bộ điều khiển điều khiển đọc dữ liệu trong RAM đƣa vào bộ xử lý số học và logic ALU,
các phép toán sẽ đƣợc thực hiện qua trung gian là thanh ghi làm việc W, quá trình sẽ kết
thúc khi kết quả trả dữ liệu về cho chƣơng trình, tiếp theo PC tăng lên 1 đơn vị, vi điều
khiển nhảy đến lệnh kế tiếp, tiếp tục 1 chu kì thực hiện lệnh
2.2 Bộ nhớ dữ liệu và các thanh ghi đặc biệt
Bộ nhớ vi điều khiển PIC chia làm 3 phần:
-

Bộ nhớ chƣơng trình-FLASH: chứa nội dung của chƣơng trình chạy trong vi điều
khiển. Bộ đếm chƣơng trình PC (Program counter) sẽ thực hiện các lệnh chứa
trong bộ nhớ chƣơng trình này theo thứ tự từ trên xuống.

-

Bộ nhớ dữ liệu tạm thời- RAM : Gồm 2 phần: các thanh ghi đặc biệt-SFR (Special
Function Register) - đây là các thanh ghi chức năng thể hiện hoặc trạng thái, điều
khiển của các khối bên trong vi điều khiển PIC (các thanh ghi trạng thái các chân
vi điều khiển nhƣ PORTA v.v, Các thanh ghi Status v.vv, TMR0 cho timer v.v ).
Các thanh ghi mục đích chung GPR (general purpose register) là nơi lƣu các giá trị
tạm thời, nơi mà các biến chƣơng trình nằm đây

-

Bộ nhớ dữ liệu không mất nội dung- EEPROM cho phép chứa các dữ liệu và dữ

liệu này không mất nội dung khi mất điện (phần này xem nhƣ thiết bị ngoại vi)

6


Hình 2.2: Bộ nhớ dữ liệu RAM
Bộ nhớ dữ liệu tạm thời (RAM) của vi điều khiển gồm 2 phần chính, chia thành 4 bank
nhớ:
-

Các thanh ghi chức năng đặc biệt SFR (Special Function Register) điều khiển quá
trình hoạt động của các bộ phận chức năng trong vi điều khiển cũng nhƣ các thiết
bị ngoại vi đƣợc tích hợp trong vi điều khiển. Nhìn vào hình vẽ tổ chức bộ nhớ
nhƣ trên ta thấy, các thanh ghi SFR phân bố từ địa chỉ 00h - 1Fh trong bank 0,
phân bố rải rác từ 80F- 9Fh trong bank 1, từ 100h đến 11Fh trong bank 2, từ 180h19Fh trong bank 3
7


-

Các thanh ghi mục đích chung GPR (General Purpose Register) dùng để chứa dữ
liệu (dùng để đặt biến) từ 20h-7Fh trong bank 0, từ A0h-EFh trong bank 1, từ
120h-16Fh trong bank 2, từ 1A0h-1F0h trong bank 3

Một số điểm chú ý khác là:
Khi truy cập các địa chỉ từ F0h-FFh trong bank 1, 170h-17Fh trong bank 2 và 1F0h1FFh trong bank 3 tức là truy cập đến 70h-7Fh trong bank 0
Các vị trí màu xám không sử dụng.
Tại mỗi thời điểm, vi điều khiển làm việc trên một bank nhớ , việc lựa chọn làm việc
bank nhớ phụ thuộc 2 bit RP1, RP0 của thanh ghi STATUS<6-5>


Bảng 2.1: Bảng chọn bank bộ nhớ
Chú ý:
Trong chƣơng trình viết cho vi điều khiển PIC, nếu sau ki thực hiện lệnh đối với 1
thanh ghi (thanh ghi SFR hoặc GPR) ở bank i, muốn thực hiện l lệnh đối với 1 thanh
ghi khác ở bank j (j#i) ta phải chọn lại bank nhớ, tức là phải có lệnh can thiệp đến 2
bit RP1 và RP0, nếu không lệnh sau sẽ không tác dụng:
Ví dụ: ta có chƣơng trình nhƣ sau:
BCF TRISA,2
ADDWF PORTA,1
Lệnh thứ 2 sẽ không có tác dụng, vì lệnh đầu tiên thao tác với thanh ghi TRISA nằm
trên bank 1, trong khi lệnh thứ 2 tác động đến PORTA nằm trên bank 0
Chƣơng trình đúng là
BSF STATUS,5 ; ĐƢA GIÁ TRỊ RP0 LÊN MỨC 1 CHỌN BANK 1
BCF TRISA,2
BCF STATUS,5 ; ĐƢA GIÁ TRỊ RP0 XUỐNG MỨC 0 CHỌN BANK 0
ADDWF PORTA,1
8


Lí do của việc phải chọn bank nhớ giải thích nhƣ sau:
Chúng ta xem lại bảng tổng hợp tất cả các lệnh của vi điều khiển PIC và để ý rằng trong
các lệnh thao tác với các thanh ghi (các thanh ghi nằm trong bộ nhớ RAM), mỗi thanh
ghi đƣợc mã hóa bằng 7 bit (tức là đánh số từ 00-7Fh)
Ví dụ:
Lệnh ADDWF f,d mã hóa lệnh nhƣ sau:
00 111 d fffffff
Nhƣ vậy:

ADDWF PORTA,0 có mã lệnh: 00 111 0 000 0100 (do địa chỉ của


PORTA=0x05=000 0100)
ADDWF TRISA, 0 không thể viết bằng đƣợc vì địa chỉ TRISA=0x85=1000 0100 gồm 8
bit không thể mã hóa đƣợc bằng 7 bit nhƣ trong luật mã hóa lệnh
Để giải quyết vấn đề này, để mã hóa lệnh ADDWF TRISA,0 vi điều khiển mã hóa thanh
ghi TRISA bằng 7 bit nhƣ PORTA, việc phân biệt PORTA và TRISA phụ thuộc vào các
bit chọn bank nhớ RP1 và RP0.
Giải thích này cũng tƣơng tự cho các lệnh thao tác trên thanh ghi của bank 1, bank 2 và
bank 3.
Do đó, nếu khi thực hiện lệnh tiếp theo có thao tác với thanh ghi thuộc bank nhớ khác với
bank nhớ đang đƣợc tác động hiện tại cần phải có lệnh chọn lại bank nhớ
Địa chỉ gián tiếp
Để hiểu về địa chỉ gián tiếp ta xem địa chỉ trực tiếp nhƣ thế nào
Để dễ hiểu ta cho ví dụ:
CLRF 0x30
Câu lệnh này thực hiện việc xóa thanh ghi có địa chỉ 30h trong bộ nhớ Ram. Rõ ràng là
địa chỉ ở đây là lấy trực tiếp trong RAM, địa chỉ đƣợc ghi trực tiếp trong lệnh
Trong một số trƣờng hợp ta dùng đến địa chỉ gián tiếp, cụ thể là: thanh ghi FSR (File
Select Register) chứa địa chỉ của thanh ghi trong RAM và thanh ghi INDF sẽ ánh xạ vào
thanh ghi RAM có địa chỉ là nội dung của FSR, mọi thao tác trên INDF xem nhƣ là thao
tác trên thanh ghi của RAM nêu trên
Ví dụ:
9


MOVLW

0x30
FSR ; sau lệnh này FSR chứa 0x30 tức là chỉ đến thanh ghi có địa

MOVWF


chỉ 0x30 trong RAM
INDF; xóa INDF tức là xóa nội dụng của thanh ghi địa chỉ 0x30

CLRF

Hình 2.3: Địa chỉ gián tiếp
Hình vẽ trên cho ta cách mà vi điều khiển xác định thanh ghi nào trong Ram đƣợc thực
hiện.
Trở lại ví dụ trên:
CLRF 0x30

lệnh này mã hóa nhƣ sau: 00 0001 1 fff ffff

Trong đó fff ffff= mã thanh ghi = 011 0000
Khi đó RP1=0, RP0=0 bank nhớ 0 đƣợc chọn
Rõ ràng là thông qua 7 byte thấp của opcode và giá trị RP1, RP0 vi điều khiển xác định
đƣợc thanh ghi trong bộ nhớ RAM
Đối với lệnh gián tiếp:
MOVLW
MOVWF

0x30
FSR

CLRF INDF;
10


Vi điều khiển dựa vào bit IRP (là bít 7 của thanh ghi STATUS) và bít 7 của FSR để xác

định bank nhớ nơi chứa thanh ghi. 7 bít còn lại FSR<6-0> xác định chính xác vị trí của
thanh ghi đó
IRP

FSR<7>

Bank

0

0

0

0

1

1

1

0

2

1

1


3

Bảng 2.2: Bảng các bit chọn bank
2.3 Bộ nhớ chƣơng trình- Mã hóa lệnh
2.3.1 Bộ nhớ chƣơng trình
Bộ nhớ chƣơng trình là nơi chứa các lệnh đã được mã hóa. Quá trình mã hóa đã đƣợc
thực hiện trong khâu dịch chƣơng trình trên máy tính ra file hex và nạp chƣơng trình vào
bộ nhớ chƣơng trình.
Mỗi một lệnh đã đƣợc mã hóa đƣợc chứa trong 1 thanh ghi 14 bit trong bộ nhớ chƣơng
trình
Nhƣ vậy khi hình dung về bộ nhớ chƣơng trình ta có hình ảnh sau:
Bit

Bit

Bit

Bit

Bit

Bit

Bit

Bit

Bit

Bit


Bit

Bit

Bit

Bit

13

12

11

10

9

8

7

6

5

4

3


2

1

0

0

0

0

1

1

1

0

1

0

1

1

0


1

0

0

0

0

1

0

1

1

0

1

1

1

1

1


0

---

---

--

--

--

--

--

--

--

--

--

--

--

--


--

--

--

--

--

--

--

--

--

--

--

--

--

--

-


--

--

--

--

--

--

--

--

--

--

--

--

--

1

1


1

1

1

1

0

0

1

1

1

0

1

1

0

1

1


1

0

1

0

1

0

1

0

1

0

1

Bảng 2.3: Mô hình bộ nhớ chương trình

11


Chƣơng trình của vi điều khiển chạy theo thứ tự từ địa chỉ thấp đến địa chỉ cao, địa chỉ
lệnh là nội dung của thanh ghi bộ đếm chƣơng trình PC (Program Counter). Đối với

pic16f877a, thanh ghi PC có độ dài 13 bit.
Nếu dùng 2 bit địa chỉ ta phân biệt đƣợc 4 địa chỉ: 00,01,10,11
Nếu dùng 3 bit địa chỉ ta phân biệt đƣợc 8 địa chỉ: 000,001,010,011,100,101,110,111
----Suy ra, PC dùng 13 bit địa chỉ ta phân biệt đƣợc 2^13= 2^3 x 2^10=8K địa chỉ
Khi bật nguồn cho vi điều khiển (hay ấn nút reset chƣơng trình), PC đƣợc xóa về 0
Sau khi thực hiện xong 1 lệnh nội dung của PC tăng lên 1 đơn vị: PC=PC+1 (trừ 1 số
lệnh đặc biệt nhƣ gọi chƣơng trình con, goto v.v.v)
Do vi điều khiển sẽ thực hiện lệnh tại địa chỉ chứa trong thanh ghi PC nên theo phân tích
trên có thể nói, vi điều khiển thực hiện lệnh tuần tự từ địa chỉ thấp đến địa chỉ cao
2.3.2 Mã hóa và giải mã lệnh
Nhƣ đã nói ở trên, khi chƣơng trình đã nằm trong bộ nhớ (tức là đã đƣợc nạp vào), các
lệnh đã đƣợc mã hóa thành số nhị phân 14 bit chứa trong các thanh ghi của bộ nhớ
chƣơng trình.
Việc mã hóa này phải tuân theo qui luật của từng loại vi điều khiển mà cụ thể đối với
PIC16F877a thì việc mã hóa phải tuân theo qui luật của nhà sản xuất microchip qui định
để trong quá trình thực hiện 1 lệnh, bộ điều khiển bên trong của vi điều khiển PIC có thể
giải mã (để hiểu) và thực thi lệnh đó đƣợc.
Để tiện cho việc theo dõi, ta đƣa ra bảng tổng hợp các lệnh vi điều khiển 16f877a nhƣ
sau:

12


Bảng 2.4: Bảng mã hóa các lệnh
Toàn bộ tập lệnh chia làm 3 dạng:
-

Lệnh thao tác theo từng byte (Byte-Oriented)

-


Lệnh thao tác theo từng bit (Bit-Oriented)

-

Lệnh thao tác với hằng số

Trong vi điều khiển pic16f877a không có lệnh thực hiện tƣơng tác giữa 2 thanh ghi,
hay giữa thanh ghi và một số (chú ý ở đây, thanh ghi là thanh ghi nằm trong bộ nhớ
RAM, ví dụ nhƣ PORTA hoặc thanh ghi có địa chỉ 0x21 )
Để giải quyết vấn đề trên, trong vi điều khiển pic 16f877a có thanh ghi đặc biệt làm
chức năng trung gian cho các thao tác trên gọi là thanh ghi làm việc W (work register)
Để dễ hiểu:
Giả sử ta có 2 biến a,b (tất nhiên là đƣợc khai báo và cấp phát trong bộ nhớ RAM)
13


Ta muốn thực hiện phép toán:
a=a+b
Trong PIC không có lệnh thực hiện giữa 2 thanh ghi a và b. Để thực hiện lệnh này ta
phải qua các bƣớc:
W=0
W= w+b

(sau lệnh này w=b)

a=w+a (sau lện này a=w+a=b+a)
Các lệnh thực hiện chuỗi phép toán trên nhƣ sau:
CLRW
ADDWF b,0

ADDWF a,1
Phần cụ thể về lệnh sẽ đƣợc giới thiệu sau, ta trở lại vấn đề mã hóa lệnh
Cấu trúc một lệnh:
Cấu trúc một lệnh phụ thuộc vào 3 dạng thao tác theo byte, theo bit , thao tác với hằng
số
-

Các lệnh thao tác theo byte
Cấu trúc lệnh:
o Mã lệnh

thanhghi,d

Đây là các tác động giữa thanh ghi trong RAM và thanh ghi làm việc W, d chỉ
hƣớng kết quả đƣợc lƣu trữ. d=0 kết quả chứa trong w, d=1 kết quả chứa trong thanh ghi
Ví dụ: cộng thanh ghi a với w, kết quả chứa trong a
ADDWF a,1
cộng thanh ghi a với w, kết quả chứa trong w
ADDWF a,0
Câu hỏi đặt ra là khi vi điều khiển đọc mã lệnh trong bộ nhớ gồm các con số nhị phân
làm sao nó xác định đƣợc đâu là lệnh cộng (ADDWF) đâu là lệnh AND (ANDWF) ?
Câu trả lời là trong lúc mã hóa lệnh một số bit đầu tiên của chuỗi 14 bit lệnh dành để
phân biệt các lệnh với nhau hay còn gọi là mã toán tử hay theo tiếng anh là opcode
Đối với lệnh theo tác theo byte, vi điều khiển dùng 6 bit để mã hóa opcode
14


Để phân biệt khi nào kết quả chứa trong thanh ghi, khi nào thì chứa trong w, vi điều
khiển dành 1 bít hƣớng d: d=0 kết quả chứa trong thanh ghi w, d=1 kết quả chứa
trong thanh ghi.

7 bit còn lại trong để phân biệt lệnh tác động với thanh ghi nào trong bộ nhớ RAM
13

8

7

6

OPCODE (toán tử)

d(hƣớng)

Ví dụ:

ADDWF

0

FILE (địa chỉ thanh ghi)

a, 0

Giải sử a địa chỉ là 0x30= 0b00110000
Mã lệnh sẽ là:
OPCODE (toán tử)

d(hƣớng)

00 0111


0

-

FILE (địa chỉ thanh ghi)
0110000

Các lệnh thao tác theo bit
Cấu trúc lệnh gồm 3 phần:
o Mã lệnh

thanh ghi, bit

Các lệnh bao gồm lệnh set 1 bit nào đó của một thanh ghi nào đó lên mức 1 hoặc xóa bít
đó về 0, hoặc kiểm tra 1 bit nào đó của một thanh ghi nào đó bằng 0 hoặc bằng 1 v.v
Từ đây, ta có thể thấy, cần một số bit trong 14 bit của 1 lệnh dành để phân biệt các lệnh
với nhau, cụ thể ở đây là 4 bit, cần 3 bít để xác định vị trí bít nào trong thanh ghi bị tác
động (vì vị trí bít là 0-7), còn lại 7 bít để xác định thanh ghi nào trong các thanh ghi bộ
nhớ RAM bị tác động
13

10 9

OPCODE (toán tử)

7

Vị trí bít


Ví dụ:

6

0

FILE (địa chỉ thanh ghi)

BCF a,3

Xóa bít 3=011 của thanh ghi a (giả sử a đƣợc khai báo trƣớc và có địa chỉ
0x24=0b0010 0100 trong bộ nhớ RAM)
13

10 9

7

6

0
15


OPCODE (toán tử)

Vị trí bít

01 00


011

-

FILE (địa chỉ thanh ghi)
010 0100

Các lệnh thao tác với hằng số và điều khiển rẽ nhánh chƣơng trình:
Cấu trúc lệnh:
o Mã lệnh

hằng số k

Các lệnh thông thường:
13

8 7

OPCODE (toán tử)

0

Hằng số k

Trừ 2 lệnh Call k và goto k
13

11 10

0


OPCODE (toán tử)

Hằng số k

Ví dụ:

ADDLW

Miêu tả:

cộng 233 vào thanh ghi w

13

233

8 7

OPCODE (toán tử)

Hằng số k

11 111

1110 1001

0

Sau khi phân tích nhƣ trên, nhìn lại bảng 1: tập hợp tất cả các lệnh của vi điều khiển

pic16f877a ta đƣa ra nhận xét sau:
-

2 bit đầu của 14 bit mã hóa lệnh xác định 3 dạng lệnh: thao tác theo byte (00), thao
tác theo bit (01), thao tác với hằng số (11 hoặc 10 hoặc 00)

-

Có tấc cả 18 lệnh thao tác byte, nhƣ đã nêu ở trên, để mã hóa mã lệnh (opcodetoán tử) dùng hết 6 bít: 2 bít phân biệt dạng thao tác theo byte (00) vậy còn 4 bit
để phân biệt 18 lệnh thao tác byte. Nhƣ ta biết với 4 bit chỉ phân biệt đƣợc 2^4
=16 lệnh, làm sao phân biệt đƣợc 18 lệnh.

16


Thực ra vi điều khiển dùng 14 mã lệnh cho 14 lệnh, 2 mã lệnh còn lại, cụ thể là 00
0001 cùng cho 2 lệnh CLRF (xóa nội dung thanh ghi) CLRW (xóa nội dung thanh
ghi W) và mã 00 0000 cùng cho 2 lệnh MOVWF (chuyển nội dung của thanh ghi
w sang thanh ghi F (có địa chỉ cụ thể trong ram) ) và lệnh NOP (lệnh không thực
hiện nhiệm vụ gì). Thế làm sao phân biệt đƣợc CLRF và CLRW? Đơn giản là khi
gặp mã lệnh 00 0001 vi điều khiển kiểm tra tiếp bit hƣớng d: rõ ràng nếu d=0 (kết
quả chứa trong w) thì đây là lệnh CLRW, nếu d=1 (kết quả chứa trong thanh ghi f)
thì đây là lệnh CLRF
Khi gặp mã 00 0000, vi điều khiển kiểm tra tiếp bit hƣớng d, d =1 thì đây là lệnh
MOVWF, d=0 là lệnh NOP
-

Có 4 lệnh thao tác theo bit. 2 bit mã thao tác theo bit là 01, 2 bit còn lại trong
OPCODE (xem bên trên) để mã hóa 4 lệnh


-

Có 13 lệnh thao tác với hằng số và điều khiển: một số lệnh có 2 bit mã thao tác là
11 hoặc 10 hoặc 00. Kiểm tra các bit còn lại ta thấy đều có cách để vi điều khiển
thực hiện phân biệt đƣợc các lệnh với nhau
Cấu trúc bộ nhớ và stack:

17


Hình 2.4: Tổ chức bộ nhớ chương trình và Stack
Thanh ghi bộ đếm chƣơng trình:
Tại mỗi thời điểm, vi điều khiển thực hiện 1 lệnh trong bộ nhớ chƣơng trình có địa chỉ
cho bởi thanh ghi bộ đếm chƣơng trình PC (Program Counter) gồm 13 bit. Nhắc lại là với
độ dài 13 bit, thanh ghi PC có thể phân biệt đƣợc tối đa 2^13=8K địa chỉ.
Cấu trúc thanh ghi PC gồm 2 phần: phần thấp PCL (Program Counter Low) 8 bit 0-7,
phần cao PCH (Program Counter High) 5 bit 8-12
12
PCH

11

10

9

8

7


6

5

4

3

2

1

0

PCL

Trong đó các bit trong PCL là các bit có thể đọc ghi đƣợc
18


Các bit trong PCH<12-8> không thể đọc ghi và đƣợc cập nhật thông qua thanh ghi
PCLATCH<4-0>. Nghĩa là mỗi một lần tác động thay đổi 4 bit PCLATCH sẽ dẫn đến
thay đổi nội dung PCH.
Nhìn vào tổ chức bộ nhớ chƣơng trình của vi điều khiển ta thấy rằng bộ nhớ chƣơng trình
gồm 8 K chia thành 4 bank nhớ, mỗi bank có dung lƣợng 2 K từ nhớ:
-

Bank 0: 0000h-07FFh

-


Bank 1: 0800h-0FFFh

-

Bank 2: 1000h-17FFh

-

Bank 3: 1800h-1FFFh

2 bit cao PCLATCH<4-3> sẽ qui định vi điều khiển đang truy cập bank nhớ nào trong 4
bank nêu trên.
Khi bàn đến các lệnh CALL, GOTO, các lệnh trở về từ chƣơng trình con, chƣơng trình
ngắt ta sẽ quay lại vấn đề này
Reset vector:
Mỗi khi chƣơng trình vi điều khiển bị reset lại (tắt nguồn, ấn nút reset), thanh ghi PC bị
xóa về 0, vậy vi điều khiển bắt đầu thực hiện lệnh chứa tại địa chỉ 0000h. Do đó địa chỉ
này gọi là địa chỉ vector reset
Stack:
Trong khi thực hiện chƣơng trình, sẽ có những đoạn chƣơng trình đƣợc thực hiện nhiều
lần, ngƣời lập trình để đơn giản chƣơng trình sẽ đƣa đoạn chƣơng trình đó thành chƣơng
trình con, mỗi lần cần thực hiện đoạn chƣơng trình thì đơn giản là gọi chƣơng trình con
đó.
Ví dụ chƣơng trình con hay dùng nhất là chƣơng trình delay ví dụ nhƣ các chƣơng trình
con delay 100ms dƣới đây
;************* 1msec Timer Subroutine *****************
t1m

movlw d'2'


;(1)

Set loop cnt1

movwf cnt1m

;(1)

Save loop cnt1

tm1lp1 movlw d'249'
movwf cnt500u

;(1)*2
;(1)*2

Set loop cnt2
Save loop cnt2
19


tm1lp2 nop

;(1)*249*2 Time adjust

nop

;(1)*249*2 Time adjust


decfsz cnt500u,f
goto

;(1)*249*2 cnt500u-1=0 ?

tm1lp2

;(2)*248*2 No, continue

decfsz cnt1m,f

;(1)*2

goto

;(2)

tm1lp1

return

;(2)

cnt1m-1=0 ?
No. Continue

Yes. Cnt end

;Total 2501*0.4usec=1msec


;************* 100msec Timer Subroutine ***************
t100m movlw d'100'
movwf cnt100m
tm2lp call

t1m

tm2lp

return

;Save loop counter
;1msec subroutine

decfsz cnt100m,f
goto

;Set loop counter

;cnt100m - 1 = 0 ?
;No. Continue

;Yes. Count end

;************* 500msec Timer Subroutine ***************
t500m movlw d'5'

;Set loop counter

movwf cnt500m

tm3lp call

t100m

;100msec subroutine

decfsz cnt500m,f
goto

tm3lp

return

;Save loop counter

;cnt500m - 1 = 0 ?
;No. Continue

;Yes. Count end

chƣơng trình chính:
----20


----bcf a,3
call t1m
bsf a,3
----------Nhƣ vậy sau khi thực hiện lệnh bcf a,3, gặp lệnh call t1m, thanh ghi PC đƣợc load địa chỉ
bắt đầu của chƣơng trình t1m, sau khi gặp lệnh return vi điều khiển trở về chƣơng trình
chính thực hiện lệnh bsf a,3. Câu hỏi đặt ra là làm sao vi điều khiển nhớ đƣợc địa chỉ trở

về? thực ra khi gặp lệnh CALL t1m, nội dung thanh ghi PC tăng lên 1 đơn vị và giá trị
này đƣợc lƣu vào stack, sau đó PC đƣợc load địa chỉ của lệnh đầu tiên trong chƣơng trình
con t1m và do đó vi điều khiển sẽ thực hiện lệnh của chƣơng trình con t100m, cho đến
khi gặp lệnh return, PC load đƣợc chỉ đã lƣu trƣớc đó ở stack ra, và do đó thực hiện tiếp
lệnh bsf a,3
Qua ví dụ nói trên ta đã hình dung đƣợc nhiệm vụ của stack là lƣu địa chỉ trở về từ
chƣơng trình con, chƣơng trình ngắt (sẽ đề cập sau)
Stack của vi điều khiển pic16f877a có thể quản lý đến 8 mức stack. Nếu sử dụng đến
mức stack thì 9 thì mức stack 9 này sẽ viết đè lên mức 1.

Vector ngắt:
Chƣa bàn đến ngắt, nhƣng chúng ta hình dung nhƣ thế này: mặc định vi điều khiển thực
hiện chƣơng trình chính, khi có sự kiện ngắt xảy ra, nếu ngắt đó đƣợc cài đặt trƣớc trong

21


chƣơng trình thì vi điều khiển sẽ dừng thực hiện chạy chƣơng trình chính và nhảy vào địa
chỉ 0004h, tại đó phần xử lý ngắt này do ngƣời lập trình viết chƣơng trình thực hiện
Và địa chỉ 0004h trong bộ nhớ chƣơng trình đƣợc gọi là vector ngắt.

22


CHƢƠNG 3: LẬP TRÌNH HỢP NGỮ VỚI VI ĐIỀU KHIỂN PIC
3.1 Cú pháp của chƣơng trình bằng hợp ngữ
Các dạng số dùng trong chƣơng trình hợp ngữ và cách viết trong hợp ngữ nhƣ sau:
Dạng

Cách viết


Ví dụ

DECIMAL

D‟Số‟

D‟100‟

. „Số‟
H „Số‟

H‟20‟

0xSố

0x20

OCTAL

O „Số‟

O‟10‟

BINARY

B‟Số‟

B‟00011000‟


ASCII

A‟kí tự‟

A‟X‟

„kí tự‟

„X‟

HEXADECIMAL

Bảng 3.1: Dạng số sử dụng trong ngôn ngữ hợp ngữ
3.2 Biến và hằng, các chỉ dẫn biên dịch hợp ngữ
3.2.1 Biến hằng
Có một số phƣơng pháp đặt biến, hằng số nhƣ sau:
-

Dùng chỉ dẫn equ:
Tên hằng, biến
Ví dụ:

-

count equ 0x20

Dùng chỉ dẫn set:
Tên hằng, biến
Ví dụ:


-

giá trị

equ

set

giá trị

count1 set 0x20

Dùng chỉ dẫn variable:
Variable Tên hằng, biến = [biểu thức hoặc số]
Ví dụ:

Variable count3=0x20
Hoặc Variable count3
23


-

Dùng chỉ dẫn cblock:
Cblock địa chỉ
Biến1, biến 2, .....
Endc
Ví dụ: cblock 0x20
Count1, count2, count3
Endc

Khai báo cả một vùng các biến 1, 2 ..... bắt đầu từ địa chỉ
Một số chú ý:

-

Khi đặt biến hằng bằng equ ta không thể định nghĩa lại

Ví dụ: viết nhƣ thế này là bị lỗi
Count equ 0x20
--------------------Count equ 0x23
Nhƣng có thể đặt lại giá trị với set
Ví dụ: Viết nhƣ thế này không bị lỗi
Count set 0x20
--------------------Count set 0x23
-

Biến hằng đi kèm với set và equ phải đƣợc khởi tạo giá trị (gán giá trị) nhƣng với
variable thì không cần thiết
Ví dụ:

Chƣơng trình dịch sẽ báo lỗi:
Count equ
Count set
24


Nhƣng thế này thì không báo lỗi
Variable count;
-


Thực ra khi sử dụng set, variable, equ là ta khai báo hằng Chỉ có sử dụng cblock
thì đây mới thực sự là biến và đƣợc cấp phát bộ nhớ cho biến đó
Để hiểu rõ điều này ta cùng xem 2 ví dụ sau:
Ví dụ 1:
Count equ 0x21

; khai báo hằng số count có giá trị 0x21

Movlw d‟5

; đƣa giá trị 5 vào thanh ghi w: w=5

Movwf count

; chuyển giá trị w cho thanh ghi có địa chỉ bằng count tức thanh
; ghi có địa chỉ 0x21 trong bộ nhớ RAM

Nhƣ vậy count đây xem nhƣ là một hằng số 0x21
Ví dụ 2:

CBLOCK 0x21
Count1, count2

Endc
Movlw d‟5

; đƣa giá trị 5 vào thanh ghi w: w=5

Movwf count1 ; đƣa giá trị w vào thanh ghi count1, tức thanh ghi có địa chỉ
; 0x21 nhƣ đã khai báo

Rõ ràng trong trƣờng hợp này count1 là biến, giá trị đƣa vào trong lệnh là địa chỉ
của count1 không phải là giá trị của count1

-

Khi khai báo các biến và hằng này, ta chú ý giá trị khởi tạo. Vì thực ra các biến
hằng này đƣợc sử dụng trong các lệnh nhƣ là địa chỉ các thanh ghi nằm trong vùng

25


×