1. Trang chủ
  2. » Kỹ Thuật - Công Nghệ

Giáo trình hợp ngữ - Lập trình PIC 16F877A

104 1,6K 8

Đang tải... (xem toàn văn)

Tài liệu hạn chế xem trước, để xem đầy đủ mời bạn chọn Tải xuống

THÔNG TIN TÀI LIỆU

Thông tin cơ bản

Định dạng
Số trang 104
Dung lượng 848,62 KB

Nội dung

Giáo trình hợp ngữ - Lập trình PIC 16F877A

Trang 1

CHƯƠNG 1: CẤU TRÚC VI ĐIỀU KHIỂN PIC 16F

1 Cấu trúc chung:

Hình 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

Trang 2

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

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

Trang 3

CHƯƠNG 2: BỘ NHỚ VI ĐIỀU KHIỂN PIC 16F877A

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)

2.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:

Trang 4

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.1.1 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:

Trang 5

Bảng 1: Tập hợp tấc cả 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:

Trang 6

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)

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

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

Trang 7

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

Để 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ớ

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

Trang 8

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

Trang 9

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 (opcode-toá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

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

2.1.2 Cấu trúc bộ nhớ và stack:

Trang 10

Hình 2: Tổ chức bộ nhớ chương trình và Stack 2.1.2.1 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

Trang 11

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

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ớ:

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

2.1.2.3 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

*****************

Trang 12

t1m movlw d'2' ;(1) Set loop cnt1

movwf cnt1m ;(1) Save loop cnt1

tm1lp1 movlw d'249' ;(1)*2 Set loop cnt2

movwf cnt500u ;(1)*2 Save loop cnt2

tm1lp2 nop ;(1)*249*2 Time adjust nop ;(1)*249*2 Time adjust decfsz cnt500u,f ;(1)*249*2 cnt500u-1=0

?

goto tm1lp2 ;(2)*248*2 No, continue decfsz cnt1m,f ;(1)*2 cnt1m-1=0 ? goto tm1lp1 ;(2) No Continue return ;(2) Yes Cnt end ;Total

2501*0.4usec=1msec

***************

t100m movlw d'100' ;Set loop counter

movwf cnt100m ;Save loop counter

tm2lp call t1m ;1msec subroutine

decfsz cnt100m,f ;cnt100m - 1 = 0 ?

goto tm2lp ;No Continue

return ;Yes Count end

Trang 13

;************* 500msec Timer Subroutine

***************

t500m movlw d'5' ;Set loop counter

movwf cnt500m ;Save loop counter

tm3lp call t100m ;100msec subroutine

decfsz cnt500m,f ;cnt500m - 1 = 0 ?

goto tm3lp ;No Continue

return ;Yes Count end

đã 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)

Trang 14

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

2.1.2.4 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 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

2.2 Tập lệnh vi điều khiển PIC:

2.2.1 Thời gian thực hiện 1 lệnh:

Chu kì thực hiện 1 lệnh gồm 4 bước, kí hiệu là Qi, i=1-4:

- Q1: thời gian giải mã lệnh

- Q2: thời gian đọc lệnh

- Q3: thời gian thực thi dữ liệu

- Q4: thời gian viết lệnh

Mỗi bước tương ứng với 1 chu kì xung của vi điều khiển

Trang 15

Nếu dùng bộ dao động xung thạch anh có tần số f=4MHZ

Chu kì xung =1/tần số xung=1/4MHz

Chu kì lệnh = 4 * chu kì xung= 4/4MHZ= 1us (micro giây)

Hầu như tất cả các lệnh trong 35 lệnh của vi điều khiển PIC16F thực hiện trong 1 chu kì lệnh trừ 1 số lệnh đặc biệt như lệnh CALL, GOTO, RETURN, RETFI,RETLW mất 2 chu kì lệnh

2.2.2 Tập lệnh:

Xem theo datasheet

Trang 17

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ừ 180h-19Fh trong bank 3

- 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

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

Trang 18

ADDWF PORTA,1

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)

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ớ

2.3.2 Đị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ẽ

Trang 19

á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ụ:

MOVLW 0x30

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

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

0x30

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:

Trang 20

MOVLW 0x30

MOVWF FSR

CLRF INDF;

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 đó

