You are on page 1of 8

CHƯƠNG 3

LẬP TRÌNH BẰNG HỢP NGỮ MCS51

Lập trình hợp ngữ (assembly language programming) cho họ vi điều khiển MCS51.
Một chương trình viết bằng hợp ngữ (chương trình hợp ngữ) là chương trình được viết
bằng việc sử dụng các câu lệnh trong tập lệnh của họ vi điều khiển với các mã lệnh dưới
dạng mã gợi nhớ.
Chương trình hợp ngữ thường được gọi là chương trình nguồn hay mã nguồn được
một chương trình biên dịch (chương trình dịch) dịch ra thành ngôn ngữ máy dưới dạng mã
nhị phân và được nạp vào bộ nhớ chương trình của vi điều khiển thông qua một máy nạp
chương trình (Programmer).

Hiện nay có rất nhiều chương trình biên dịch cho họ vi điều khiển MCS51 (Keil
µVision, RCHPSIM….) đã và đang được sử dụng. Tuy nhiên trong chương này sẽ sử dụng
chương trình Keil µVision3 để soạn thảo và biên dịch chương trình hợp ngữ. Keil µVision
được hình thành và phát triển từ năm 1985, phần mềm biên dịch này hỗ trợ cho nhiều dòng
vi điều khiển khác nhau với hai loại ngôn ngữ chính là hợp ngữ và C cho vi điều khiển.

3.1 Cấu trúc chương hợp ngữ


3.1.1 Quy tắc đặt tên nhãn, tên chương trình, biến, hằng số :
 Không được trùng với các từ khóa
 Không dài quá 31 ký tự, không phân biệt chữ hoa hay chữ thường
 Không tồn tại các dấu cách trong tên và các ký tự đặc biệt
 Tên thường bắt đầu các chữ cái và có tính chất gợi nhớ
 Riêng tên nhãn và tên chương trình phải kết thúc bằng dấu “:”

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


Có nhiều cách khai báo biến và hằng số trong chương trình hợp ngữ sử dụng Keil
µVision. Tuy nhiên để dễ nhớ người lập trình nên sử dụng câu lệnh khai báo với cú pháp:

Tên Biến EQU Giá trị ; chú thích

Tên Hằng số EQU Giá trị hằng ; chú thích

VD:
Buffer1 EQU 50h ; Biến Buffer1 được gán giá trị 50H
Constant_A EQU 10 ; Hằng số Constant_A được gán 10 (=0AH)
3.1.3 Khai báo chương trình con:

Cú pháp: Ví dụ:

Tên chương trình con: Add2_1byte_Hex:


; Biến (thanh ghi) vào :……………. ; Biến vào: R0, R1
; Biến (thanh ghi) ra: ……………… ; Biến ra : Acc ,C flag
; Biến (thanh ghi) thay đổi: ……….. ; Thanh ghi thay đổi: Acc, C flag
; ------------------------------------------------- ;--------------------------------------------

Câu lênh 1 Mov A, R0


Câu lệnh 2 Add A, R1
………… Ret
Câu lệnh n
Ret

3.1.4 Cấu trúc chương trình hợp ngữ:

;===========Tên chương trình ============ ;=====================================


org 00h
nop
sjmp Tên chương trình chính Vùng khai báo các Vector ngắt và các chương trình
phục vụ ngắt tương ứng
org 03h ; Ngắt Ex0
nop
reti

org 0bh ; Ngắt Timer0 Lưu ý:


nop  Khi một ngắt nào đó không dùng thì người
ljmp Tên ct Phục vụ ngắt / Reti viết chương trình phải kết thúc bằng lệnh
RETI (như ngắt EX0 và ngắt Serial)

org 13h ; Ngắt Ex1  Khi ngắt nào đó được sử dụng thì người
nop dùng phải viết lệnh
ljmp Tên ct Phục vụ ngắt / Reti Ljmp Tên Ctrình phục vụ ngắt
(Như ngắt Timer0, Ex1, Timer1)
org 1bh ; Ngắt Timer1
nop
ljmp Tên ct Phục vụ ngắt / Reti

org 23h ; Ngắt serial


