vi xu ly

10
Vi điều khiển và con người giao tiếp thông qua ngôn ngữ lập trình hợp ngữ. Để vi điều khiển có thể hiểu một chương trình được viết bằng hợp ngữ, nó phải được biên dịch thành ngôn ngữ được biểu diễn bởi các con số 0 và 1. Hợp ngữ và trình biên dịch hợp ngữ không phải là một. Hợp ngữ nhắc tới là một tập các quy tắc được sử dụng để viết chương trình cho Vi điều khiển, trong khi trình biên dịch hợp ngữ là một chương trình được cài đặt trên máy tính cá nhân được sử dụng để chuyển đổi các câu lệnh hợp ngữ thành ngôn ngữ 0 và 1. Một chương trình được biên dịch cũng được gọi là mã máy. Một chương trình là một tệp dữ liệu được lưu trên ổ đĩa cứng của máy tính (hoặc trong bộ nhớ của Vi điều khiển nếu được nạp) được viết theo các quy tắc của hợp ngữ hoặc một vài ngôn ngữ lập trình khác. Hợp ngữ là dễ hiểu đối với con người bởi nó bao gồm các từ có nghĩa và các ký hiệu alphabet. Tất cả các câu lệnh hợp ngữ được biên dịch thành chuỗi các số 0 và 1. Một tệp dữ liệu sử dụng cho việc lưu trữ chương trình được biên dịch được gọi là tệp thực thi (HEX). Sau khi được tạo ra, tệp dữ liệu được nạp vào Vi điều khiển thông qua các mạch nạp. Các chương trình hợp ngữ có thể được viết bằng mọi trình soạn thảo văn bản có khả năng tạo ra các tệp dữ liệu ASCII trên đĩa cứng hoặc trong một môi trường làm việc chuyên dụng. Các thành phần hợp ngữ Một chương trình được viết bằng ngôn ngữ assembly bao gồm một vài yếu tố được diễn dịch trong quá trình biên dịch chương trình thành tệp tin dữ liệu thực thi. Việc sử dụng những yếu tố này đòi hỏi những quy tắc nghiêm ngặt và cần phải đặc biệt chú ý đến chúng trong khi viết chương trình để tránh lỗi. Cấu trúc hợp ngữ

Upload: hoang-manh

Post on 07-Dec-2015

213 views

Category:

Documents


0 download

DESCRIPTION

fda

TRANSCRIPT

Page 1: Vi xu ly

Vi điều khiển và con người giao tiếp thông qua ngôn ngữ lập trình hợp ngữ. Để vi điều khiển có thể hiểu một chương trình được viết bằng hợp ngữ, nó phải được biên dịch thành ngôn ngữ được biểu diễn bởi các con số 0 và 1. Hợp ngữ và trình biên dịch hợp ngữ không phải là một. Hợp ngữ nhắc tới là một tập các quy tắc được sử dụng để viết chương trình cho Vi điều khiển, trong khi trình biên dịch hợp ngữ là một chương trình được cài đặt trên máy tính cá nhân được sử dụng để chuyển đổi các câu lệnh hợp ngữ thành ngôn ngữ 0 và 1. Một chương trình được biên dịch cũng được gọi là mã máy. Một chương trình là một tệp dữ liệu được lưu trên ổ đĩa cứng của máy tính (hoặc trong bộ nhớ của Vi điều khiển nếu được nạp) được viết theo các quy tắc của hợp ngữ hoặc một vài ngôn ngữ lập trình khác. Hợp ngữ là dễ hiểu đối với con người bởi nó bao gồm các từ có nghĩa và các ký hiệu alphabet. Tất cả các câu lệnh hợp ngữ được biên dịch thành chuỗi các số 0 và 1. Một tệp dữ liệu sử dụng cho việc lưu trữ chương trình được biên dịch được gọi là tệp thực thi (HEX). Sau khi được tạo ra, tệp dữ liệu được nạp vào Vi điều khiển thông qua các mạch nạp. Các chương trình hợp ngữ có thể được viết bằng mọi trình soạn thảo văn bản có khả năng tạo ra các tệp dữ liệu ASCII trên đĩa cứng hoặc trong một môi trường làm việc chuyên dụng.

Các thành phần hợp ngữ

Một chương trình được viết bằng ngôn ngữ assembly bao gồm một vài yếu tố được diễn dịch trong quá trình biên dịch chương trình thành tệp tin dữ liệu thực thi. Việc sử dụng những yếu tố này đòi hỏi những quy tắc nghiêm ngặt và cần phải đặc biệt chú ý đến chúng trong khi viết chương trình để tránh lỗi.

