1
Chương 3
LẬP TRÌNH CHO HỌ VI ĐIỀU
KHIỂN 8051
3.1 Mở đầu
3.2 Các kiểu định địa chỉ
3.3 Tập lệnh
3.4 Soạn thảo chương trình bằng ngôn ngữ lập trình
Assembly
3.5 Soạn thảo chương trình bằng ngôn ngữ lập trình C
2
3.1 Mở đầu
 Chương trình là chuỗi các lệnh mà VĐK phải xử lý, thực hiện
 Lập chương trình là soạn thảo các lệnh bằng ngôn ngữ lập trình để thực
hiện một thuật toán cụ thể
Chương trình = Thuật toán + Cơ sở dữ liệu
 Chương trình dịch: Ví dụ như Assembler, thực hiện dịch từ mã ngữ sang
mã máy
 Hệ lệnh của VĐK: Là tập lệnh mà người lập trình sử dụng để lập trình,
người lập trình chỉ có thể sử dụng các lệnh trong hệ lệnh
 Mỗi họ VĐK có một tệp lệnh riêng, chương trình viết cho hệ VĐK nào
thì VĐK đó chạy được
3
 Ngôn ngữ lập trình:
- Bậc cao: C, C++, Pascal...
- Bậc thấp:
Mã máy: mỗi một lệnh tương ứng với một mãy nhị
phân được gọi là mã lệnh
Mã ngữ: Các lệnh được mô tả ở dạng biểu trưng
(Symbol). Symbol có thể được viết tắt như MOV,
ADD,... Hoặc là được ký hiệu các khối chức năng ở
dạng Graphic...
4
Các ký hiệu cần chú ý:
Rn : Các thanh ghi từ R0 – R7 (bank thanh ghi hiện hành)
Ri : Các thanh ghi từ R0 – R1 (bank thanh ghi hiện hành)
@Rn : Định địa chỉ gián tiếp 8 bit dùng thanh ghi Rn
@DPTR : Định địa chỉ gián tiếp 16 bit dùng thanh ghi DPTR
direct : Định địa chỉ trực tiếp RAM nội (00h – 7Fh) hay SFR (80h –FFh)
(direct) : Nội dung của bộ nhớ tại địa chỉ direct
#data8 : Giá trị tức thời 8 bit
#data16 : Giá trị tức thời 16 bit
bit : Địa chỉ bit của các ô nhớ có thể định địa chỉ bit (00h – 7Fh đối với
địa chỉ bit và 20h – 2Fh đối với địa chỉ byte)
5
CÁCH VIẾT SỐ
Số Binary (nhị phân): Số nhị phân khi viết cần thêm phía sau
giá trị bằng kí tự “B”.
Ví dụ: 010101B
Số Hexa: Số hexa khi cần viết cần thêm phía sau giá trị bằng kí
tự “H”.
Ví dụ: 69H
Số thập phân: Số thập phân khi cần viết không cần thêm kí tự
hoặc thêm sau giá trị bằng kí tự “D”
Ví dụ: 45, 27, 68D
6
3.2 Các kiểu định địa chỉ
Bộ VĐK 8051 có 8 kiểu định địa chỉ:
- Thanh ghi (register)
- Trực tiếp (direct)
- Gián tiếp (Indirect)
- Tức thời (Immediate)
- Tương đối (relative)
- Tuyệt đối (absolute)
- Dài (long)
- Chỉ số (Indexed)
7
 Định địa chỉ thanh ghi
Các thanh ghi từ R0 – R7 có thể truy xuất bằng cách định địa
chỉ trực tiếp hay gián tiếp như trên.
Ngoài ra, các thanh ghi này còn có thể truy xuất bằng cách
dùng 3 bit trong mã lệnh để chọn 1 trong 8 thanh ghi (8 thanh
ghi này có địa chỉ trực tiếp thay đổi tuỳ theo bank thanh ghi
đang sử dụng).
VD: ADD A, R7 ; A = A+R7
8
 Định địa chỉ trực tiếp
Định địa chỉ trực tiếp chỉ dùng cho các thanh ghi chức năng đặc biệt
và RAM nội của 8051.
 Giá trị địa chỉ trực tiếp 8 bit được thêm vào phía sau mã lệnh.
 Nếu địa chỉ trực tiếp từ 00h – 7Fh thì đó là RAM nội của 8951 (128
byte), còn địa chỉ từ 80h – FFh là địa chỉ các thanh ghi chức năng đặc
biệt
Các lệnh sau có kiểu định địa chỉ trực tiếp:
MOV A, P0
MOV A, 30h
9
 Định địa chỉ gián tiếp
Định địa chỉ gián tiếp có thể dùng cho cả RAM nội và
RAM ngoại.
Địa chỉ của RAM xác định thông qua một thanh ghi (R0,
R1, SP cho địa chỉ 8 bit và DPTR cho địa chỉ 16 bit).
Các lệnh sau có kiểu địa chỉ gián tiếp:
MOV A, @R0
MOVX A, @DPTR
10
VD: Xoá nội dung các ô nhớ từ địa chỉ 30H đến 7FH
trong bộ nhớ RAM nội về 0H ta dùng các lệnh sau.
MOV R0, #30H
lap: MOV @R0, #0
INC R0
CJNE R0,#80H, lap
11
 Định địa chỉ tức thời
Giá trị của một hằng số có thể đưa trực tiếp vào mã
lệnh của chương trình.
Trong hợp ngữ, hằng số được xác định bằng cách sử
dụng dấu #.
VD: MOV A, #12
12
 Định địa chỉ tương đối
Kiểu định địa chỉ tương đối chỉ được sử dụng cho các
lệnh nhảy
 Là một giá trị 8bit có dấu
 Có điểm lợi là cung cấp cho ta mã không phụ thuộc
vào vị trí, điểm bất lợi là các đích nhảy bị giới hạn
trong tầm (-128 đến 127 byte)
13
14
 Định địa chỉ tuyệt đối
Kiểu định địa chỉ tuyệt đối chỉ được sử dụng với các lệnh ACALL
và AJMP
Đây là các lệnh 2 byte cho phép rẽ nhánh chương trình trong một
trang 2kB hiện hành của bộ nhớ chương
 Định địa chỉ dài
Kiểu định địa chỉ dài chỉ được dùng cho lệnh LCALL và
LJMP.
Các lệnh 3byte này chứa địa chỉ đích 16bit
15
 Định địa chỉ chỉ số
 Dùng một địa chỉ nền (chứa trong thanh ghi PC hay
DPTR) và một offset (chứa trong thanh ghi A) để tạo
địa chỉ được tác động cho các lệnh JMP hoặc MOVC.
(Địa chỉ được tác động) = (PC) hoặc (DPTR) + (A)
 Thường dùng khi truy xuất dữ liệu trong một bảng dữ
liệu đã được định nghĩa trước
16
Ví dụ: Bảng các giá trị bình phương của số nguyên.
Nếu DPTR chứa địa chỉ đầu bảng (tương ứng nhãn TABLE)
và (A) = 3, thì sau khi thực hiện lệnh:
MOVC A, @A+DPTR
17
3.3 Tập lệnh
Tập lệnh của 8051 có thể chia thành 5 nhóm:
- Nhóm lệnh số học
- Nhóm lệnh logic
- Nhóm lệnh di chuyển dữ liệu
- Nhóm lệnh xử lý bit
- Nhóm lệnh rẽ nhánh
Gốc, Đích: có thể là Rn, hoăc direct hoặc @Ri
data: hằng số bit
data16: hằng số 16bit
18
Nhóm lệnh số học
ADD A, nguồn: A = A + nguồn
Chức năng: Cộng
Mô tả:Lệnh ADD được dùng để cộng hai toán hạng, kết
quả lưu vào thanh chứa A. Toán hạng đích luôn là thanh
ghi A trong khi đó toán hạng nguồn có thể là một thanh
ghi dữ liệu trực trực tiếp hoặc là trong bộ nhớ
19
VÝ dô: H·y biÓu diÔn xem c¸c lÖnh díi ®©y t¸c ®éng ®Õn thanh ghi cê
nh thÕ nµo?
MOV A, # 0F5H ; A = F5H
MOV A, # 0BH ; A = F5 + 0B = 00
Lêi gi¶i:
F5H 1111 0101
+ 0BH + 0000 1011
100H 10000 0000
Sau phÐp céng, thanh ghi A (®Ých) chøa 00 vµ c¸c cê sÏ nh sau:
CY = 1 và cã phÐp nhí tõ D7
PF = 1 và sè c¸c sè 1 lµ 0 (mét sè ch½n) cê PF ®îc ®Æt lªn 1.
AC = 1 và cã phÐp nhí tõ D3 sang D4
20
VÝ dô: H·y viÕt ch¬ng trinh céng hai sè 16 bit. C¸c sè ®ã lµ 3CE7H vµ
3B8DH. CÊt tæng sè vµo R7 vµ R6 trong ®ã R6 chøa byte thÊp.
Lêi gi¶i:
CLR ; Xo¸ cê CY = 0
MOV A, #0E7H ; N¹p byte thÊp vµo A : A = E7H
ADD A, #8DH ; Céng byte thÊp vµo A : a = 74H vµ CY = 1
MOV R6, A ; Lu byte thÊp cña tæng vµo R6
MOV A, #3CH ; N¹p byte cao vµo A : A = 3CH
ADDC A, #3BG ; Céng byte cao cã nhí vµo A : A = 78H
MOV R7, A ; Lu byte cao cña tæng vµo R7
21
SUBB A, nguồn; A = A – nguồn – CY
Chức năng: Trừ có mượn
Mô tả: Trong 8051 chỉ có một lệnh SUBB duy nhất.
SUBB thực hiện trừ nội dung của thanh chứa A với
toán hạng nguồn cùng với cờ nhớ và cất kết quả vào
thanh chứa.
22
VÝ dô: Trinh bµy c¸c bíc liªn quan díi ®©y:
CLR C ; T¹o CY = 0
MOV A, #3FH ; N¹p 3FH vµo A (A = 3FH)
MOV R3, #23H ; N¹p 23H vµo R3 (R3 = 23H)
SUBB A, R3 ; Trõ A cho R3 ®Æt kÕt qu¶ vµo A
23
 MUL AB
Chức năng: Nhân
Mô tả: MUL AB nhân các số nguyên không dấu 8 bit trong thanh
ghi chứa A và thanh ghi B, kết quả là một số 16 bit có byte thấp
đặt trong thanh chứa A và byte cao đặt trong thanh ghi B.
Ví dụ: Phép nhân hai số 8 bit. Kết quả là dữ liệu 16 bit được
đặt trong A và B.
MOV A, #9AH
MOV B, #35H
MUL AB
24
 DIV AB
Chức năng: Chia A cho B
Mô tả: 8051 cũng chỉ hỗ trợ cho phép chia hai số không dấu byte
cho byte, tử số (số bị chia) phải ở trong thanh ghi A và mẫu số (số
chia) phải ở trong thanh ghi B. Sau khi lệnh chia DIV được thực
hiện thì thương số được đặt trong A, còn số dư được đặt trong B.
Ví dụ:
MOV A, #7AH ; Nạp số bị chia vào A = 7AH
MOV B, #10H ; Nạp số chia vào B = 10H
DIV AB ; A = 07 (thương số); B = 0AH (số dư)
25
Nhóm lệnh logic
 ANL đích, nguồn
Chức năng: Thực hiện phép nhân logic (AND)
Mô tả: ANL thực hiện phép toán AND từng bit trên toán hạng
đích và nguồn, đặt kết quả vào đích, các cờ không bị ảnh
hưởng. Toán hạng đích thường là thanh ghi tổng (tích lũy),
toán hạng nguồn có thể là thanh ghi trong bộ nhớ hoặc giá
trị cho sẵn. ANL thường được dùng để che (đặt về 0) những
bit nhất định của toán hạng.
26
Ví dụ: Cho biết kết quả của đoạn mã ở ví dụ dưới đây:
MOV A, #86H ; Gán A = 86H
ANL A, #0FH ; Thực hiện nhân logic A và 0FH
(bây giờ A = 06H)
Lời giải:
86H 10000110
0FH 00001111
06H 00000110
X
27
 ORL đích, nguồn
Chức năng: Thực hiện phép cộng logic (OR)
Mô tả: ORL thực hiện phép toán OR từng bit trên hai
toán hạng đích và nguồn, đặt kết quả vào đích, các cờ
không bị ảnh hưởng. Toán hạng đích thường là thanh
ghi tổng hoặc là địa chỉ trực tiếp, toán hạng nguồn có
thể là thanh ghi trong bộ nhớ hoặc giá trị cho sẵn. ANL
thường được dùng để thiết lập (đặt lên 1) những bit nhất
định của toán hạng.
28
Ví dụ: Cho biết kết quả của đoạn mã ở sau:
MOV A, #55H ; A = 55H
ORL A, #0Ah ; A = 5FH
Lời giải:
55H 01010101
0AH 00001010
5FH 01011111
29
 XRL đích, nguồn