nop
reti
;=========Khai báo Biến Hằng số ========= ;===================================
Biến equ giá trị ; chú thích
…………………………………… Vùng khai báo biến, hằng số
Hằng số equ giá trị ; chú thích
………………………………….
;=================================== ;===================================
; main program
;=================================== ;===================================
org 50h Lệnh định địa chỉ đầu của Ctrình chính trong ROM
Tên chương trình chính:
Lệnh 1
…………
lcall Ctr_con1 Lệnh goi Ctrình con1 trong Ctrình chính
…………
here:
sjmp here Tạo vòng lặp vô tận
;==========Ctrình_con ============= ;====================================
Ctr_con1:
Câu lệnh 1
………….
Lcall Ctr_con2 Vùng viết các Ctrình con
…………
ret Lưu ý:
;================================ Trong 1 Ctrình con có thể gọi các Ctrình con khác
Ctr_con2:
Câu lệnh a
………….
Câu lệnh k
…………
ret

;=============================== ;===================================
Ctrinh _ Phục vụ ngắt
;===============================
Tên ct Phục vụ ngắt1 : Vùng viết các Ctrình phục vụ ngắt

Câu lệnh 1 Lưu ý:


…………. Trong 1 Ctrình phục vụ ngắt có thể gọi các Ctrình
Câu lệnh m con khác
…………
Lcall Ctr_con2
…………
Reti
;===============================
Tên ct Phục vụ ngắt2 :

Câu lệnh a
………….
Câu lệnh h
…………
Lcall Ctr_con m
…………
reti

;============================== ;====================================
End Câu lệnh kết thúc Ctrình
3.2 Quản lý bảng số liệu, phép tính nhiều byte
3.2.1 Quản lý bảng số liệu
Bảng số liệu (Mảng, số nhiều byte) thường được lưu trữ trong 1 vùng nhớ nằm trong bộ
nhớ chương trình. Khi thao tác với một bảng số liệu người lâp trình sẽ cần phải biết cách
khai báo bảng số liệu, qua đó xác định được địa chỉ đầu của bảng số liệu, số lượng byte
trong 1 bảng số liệu. Để trên cơ sở đó thực hiện các phép toán trên bảng số liệu đó
a. Khai báo bảng số liệu:

Cú pháp1 : (theo kiểu Byte - DB) Cú pháp1:


Ví dụ1

Tên bảng: Table1:


DB Gtrị1, Gtrị2, ……, Gtrị N DB 05, 10, 10H, ‘Abc’, 0F8H, ‘5’

Chú ý : Address_Table1 Gtrị (hex)


 Các giá trị có thể ở các dạng khác nhau
(DEC, HEX, BIN,ASCII) [ Table1 +00] h 05
 Có thể tồn tại nhiều bảng khác nhau [ Table1 +01] h 0A
trong 1 chương trình [ Table1 +02] h 10
 Các giá trị trên cùng một dòng, nếu phải [ Table1 +03] h 41
khai báo nhiều thì phải khai báo như [ Table1 +04] h 62
sau: Tên bảng: [ Table1 +05] h 63
DB Gtrị1 [ Table1 +06] h F8
DB Gtrị 2 [ Table1 +07] h 35
……………..
DB Gtrị N Bảng có tên Table1 có 8 byte trong miền
 Cách này người lập trình khó biết chính nhớ có địa chỉ đầu được chương trình dịch
xác địa chỉ đầu của bảng số liệu tự động cấp phát

Cách 2: Kết hợp với lệnh định địa chỉ con Ví dụ2:
trỏ

Org Địa chỉ Org 8000h


Tên bảng: Table2:
DB Gtrị1, Gtrị2, ……, Gtrị N DB 05, 10, 10H, ‘Abc’, 0F8H, ‘5’

Lưu ý: Address_Table2 Gtrị (hex)


 Người lập trình phải cẩn thận trong việc
lựa chọn địa chỉ đầu của bảng, vì có thể [ 8000] h 05
vùng nhớ này đang được chương trình [ 8001] h 0A
sử dụng . Vì vậy thông thường bảng [ 8002] h 10
hay được đặt tại vùng cuối cùng của [ 8003] h 41
bộ nhớ chương trình [ 8004] h 62
[ 8005] h 63
[ 8006] h F8
[ 8007] h 35
Cú pháp2 : (theo kiểu Word - DW) Cú pháp2:
Ví dụ1

Tên bảng: Table3:


DW Gtrị1, Gtrị2, ……, Gtrị N DW 05, 10, ‘5’, 0F8AH,