Cấu trúc hợp ngữ

Như đã đề cập, chúng ta phải thực hiện một số quy định cụ thể cho phép quá trình biên dịch sang mã thực thi (HEX) để chạy mà không có lỗi. Các quy tắc bắt buộc chính là trình tự sắp đặt các câu lệnh để tạo nên một chương trình hợp ngữ. Có một số quy tắc sau:

Mỗi dòng chương trình có độ dài tối đa là 255 ký tự.

Mỗi dòng chương trình được dịch phải bắt đầu cùng với một ký tự, nhãn, ghi nhớ và chỉ thị.

Page 2: Vi xu ly

Đoạn văn bản sau dấu “;” trong một dòng chương trình đại diện cho một lời chú thích và sẽ được bỏ qua bởi trình dịch (không được dịch).

Tất cả các thành phần của một dòng chương trình (các nhãn, các câu lệnh) phải được phân tách bởi ít nhất một ký tự trắng. Thường sử dụng dấu TAB để thực hiện việc này.

Nhãn

Một nhãn đại diện cho một phiên bản văn bản của một vài địa chỉ trong bộ nhớ ROM hoặc RAM. Mỗi nhãn phải bắt đầu với một ký tự alphabet hoặc “_” và có độ dài tối đa 32 kí tự.

Nó là đủ để nhập tên của một nhãn thay vì địa chỉ 16-bit trong câu lệnh gọi một vài hàm con hoặc bước nhảy. Nhãn với tên giống nhau nên được viết tại đầu dòng chương trình nơi mà một hàm con bắt đầu hay nơi một lệnh nhảy được thực thi. Quy luật chung đó là các nhãn nên được đặt với tên dễ dàng nhận biết.

Trong quá trình biên dịch chương trình, trình dịch sẽ tự động thay thế các nhãn bởi địa chỉ tương ứng.

Lời chú thích

Lời chú thích thường là một đoạn văn bản giải thích được viết bởi lập trình viên để làm cho chương trình rõ nghĩa và dễ hiểu hơn. Không nhất thiết là phải chú giải mọi dòng lệnh. Khi có ba hoặc bốn dòng mã làm việc cùng nhau để thực hiện một số nhiệm vụ cấp độ cao hơn, nó là tốt hơn để có một nhận xét tại đầu nhóm dòng lệnh. Vì vậy, chúng ta sẽ chỉ thêm lời chú thích nếu cần thiết và phải bắt đầu với ký tự “;”. Các lời nhận xét được thêm vào mã nguồn hợp ngữ không được biên dịch vào mã máy.

Câu lệnh

Các câu lệnh được định nghĩa cho mỗi dòng Vi điều khiển bởi nhà sản xuất. Vì vậy, người sử dụng phải tuân theo các quy tắc sử dụng của họ. Cách viết các

Page 3: Vi xu ly

câu lệnh được gọi là cú pháp lệnh. Trong ví dụ bên dưới, các câu lệnh “movlp” và “goto” được PIC 16F887 nhận ra là có lỗi khi mà cú pháp lệnh được viết sai.

Các toán hạng

Toán hạng là một giá trị hay một đối số. Các toán hạng có thể là một thanh ghi, biến, hằng số chữ, nhãn hãy địa chỉ bộ nhớ.

Các chỉ thị

Không giống như các câu lệnh được ghi vào bộ nhớ chương trình trên chip sau khi biên dịch, các chỉ thị là các lệnh của hợp ngữ và không ảnh hưởng trực tiếp tới hoạt động của Vi điều khiển. Một vài trong số chúng phải được sử dụng trong mọi chương trình trong khi có những chỉ thị khác chỉ được sử dụng để tạo sự thuận lợi hay cải thiện hoạt động. Các chỉ thị được ghi tới cột dành riêng cho các câu lệnh. Mỗi dòng chương trình chỉ chứa một chỉ thị. Phần này sẽ chỉ giới thiệu một số chỉ thị thường được sử dụng nhất.

Chỉ thị LIST P

Chỉ thị này phải được viết tại điểm bắt đầu của mỗi chương trình. Nó có vai trò định nghĩa loại Vi điều khiển được sử dụng.

LIST P=16f887

Page 4: Vi xu ly

Chỉ thị EQU

Chỉ thị này được sử dụng để thay thế cho một giá trị số bởi một ký tự. Theo cách này, một vài vị trí cụ thể trong bộ nhớ được gán với một tên.

MAXIMUM equ H’25