Chức năng: Thực hiện phép trừ logic (XOR)
Mô tả: XRL thực hiện phép toán XOR từng bít trên hai
toán hạng đích và nguồn, đặt kết quả vào đích, các cờ
không bị ảnh hưởng. Toán hạng đích thường là thanh
ghi tổng hoặc địa chỉ trực tiếp, toán hạng nguồn có thể là
thanh ghi trong bộ nhớ hoặc giá trị cho sẵn.
30
Ví dụ: Cho biết kết quả của đoạn mã sau đây:
MOV A, #55H
XRL A, #79H
Lời giải:
55H 01010101
79H 01111001
2CH 00101100
31
 CPJ A
Chức năng: Lấy bù nội dung của thanh ghi A.
Mô tả: Nội dung của thanh ghi A được lấy bù logic (phép
biến đổi các bit 0 thành các bit 1 và đổi các bit 1 sang bit 0).
Các cờ không bị ảnh hưởng.
MOV A, #55H
CPJ A ; Bây giờ nội dung của thanh ghi A là AAH
; Vì 01010101 (55H) 10101010 (AAH)
32
 CPL bit
Chức năng: Lấy bù bit.
Mô tả: Nội dung của bit chỉ ra trong lệnh được lấy bù logic
(đổi các bit 0 thành các bit 1 và đổi các bit 1 sang bit 0).
Các cờ không bị ảnh hưởng. CPL có thể được thao tác trên
các cờ nhớ và trên một bit bất kỳ được định đại chỉ bit.
33
 CJNE đích, nguồn, địa chỉ tương đối
Chức năng: So sánh và nhảy nếu không bằng nhau
Mô tả: Lệnh CJNE so sánh hai toán hạng nguồn và đích
và rẽ nhánh đến địa chỉ tương đối nếu hai toán hạng
không bằng nhau. Ngoài ra cờ nhớ CY được lập nếu
toán hạng đích nhỏ hơn toán hạng nguồn. Các toán
hạng vẫn giữ nuyên không thay đổi
34
 RR A
Chức năng: Quay các bit thanh ghi sang phải
Mô tả: Lệnh RR thực hiện quay các bit của thanh ghi A sang
phải một vị trí, bit D0 rời từ vị trí bit thấp nhất và chuyển
sang bit cao nhất D7. Các cờ không bị ảnh hưởng
Ví dụ:
MOV A, #6AH ; A = 01101010
RR A ; A = 00110101
RR A ; A = 10011010
RR A ; A = 01001101
MSB LSB
35
 RL A
Chức năng: Quay các bit thanh ghi sang trái
Mô tả: Lệnh RL thực hiện quay các bit của thanh ghi A sang
trái một vị trí, bit D7 rời từ vị trí bit cao nhất và chuyển sang
bit thấp nhất D7. Các cờ không bị ảnh hưởng
Ví dụ:
MOV A, #6AH ; A = 01101010
RL A ; A = 11010100
RL A ; A = 10101001
RL A ; A = 01010011
MSB LSB
36
 RLC A
Chức năng: Quay trái qua cờ nhớ
Mô tả: Lệnh RLC thực hiện quay các bit của thanh ghi A
sang trái một vị trí, bit MSB vào cờ nhớ (CY), sau đó bit CY
được chuyển vào bit LSB. Cờ nhớ CY tác động như là một
bit bộ phận của thanh ghi A làm nó trở thành thanh ghi 9 bit.
37
Ví dụ:
SET C ; C = 1
MOV A, #71H ; A = 01110001 C = 0
RLC A ; A = 11100011 C = 1
RLC A ; A = 11000110 C = 1
RLC A ; A = 10001101 C = 1
MSB LSB
CY
38
 RRC A
Chức năng: Quay phải qua cờ nhớ
Mô tả: Lệnh RRC thực hiện quay các bit của thanh ghi A
sang phải một vị trí, bit LSB vào cờ nhớ (CY), sau đó bit CY
được chuyển vào bit MSB
Ví dụ:
SET C ; C = 1
MOV A, #71H ; A = 01110001
RRC A ; A = 10111000 C = 1
RRC A ; A = 11011100 C = 0
MSB LSB CY
39
 SWAP A
Chức năng: Lệnh hoán đổi thanh ghi A
Mô tả: SWAP hoán đổi 4 bit nửa phần cao của byte và
4 bit thấp của byte với nhau, SWAP chỉ hoạt động trên
thanh ghi A. Các cờ không bị ảnh hưởng.
D7 D6 D5 D4 D3 D2 D1 D0
Trước khi thực hiện
Sau khi thực hiện
D3 D2 D1 D0 D7 D6 D5 D4
40
Nhóm lệnh dịch chuyển dữ liệu
1. Nhóm lệnh dịch chuyển dữ liệu trong RAM nội
 MOV đích, nguồn
Chức năng: Di chuyển bit nguồn đến bit đích.
Mô tả: Nội dung của bit được chỉ ra bởi toán hạng nguồn
được sao chép vào vị trí bit ở toán hạng thứ nhất. Một trong
hai toán hạng phải là cờ nhớ, toán hạng còn lại là bit bất kỳ
được định địa chỉ bit, bit nguồn không bị ảnh hưởng, các
thanh ghi khác và các cờ không bị ảnh hưởng.
41
Ví dụ:
CLP P0.0 ; Bit P0.0 bị xóa về 0
SETB C ; Bit cờ nhờ được thiết lập
MOV P0.1, C ; Bit cờ chuyển vào P0.1 (bằng 1)
MOV C, P0.0 ; Bit cờ bị xóa về 0
42
 XCH đích, nguồn
Chức năng: Hoán chuyển nội dung của toán hạng đích
và toán hạng nguồn.
Mô tả: Toán hạng đích phải là thanh ghi chứa A, lệnh
XCH hoán chuyển nội dụng của byte nguồn với thanh
ghi chứa
43
2. Nhóm lệnh dịch chuyển dữ liệu trong RAM ngoài
 MOVC A, @A + DPTR
Chức năng: Di chuyển bit nguồn đến bit đích
Mô tả: MOVC nạp cho thanh chứa byte hằng số từ bộ nhớ
chương trình. Địa chỉ của byte được nạp là tổng của giá trị 8
bit không dấu ban đầu chứa trong thanh chứa nội dung của
thanh ghi địa chỉ cơ sở (thanh ghi cơ sở có thể là thanh ghi
con trỏ dữ liệu hoặc PC).
44
 MOVC A, @A + PC
Cũng hoạt động tương tự như câu lệnh ở trên, ngoại trừ ở đây
bộ đếm chương trình được dùng để chứa địa chỉ cơ sở và
bảng được truy xuất nhờ vào bộ nhớ chương trình con. Trước
tiên số của điểm nhập yêu cầu được nạp cho thanh chứa A,
sau đó chương trình con được gọi. Chuỗi lệnh cho phép khởi
động và gọi có thể là:
45
Ví dụ:
MOV A, ENTRY_NUMBER
CALL LOOK_UP//gọi
LOOP_UP: INC A // tăng gía trị thanh ghi A
MOVC A, @A+PC
RET // kết thúc 1 chương trình con
TABLE: DB data0, data1, data2,... //nhãn
Bảng được định nghĩa sau lệnh INC trong chương trình,
lệnh tăng được cần đến PC trỏ tới lệnh INC khi lệnh MOVC
được thực thi. Việc tăng nội dung thanh ghi chứa sẽ bỏ qua
lệnh RET.
46
Nhóm lệnh xử lý bit
 SETB bit
Chức năng: Thiết lập bit
Mô tả: SETB đặt bit được chỉ ra trong lệnh bằng 1, SETB có
thể thao tác trên các cờ nhờ hoặc các bit được định địa chỉ
bit.
Ví dụ:
SETB C ; Thiết lập cờ nhớ bằng 1
47
 CLR bit
Chức năng: Xóa bit
Mô tả: CLR xóa bit được chỉ ra trong lệnh về 0, CLR có
thể thao tác trên các cờ nhớ hoặc các bit được định
nghĩa địa chỉ bit.
Ví dụ:
CLR P0.1 ; xóa bit 1 của cổng P0
CLR TR0
48
 CPL bit
Chức năng: Lấy bù bit
Mô tả: CPL được chỉ ra trong lệnh được lấy bù, một bit
có giá trị 1 được đổi thành 0 và ngược lại. CPL có thể
thao tác trên các cờ nhớ hoặc các bit được định địa chỉ
bit.
Ví dụ:
SETB P0.1 ; bit 1 của cổng P0 được đặt thành 1
CPL P0.1 ; đảo lại bit 1 của cổng P0 bằng 0
49
Nhóm lệnh rẽ nhánh
Phần này sẽ trình bày các lệnh chuyển điều khiển có trong hợp
ngữ của 8051 như các lệnh sử dụng cho vòng lặp, các lệnh nhảy
có và không có điều kiện, lệnh gọi chương trình con.
1.Các lệnh nhảy có điều kiện
 JZ nhãn_đích
Chức năng: Nhảy nếu A = 0
Mô tả: Khi thực hiện lệnh JZ, nội dung của thanh ghi A được
kiểm tra. Nếu nó bằng không thì nó nhảy đến địa chỉ đích, ngược
lại thì tiếp tục với lệnh tiếp theo.
50
Ví dụ xét đoạn mã sau:
MOV A, R0 ; Nạp giá trị của R0 vào A
JZ nhãn ; Nhảy đến LABLE nếu A = 0
MOV A, R1 ; Nạp giá trị của R1 vào A
JNZ LABLE ; Nhảy đến LABLE nếu A # 0
LABLE:
51
 JNC nhãn_đích
Chức năng: Nhảy nếu không có nhớ (CY = 0)
Mô tả: Khi thực hiện lệnh JNC, bộ xử lý kiểm tra cờ nhớ
nếu CY = 0 thì CPU bắt đầu nạp và thực hiện các lệnh từ
địa chỉ của nhãn. Nếu cờ CY = 1, CPU sẽ chuyển đến địa
chỉ đích, ngược lại thì tiếp tục với lệnh tiếp theo.
52
Lệnh Hoạt động
JZ Nhảy nếu A = 0
JNZ Nhảy nếu A # 0
DJNZ Giảm và nhảy nếu A = 0
CJNE A, byte Nhảy nếu A # byte
CJNE byte, # data Nhảy nếu byte # data
JC Nhảy nếu CY = 1
JNC Nhảy nếu CY = 0
JB Nhảy nếu bit = 1
JNB Nhảy nếu bit = 0
JNC Nhảy nếu bit = 1 và xóa nó
53
2. Các lệnh nhảy không điều kiện
 LJMP nhãn_đích
Chức năng: Nhảy dài
Mô tả: Nhảy xa LJMP là một lệnh 3 byte trong đó byte đầu
tiên là mã lệnh còn 2 byte còn lại là địa chỉ 16 bit của đích.
Địa chỉ đích 2 byte có một phép nhảy đến bất kỳ vị trí nhớ
nào trong khoảng 0000H - FFFFH
54
 SJMP nhãn_đích
Chức năng: Nhảy ngắn
Mô tả: Trong 2 byte của lệnh SJMP này thì byte đầu tiên là
mã lệnh và byte thứ hai là chỉ tương đối của địa chỉ đích.
Đích chỉ tương đối trong phạm vi 00 – FFH được chia thành
địa chỉ nhảy tiến và địa chỉ lùi, nghĩa là từ -128 đến +127
byte của bộ nhớ tương đối so với địa chỉ hiện thời của bộ
đếm chương trình. Nếu là lệnh nhảy tới thì địa chỉ đích có
thể nằm trong khoảng 127 byte từ gía trị hiện thời của bộ
đếm chương trình. Nếu địa chỉ đích ở phía sau thì nó có thể
nằm trong khoảng -128 byte từ giá trị hiện hành của PC.
55
3. Các lệnh gọi
 ACALL nhãn _ lệnh
Chức năng: gọi đến địa chỉ tuyệt đối
Mô tả: ACALL gọi không điều kiện một chương trình con đặt
tại địa chỉ được chỉ ra trong lệnh. Do ACALL chỉ có 2 byte
nên địa chỉ đích của chương trình con phải nằm trong
khoảng 2k. Byte địa chỉ vì chỉ có 11 bit của 2 byte được sử
dụng cho địa chỉ.
56
 LCALL nhãn _ lệnh