Trang 21

CHƯƠNG 3: LẬP TRÌNH HỢP NGỮ 3.1 Dạng số trong chương trình 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:

3.3 Khai báo biến,hằng số:

Có một số phương pháp đặt biến, hằng số như sau:

Trang 22

Variable Tên hằng, biến = [biểu thức hoặc số]

- 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

Trang 23

Ví dụ: Chương trình dịch sẽ báo lỗi:

Count equ Count set Nhưng thế này thì không báo lỗi

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

Trang 24

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 nhớ RAM Như ta biết địa chỉ dành cho các biến phải ở trong vùng các thanh ghi mục đích chung:

Trong bank 0: 0x20->0x7f

Bank 1: 0xA0->0xEF Bank 2: 0x120->0x16F Bank 3: 0x1A0-0x1EF

Do đó giá trị khởi tạo cho các biến hằng khi khai báo cũng phải nằm trong vùng này

- Khi làm việc với các biến hằng cần phải nhớ địa chỉ của thanh ghi trong lệnh Nếu đang thao tác với thanh ghi thuộc bank nhớ i (i=0-3) chuyển sang lệnh tiếp theo làm việc với một thanh ghi khác thuộc bank nhớ j (j=0-3 và j#i) cần phải có lệnh chuyển bank nhớ như trong chương 2 đã giới thiệu

3.4 Chỉ dẫn biên dịch chương trình ORG:

Cách thức:

ORG địa chỉ 1

Lệnh 1 Lệnh 2 - Lệnh n

ORG địa chỉ 2

Lệnh m Lệnh m+1 -

Trang 25

Miêu tả: chỉ dẫn biên dịch này để điều khiển chương trình dịch MPLAB phân

bố các lệnh nằm sau ORG (ở đây là lệnh 1, lệnh 2, lệnh n) và trước một chỉ dẫn ORG tiếp theo (ORG địa chỉ 2) vào bộ nhớ chương trình từ địa chỉ bắt đầu

là địa chỉ 1

3.5 Nhãn:

Nhãn-label: là chuỗi kí tự do người lập trình đánh vào để đánh dấu một chuỗi thao tác lệnh nào đó hoặc 1 chương trình con nào đó Nhãn còn được dùng trong các câu lệnh goto và call:

GOTO nhãn CALL nhãn

Trang 26

- Không được bắt đầu bằng các con số 0-9, *, & , giữa các kí tự không có các

kí tự đặc biệt

- Không được giống các từ đặc biệt của chương trình như ORG, các lệnh v.v

3.6 Cấu trúc của một chương trình hợp ngữ:

Cấu trúc cơ bản gồm các phần như sau:

; DUA FILE LIET KE VAO

#include p16f877a.inc ; chỉ dẫn bao gồm file định nghĩa chip vi điều khiển

; KHAI BAO CAU HINH

CONFIG _HS_OSC & _WDT_OFF &_LVP_OFF

; KHAI BAO BIEN O DAY

; DIA CHI BIEN O VUNG NHO BIEN BANK0

cblock 0x21

vong1, vong2, vong3

endc

variable giatricong=0x25

;CHUONG TRINH VI DIEU KHIEN CHAY TAI DAY

org 0x000; CHI DAN BIEN DICH

; NHAY TOI CHUONG TRINH CHINH

goto main

; chi dan bien dich

; CHUONG TRINH CHINH BAT DAU TU DAY

Trang 28

Thực ra chỉ dẫn này ra lệnh cho MPLAB copy toàn bộ nội dung của file

“C:\Program Files\Microchip\MPASM Suite\p16f877a.inc” vào phần đầu

của chương trình vi điều khiển

Nội dung của file này thực ra là định nghĩa các thanh ghi và các cài đặt trong chương trình

Chúng ta xem lệnh trong vi điều khiển như sau:

MOVLW B’00001111

MOVWF PORTA,1

Trang 29

Vi điều khiển không biết từ “PORTA” là gì cả, nó chỉ biết rằng thanh ghi đặc biệt có địa chỉ 0x05 trong bộ nhớ RAM là nơi lưu trữ trạng thái và điều khiển của các chân trên PORTA

Như vậy để can thiệp đến các chân này người lập trình phải gửi lệnh

MOVLW B’00001111

MOVWF 0x05,1 Tuy nhiên, có rất nhiều thanh ghi đặc biệt trong vi điều khiển, người sử dụng không thể nhớ được địa chỉ của nó để mà viết lệnh Để tiện cho người lập trình, chương trình biên dịch MPLAB chuẩn bị sẵn file định nghĩa p16f877a.inc trong đó định nghĩa:

PORTA equ h’00005

Và người lập trình chỉ việc đưa dòng: #include p16f877a.inc

Toàn bộ nội dung của file trên sẽ được đưa vào chương trình và khi đó người dùng viết các dòng lệnh có PORTA thì trình dịch sẽ tự động hiểu là 0x05 (vì PORTA đã định nghĩa bằng 5)

Khi ta dùng vi điều khiển khác ví dụ như pic 18f4431 ta đơn giản thay đổi

dòng bao hàm bằng: #include p18f4431inc

- Phần thứ hai, khai báo cấu hình cho vi điều khiển

CONFIG _HS_OSC & _WDT_OFF &_LVP_OFF

Mục đích của khai báo cấu hình là cài đặt một số chế độ hoạt động của vi điều khiển như chọn nguồn xung dao động, tắt đồng hồ watchdog timer v.v

Các tham số cài đặt cho config xem ở file header

- Phần thứ ba, khai báo biến, sử dụng các phương pháp khai báo như đã giới

thiệu ở các mục trước

- Phần thứ tư, chương trình, kết thúc bởi nhãn END

- Các chương trình con phải đặt trước END, kết thúc chương trình con có

lệnh return

- Trong chương trình có sử dụng các chỉ dẫn biên dịch ORG để phân bố bộ nhớ cho chương trình như đã đề cập trước đây

Trang 30

3.7 Dạng thức của 1 lệnh:

Có 3 loại lệnh:

- Lệnh thao tác với byte

- Lênh thao tác với bit

- Lệnh thao tác với số

3.7.1 Lệnh thao tác với byte:

Dạng lệnh: lệnh f,d

Trừ các lệnh: CLRW ( xóa thanh ghi W)

CLRF f (xóa thanh ghi f) NOP (lệnh không làm gì) Trong đó:

- Lệnh là từ gợi nhớ về phép toán thực hiện Ví dụ: ADDWF là cộng thanh

ghi W và thanh ghi F

- F: là địa chỉ của thanh ghi (trong bộ nhớ RAM) được thao tác trong lệnh

Ví dụ: ADDWF PORTA,1

ADDWF 0x05,1

Cả hai lệnh trên là giống nhau: Cộng thanh ghi w và thanh ghi có địa chỉ 0x05 trong bộ nhớ RAM Vi điều khiển chỉ biết địa chỉ 0x05 không biết PORTA là gì

- d: chỉ ra kết quả của lệnh chứa ở đâu

o Nếu d=0: kết quả chứa trong w

o Nếu d=1: kết quả chứa trong thanh ghi f

o Mặc định: d=1, kết quả chứa trong thanh ghi f

Ví dụ: ADDWF 0x05,0

W=W+thanh ghi có địa chỉ 0x05 ADDWF 0x05,1

Thanh ghi có địa chỉ 0x05=W+ Thanh ghi có địa chỉ 0x05

3.7.2 Lệnh thao tác với bit:

Dạng lệnh: lệnh f,b

Trang 31

Trong đó:

- Lệnh là từ gợi nhớ về phép toán thực hiện

- f: địa chỉ thanh ghi

- Lệnh là từ gợi nhớ về phép toán thực hiện

- Số là tham số trong phép toán

Trang 32

Miêu tả: kiểm tra bít ở vị trí bít trên thanh ghi, nếu bít đó bằng 0 bỏ qua lệnh 1 thực hiện lệnh 2, nếu bít đó bằng 1 thực hiện lệnh 1 (theo kiểu tuần tự) Chú ý là khi bit =0, lệnh này mất 2 chu kì lệnh, khi bit =1 lệnh này mất 1 chu

Miêu tả: Lệnh này trước hết tự động giảm giá trị của thanh ghi đi 1 đơn vị

và sau đo kiểm tra nếu thanh ghi đó bằng 0 bỏ qua lệnh 1 thực hiện lệnh 2, nếu khác 0 thực hiện lệnh 1 (theo kiểu tuần tự như bình thường)

Chú ý là khi thanhghi =1, lệnh này mất 2 chu kì lệnh, khi thanhghi#1 lệnh này mất 1 chu kì lệnh

- Dạng lệnh:

INCFSZ địa chỉ thanh ghi,hướng

Lệnh 1

Lệnh 2

Miêu tả: Lệnh này trước hết tự động tăng giá trị của thanh ghi đi 1 đơn vị

và sau đo kiểm tra nếu thanh ghi đó bằng 0 bỏ qua lệnh 1 thực hiện lệnh 2, nếu khác 0 thực hiện lệnh 1 (theo kiểu tuần tự như bình thường)

3.8.3 Lệnh nhảy không điều kiện GOTO:

Dạng lệnh: GOTO nhãn

Miêu tả: nhảy đến đoạn chương trình bắt đầu bởi nhãn

Để hiểu rõ đoạn chương trình trên ta có ví dụ sau:

START:

BSF PORTB,1

CALL DELAY

Trang 33

000D 200F CALL 0xf 34: CALL DELAY

000E 280A GOTO 0xa 35: GOTO START

Cột thứ nhất chứa địa chỉ của lệnh Cột thứ 3 là lệnh thực sự đã được phân giải

Ta thấy lệnh nằm ngay sau nhãn là BSF PORTB,1 có địa chỉ là 0x0a trong bộ nhớ chương trình

Vì vậy trong cột 3, ta có lệnh GOTO 0xa

Như vậy dạng lệnh thực sự là GOTO k

Khi gặp lệnh này: PC<10:0>=k; PC<12:11>=PCLATCH<4:3>

Tóm lại có thể giải thích lại như sau:

Khi gặp lệnh: goto nhãn

Trong trường hợp trên là goto start

MPLAB tính ra địa chỉ của lệnh nằm ngay sau nhãn start, giả sử đó là k

Trong trường hợp trên là lệnh BSF PORTB,1 có địa chỉ k=0x0a

MPLAB điều khiển đưa giá trị k vào thanh ghi PC: PC=k

Trang 34

Do đó chương trình vi điều khiển sẽ chạy lệnh BSF PORTB,1

Mã hóa lệnh: 10 1kkk kkkk kkkk

Nhìn vào mã hóa lệnh ta thấy địa chỉ k gồm 11 bit kkk kkkk kkkk

Như vậy thực ra chỉ 11 bit đầu của thanh ghi PC là chứa giá trị k:

Như vậy lệnh GOTO UPDATE nằm ở địa chỉ 0x0E

Như vậy khi gặp lệnh này, 2 bit của thanh ghi PCLATCH<4:3>=00

Lệnh nằm sau nhãn UPDATE là MOVLW 0xFF nằm ở địa chỉ 0x800 (do có chỉ dẫn biên dịch ORG 0x800)

Suy ra địa chỉ là: 0x800=1000 0000 0000

Trang 35

Như vậy khi gặp lệnh GOTO UPDATE, thanh ghi PC được nạp giá trị:

PC<10:0> = 000 0000 0000

PCLATCH vẫn không đổi: PCLATCH<4:3>=00

Suy ra, PC<12:11>=PC<4:3>=00

Suy ra: PC=0 0000 0000 0000 =0x00

Vậy chương trình nhảy đến địa chỉ 0x00!!!!!

Chắc chắn là chương trình sẽ không chạy được đoạn lệnh nằm sau UPDATE

Để chạy đúng, đơn giản là ta phải dùng lệnh cho PCLATCH<4:3>=01

Đoạn chương trình đúng sẽ như sau:

Trang 36

PC+1 vào ngăn xếp để sau khi thực hiện đoạn chương trình con, vi điều khiển chạy về chương trình chính và thực hiện lệnh kế tiếp đó

3.8.5 Các toán tử:

Các kí hiệu +,-,*, / v.v.v gọi là các toán tử

Chương trình hợp ngữ MPLAB qui định một tập các toán tử như sau:

Qua bảng trên ta dễ dàng hiểu được chức năng của từng toán tử

Ở đây chỉ lưu ý một số toán tử đặc biệt như sau:

- Toán tử $: thường đi kèm với lệnh goto

Trang 37

Goto $ Sau khi thực hiện lệnh này, thanh ghi PC giữ giá trị không đổi: PC=PC

(Thông thường sau khi thực hiện 1 lệnh, PC=PC+1, vi điều khiển thực hiện lệnh tiếp theo)

Goto $-n Sau khi thực hiện các lệnh này, PC=PC-$, như vậy sau khi thực hiện lệnh này, vi điều khiển sẽ nhảy đến thực hiện lệnh trước lệnh hiện tại n lệnh

Tương tự với:

Goto $+n

Ví dụ:

decfsz bien1,F goto $-1 decfsz bien2,F goto $-3 Như vậy khi gặp lệnh goto $-1, vi điều khiển nhảy về thực hiện lệnh trước đó nằm cách 1 lệnh decfsz bien1,f, khi gặp lệnh goto $-3, vi điều khiển nhảy về thực hiện lệnh trướ đó nằm cách 3 lệnh tức là sẽ thực hiện lệnh decfsz bien1,f

- Toán tử !: hay được dùng trong câu điều kiện

If(!(a= =b)) nghĩa là nếu a!=b

3.9 Chu kì lệnh:

Chu kì thực hiện 1 lệnh gồm 4 bước, kí hiệu là Qi, i=1-4:

- Q1: thời gian giải mã lệnh

- Q2: thời gian đọc lệnh

Trang 38

- Q3: thời gian thực thi dữ liệu

- Q4: thời gian viết dữ liệu

Mỗi bước tương ứng với 1 chu kì xung của vi điều khiển Xung dao động của vi điều khiển được tạo ra từ mạch dao động bên ngoài như thạch anh, mạch RC hoặc mạch dao động bên trong (Phần cấu hình cho dao động sẽ được đề cập ở mục khác)

Nếu dùng bộ dao động xung thạch anh có tần số f=4MHZ

Chu kì xung =1/tần số xung=1/4MHz

Chu kì lệnh = 4 * chu kì xung= 4/4MHZ= 1us (micro giây)

Hầu như tất cả các lệnh trong 35 lệnh của vi điều khiển PIC16F thực hiện trong 1 chu kì lệnh trừ 1 số lệnh đặc biệt như lệnh CALL, GOTO, RETURN, RETFI,RETLW mất 2 chu kì lệnh Ngoài ra còn có một số lệnh khi thì thực hiện trong 1 chu kì lệnh khi thì 2

Đó là các lệnh DECFSZ, INCFSZ, BTFSZ, BTFSC (Xem tập lệnh trang datasheet 16f877a)

158-Ta lấy lệnh DECFSZ để giải thích cho dễ hiểu:

GOTO nhan1 GOTO nhan2

Lệnh đầu tiên DECFSZ giảm thanh ghi bien đi 1 đơn 1: bien=bien-1

Sau đó lệnh này kiểm tra bien:

Nếu bien=0 nhảy qua 1 lệnh, tức là nhảy đến và thực hiện lệnh GOTO nhan2 Nếu bien#0 thì không nhảy tức là thực hiện lệnh GOTO nhan2

Như vậy nếu bien#0 (tức là trước khi gặp lệnh này bien #1)thì vi điều khiển mất một chu kì lệnh để thực hiện lệnh(để thực hiện thao tác trừ)

Nếu bien=0 (tức là trước khi gặp lệnh này bien=1) thì vi điều khiển mất 2 chu kì lệnh để thực hiện lệnh(1 chu kì lệnh để thao tác trừ + 1 chu kì lệnh để nhảy)

Thời gian thực hiện lệnh INCFSZ, BTFSC,BTFSS cũng tương tự như vậy

Trang 39

3.10 Chương trình con tạo thời gian trễ:

Trong thực tế viết chương trình điều khiển cho một số thiết bị ta hay tạo một khoảng thời gian trễ

Ví dụ: sự kiện 1

Chờ một khoảng thời gian

sự kiện 2

Vì vậy đòi hỏi ta phải có một chương trình con để tạo thời gian trễ này

Ý tưởng để có một chương trình con tạo thời gian trễ là:

Muốn tạo ra một khoảng thời gian trễ n (micro giây) ta tạo một chương trình mà thời gian để thực hiện xong nó là n (micro giây)

Ta đã biết: một lệnh thực hiện trong 1 chu kì lệnh (trừ một số lệnh đặc biệt), một chu kì lệnh tính theo đơn vị micro giây

Ví dụ: nếu dùng bộ dao động ngoài sử dụng thạch anh có tần số fosc=4Mhz

Suy ra, chu kì lệnh= 4*chu kì xung= 4/tần số xung= 4/4Mhz=1 mico giây

Như vậy để tạo ra khoảng thời gian n micro giây đơn giản ta tạo ra một chương trình mà thời gian thực hiện nó là n chu kì lệnh

Ví dụ: để tạo thời gian trễ 20 mico giây

Tuy nhiên cách làm đó thì hơi thủ công, và ta cũng không có thời gian để mà đánh

n dòng NOP như vậy (ví dụ: n=200.000!!!!)

Ta phải dùng các lệnh khác với thuật toán phức tạp hơn Ta đi vào từng bước khảo sát phương pháp này

3.10.1 Vòng 1:

Ta có các câu lệnh sau:

Trang 40

decfsz vong1,F

goto $-1

Trong đó vong1 là biến đã được tạo ra trước đó

Ta tính thử thời gian thực hiện 2 lệnh trên:

Như đã bàn ở các mục trước lệnh goto mất 2 chu kì lệnh, lệnh DECFSZ f,z mất 1 chu kì lệnh khi f #0 và mất 2 chu kì lệnh khi f=0

Giả sử ban đầu:

Như vậy mất tổng cộng: (1+2)+2= 5 chu kì lệnh

Giả sử ban đầu:

NO

Ngày đăng: 24/04/2014, 15:28

HÌNH ẢNH LIÊN QUAN

Hình 1: Cấu trúc chung của vi điều khiển - Giáo trình hợp ngữ - Lập trình PIC 16F877A
Hình 1 Cấu trúc chung của vi điều khiển (Trang 1)
Bảng 1: Tập hợp tấc cả các lệnh - Giáo trình hợp ngữ - Lập trình PIC 16F877A
Bảng 1 Tập hợp tấc cả các lệnh (Trang 5)
Hình 2: Tổ chức bộ nhớ chương trình và Stack  2.1.2.1  Thanh ghi bộ đếm chương trình: - Giáo trình hợp ngữ - Lập trình PIC 16F877A
Hình 2 Tổ chức bộ nhớ chương trình và Stack 2.1.2.1 Thanh ghi bộ đếm chương trình: (Trang 10)
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 - Giáo trình hợp ngữ - Lập trình PIC 16F877A
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 (Trang 19)
Hình 2.1: Hiển thị led đơn - Giáo trình hợp ngữ - Lập trình PIC 16F877A
Hình 2.1 Hiển thị led đơn (Trang 49)
Hình 2.3: Cấu tạo của 2 loại led 7 đoạn  4.2.2 Hiển thị 1 led 7 đoạn dùng vi điều khiển: - Giáo trình hợp ngữ - Lập trình PIC 16F877A
Hình 2.3 Cấu tạo của 2 loại led 7 đoạn 4.2.2 Hiển thị 1 led 7 đoạn dùng vi điều khiển: (Trang 50)
Hình 2.5: Hiển thị 2 led 7 đoạn - Giáo trình hợp ngữ - Lập trình PIC 16F877A
Hình 2.5 Hiển thị 2 led 7 đoạn (Trang 52)
Hình 2.6: Các chân LCD  4.3.1 Các chân cơ bản của LCD 2 dòng 16 kí tự: - Giáo trình hợp ngữ - Lập trình PIC 16F877A
Hình 2.6 Các chân LCD 4.3.1 Các chân cơ bản của LCD 2 dòng 16 kí tự: (Trang 54)
Sơ đồ như sau: - Giáo trình hợp ngữ - Lập trình PIC 16F877A
Sơ đồ nh ư sau: (Trang 60)

TỪ KHÓA LIÊN QUAN

TRÍCH ĐOẠN

TÀI LIỆU CÙNG NGƯỜI DÙNG

TÀI LIỆU LIÊN QUAN

w