Điều này có nghĩa rằng, một vị trí bộ nhớ tại địa chỉ 25 (hex) được gán với tên “MAXIMUM”. Mỗi khi có sự xuất hiện của nhãn “MAXIMUM” trong chương trình sẽ được dịch bởi trình dịch như là địa chỉ 25 (MAXIMUM = H’25). Các ký hiệu có thể được định nghĩa theo cách này chỉ một lần trong một chương trình. Vì vậy, chỉ lệnh này thường được sử dụng tại thời điểm bắt đầu chương trình.

Chỉ thị ORG

Chỉ thị này quy định một vị trí trong bộ nhớ chương trình nơi mà chương trình theo sau chỉ thị được đặt.

ORG 0x100

START ... ...

...

ORG 0x1000

TABLE ...

...

Chương trình này bắt đầu tại vị trí 0x100. Bảng (TABLE) chứa dữ liệu được lưu tại vị trí 1024 (1000h)

Chỉ thị END

Mỗi chương trình phải được kết thúc bởi chỉ thị này. Khi chương trình gặp chỉ thị này, trình dịch lập tức sẽ kết thúc quá trình biên dịch.

...

END ; kết thúc chương trình

Chỉ thị IF, ENDIF và ELSE

Những chỉ thị này được sử dụng để tạo ra các khối điều kiện trong một chương trình. Mỗi một trong các khối này bắt đầu cùng với chỉ thị IF và kết thúc bởi chỉ thị ENDIF hoặc ELSE. Một câu lệnh hoặc một ký hiệu (trong ngoặc đơn) theo sau các chỉ thị IF đại diện cho một điều kiện quyết định phần nào của chương trình được biên dịch:

Nếu câu lệnh là đúng hoặc giá trị của biểu ký hiệu bằng 1, chương trình sẽ biên dịch tất cả các câu lệnh được viết trước chỉ chỉ ELSE hoặc ENDIF.

Nếu câu lệnh là sai hay giá trị của ký hiệu bằng 0, chỉ có các câu lệnh viết sau chỉ thị ELSE hoặc ENDIF được biên dịch.

Page 5: Vi xu ly

IF (VERSION > 3)

CALL Table_2

CALL

ENDIF

...

Macro và chương trình con

Cùng một trình tự các câu lệnh tính toán thường được sử dụng nhiều lần trong một chương trình. Các lập trình viên cần phải chú ý tới các chi tiết nhỏ nhất khi viết chương trình, bởi chỉ một câu lệnh hoặc tên nhãn sai có thể khiến chương trình làm việc không chính xác hoặc không làm việc. Vì vậy sẽ là bớt tẻ nhạt và tránh được nhưng lỗi không đáng có các macro và chương trình con được sử dụng.

Macro

Macro chứa các biểu tượng được người lập trình định nghĩa để đại diện cho các dòng văn bản. Nó được định nghĩa bằng cách sử dụng chỉ thị macro với tên và các đối số nếu cần. Macro phải được định nghĩa trước khi được sử dụng. Một khi macro đã được định nghĩa, tên của nó có thể được sử dụng trong chương trình. Khi trình biên dịch gặp tên của macro, nó sẽ thay thế bởi chuỗi các câu lệnh thích hợp và xử lý khi chúng xuất hiện trong chương trình.

tên_macro macro arg1, arg2...

...

chuỗi câu lệnh

...

endm

Ví dụ dưới đây chỉ ra bốn macro. Hai macro đầu tiên được sử dụng để lựa chọn các bank, macro thứ ba cho phép ngắt và macro cuối cùng cấm ngắt.

bank0 macro ; macro bank0

bcf STATUS, RP0 ; xóa bit RP0

bcf STATUS, RP1 ; xóa bit RP1

endm ; kết thúc macro

bank1 macro ; macro bank1

bsf STATUS, RP0 ; set bit RP0

bcf STATUS, RP1 ; xóa bit RP1

endm ; kết thúc macro

Page 6: Vi xu ly

enableint macro ; cho phép ngắt toàn cục

bsf INTCON, 7 ; set bit

endm ; kết thúc macro

disableint macro ; cấm ngắt toàn cục

bcf INTCON, 7 ; xóa bit

endm ; kết thúc macro

Các macro được định nghĩa theo cách này có thể được lưu trong một tệp dữ liệu cụ thể với phần mở rộng INC. Với ví dụ trên, bốn macro không có các đối số. Tuy nhiên, trong một số trường hợp các macro có thể chứa các đối số nếu cần.

Ví dụ dưới đây chỉ ra các macro với các đối số. Pin được cấu hình là ngõ vào nếu bit tương ứng của thanh ghi TRIS được set tới mức logic 1. Ngược lại, nó được cấu hình là ngõ ra.

input macro arg1, arg2 ; macro input