Chức năng: Gọi xa
Mô tả: Trong lệnh 3 byte này thì byte đầu tiên là mã lệnh,
còn hai byte sau được dùng cho địa chỉ của chương trình
con đích. Do vậy LCALL có thể được dùng để gọi các
chương trình con ở bất kỳ vị trí nào trong phạm vi 64k byte,
không gian địa chỉ của 8051. Để đảm bảo rằng sau khi thực
hiện một chương trình được gọi 8051 biết được chỗ quay
trở về thì nó tự động cất vào ngăn xếp địa chỉ của lệnh
đứng ngay sau lệnh gọi LCALL.
3.4 Soạn thảo chương trình bằng ngôn ngữ lập trình Assembly
57
Khung chương trình hợp ngữ khi không sử dụng ngắt:
; [Tên chương trình] - [Mô tả chương trình]
; [Mô tả chi tiết ứng dụng]
; [Tác giả]
; Ngày bắt đầu:
; Ngày chỉnh sửa gần nhất:
; Chú ý về phần cứng:
; [Dùng bộ VĐK nào, tần số xung nhịp, cách đấu nối chân
; Khai báo biến
[Tên_biến] EQU [Địa_chỉ] ; Mô tả biến
; Khai báo hằng
[ Tên_hằng EQU Giá_trị] ; Mô tả hằng
; Bắt đầu chương trình chính
ORG 0000H
MAIN:
; Các lệnh của thân chương trình chính
...........
3.4 Soạn thảo chương trình bằng ngôn ngữ lập trình Assembly
58
CALL Tên_ctc ; Gọi chương trình con
..........
[SJMP MAIN ; Kết thúc chương trình chính]
;*****************************
; Bắt đầu các chương trình con
Tên_ctc:
;Các lệnh của thân chương trình con
...................
RET ; Kết thúc chương trình con và quay về chương trình
chín
.................... ; Các chương trình con khác
;*****************************
; Kết thúc toàn bộ chương trình
END
Trình tự các bước thiết kế chương trình
Ngôn ngữ bậc cao
 Ngôn ngữ cấp cao điển hình như Pascal, C sử dụng các
từ và phát biểu dễ hiểu đối với con người hay là ngôn ngữ
gần với con người
 Ngôn ngữ lập trình bậc cao thì dễ hiểu đối với con
người
Ngôn ngữ bậc thấp
 Hợp ngữ (Assembly Language Programming) là ngôn ngữ của máy
tính có vị trí giữa ngôn ngữ máy và ngôn ngữ cấp cao
 Hợp ngữ thay thế các mã nhị phân của ngôn ngữ máy bằng các mã
gợi giúp ta dễ nhớ và dễ lập trình hơn
 Chương trình hợp ngữ không thể thực thi trục tiếp bởi máy tính.
Sau khi viết xong, chương trình này phải trải qua quá trình dịch thành
ngôn ngữ máy
 Trình dịch hợp ngữ là chương trình dùng để dịch một chương trình
hợp ngữ thành chương trình ngôn ngữ máy
Giới thiệu khung của chương trình hợp ngữ
Cú pháp của chương trình hợp ngữ
Trong hợp ngữ, một dòng lệnh có thể có những trường sau:
Tên Mã lệnh Các toán hạng Chú giải
Ví dụ 1: Dòng lệnh là hướng dẫn cho chương trình
dịch
ORG 0000H
END
Ví dụ 2: Một dòng lệnh dưới dạng mã gợi nhớ
TIEP: MOV A, 50H // nạp vào A nội dung của ô nhớ có địa
chỉ 50H
Trong đó:
- Trường tên là nhãn TIEP:
- Trường mã lệnh là lệnh MOV
- Trường toán hạng là các toán hạng: A và 50H
- Trường chú giải là lời giải thích: ";nạp...."
Trường tên:
 Chứa các nhãn, tên biến, hoặc tên thủ tục. Khi dịch chương
trình các tên và nhãn này sẽ được gán bằng các địa chỉ cụ thể của
ô nhớ.
 Tên và nhãn có thể có độ dài từ 1 đến 31 ký tự, không chứa
dấu cách, hoặc bắt đầu bằng số, không trùng với các từ khoá của
trình biên dịch. Có thể dùng ký tự đặc biệt "_" để kết nối các từ
trong tên.
 Một nhãn thường kết thúc bằng dấu hai chấm ":".
Trường mã lệnh:
 Trong trường mã lệnh có thể là lệnh thật hoặc lệnh
giả
 Nếu là lệnh thật thì đó là mã lệnh gợi nhớ, mã lệnh
này sẽ được chương trình dịch dịch ra mã máy.
 Nếu là lệnh giả thì đó là một hướng dẫn chương trình
dịch và không được dịch ra mã máy.
Trường toán hạng:
 Nếu trong lệnh thật thì trường này chứa các toán
hạng của lệnh. Trong một lệnh có thể có 0,1 hoặc 2
toán hạng. Lệnh 1 toán hạng thì toán hạng đó có thể là
Gốc hoặc Đích. Lệnh 2 toán hạng thì một toán hạng là
Gốc, một toán hạng là Đích.
 Đối với hướng dẫn chương trình dịch thì trường này
chứa các thông tin liên quan đến các lệnh giả của hướng
dẫn.
Trường chú giải:
- Trường chú giải phải được bắt đầu bằng dấu chấm phẩy ";".
- Trường này được dùng để ghi các lời giải thích của người
lập trình cho các lệnh của chương trình để giúp cho người đọc
chương trình dễ hiểu.
- Khi biên dịch chương trình sẽ bỏ qua phần sau dấu ";" trên dòng
lệnh do vậy ta có thể dùng dấu ";" để loại bỏ một dòng lệnh nào đó
trong chương trình.
Dữ liệu cho chương trình:
Khi cung cấp dữ liệu cho chương trình hợp ngữ,
số cho ở hệ nào phải được kèm đuôi của hệ đó
(trừ hệ thập phân). Riêng đối với hệ hexa nếu một
số được bắt đầu bằng các chữ (a...f hoặc A...F)
thì ta phải thêm 0 ở trước số để chương trình dịch
không hiểu nhầm đó là một tên hay một nhãn.
Ví dụ:
0011B ; Số hệ hai
1234 ; Số hệ mười
0ABCDH ; Số hệ mười sáu
1EGFH ; Số hệ mười sáu
- Nếu dữ liệu là ký tự hoặc chuỗi ký tự thì chúng phải
được đóng trong dấu nháy đơn .
VD: 'A', 'abc'. Khi dịch, chương trình dịch sẽ dịch ký tự ra
mã ASCII tương ứng của nó, vì vậy ta có thể cung cấp dữ
liệu ký tự cho chương trình dưới dạng mã ASCII của nó.
Các chỉ dẫn
Các chỉ dẫn là các lệnh đối với trình dịch hợp ngữ. Các chỉ
dẫn không được dịch ra mã máy và không phải là các lệnh
thuộc tập lệnh của bộ VĐK. Tuy nhiên các chỉ dẫn lại được
đặt trong trường mã gợi nhớ của chương trình. Ở đây ta sẽ
giới thiệu một vài loại chỉ dẫn sau:
- Điều khiển trạng thái của trình dịch hợp ngữ: ORG, END
- Định nghĩa ký hiệu: EQU, BIT,...
- Dành trước vùng nhớ/khởi động vùng nhớ: DB, DW
ORG (set origin)
Dạng chỉ dẫn ORG như sau:
ORG biểu_thức
Chỉ dẫn ORG thay đổi nội dụng bộ đếm vị trí để thiết lập một
gốc mới của chương trình cho các phát biểu theo sau.
Ví dụ:
ORG 0030H ; Bộ đếm vị trí được thiết lập bằng 0030H
END
Dạng của chỉ dẫn END như sau:
END
END là phát biểu cuối cùng của chương trình
nguồn. Không có gì theo sau phát biểu END được
xử lý bởi trình dịch hợp ngữ.
EQU (equate)
Dạng của chỉ dẫn EQU như sau:
TÊN EQU Biểu_thức
Chỉ dẫn EQU gán giá trị số cho TÊN. Biểu_thức là một hằng
số hay một biểu thức chứa các hằng số.
VD:
X1 EQU 35H ; X1 có giá trị 35H
Khi biên dịch TÊN sẽ được thay thể bằng giá trị đã gán cho
nó tại những nơi nó xuất hiện trong chương trình.
BIT
X BIT P0.0
Chỉ dẫn BIT cho phép gán giá trị của một bit cho trường tên.
DB
Dạng của chỉ dẫn DB như sau:
[Nhãn:] DB Giá_trị [,Giá_trị, ...]
Chỉ dẫn DB khởi động vùng nhớ mã (ô nhớ trong bộ nhớ
chương trình) với các giá trị có độ dài 1 byte.
Trên thực tế chỉ dẫn này thường được dùng để đặt các hằng
số vào bộ nhớ chương trình. Danh sách các giá trị là một chuỗi
của một hay nhiều giá trị byte cách nhau bởi dấu phẩy.
VD:
ORG 100H
Binh_phuong:
DB 0,1,4,9,16,25 ; bình phương
Chao:
DB 'Hello!' ; chuỗi ký tự
Sau chỉ dẫn này trương trình dịch sẽ tạo ra một chuỗi các
byte liên tiếp chứa các hằng số. Ở ô nhớ có địa chỉ 100H là
0, ô nhớ 101H là 1…Giá trị của tên cũng chính là địa chỉ
đầu tiên của dãy các ô nhớ.
DW
Dạng của chỉ dẫn DW như sau:
[Nhãn:] DW Giá_trị [,Giá_trị, ...]
Chỉ dẫn DW tương tự như chỉ dẫn DB ngoại trừ 2 vị trí
nhớ (16bit) được gán cho mỗi thành phần dữ liệu.
VD:
MW: DW 12, 345H, 555
Cách tạo và cho chạy một chương trình hợp ngữ.
 Keil cho phép ta có thể đồng thời soạn thảo chương
trình hợp ngữ, biên dịch.
 Chạy mô phỏng thử chương trình trên máy tính.
 Khi biên dịch chương trình ta sẽ được file mã máy của
chương trình, file này có đuôi .hex.
 File mã máy này có thể nạp vào VĐK để chạy thử trên KIT
phát triển, và cũng có thể cho chạy thử trên máy tính.
Các cấu trúc lập trình cơ bản thực hiện bằng hợp ngữ
Cấu trúc tuần tự
Cấu trúc tuần tự là cấu trúc đơn giản nhất. Trong cấu trúc
tuần tự, các lệnh được sắp xếp tuần tự, lệnh này tiếp theo
lệnh kia.
Lệnh 1
Lệnh 2
…
Lệnh n
VD: Các biến T1 và T2 chứa các giá trị nhiệt độ cao và thấp.
Hãy tính giá trị trung bình của nhiệt độ và chứa kết quả trong
thanh chứa A.
Giải:
MOV A, 0 ; xoá A để chứa giá trị nhiệt độ trung bình
ADD A, T1 ; cộng nhiệt độ thứ nhất.
ADD A, T2 ; cộng nhiệt độ thứ hai.
MOV B,#2
DIV AB ; chia 2 kết quả trong A ta được nhiệt độ TB
Thoat: ; lối ra của cấu trúc
Cấu trúc IF_THEN
Ngữ pháp:
IF Điều kiện THEN Công việc
VD : IF (R0=10H) THEN A=#0FFH
VAO:
CJNE R0,#10H,RA
MOV A, #0FFH
SJMP RA
Cấu trúc IF_THEN_ELSE
Ngữ pháp:
IF Điều kiện THEN Công việc 1 ELSE Công việc 2A
Ví dụ:
Gán cho A giá trị lớn nhất trong 2 số
chứa trong X1 và X2
MOV A,X1 ; Gán A=X1
SUBB A,X2 ; A=A-X2=X1-X2 (CJNE
A,X2)
JC NHO ; X1 < X2 ?, Đúng thì
nhảy đến NHO
MOV A, X1 ; Sai, X1 ≥ X2 thì A = X1
SJMP RA
NHO: MOV A, X2 ; A = X2
RA:
Cấu trúc CASE
Ngữ pháp:
CASE Biểu thức
Giá trị 1: Công việc 1
Giá trị 2: Công việc 2
…
Giá trị n: Công việc n
Các GT #: Công việc
END CASE
Ví dụ: Điều khiển đèn LED 7 đoạn trực tiếp từ cổng P1.
VAO:CJNE A,#0,T1 //so sánh A và 0
MOV P1,#0C0H
SJMP EXIT
T1 :CJNE A,#1,T2
MOV P1,#06H
SJMP EXIT
…
EXIT:
Cấu trúc lặp FOR_DO
Ngữ pháp:
FOR Số lần lặp DO Công việc
Ví dụ: Xoá nội dung các ô nhớ nội
từ địa chỉ 30H đến 7FH (80byte)
trong RAM nội về 0.
Vào: MOV R0,#30H
MOV R1,#80
Lap: MOV @R0,#0
INC R0
DJNZ R1, Lap
Ra:
Cấu trúc WHILE_DO
Ngữ pháp:
WHILE Điều kiện DO Công việc
VD: Các biến T1 và T2 chứa các giá trị nhiệt độ cao và thấp. Hãy
tính giá trị trung bình của nhiệt độ và chứa kết quả trong thanh
chứa A.
Giải:
MOV A, 0 ; xoá A để chứa giá trị nhiệt độ trung bình
ADD A, T1 ; cộng nhiệt độ thứ nhất.
ADD A, T2 ; cộng nhiệt độ thứ hai.
MOV B,#2
DIV AB ; chia 2 kết quả trong A ta được nhiệt độ TB
Thoat: ; lối ra của cấu trúc
Ví dụ: Chương trình đọc vùng nhớ bắt đầu tại địa chỉ 100H
vào thanh ghi A, đến khi gặp ký tự '$' thì thoát:
VAO:
MOV DPTR, #100H
MOV A,#0
TIEP:
CJNE A,’$’,TIEP_TUC
SJMP RA
TIEP_TUC:
MOV A,@DPTR
SJMP TIEP
Lập trình điều khiển dữ liệu trên các cổng VĐK
Lập trình điều khiển Led đơn
Các lệnh cơ bản
- Lệnh MOV: di chuyển dữ liệu
VD: MOV A,30h ; chuyển nội dung của ô nhớ 30h vào thanh ghi A
MOV A,#30h ; chuyển giá trị 30h vào thanh ghi A
MOV A,R0 ; chuyển nội dung của thanh ghi R0 vào thanh ghi A
MOV A,@R0 ; chuyển nội dung của ô nhớ vào thanh ghi A, địa chỉ của ô
nhớ chứa trong thanh ghi R0 (nếu R0 = 30h thì lệnh này tương đương
lệnh MOV A,30h)
- Lệnh INC: tăng giá trị lên 1
- Lệnh DEC: giảm giá trị xuống 1
- Lệnh SJMP: lệnh nhảy không điều kiện
- Lệnh DJNZ: giảm và nhảy khi giá trị khác 0. Lệnh DJNZ thường dùng để
tạo vòng lặp và có dạng sau:
MOV R7,#số_lần_lặp
loop: ..…
……
DJNZ R7,loop
- Lệnh CJNE: so sánh và nhảy nếu không bằng
- Lệnh CALL: gọi chương trình con
- Lệnh RET, RETI: lệnh trả về từ chương trình con hay chương trình
phục vụ ngắt
- Lệnh PUSH: lưu trữ nội dung thanh ghi vào stack
- Lệnh POP: lấy nội dung từ stack.
- Lệnh DIV AB: chia nội dung thanh ghi A cho thanh ghi
B, thương số
chứa trong A và số dư chứa trong B.
- Lệnh MOVC: chuyển giá trị hằng số vào thanh ghi A,
thường dùng
cho mục đích tra bảng
Sơ đồ kết nối Led đơn
Mạch điều khiển led đơn mô tả như hình vẽ. Lưu ý rằng các port của AT89C51
có dòng tối đa là 10 mA nên khi cần điều khiển nhiều Led cần mắc thêm mạch
khuếch đại.
Sơ đồ kết nối dùng mạch khuếch đại
Kết nối Led đơn với AT89C51
// Chương trình chính
Main:
MOV P0,#0FFh ; Sáng 8 Led
CALL Delay
MOV P0,#0 ; Tắt 8 Led
CALL Delay
SJMP main
//Chương trình con
Delay:
PUSH 07h
PUSH 06h
MOV R6,#255
//Chương trình con
Delay1:
MOV R7,#255
DJNZ R7,$
DJNZ R6,Delay1
POP 06h
POP 07h
RET
END
Điều khiển Led 7 đoạn
- Dạng Led:
Hình vẽ – Hình dạng của Led 7 đoạn
- Led Anode chung:
Hình vẽ – Led 7 đoạn dạng anode chung
Đối với dạng Led anode chung, chân COM phải có mức
logic 1 và muốn sáng Led thì tương ứng các chân a – f, dp
sẽ ở mức logic 0.
Bảng 1: Bảng mã cho Led Anode chung (a là MSB, dp là LSB):
Bảng mã cho Led Anode chung (a là LSB, dp là MSB):
- Led Cathode chung
Đối với dạng Led Cathode chung, chân COM phải có mức
logic 0 và muốn sáng Led thì tương ứng các chân a – f, dp
sẽ ở mức logic 1.
Bảng mã cho Led Cathode chung (a là MSB, dp là LSB):
Bảng mã cho Led Anode chung (a là LSB, dp là MSB):
Kết nối Led 7 đoạn dùng phương pháp quét
Kết nối Led 7 đoạn dùng phương pháp chốt
Ví dụ: Viết chương trình hiển thị số 0 ra Led1 và số 1 ra Led2
Chương trình thực hiện như sau:
MOV P1,#0 ; Xoá P1 để tắt Led
Main:
MOV P0,#0C0h ; Mã số 0
SETB P1.0 ; Sáng Led1
CALL Delay ; Thời gian trì hoãn để thấy Led sáng
CLR P1.0 ; Tắt Led1
MOV P0,#0F9h ; Mã số 1
SETB P1.1 ; Sáng Led2
CALL Delay
CLR P1.1 ; Tắt Led2
SJMP main
;--------------------
Delay:
MOV TMOD,#01h
MOV TH0,#(-200)
MOV TL0,#(-200)
SETB TR0
JNB TF0,$
CLR TF0
CLR TR0
RET
END
3.5 Cấu trúc một chương trình C
• Chương trình C đơn giản cho 8051
• Cấu trúc chung của chương trình C cho 8051
• Các loại biến trong C cho 8051
• Các toán tử cơ bản
• Các cấu trúc rẽ nhánh và kiểm tra thường dùng
• Các quy tắc lập trình
103
Chương trình C đơn giản
#include<AT89X51.h>
void main()
{
P0_0 = 0;
P0_1 = 1;
}
104
Cấu trúc chung của một chương trình C cho 8051
// --- Khai báo thư viện sử dụng-----------------------------------------
#include<AT89X51.h>
#include<stdio.h>
//---Gán chân---------------------------------------------------------------
#define NutBam P3_0
sbit Led = P0_0;
//---Khai báo hằng---------------------------------------------------------
#define ON 1
#define OFF 0
usigned char so[10] = {0x40,0x79,0x24,0x30,0x19,0x12};
//---Khai báo biến toàn cục----------------------------------------------
bit t;
unsigned char x,y; 105
//---Khai báo và định nghĩa các chương trình con CTC
//CCT1: Chương trình con 1
void CTC1(void)
{
//Khai báo biến cục bộ
//Các câu lệnh
}
//----Chương trình con phục vụ ngắt nếu có---------------------------
void Tên_Hàm(void) interrupt nguồn ngắt using băng thanh ghi
{
// Khai báo biến cục bộ
// Các câu lệnh
} 106
Cấu trúc chung của một chương trình C cho 8051
// Hàm chính bắt buộc chương trình nào cũng có
void main(void)
{
//Các câu lệnh khởi tạo
//Vòng lặp vô hạn
while(1)
{
// Các câu lệnh chương trình
CTC1();
CTC2();
}
}
107
Cấu trúc chung của một chương trình C cho 8051
Các loại biến trong C cho 8051
108
Dạng biến Số bit Số byte Miền giá trị
bit 1 0,1
char 8 1
unsigned char 8 1
short 16 2
usigned short 16 2
int 16 2
unsigned int 16 2
long 32 4
unsigned long 32 4
enum 16 2

Các toán tử cơ bản
109
Tên phép toán Ký hiệu
Phép gán =
Các phép toán số học
Phép cộng +
Phép trừ -
Phép nhân *
Phép chia lấy thương /
Phép chia lấy dư %
Các phép toán logic
So sánh bằng ==
And &&
Or ||
Not !
Dịch trái và dịch phải << >>
Các cấu trúc rẽ nhánh và kiểm tra thường dùng
• Câu lệnh rẽ nhánh if:
• Câu lệnh rẽ nhánh if/else:
110
if(điều kiện)
{
//Các câu lệnh xử lý
}
if(giay==60)
{
phut = phut + 1;
giay = 0;
}
if(điều kiện)
{
//Khối lệnh 1
}
else
{
//Khối lệnh 2
}
if(nut==bam)
{
P2_0 = 0;
}
else
{
P2_0 = 1;
}
• Câu lệnh rẽ nhánh switch/case:
111
switch (Biến)
{ case giá trị 1:
// Khối lệnh 1
break;
case giá trị 2:
break;
…
case default:
// Khối lệnh default
break;
}
Switch (count)
{ case 0:
P2 = 0;
break;
case 1:
P2 = 1;
break;
case default:
P2 = 2;
break;
}
• Câu lệnh vòng lặp xác định for:
• Câu lệnh vòng lặp while:
112
for (i=m; i<n; i++)
{
// Các câu lệnh xử lý
}
for(i=0;i<100;i++)
{
time++
P1= P1 +1;
}
while(Điều kiện)
{
// Các câu lệnh
}
while(i<100)
{
time++
P1= P1 +1;
}
Các quy tắc lập trình
Quy tắc 1:
• Chương trình nên được tách
thành nhiều chương trình con.
• Mỗi chương trình con thực
hiện một nhiệm vụ độc lập.
• Việc tách thành các chương
trình con giúp cho chương
trình sáng sủa, và dễ kiểm tra.
Robot vận
chuyển hàng hóa
Lệch trái Lệch phải
Đếm số vạch
= 3
END
Đ
S
Quy tắc 2:
• Hạn chế sử dụng biến toàn
cục.
• Không nên sử dụng biến toàn
cục để truyền thông tin giữa
các chương trình con.
• Nên sử dụng các thông số khi
truyền thông tin cho các
chương trình con.
114
Các quy tắc lập trình
#include<REGX51.h>
unsigned int t;
void delay( )
{
for(t=0;t<=100;t++) {;}
}
void RePhai( )
{
P2=0x01;
delay();
}
void main( )
{
for(t=0;t<=10;t++)
RePhai();
#include<REGX51.h>
void delay( )
{
int t;
for(t=0;t<=100;t++)
{;}
}
void RePhai ( )
{
unsigned int T;
for(T=0;T<5;T++)
{
P2=0x00;
delay( );
}
}
void main( )
{
RePhai( );
}
• Quy tắc 3: Chương trình nên được viết đơn giản, rõ
ràng
115
Các quy tắc lập trình
KHÔNG NÊN VIẾT NÊN VIẾT
A[++] = 1; A[i]=1;
i++;
If(DoSomething( )==flase Result = DoSomething( )
If(result==false)
Quy tắc 4: Mỗi câu lệnh nên được đặt riêng trên một
dòng và phải viết đúng cấu trúc ngôn ngữ.
• Dễ đọc chương trình
• Dễ quan sát, tìm lỗi.
• Viết thụt đầu dòng
hợp lý.
• Các câu lệnh nằm
giữa cặp dấu {} được
viết thụt vào một
khoảng tab.
• Các lệnh ngang cấp
phải thụt vào như
nhau.
116
KHÔNG NÊN VIẾT NÊN VIẾT
#include<REGX51.H>
int t;
void delay( )
{
for(i=0;i<=3000;i++)
{;}
}
void RePhai( )
{
P2 = 0x00; delay( );
P2 = 0xFF; delay( );
}
void main( )
{
for(i=0;i<5;i++)
}
#include<REGX51.H>
int t;
void delay( )
{
for(i=0;i<=3000;i++)
{;}
}
void RePhai( )
{
P2 = 0x00;
delay( );
P2 = 0xFF;
delay( );
}
void main( )
{
for(i=0;i<5;i++)
}
Quy tắc 5: Chú thích cho chương trình.
• Viết ngắn gọn, nếu
chú thích trên một
dòng sử dụng ký hiệu
//, nhiều dòng sử
dụng cặp ký hiệu /*
*/
• Viết chú thích cho
từng hàm
• Chú thích cho từng
tập tin mã nguồn.
117
#include <REG51.H>
/*-------------------------------------------------------
Ví dụ về điều khiển LED FASH
Vi điều khiển AT89C51
Người viết: Ngô Quang Vĩ
Ngày viết code:
Ngày sửa code:
-------------------------------------------------------*/
#include<REGX51.H>
void delay_ms(unsigned int t )
{
unsigned int x,y;
for(x=0;x<t;x++)
{
for(y=0;y<=123;y++) {};
}
}
Void main()
{
while(1)
{
P2_0 = !P2_0;
delay_ms(500);
}
}
BÀI TẬP
118
119
120

CHUONG-3-LẬP-TRÌNH-CHO-HỌ-VI-ĐIỀU-KHIỂN-8051.pdf

  • 1.
    1 Chương 3 LẬP TRÌNHCHO HỌ VI ĐIỀU KHIỂN 8051 3.1 Mở đầu 3.2 Các kiểu định địa chỉ 3.3 Tập lệnh 3.4 Soạn thảo chương trình bằng ngôn ngữ lập trình Assembly 3.5 Soạn thảo chương trình bằng ngôn ngữ lập trình C
  • 2.
    2 3.1 Mở đầu Chương trình là chuỗi các lệnh mà VĐK phải xử lý, thực hiện  Lập chương trình là soạn thảo các lệnh bằng ngôn ngữ lập trình để thực hiện một thuật toán cụ thể Chương trình = Thuật toán + Cơ sở dữ liệu  Chương trình dịch: Ví dụ như Assembler, thực hiện dịch từ mã ngữ sang mã máy  Hệ lệnh của VĐK: Là tập lệnh mà người lập trình sử dụng để lập trình, người lập trình chỉ có thể sử dụng các lệnh trong hệ lệnh  Mỗi họ VĐK có một tệp lệnh riêng, chương trình viết cho hệ VĐK nào thì VĐK đó chạy được
  • 3.
    3  Ngôn ngữlập trình: - Bậc cao: C, C++, Pascal... - Bậc thấp: Mã máy: mỗi một lệnh tương ứng với một mãy nhị phân được gọi là mã lệnh Mã ngữ: Các lệnh được mô tả ở dạng biểu trưng (Symbol). Symbol có thể được viết tắt như MOV, ADD,... Hoặc là được ký hiệu các khối chức năng ở dạng Graphic...
  • 4.
    4 Các ký hiệucần chú ý: Rn : Các thanh ghi từ R0 – R7 (bank thanh ghi hiện hành) Ri : Các thanh ghi từ R0 – R1 (bank thanh ghi hiện hành) @Rn : Định địa chỉ gián tiếp 8 bit dùng thanh ghi Rn @DPTR : Định địa chỉ gián tiếp 16 bit dùng thanh ghi DPTR direct : Định địa chỉ trực tiếp RAM nội (00h – 7Fh) hay SFR (80h –FFh) (direct) : Nội dung của bộ nhớ tại địa chỉ direct #data8 : Giá trị tức thời 8 bit #data16 : Giá trị tức thời 16 bit bit : Địa chỉ bit của các ô nhớ có thể định địa chỉ bit (00h – 7Fh đối với địa chỉ bit và 20h – 2Fh đối với địa chỉ byte)
  • 5.
    5 CÁCH VIẾT SỐ SốBinary (nhị phân): Số nhị phân khi viết cần thêm phía sau giá trị bằng kí tự “B”. Ví dụ: 010101B Số Hexa: Số hexa khi cần viết cần thêm phía sau giá trị bằng kí tự “H”. Ví dụ: 69H Số thập phân: Số thập phân khi cần viết không cần thêm kí tự hoặc thêm sau giá trị bằng kí tự “D” Ví dụ: 45, 27, 68D
  • 6.
    6 3.2 Các kiểuđịnh địa chỉ Bộ VĐK 8051 có 8 kiểu định địa chỉ: - Thanh ghi (register) - Trực tiếp (direct) - Gián tiếp (Indirect) - Tức thời (Immediate) - Tương đối (relative) - Tuyệt đối (absolute) - Dài (long) - Chỉ số (Indexed)
  • 7.
    7  Định địachỉ thanh ghi Các thanh ghi từ R0 – R7 có thể truy xuất bằng cách định địa chỉ trực tiếp hay gián tiếp như trên. Ngoài ra, các thanh ghi này còn có thể truy xuất bằng cách dùng 3 bit trong mã lệnh để chọn 1 trong 8 thanh ghi (8 thanh ghi này có địa chỉ trực tiếp thay đổi tuỳ theo bank thanh ghi đang sử dụng). VD: ADD A, R7 ; A = A+R7
  • 8.
    8  Định địachỉ trực tiếp Định địa chỉ trực tiếp chỉ dùng cho các thanh ghi chức năng đặc biệt và RAM nội của 8051.  Giá trị địa chỉ trực tiếp 8 bit được thêm vào phía sau mã lệnh.  Nếu địa chỉ trực tiếp từ 00h – 7Fh thì đó là RAM nội của 8951 (128 byte), còn địa chỉ từ 80h – FFh là địa chỉ các thanh ghi chức năng đặc biệt Các lệnh sau có kiểu định địa chỉ trực tiếp: MOV A, P0 MOV A, 30h
  • 9.
    9  Định địachỉ gián tiếp Định địa chỉ gián tiếp có thể dùng cho cả RAM nội và RAM ngoại. Địa chỉ của RAM xác định thông qua một thanh ghi (R0, R1, SP cho địa chỉ 8 bit và DPTR cho địa chỉ 16 bit). Các lệnh sau có kiểu địa chỉ gián tiếp: MOV A, @R0 MOVX A, @DPTR
  • 10.
    10 VD: Xoá nộidung các ô nhớ từ địa chỉ 30H đến 7FH trong bộ nhớ RAM nội về 0H ta dùng các lệnh sau. MOV R0, #30H lap: MOV @R0, #0 INC R0 CJNE R0,#80H, lap
  • 11.
    11  Định địachỉ tức thời Giá trị của một hằng số có thể đưa trực tiếp vào mã lệnh của chương trình. Trong hợp ngữ, hằng số được xác định bằng cách sử dụng dấu #. VD: MOV A, #12
  • 12.
    12  Định địachỉ tương đối Kiểu định địa chỉ tương đối chỉ được sử dụng cho các lệnh nhảy  Là một giá trị 8bit có dấu  Có điểm lợi là cung cấp cho ta mã không phụ thuộc vào vị trí, điểm bất lợi là các đích nhảy bị giới hạn trong tầm (-128 đến 127 byte)
  • 13.
  • 14.
    14  Định địachỉ tuyệt đối Kiểu định địa chỉ tuyệt đối chỉ được sử dụng với các lệnh ACALL và AJMP Đây là các lệnh 2 byte cho phép rẽ nhánh chương trình trong một trang 2kB hiện hành của bộ nhớ chương  Định địa chỉ dài Kiểu định địa chỉ dài chỉ được dùng cho lệnh LCALL và LJMP. Các lệnh 3byte này chứa địa chỉ đích 16bit
  • 15.
    15  Định địachỉ chỉ số  Dùng một địa chỉ nền (chứa trong thanh ghi PC hay DPTR) và một offset (chứa trong thanh ghi A) để tạo địa chỉ được tác động cho các lệnh JMP hoặc MOVC. (Địa chỉ được tác động) = (PC) hoặc (DPTR) + (A)  Thường dùng khi truy xuất dữ liệu trong một bảng dữ liệu đã được định nghĩa trước
  • 16.
    16 Ví dụ: Bảngcác giá trị bình phương của số nguyên. Nếu DPTR chứa địa chỉ đầu bảng (tương ứng nhãn TABLE) và (A) = 3, thì sau khi thực hiện lệnh: MOVC A, @A+DPTR
  • 17.
    17 3.3 Tập lệnh Tậplệnh của 8051 có thể chia thành 5 nhóm: - Nhóm lệnh số học - Nhóm lệnh logic - Nhóm lệnh di chuyển dữ liệu - Nhóm lệnh xử lý bit - Nhóm lệnh rẽ nhánh Gốc, Đích: có thể là Rn, hoăc direct hoặc @Ri data: hằng số bit data16: hằng số 16bit
  • 18.
    18 Nhóm lệnh sốhọc ADD A, nguồn: A = A + nguồn Chức năng: Cộng Mô tả:Lệnh ADD được dùng để cộng hai toán hạng, kết quả lưu vào thanh chứa A. Toán hạng đích luôn là thanh ghi A trong khi đó toán hạng nguồn có thể là một thanh ghi dữ liệu trực trực tiếp hoặc là trong bộ nhớ
  • 19.
    19 VÝ dô: H·ybiÓu diÔn xem c¸c lÖnh díi ®©y t¸c ®éng ®Õn thanh ghi cê nh thÕ nµo? MOV A, # 0F5H ; A = F5H MOV A, # 0BH ; A = F5 + 0B = 00 Lêi gi¶i: F5H 1111 0101 + 0BH + 0000 1011 100H 10000 0000 Sau phÐp céng, thanh ghi A (®Ých) chøa 00 vµ c¸c cê sÏ nh sau: CY = 1 và cã phÐp nhí tõ D7 PF = 1 và sè c¸c sè 1 lµ 0 (mét sè ch½n) cê PF ®îc ®Æt lªn 1. AC = 1 và cã phÐp nhí tõ D3 sang D4
  • 20.
    20 VÝ dô: H·yviÕt ch¬ng trinh céng hai sè 16 bit. C¸c sè ®ã lµ 3CE7H vµ 3B8DH. CÊt tæng sè vµo R7 vµ R6 trong ®ã R6 chøa byte thÊp. Lêi gi¶i: CLR ; Xo¸ cê CY = 0 MOV A, #0E7H ; N¹p byte thÊp vµo A : A = E7H ADD A, #8DH ; Céng byte thÊp vµo A : a = 74H vµ CY = 1 MOV R6, A ; Lu byte thÊp cña tæng vµo R6 MOV A, #3CH ; N¹p byte cao vµo A : A = 3CH ADDC A, #3BG ; Céng byte cao cã nhí vµo A : A = 78H MOV R7, A ; Lu byte cao cña tæng vµo R7
  • 21.
    21 SUBB A, nguồn;A = A – nguồn – CY Chức năng: Trừ có mượn Mô tả: Trong 8051 chỉ có một lệnh SUBB duy nhất. SUBB thực hiện trừ nội dung của thanh chứa A với toán hạng nguồn cùng với cờ nhớ và cất kết quả vào thanh chứa.
  • 22.
    22 VÝ dô: Trinhbµy c¸c bíc liªn quan díi ®©y: CLR C ; T¹o CY = 0 MOV A, #3FH ; N¹p 3FH vµo A (A = 3FH) MOV R3, #23H ; N¹p 23H vµo R3 (R3 = 23H) SUBB A, R3 ; Trõ A cho R3 ®Æt kÕt qu¶ vµo A
  • 23.
    23  MUL AB Chứcnăng: Nhân Mô tả: MUL AB nhân các số nguyên không dấu 8 bit trong thanh ghi chứa A và thanh ghi B, kết quả là một số 16 bit có byte thấp đặt trong thanh chứa A và byte cao đặt trong thanh ghi B. Ví dụ: Phép nhân hai số 8 bit. Kết quả là dữ liệu 16 bit được đặt trong A và B. MOV A, #9AH MOV B, #35H MUL AB
  • 24.
    24  DIV AB Chứcnăng: Chia A cho B Mô tả: 8051 cũng chỉ hỗ trợ cho phép chia hai số không dấu byte cho byte, tử số (số bị chia) phải ở trong thanh ghi A và mẫu số (số chia) phải ở trong thanh ghi B. Sau khi lệnh chia DIV được thực hiện thì thương số được đặt trong A, còn số dư được đặt trong B. Ví dụ: MOV A, #7AH ; Nạp số bị chia vào A = 7AH MOV B, #10H ; Nạp số chia vào B = 10H DIV AB ; A = 07 (thương số); B = 0AH (số dư)
  • 25.
    25 Nhóm lệnh logic ANL đích, nguồn Chức năng: Thực hiện phép nhân logic (AND) Mô tả: ANL thực hiện phép toán AND từng bit trên toán hạng đích và nguồn, đặt kết quả vào đích, các cờ không bị ảnh hưởng. Toán hạng đích thường là thanh ghi tổng (tích lũy), toán hạng nguồn có thể là thanh ghi trong bộ nhớ hoặc giá trị cho sẵn. ANL thường được dùng để che (đặt về 0) những bit nhất định của toán hạng.
  • 26.
    26 Ví dụ: Chobiết kết quả của đoạn mã ở ví dụ dưới đây: MOV A, #86H ; Gán A = 86H ANL A, #0FH ; Thực hiện nhân logic A và 0FH (bây giờ A = 06H) Lời giải: 86H 10000110 0FH 00001111 06H 00000110 X
  • 27.
    27  ORL đích,nguồn Chức năng: Thực hiện phép cộng logic (OR) Mô tả: ORL thực hiện phép toán OR từng bit trên hai toán hạng đích và nguồn, đặt kết quả vào đích, các cờ không bị ảnh hưởng. Toán hạng đích thường là thanh ghi tổng hoặc là địa chỉ trực tiếp, toán hạng nguồn có thể là thanh ghi trong bộ nhớ hoặc giá trị cho sẵn. ANL thường được dùng để thiết lập (đặt lên 1) những bit nhất định của toán hạng.
  • 28.
    28 Ví dụ: Chobiết kết quả của đoạn mã ở sau: MOV A, #55H ; A = 55H ORL A, #0Ah ; A = 5FH Lời giải: 55H 01010101 0AH 00001010 5FH 01011111
  • 29.
    29  XRL đích,nguồn Chức năng: Thực hiện phép trừ logic (XOR) Mô tả: XRL thực hiện phép toán XOR từng bít trên hai toán hạng đích và nguồn, đặt kết quả vào đích, các cờ không bị ảnh hưởng. Toán hạng đích thường là thanh ghi tổng hoặc địa chỉ trực tiếp, toán hạng nguồn có thể là thanh ghi trong bộ nhớ hoặc giá trị cho sẵn.
  • 30.
    30 Ví dụ: Chobiết kết quả của đoạn mã sau đây: MOV A, #55H XRL A, #79H Lời giải: 55H 01010101 79H 01111001 2CH 00101100
  • 31.
    31  CPJ A Chứcnăng: Lấy bù nội dung của thanh ghi A. Mô tả: Nội dung của thanh ghi A được lấy bù logic (phép biến đổi các bit 0 thành các bit 1 và đổi các bit 1 sang bit 0). Các cờ không bị ảnh hưởng. MOV A, #55H CPJ A ; Bây giờ nội dung của thanh ghi A là AAH ; Vì 01010101 (55H) 10101010 (AAH)
  • 32.
    32  CPL bit Chứcnăng: Lấy bù bit. Mô tả: Nội dung của bit chỉ ra trong lệnh được lấy bù logic (đổi các bit 0 thành các bit 1 và đổi các bit 1 sang bit 0). Các cờ không bị ảnh hưởng. CPL có thể được thao tác trên các cờ nhớ và trên một bit bất kỳ được định đại chỉ bit.
  • 33.
    33  CJNE đích,nguồn, địa chỉ tương đối Chức năng: So sánh và nhảy nếu không bằng nhau Mô tả: Lệnh CJNE so sánh hai toán hạng nguồn và đích và rẽ nhánh đến địa chỉ tương đối nếu hai toán hạng không bằng nhau. Ngoài ra cờ nhớ CY được lập nếu toán hạng đích nhỏ hơn toán hạng nguồn. Các toán hạng vẫn giữ nuyên không thay đổi
  • 34.
    34  RR A Chứcnăng: Quay các bit thanh ghi sang phải Mô tả: Lệnh RR thực hiện quay các bit của thanh ghi A sang phải một vị trí, bit D0 rời từ vị trí bit thấp nhất và chuyển sang bit cao nhất D7. Các cờ không bị ảnh hưởng Ví dụ: MOV A, #6AH ; A = 01101010 RR A ; A = 00110101 RR A ; A = 10011010 RR A ; A = 01001101 MSB LSB
  • 35.
    35  RL A Chứcnăng: Quay các bit thanh ghi sang trái Mô tả: Lệnh RL thực hiện quay các bit của thanh ghi A sang trái một vị trí, bit D7 rời từ vị trí bit cao nhất và chuyển sang bit thấp nhất D7. Các cờ không bị ảnh hưởng Ví dụ: MOV A, #6AH ; A = 01101010 RL A ; A = 11010100 RL A ; A = 10101001 RL A ; A = 01010011 MSB LSB
  • 36.
    36  RLC A Chứcnăng: Quay trái qua cờ nhớ Mô tả: Lệnh RLC thực hiện quay các bit của thanh ghi A sang trái một vị trí, bit MSB vào cờ nhớ (CY), sau đó bit CY được chuyển vào bit LSB. Cờ nhớ CY tác động như là một bit bộ phận của thanh ghi A làm nó trở thành thanh ghi 9 bit.
  • 37.
    37 Ví dụ: SET C; C = 1 MOV A, #71H ; A = 01110001 C = 0 RLC A ; A = 11100011 C = 1 RLC A ; A = 11000110 C = 1 RLC A ; A = 10001101 C = 1 MSB LSB CY
  • 38.
    38  RRC A Chứcnăng: Quay phải qua cờ nhớ Mô tả: Lệnh RRC thực hiện quay các bit của thanh ghi A sang phải một vị trí, bit LSB vào cờ nhớ (CY), sau đó bit CY được chuyển vào bit MSB Ví dụ: SET C ; C = 1 MOV A, #71H ; A = 01110001 RRC A ; A = 10111000 C = 1 RRC A ; A = 11011100 C = 0 MSB LSB CY
  • 39.
    39  SWAP A Chứcnăng: Lệnh hoán đổi thanh ghi A Mô tả: SWAP hoán đổi 4 bit nửa phần cao của byte và 4 bit thấp của byte với nhau, SWAP chỉ hoạt động trên thanh ghi A. Các cờ không bị ảnh hưởng. D7 D6 D5 D4 D3 D2 D1 D0 Trước khi thực hiện Sau khi thực hiện D3 D2 D1 D0 D7 D6 D5 D4
  • 40.
    40 Nhóm lệnh dịchchuyển dữ liệu 1. Nhóm lệnh dịch chuyển dữ liệu trong RAM nội  MOV đích, nguồn Chức năng: Di chuyển bit nguồn đến bit đích. Mô tả: Nội dung của bit được chỉ ra bởi toán hạng nguồn được sao chép vào vị trí bit ở toán hạng thứ nhất. Một trong hai toán hạng phải là cờ nhớ, toán hạng còn lại là bit bất kỳ được định địa chỉ bit, bit nguồn không bị ảnh hưởng, các thanh ghi khác và các cờ không bị ảnh hưởng.
  • 41.
    41 Ví dụ: CLP P0.0; Bit P0.0 bị xóa về 0 SETB C ; Bit cờ nhờ được thiết lập MOV P0.1, C ; Bit cờ chuyển vào P0.1 (bằng 1) MOV C, P0.0 ; Bit cờ bị xóa về 0
  • 42.
    42  XCH đích,nguồn Chức năng: Hoán chuyển nội dung của toán hạng đích và toán hạng nguồn. Mô tả: Toán hạng đích phải là thanh ghi chứa A, lệnh XCH hoán chuyển nội dụng của byte nguồn với thanh ghi chứa
  • 43.
    43 2. Nhóm lệnhdịch chuyển dữ liệu trong RAM ngoài  MOVC A, @A + DPTR Chức năng: Di chuyển bit nguồn đến bit đích Mô tả: MOVC nạp cho thanh chứa byte hằng số từ bộ nhớ chương trình. Địa chỉ của byte được nạp là tổng của giá trị 8 bit không dấu ban đầu chứa trong thanh chứa nội dung của thanh ghi địa chỉ cơ sở (thanh ghi cơ sở có thể là thanh ghi con trỏ dữ liệu hoặc PC).
  • 44.
    44  MOVC A,@A + PC Cũng hoạt động tương tự như câu lệnh ở trên, ngoại trừ ở đây bộ đếm chương trình được dùng để chứa địa chỉ cơ sở và bảng được truy xuất nhờ vào bộ nhớ chương trình con. Trước tiên số của điểm nhập yêu cầu được nạp cho thanh chứa A, sau đó chương trình con được gọi. Chuỗi lệnh cho phép khởi động và gọi có thể là:
  • 45.
    45 Ví dụ: MOV A,ENTRY_NUMBER CALL LOOK_UP//gọi LOOP_UP: INC A // tăng gía trị thanh ghi A MOVC A, @A+PC RET // kết thúc 1 chương trình con TABLE: DB data0, data1, data2,... //nhãn Bảng được định nghĩa sau lệnh INC trong chương trình, lệnh tăng được cần đến PC trỏ tới lệnh INC khi lệnh MOVC được thực thi. Việc tăng nội dung thanh ghi chứa sẽ bỏ qua lệnh RET.
  • 46.
    46 Nhóm lệnh xửlý bit  SETB bit Chức năng: Thiết lập bit Mô tả: SETB đặt bit được chỉ ra trong lệnh bằng 1, SETB có thể thao tác trên các cờ nhờ hoặc các bit được định địa chỉ bit. Ví dụ: SETB C ; Thiết lập cờ nhớ bằng 1
  • 47.
    47  CLR bit Chứcnăng: Xóa bit Mô tả: CLR xóa bit được chỉ ra trong lệnh về 0, CLR có thể thao tác trên các cờ nhớ hoặc các bit được định nghĩa địa chỉ bit. Ví dụ: CLR P0.1 ; xóa bit 1 của cổng P0 CLR TR0
  • 48.
    48  CPL bit Chứcnăng: Lấy bù bit Mô tả: CPL được chỉ ra trong lệnh được lấy bù, một bit có giá trị 1 được đổi thành 0 và ngược lại. CPL có thể thao tác trên các cờ nhớ hoặc các bit được định địa chỉ bit. Ví dụ: SETB P0.1 ; bit 1 của cổng P0 được đặt thành 1 CPL P0.1 ; đảo lại bit 1 của cổng P0 bằng 0
  • 49.
    49 Nhóm lệnh rẽnhánh Phần này sẽ trình bày các lệnh chuyển điều khiển có trong hợp ngữ của 8051 như các lệnh sử dụng cho vòng lặp, các lệnh nhảy có và không có điều kiện, lệnh gọi chương trình con. 1.Các lệnh nhảy có điều kiện  JZ nhãn_đích Chức năng: Nhảy nếu A = 0 Mô tả: Khi thực hiện lệnh JZ, nội dung của thanh ghi A được kiểm tra. Nếu nó bằng không thì nó nhảy đến địa chỉ đích, ngược lại thì tiếp tục với lệnh tiếp theo.
  • 50.
    50 Ví dụ xétđoạn mã sau: MOV A, R0 ; Nạp giá trị của R0 vào A JZ nhãn ; Nhảy đến LABLE nếu A = 0 MOV A, R1 ; Nạp giá trị của R1 vào A JNZ LABLE ; Nhảy đến LABLE nếu A # 0 LABLE:
  • 51.
    51  JNC nhãn_đích Chứcnăng: Nhảy nếu không có nhớ (CY = 0) Mô tả: Khi thực hiện lệnh JNC, bộ xử lý kiểm tra cờ nhớ nếu CY = 0 thì CPU bắt đầu nạp và thực hiện các lệnh từ địa chỉ của nhãn. Nếu cờ CY = 1, CPU sẽ chuyển đến địa chỉ đích, ngược lại thì tiếp tục với lệnh tiếp theo.
  • 52.
    52 Lệnh Hoạt động JZNhảy nếu A = 0 JNZ Nhảy nếu A # 0 DJNZ Giảm và nhảy nếu A = 0 CJNE A, byte Nhảy nếu A # byte CJNE byte, # data Nhảy nếu byte # data JC Nhảy nếu CY = 1 JNC Nhảy nếu CY = 0 JB Nhảy nếu bit = 1 JNB Nhảy nếu bit = 0 JNC Nhảy nếu bit = 1 và xóa nó
  • 53.
    53 2. Các lệnhnhảy không điều kiện  LJMP nhãn_đích Chức năng: Nhảy dài Mô tả: Nhảy xa LJMP là một lệnh 3 byte trong đó byte đầu tiên là mã lệnh còn 2 byte còn lại là địa chỉ 16 bit của đích. Địa chỉ đích 2 byte có một phép nhảy đến bất kỳ vị trí nhớ nào trong khoảng 0000H - FFFFH
  • 54.
    54  SJMP nhãn_đích Chứcnăng: Nhảy ngắn Mô tả: Trong 2 byte của lệnh SJMP này thì byte đầu tiên là mã lệnh và byte thứ hai là chỉ tương đối của địa chỉ đích. Đích chỉ tương đối trong phạm vi 00 – FFH được chia thành địa chỉ nhảy tiến và địa chỉ lùi, nghĩa là từ -128 đến +127 byte của bộ nhớ tương đối so với địa chỉ hiện thời của bộ đếm chương trình. Nếu là lệnh nhảy tới thì địa chỉ đích có thể nằm trong khoảng 127 byte từ gía trị hiện thời của bộ đếm chương trình. Nếu địa chỉ đích ở phía sau thì nó có thể nằm trong khoảng -128 byte từ giá trị hiện hành của PC.
  • 55.
    55 3. Các lệnhgọi  ACALL nhãn _ lệnh Chức năng: gọi đến địa chỉ tuyệt đối Mô tả: ACALL gọi không điều kiện một chương trình con đặt tại địa chỉ được chỉ ra trong lệnh. Do ACALL chỉ có 2 byte nên địa chỉ đích của chương trình con phải nằm trong khoảng 2k. Byte địa chỉ vì chỉ có 11 bit của 2 byte được sử dụng cho địa chỉ.
  • 56.
    56  LCALL nhãn_ lệnh Chức năng: Gọi xa Mô tả: Trong lệnh 3 byte này thì byte đầu tiên là mã lệnh, còn hai byte sau được dùng cho địa chỉ của chương trình con đích. Do vậy LCALL có thể được dùng để gọi các chương trình con ở bất kỳ vị trí nào trong phạm vi 64k byte, không gian địa chỉ của 8051. Để đảm bảo rằng sau khi thực hiện một chương trình được gọi 8051 biết được chỗ quay trở về thì nó tự động cất vào ngăn xếp địa chỉ của lệnh đứng ngay sau lệnh gọi LCALL.
  • 57.
    3.4 Soạn thảochương trình bằng ngôn ngữ lập trình Assembly 57 Khung chương trình hợp ngữ khi không sử dụng ngắt: ; [Tên chương trình] - [Mô tả chương trình] ; [Mô tả chi tiết ứng dụng] ; [Tác giả] ; Ngày bắt đầu: ; Ngày chỉnh sửa gần nhất: ; Chú ý về phần cứng: ; [Dùng bộ VĐK nào, tần số xung nhịp, cách đấu nối chân ; Khai báo biến [Tên_biến] EQU [Địa_chỉ] ; Mô tả biến ; Khai báo hằng [ Tên_hằng EQU Giá_trị] ; Mô tả hằng ; Bắt đầu chương trình chính ORG 0000H MAIN: ; Các lệnh của thân chương trình chính ...........
  • 58.
    3.4 Soạn thảochương trình bằng ngôn ngữ lập trình Assembly 58 CALL Tên_ctc ; Gọi chương trình con .......... [SJMP MAIN ; Kết thúc chương trình chính] ;***************************** ; Bắt đầu các chương trình con Tên_ctc: ;Các lệnh của thân chương trình con ................... RET ; Kết thúc chương trình con và quay về chương trình chín .................... ; Các chương trình con khác ;***************************** ; Kết thúc toàn bộ chương trình END
  • 59.
    Trình tự cácbước thiết kế chương trình Ngôn ngữ bậc cao  Ngôn ngữ cấp cao điển hình như Pascal, C sử dụng các từ và phát biểu dễ hiểu đối với con người hay là ngôn ngữ gần với con người  Ngôn ngữ lập trình bậc cao thì dễ hiểu đối với con người
  • 60.
    Ngôn ngữ bậcthấp  Hợp ngữ (Assembly Language Programming) là ngôn ngữ của máy tính có vị trí giữa ngôn ngữ máy và ngôn ngữ cấp cao  Hợp ngữ thay thế các mã nhị phân của ngôn ngữ máy bằng các mã gợi giúp ta dễ nhớ và dễ lập trình hơn  Chương trình hợp ngữ không thể thực thi trục tiếp bởi máy tính. Sau khi viết xong, chương trình này phải trải qua quá trình dịch thành ngôn ngữ máy  Trình dịch hợp ngữ là chương trình dùng để dịch một chương trình hợp ngữ thành chương trình ngôn ngữ máy
  • 61.
    Giới thiệu khungcủa chương trình hợp ngữ Cú pháp của chương trình hợp ngữ Trong hợp ngữ, một dòng lệnh có thể có những trường sau: Tên Mã lệnh Các toán hạng Chú giải Ví dụ 1: Dòng lệnh là hướng dẫn cho chương trình dịch ORG 0000H END
  • 62.
    Ví dụ 2:Một dòng lệnh dưới dạng mã gợi nhớ TIEP: MOV A, 50H // nạp vào A nội dung của ô nhớ có địa chỉ 50H Trong đó: - Trường tên là nhãn TIEP: - Trường mã lệnh là lệnh MOV - Trường toán hạng là các toán hạng: A và 50H - Trường chú giải là lời giải thích: ";nạp...."
  • 63.
    Trường tên:  Chứacác nhãn, tên biến, hoặc tên thủ tục. Khi dịch chương trình các tên và nhãn này sẽ được gán bằng các địa chỉ cụ thể của ô nhớ.  Tên và nhãn có thể có độ dài từ 1 đến 31 ký tự, không chứa dấu cách, hoặc bắt đầu bằng số, không trùng với các từ khoá của trình biên dịch. Có thể dùng ký tự đặc biệt "_" để kết nối các từ trong tên.  Một nhãn thường kết thúc bằng dấu hai chấm ":".
  • 64.
    Trường mã lệnh: Trong trường mã lệnh có thể là lệnh thật hoặc lệnh giả  Nếu là lệnh thật thì đó là mã lệnh gợi nhớ, mã lệnh này sẽ được chương trình dịch dịch ra mã máy.  Nếu là lệnh giả thì đó là một hướng dẫn chương trình dịch và không được dịch ra mã máy.
  • 65.
    Trường toán hạng: Nếu trong lệnh thật thì trường này chứa các toán hạng của lệnh. Trong một lệnh có thể có 0,1 hoặc 2 toán hạng. Lệnh 1 toán hạng thì toán hạng đó có thể là Gốc hoặc Đích. Lệnh 2 toán hạng thì một toán hạng là Gốc, một toán hạng là Đích.  Đối với hướng dẫn chương trình dịch thì trường này chứa các thông tin liên quan đến các lệnh giả của hướng dẫn.
  • 66.
    Trường chú giải: -Trường chú giải phải được bắt đầu bằng dấu chấm phẩy ";". - Trường này được dùng để ghi các lời giải thích của người lập trình cho các lệnh của chương trình để giúp cho người đọc chương trình dễ hiểu. - Khi biên dịch chương trình sẽ bỏ qua phần sau dấu ";" trên dòng lệnh do vậy ta có thể dùng dấu ";" để loại bỏ một dòng lệnh nào đó trong chương trình.
  • 67.
    Dữ liệu chochương trình: Khi cung cấp dữ liệu cho chương trình hợp ngữ, số cho ở hệ nào phải được kèm đuôi của hệ đó (trừ hệ thập phân). Riêng đối với hệ hexa nếu một số được bắt đầu bằng các chữ (a...f hoặc A...F) thì ta phải thêm 0 ở trước số để chương trình dịch không hiểu nhầm đó là một tên hay một nhãn.
  • 68.
    Ví dụ: 0011B ;Số hệ hai 1234 ; Số hệ mười 0ABCDH ; Số hệ mười sáu 1EGFH ; Số hệ mười sáu - Nếu dữ liệu là ký tự hoặc chuỗi ký tự thì chúng phải được đóng trong dấu nháy đơn . VD: 'A', 'abc'. Khi dịch, chương trình dịch sẽ dịch ký tự ra mã ASCII tương ứng của nó, vì vậy ta có thể cung cấp dữ liệu ký tự cho chương trình dưới dạng mã ASCII của nó.
  • 69.
    Các chỉ dẫn Cácchỉ dẫn là các lệnh đối với trình dịch hợp ngữ. Các chỉ dẫn không được dịch ra mã máy và không phải là các lệnh thuộc tập lệnh của bộ VĐK. Tuy nhiên các chỉ dẫn lại được đặt trong trường mã gợi nhớ của chương trình. Ở đây ta sẽ giới thiệu một vài loại chỉ dẫn sau: - Điều khiển trạng thái của trình dịch hợp ngữ: ORG, END - Định nghĩa ký hiệu: EQU, BIT,... - Dành trước vùng nhớ/khởi động vùng nhớ: DB, DW
  • 70.
    ORG (set origin) Dạngchỉ dẫn ORG như sau: ORG biểu_thức Chỉ dẫn ORG thay đổi nội dụng bộ đếm vị trí để thiết lập một gốc mới của chương trình cho các phát biểu theo sau. Ví dụ: ORG 0030H ; Bộ đếm vị trí được thiết lập bằng 0030H
  • 71.
    END Dạng của chỉdẫn END như sau: END END là phát biểu cuối cùng của chương trình nguồn. Không có gì theo sau phát biểu END được xử lý bởi trình dịch hợp ngữ.
  • 72.
    EQU (equate) Dạng củachỉ dẫn EQU như sau: TÊN EQU Biểu_thức Chỉ dẫn EQU gán giá trị số cho TÊN. Biểu_thức là một hằng số hay một biểu thức chứa các hằng số. VD: X1 EQU 35H ; X1 có giá trị 35H Khi biên dịch TÊN sẽ được thay thể bằng giá trị đã gán cho nó tại những nơi nó xuất hiện trong chương trình.
  • 73.
    BIT X BIT P0.0 Chỉdẫn BIT cho phép gán giá trị của một bit cho trường tên. DB Dạng của chỉ dẫn DB như sau: [Nhãn:] DB Giá_trị [,Giá_trị, ...] Chỉ dẫn DB khởi động vùng nhớ mã (ô nhớ trong bộ nhớ chương trình) với các giá trị có độ dài 1 byte. Trên thực tế chỉ dẫn này thường được dùng để đặt các hằng số vào bộ nhớ chương trình. Danh sách các giá trị là một chuỗi của một hay nhiều giá trị byte cách nhau bởi dấu phẩy.
  • 74.
    VD: ORG 100H Binh_phuong: DB 0,1,4,9,16,25; bình phương Chao: DB 'Hello!' ; chuỗi ký tự Sau chỉ dẫn này trương trình dịch sẽ tạo ra một chuỗi các byte liên tiếp chứa các hằng số. Ở ô nhớ có địa chỉ 100H là 0, ô nhớ 101H là 1…Giá trị của tên cũng chính là địa chỉ đầu tiên của dãy các ô nhớ.
  • 75.
    DW Dạng của chỉdẫn DW như sau: [Nhãn:] DW Giá_trị [,Giá_trị, ...] Chỉ dẫn DW tương tự như chỉ dẫn DB ngoại trừ 2 vị trí nhớ (16bit) được gán cho mỗi thành phần dữ liệu. VD: MW: DW 12, 345H, 555
  • 76.
    Cách tạo vàcho chạy một chương trình hợp ngữ.  Keil cho phép ta có thể đồng thời soạn thảo chương trình hợp ngữ, biên dịch.  Chạy mô phỏng thử chương trình trên máy tính.  Khi biên dịch chương trình ta sẽ được file mã máy của chương trình, file này có đuôi .hex.  File mã máy này có thể nạp vào VĐK để chạy thử trên KIT phát triển, và cũng có thể cho chạy thử trên máy tính.
  • 77.
    Các cấu trúclập trình cơ bản thực hiện bằng hợp ngữ Cấu trúc tuần tự Cấu trúc tuần tự là cấu trúc đơn giản nhất. Trong cấu trúc tuần tự, các lệnh được sắp xếp tuần tự, lệnh này tiếp theo lệnh kia. Lệnh 1 Lệnh 2 … Lệnh n
  • 78.
    VD: Các biếnT1 và T2 chứa các giá trị nhiệt độ cao và thấp. Hãy tính giá trị trung bình của nhiệt độ và chứa kết quả trong thanh chứa A. Giải: MOV A, 0 ; xoá A để chứa giá trị nhiệt độ trung bình ADD A, T1 ; cộng nhiệt độ thứ nhất. ADD A, T2 ; cộng nhiệt độ thứ hai. MOV B,#2 DIV AB ; chia 2 kết quả trong A ta được nhiệt độ TB Thoat: ; lối ra của cấu trúc
  • 79.
    Cấu trúc IF_THEN Ngữpháp: IF Điều kiện THEN Công việc VD : IF (R0=10H) THEN A=#0FFH VAO: CJNE R0,#10H,RA MOV A, #0FFH SJMP RA
  • 80.
    Cấu trúc IF_THEN_ELSE Ngữpháp: IF Điều kiện THEN Công việc 1 ELSE Công việc 2A Ví dụ: Gán cho A giá trị lớn nhất trong 2 số chứa trong X1 và X2 MOV A,X1 ; Gán A=X1 SUBB A,X2 ; A=A-X2=X1-X2 (CJNE A,X2) JC NHO ; X1 < X2 ?, Đúng thì nhảy đến NHO MOV A, X1 ; Sai, X1 ≥ X2 thì A = X1 SJMP RA NHO: MOV A, X2 ; A = X2 RA:
  • 81.
    Cấu trúc CASE Ngữpháp: CASE Biểu thức Giá trị 1: Công việc 1 Giá trị 2: Công việc 2 … Giá trị n: Công việc n Các GT #: Công việc END CASE
  • 82.
    Ví dụ: Điềukhiển đèn LED 7 đoạn trực tiếp từ cổng P1. VAO:CJNE A,#0,T1 //so sánh A và 0 MOV P1,#0C0H SJMP EXIT T1 :CJNE A,#1,T2 MOV P1,#06H SJMP EXIT … EXIT:
  • 83.
    Cấu trúc lặpFOR_DO Ngữ pháp: FOR Số lần lặp DO Công việc Ví dụ: Xoá nội dung các ô nhớ nội từ địa chỉ 30H đến 7FH (80byte) trong RAM nội về 0. Vào: MOV R0,#30H MOV R1,#80 Lap: MOV @R0,#0 INC R0 DJNZ R1, Lap Ra:
  • 84.
    Cấu trúc WHILE_DO Ngữpháp: WHILE Điều kiện DO Công việc VD: Các biến T1 và T2 chứa các giá trị nhiệt độ cao và thấp. Hãy tính giá trị trung bình của nhiệt độ và chứa kết quả trong thanh chứa A. Giải: MOV A, 0 ; xoá A để chứa giá trị nhiệt độ trung bình ADD A, T1 ; cộng nhiệt độ thứ nhất. ADD A, T2 ; cộng nhiệt độ thứ hai. MOV B,#2 DIV AB ; chia 2 kết quả trong A ta được nhiệt độ TB Thoat: ; lối ra của cấu trúc
  • 85.
    Ví dụ: Chươngtrình đọc vùng nhớ bắt đầu tại địa chỉ 100H vào thanh ghi A, đến khi gặp ký tự '$' thì thoát: VAO: MOV DPTR, #100H MOV A,#0 TIEP: CJNE A,’$’,TIEP_TUC SJMP RA TIEP_TUC: MOV A,@DPTR SJMP TIEP
  • 86.
    Lập trình điềukhiển dữ liệu trên các cổng VĐK Lập trình điều khiển Led đơn Các lệnh cơ bản - Lệnh MOV: di chuyển dữ liệu VD: MOV A,30h ; chuyển nội dung của ô nhớ 30h vào thanh ghi A MOV A,#30h ; chuyển giá trị 30h vào thanh ghi A MOV A,R0 ; chuyển nội dung của thanh ghi R0 vào thanh ghi A MOV A,@R0 ; chuyển nội dung của ô nhớ vào thanh ghi A, địa chỉ của ô nhớ chứa trong thanh ghi R0 (nếu R0 = 30h thì lệnh này tương đương lệnh MOV A,30h) - Lệnh INC: tăng giá trị lên 1 - Lệnh DEC: giảm giá trị xuống 1 - Lệnh SJMP: lệnh nhảy không điều kiện
  • 87.
    - Lệnh DJNZ:giảm và nhảy khi giá trị khác 0. Lệnh DJNZ thường dùng để tạo vòng lặp và có dạng sau: MOV R7,#số_lần_lặp loop: ..… …… DJNZ R7,loop - Lệnh CJNE: so sánh và nhảy nếu không bằng - Lệnh CALL: gọi chương trình con - Lệnh RET, RETI: lệnh trả về từ chương trình con hay chương trình phục vụ ngắt
  • 88.
    - Lệnh PUSH:lưu trữ nội dung thanh ghi vào stack - Lệnh POP: lấy nội dung từ stack. - Lệnh DIV AB: chia nội dung thanh ghi A cho thanh ghi B, thương số chứa trong A và số dư chứa trong B. - Lệnh MOVC: chuyển giá trị hằng số vào thanh ghi A, thường dùng cho mục đích tra bảng
  • 89.
    Sơ đồ kếtnối Led đơn Mạch điều khiển led đơn mô tả như hình vẽ. Lưu ý rằng các port của AT89C51 có dòng tối đa là 10 mA nên khi cần điều khiển nhiều Led cần mắc thêm mạch khuếch đại.
  • 90.
    Sơ đồ kếtnối dùng mạch khuếch đại
  • 91.
    Kết nối Ledđơn với AT89C51
  • 92.
    // Chương trìnhchính Main: MOV P0,#0FFh ; Sáng 8 Led CALL Delay MOV P0,#0 ; Tắt 8 Led CALL Delay SJMP main //Chương trình con Delay: PUSH 07h PUSH 06h MOV R6,#255 //Chương trình con Delay1: MOV R7,#255 DJNZ R7,$ DJNZ R6,Delay1 POP 06h POP 07h RET END
  • 93.
    Điều khiển Led7 đoạn - Dạng Led: Hình vẽ – Hình dạng của Led 7 đoạn
  • 94.
    - Led Anodechung: Hình vẽ – Led 7 đoạn dạng anode chung
  • 95.
    Đối với dạngLed anode chung, chân COM phải có mức logic 1 và muốn sáng Led thì tương ứng các chân a – f, dp sẽ ở mức logic 0. Bảng 1: Bảng mã cho Led Anode chung (a là MSB, dp là LSB):
  • 96.
    Bảng mã choLed Anode chung (a là LSB, dp là MSB):
  • 97.
    - Led Cathodechung Đối với dạng Led Cathode chung, chân COM phải có mức logic 0 và muốn sáng Led thì tương ứng các chân a – f, dp sẽ ở mức logic 1.
  • 98.
    Bảng mã choLed Cathode chung (a là MSB, dp là LSB):
  • 99.
    Bảng mã choLed Anode chung (a là LSB, dp là MSB):
  • 100.
    Kết nối Led7 đoạn dùng phương pháp quét
  • 101.
    Kết nối Led7 đoạn dùng phương pháp chốt
  • 102.
    Ví dụ: Viếtchương trình hiển thị số 0 ra Led1 và số 1 ra Led2 Chương trình thực hiện như sau: MOV P1,#0 ; Xoá P1 để tắt Led Main: MOV P0,#0C0h ; Mã số 0 SETB P1.0 ; Sáng Led1 CALL Delay ; Thời gian trì hoãn để thấy Led sáng CLR P1.0 ; Tắt Led1 MOV P0,#0F9h ; Mã số 1 SETB P1.1 ; Sáng Led2 CALL Delay CLR P1.1 ; Tắt Led2 SJMP main ;-------------------- Delay: MOV TMOD,#01h MOV TH0,#(-200) MOV TL0,#(-200) SETB TR0 JNB TF0,$ CLR TF0 CLR TR0 RET END
  • 103.
    3.5 Cấu trúcmột chương trình C • Chương trình C đơn giản cho 8051 • Cấu trúc chung của chương trình C cho 8051 • Các loại biến trong C cho 8051 • Các toán tử cơ bản • Các cấu trúc rẽ nhánh và kiểm tra thường dùng • Các quy tắc lập trình 103
  • 104.
    Chương trình Cđơn giản #include<AT89X51.h> void main() { P0_0 = 0; P0_1 = 1; } 104
  • 105.
    Cấu trúc chungcủa một chương trình C cho 8051 // --- Khai báo thư viện sử dụng----------------------------------------- #include<AT89X51.h> #include<stdio.h> //---Gán chân--------------------------------------------------------------- #define NutBam P3_0 sbit Led = P0_0; //---Khai báo hằng--------------------------------------------------------- #define ON 1 #define OFF 0 usigned char so[10] = {0x40,0x79,0x24,0x30,0x19,0x12}; //---Khai báo biến toàn cục---------------------------------------------- bit t; unsigned char x,y; 105
  • 106.
    //---Khai báo vàđịnh nghĩa các chương trình con CTC //CCT1: Chương trình con 1 void CTC1(void) { //Khai báo biến cục bộ //Các câu lệnh } //----Chương trình con phục vụ ngắt nếu có--------------------------- void Tên_Hàm(void) interrupt nguồn ngắt using băng thanh ghi { // Khai báo biến cục bộ // Các câu lệnh } 106 Cấu trúc chung của một chương trình C cho 8051
  • 107.
    // Hàm chínhbắt buộc chương trình nào cũng có void main(void) { //Các câu lệnh khởi tạo //Vòng lặp vô hạn while(1) { // Các câu lệnh chương trình CTC1(); CTC2(); } } 107 Cấu trúc chung của một chương trình C cho 8051
  • 108.
    Các loại biếntrong C cho 8051 108 Dạng biến Số bit Số byte Miền giá trị bit 1 0,1 char 8 1 unsigned char 8 1 short 16 2 usigned short 16 2 int 16 2 unsigned int 16 2 long 32 4 unsigned long 32 4 enum 16 2 
  • 109.
    Các toán tửcơ bản 109 Tên phép toán Ký hiệu Phép gán = Các phép toán số học Phép cộng + Phép trừ - Phép nhân * Phép chia lấy thương / Phép chia lấy dư % Các phép toán logic So sánh bằng == And && Or || Not ! Dịch trái và dịch phải << >>
  • 110.
    Các cấu trúcrẽ nhánh và kiểm tra thường dùng • Câu lệnh rẽ nhánh if: • Câu lệnh rẽ nhánh if/else: 110 if(điều kiện) { //Các câu lệnh xử lý } if(giay==60) { phut = phut + 1; giay = 0; } if(điều kiện) { //Khối lệnh 1 } else { //Khối lệnh 2 } if(nut==bam) { P2_0 = 0; } else { P2_0 = 1; }
  • 111.
    • Câu lệnhrẽ nhánh switch/case: 111 switch (Biến) { case giá trị 1: // Khối lệnh 1 break; case giá trị 2: break; … case default: // Khối lệnh default break; } Switch (count) { case 0: P2 = 0; break; case 1: P2 = 1; break; case default: P2 = 2; break; }
  • 112.
    • Câu lệnhvòng lặp xác định for: • Câu lệnh vòng lặp while: 112 for (i=m; i<n; i++) { // Các câu lệnh xử lý } for(i=0;i<100;i++) { time++ P1= P1 +1; } while(Điều kiện) { // Các câu lệnh } while(i<100) { time++ P1= P1 +1; }
  • 113.
    Các quy tắclập trình Quy tắc 1: • Chương trình nên được tách thành nhiều chương trình con. • Mỗi chương trình con thực hiện một nhiệm vụ độc lập. • Việc tách thành các chương trình con giúp cho chương trình sáng sủa, và dễ kiểm tra. Robot vận chuyển hàng hóa Lệch trái Lệch phải Đếm số vạch = 3 END Đ S
  • 114.
    Quy tắc 2: •Hạn chế sử dụng biến toàn cục. • Không nên sử dụng biến toàn cục để truyền thông tin giữa các chương trình con. • Nên sử dụng các thông số khi truyền thông tin cho các chương trình con. 114 Các quy tắc lập trình #include<REGX51.h> unsigned int t; void delay( ) { for(t=0;t<=100;t++) {;} } void RePhai( ) { P2=0x01; delay(); } void main( ) { for(t=0;t<=10;t++) RePhai(); #include<REGX51.h> void delay( ) { int t; for(t=0;t<=100;t++) {;} } void RePhai ( ) { unsigned int T; for(T=0;T<5;T++) { P2=0x00; delay( ); } } void main( ) { RePhai( ); }
  • 115.
    • Quy tắc3: Chương trình nên được viết đơn giản, rõ ràng 115 Các quy tắc lập trình KHÔNG NÊN VIẾT NÊN VIẾT A[++] = 1; A[i]=1; i++; If(DoSomething( )==flase Result = DoSomething( ) If(result==false)
  • 116.
    Quy tắc 4:Mỗi câu lệnh nên được đặt riêng trên một dòng và phải viết đúng cấu trúc ngôn ngữ. • Dễ đọc chương trình • Dễ quan sát, tìm lỗi. • Viết thụt đầu dòng hợp lý. • Các câu lệnh nằm giữa cặp dấu {} được viết thụt vào một khoảng tab. • Các lệnh ngang cấp phải thụt vào như nhau. 116 KHÔNG NÊN VIẾT NÊN VIẾT #include<REGX51.H> int t; void delay( ) { for(i=0;i<=3000;i++) {;} } void RePhai( ) { P2 = 0x00; delay( ); P2 = 0xFF; delay( ); } void main( ) { for(i=0;i<5;i++) } #include<REGX51.H> int t; void delay( ) { for(i=0;i<=3000;i++) {;} } void RePhai( ) { P2 = 0x00; delay( ); P2 = 0xFF; delay( ); } void main( ) { for(i=0;i<5;i++) }
  • 117.
    Quy tắc 5:Chú thích cho chương trình. • Viết ngắn gọn, nếu chú thích trên một dòng sử dụng ký hiệu //, nhiều dòng sử dụng cặp ký hiệu /* */ • Viết chú thích cho từng hàm • Chú thích cho từng tập tin mã nguồn. 117 #include <REG51.H> /*------------------------------------------------------- Ví dụ về điều khiển LED FASH Vi điều khiển AT89C51 Người viết: Ngô Quang Vĩ Ngày viết code: Ngày sửa code: -------------------------------------------------------*/ #include<REGX51.H> void delay_ms(unsigned int t ) { unsigned int x,y; for(x=0;x<t;x++) { for(y=0;y<=123;y++) {}; } } Void main() { while(1) { P2_0 = !P2_0; delay_ms(500); } }
  • 118.
  • 119.
  • 120.