Tương tự như sử dụng theo kiểu định nghĩa Address_Table3 Gtrị (hex)
theo Byte chỉ có khác là mỗi giá trị phải
được lưu vào 2 byte [ Table3 +00] h 00
[ Table3 +01] h 05
[ Table3 +02] h 00
[ Table3 +03] h 0A
[ Table3 +04] h 00
[ Table3 +05] h 35
[ Table3 +06] h 0F
[ Table3 +07] h 8A

Bảng có tên Table3 có 8 byte trong miền


nhớ có địa chỉ đầu được chương trình dịch
tự động cấp phát (với)

b. Phép tính nhiều byte:


Khi thực hiện các phép tính (cộng trừ,…) người lập trình phải xác định được kết
quả là số mấy byte để có phương án xác định vùng nhớ nào sẽ lưu giữ kết quả của phép
tính. Các thao tác đối với một bảng số liệu thường là đọc và viết vào bảng thông qua
con trỏ ( pointer) với các lệnh :
Nếu bảng trong vùng RAM trong của MCS51 :
Lệnh đọc từ vùng nhớ Movx A, @Ri ; (Ri là R0, R1)
Lệnh viết vào vùng nhớ Movx @Ri, A ; (Ri là R0, R1)

Nếu bảng trong vùng RAM ngoài của MCS51 :


Lệnh đọc từ vùng nhớ Movx A, @Dptr
Movx A, @A+Dptr
Lệnh viết vào vùng nhớ Movx @Dptr, A

Nếu bảng trong vùng ROM của MCS51 :


Lệnh đọc từ vùng nhớ Movc A, @A+Dptr
Movx A, @A+PC

Ví dụ:
Viết đoạn trình chuyển hai mảng dữ liệu 50 byte. Biết mảng 1 có địa chỉ 50h trong Ram
trong và mảng 2 có địa chỉ 1234h ở RAM ngoài.
Đoạn chương trình Lưu đồ thuật toán

Start

mov R0,#50H Dptr ← #1234H


mov dptr,#1234H R0 ← #50H
mov R2,#50 R2 ← #50
Loop:
mov A,@dptr
xch A,@R0
movx @dptr,A
A←@dptr
inc R0
A↔ @R0
inc dptr
@dptr←A
djnz R2,Loop
dptr +1
R0 + 1
R2 - 1

No
R2 = 0

Yes

End
Ví dụ 2:
Viết chương trình trừ hai số 8 byte, kết quả cất vào số thứ 1. Biết số thứ nhất đặt tại ô nhớ
1000H tại RAM ngoài và số thứ hai đặt tại 60H RAM trong và LSB đặt tại ô có địa chỉ
thấp nhất

Đoạn chương trình Lưu đồ thuật toán


org 00h
nop
sjmp Start

org 03h ; Ngắt Ex0


nop Start
reti

org 0bh ; Ngắt Timer0 xóa cờ C


nop R1 #8
reti R0←#60H
dptr←#1000H
org 13h ; Ngắt Ex1
nop
reti
A← @dptr
org 1bh ; Ngắt Timer1 A←A-@R0-C
nop @dptr←A
reti R0+1
dptr+ 1
org 23h ; Ngắt serial R1- 1
nop
reti
No
;===================================
; main program R1 = 0
;===================================
org 50h Yes
Start:
clr C End
mov R1,#08H
mov R0,#60H
mov dptr,#1000H
Lap:
mov A,@dptr
subb A,@R0
movx @dptr,A
inc R0
inc dptr
djnz R1,Lap
End
c. Tra bảng:
Tra bảng dùng để tìm ra giá trị xác định do người lập trình đã tính toán và tạo ra bảng
số liệu sẵn của một hàm hay một công thức nào đó, thông thường là các hàm siêu việt,
bảng mã …,vì vậy các bảng số liệu sẽ được lưu trong bộ nhớ chương trình. Do đó khi
thao tác với bảng số liệu sẽ sử dụng các câu lênh sau:
;---------------------------------------------------------------
Look_up_Table:
mov dptr,#Table ; lấy điạ chỉ bảng đưa vào thanh ghi Dptr
movc a,@a+dptr ; lấy giá trị trong bảng tương ưng với giá trị của A
ret
;----------------------------------------------------------------
Table:
db 0c0h, 0f9h, 0a4h, 0b0h, 099h, 092h, 082h, 0f8h, 080h, 090h
;--------------------------------------------------------------------------------------

3.3 Đổi mã ASCII-BCD-HEX

3.4 Điều khiển vào ra: tra mức, sườn tín hiệu, điều khiển quét
3.5 Ngắt trong MCS51: Ngắt ngoài

You might also like