bank1 ; macro bank1 có chứa thanh ghi TRIS

bsf arg1, arg2 ; set bit được chỉ định (1 = vào)

bank0 ; macro lựa chọn bank0

endm ; kết thúc macro

output macro arg1,arg2 ; macro output

bank1 ; macro bank1 có chứa thanh ghi TRIS

bcf arg1,arg2 ; xóa bit chỉ định (0 = ra)

bank0 ; macro chọn bank0

endm ; kết thúc macro

Macro với các đối số có thể được gọi theo cách sau đây:

...

output TRISB, 7 ; Pin RB7 được cấu hình là ngõ ra

...

Khi gọi macro này, đối số đầu tiên được chỉ định TRISB sẽ thay cho đối số arg1 trong macro định nghĩa. Tương tự, số 7 thay thế cho arg2, và đoạn mã dưới đây được tạo ra.

...

Page 7: Vi xu ly

bsf STATUS, RP0 ; set bit RP0 = BANK1

bcf STATUS, RP1 ; xóa bit RP0 = BANK1

bcf TRISB, 7 ; cấu hình RB7 là ngõ ra

bcf STATUS,RP0 ; xóa bit RP0 = BANK0

bcf STATUS,RP1 ; xóa bit RP1 = BANK0

...

Như vậy với việc sử dụng các macro, chương trình sẽ dễ đọc và linh hoạt hơn. Nhược điểm chính của macro là nó chiếm nhiều dung lượng bộ nhớ bởi mỗi tên macro trong chương trình sẽ được thay thế bởi mã xác định trước của nó. Do đó có một thực tế là các chương trình lớn sẽ là phức tạp hơn nếu sử dụng các macro.

Hàm con

Hàm con bao gồm một chuỗi các câu lệnh, bắt đầu bởi một nhãn (tên_chương_trình_con) và kết thúc với câu lệnh return hoặc retlw. Sự khác biệt chính giữa hàm con và macro đó là hàm con sẽ không được thay thế bởi mã của nó trong chương trình, mà chương trình sẽ nhảy tới hàm con để thực hiện nó. Điều này sẽ xảy ra mỗi khi trình dịch bắt gặp câu lệnh call tên_chương_trình_con trong chương trình. Khi gặp câu lệnh return, nó sẽ thoát khỏi chương trình con và tiếp tục thực hiện chương trình chính từ nơi mà nó nhảy tới chương trình con. Chương trình con được định nghĩa trước hoặc sau khi gọi.

Label ; tên của hàm con là ‘Label’

Chuỗi câu lệnh…

Chuỗi câu lệnh…

Chuỗi câu lệnh…

return hoặc retlw

Chương trình ví dụ dưới đây thực hiện phép tính cộng các biến 2 byte ARG1, ARG2 và lưu kết quả vào biến RES. Khi các biến 2 byte được sử dụng, điều cần thiết là phải định nghĩa byte cao và byte thấp. Chương trình này rất đơn giản. Trước tiên nó sẽ cộng các byte thấp hơn của các biến ARG1 và ARG2 và sau đó là các byte cao. Nếu tổng của 2 byte thấp lớn hơn 255 (giá trị lớn nhất của một byte) thì phần dữ sẽ được cộng tới biến RESH.

; chương trình cộng 2 số 16-bit

ARG1H ; byte cao của đối số 1

ARG1L ; byte thấp của đối số 1

ARG2H ; byte cao của đối số 2

Page 8: Vi xu ly

ARG2L ; byte thấp của đối số 2

RESH ; byte cao của kết quả

RESL ; byte thấp của kết quả

ORG 0x00 ; vector reset

goto Start

; ghi giá trị tới các biến

Start

movlw 0x01 ; ARG1=0x0104

movwf ARG1H

movlw 0x04

movwf ARG1L

movlw 0x07 ; ARG2=0x0705

movwf ARG2H

movlw 0x05

movwf ARG2L

; chương trình chính

Main

call Add16 ; gọi hàm con Add16

Loop goto Loop ; vòng lặp

Add16 ; hàm con để cộng 2 số 16-bit

clrf RESH ; RESH=0

movf ARG1L, w ; w=ARG1L

addwf ARG2L, w ; w=w+ARG2L

movwf RESL ; RESL=w

btfsc STATUS, C ; kiểm tra xem kết quả có lớn hơn 255?

incf RESH,f ; nếu lớn hơn, tăng RESH thêm 1

movf ARG1H, w ; w=ARG1H

addwf ARG2H, w ; w=w+ARG2

addwf RESH, f ; RESH=w

return ; trở lại từ hàm con

end ; kết thúc chương trình