Professional Documents
Culture Documents
1
4/12/2022
2
4/12/2022
#include<regx51.h>
#include<string.h> Khai báo biến toàn cục
#define Led1 P1_0
4.1.2 Hàm
a. Khai báo hàm
Hàm thực hiện việc tính toán trên các tham số và cho lại giá trị kết quả, hoặc chỉ
thực hiện một chức năng nào đó mà không cần trả lại kết quả.
Hàm thường được khai báo ở đầu chương trình.
Cách để khai báo một hàm như sau:
3
4/12/2022
Ví dụ
Định nghĩa hàm tính tổng 2 số nguyên (kiểu int). Số nguyên a và số
nguyên b là 2 tham số truyền vào () và giá trị trả về là số nguyên a+b.
int tinh_tong(int a, int b)
{
return (a+b);
}
Định nghĩa hàm tìm số lớn nhất từ 2 tham số truyền vào a và b. Nếu a lớn
hơn b thì trả về giá trị là a (return a), ngược lại sẽ trả về giá trị b (return b).
int solonnhat(int a, int b)
{
if(a > b) return a;
else return b;
}
4
4/12/2022
Ví dụ
…
Void main()
{ int tong, so_lon_nhat,a,b,c=5,d=7;
tong=c + d;
a= tong;
if (c>d)
so_lon_nhat=c;
else
so_lon_nhat=c;
b=so_lon_nhat;
Ví dụ
int tinh_tong(int, int); //khai báo hàm không có tên biến
int so_lon_nhat(int, int); // khai báo hàm có tên biến
…
int tinh_tong(int c, int d)
Void main()
{
return (c+d); { int tong,so_lon_nhat,a,b,c=5,d=7;
} tong=c + d;
int solonnhat(int a, int b) a= tong;
{
if (c>d)
if(c > d) return c;
else return d; so_lon_nhat=c;
} else
…
Void main() so_lon_nhat=d;
{ int a,b,c=5,d=7;
a=tinh_tong(a,b); c=so_lon_nhat;
d=so_lon_nhat(a,b); }
} 10
5
4/12/2022
11
12
6
4/12/2022
Mảng
Mảng là một tập hợp nhiều phần tử cùng một kiểu giá trị
và chung một tên. Các phần tử của mảng phân biệt với
nhau bởi chỉ số hay số thứ tự của phần tử trong dãy phẩn
tử. Mỗi phần tử có vai trò như một biến và lưu trữ được
một giá trị độc lập với các phần tử khác của mảng.
Mảng có thể là mảng một chiều hoặc mảng nhiều chiều
Khai báo:
- Cú pháp: Tên_kiểu Vùng_nhớ
Tên_mảng[số_phần_tử_mảng];
Khi bỏ trống số phần tử mảng ta sẽ có mảng có số phần tử
bất kì.
Ví dụ:
Unsigned int data a[5],b[2] [3];
13
Con trỏ
Khi ta khai báo một biến, biến đó sẽ được cấp phát một khoảng nhớ bao
gồm một số byte nhất định dùng để lưu trữ giá trị. Địa chỉ đầu tiên của
khoảng nhớ đó chính là địa chỉ của biến được khai báo.
Con trỏ là một biến dùng để chứa địa chỉ mà không chứa giá trị, hay
giá trị của con trỏ chính là địa chỉ khoảng nhớ mà nó trỏ tới.
Với các vùng nhớ cụ thể con trỏ tới vùng nhớ đó chiếm dung lượng
phụ thuộc vào độ lớn của vùng nhớ đó. Con trỏ tổng quát khi không
xác định trước vùng nhớ sẽ có dung lượng lớn nhất vì vậy tốt nhất nên
sử dụng con trỏ cụ thể.
14
7
4/12/2022
15
là các ký hiệu dùng để kết hợp hay phủ định biểu thức
có chứa các toán tử quan hệ.
16
8
4/12/2022
18
9
4/12/2022
Phép AND
Kí hiệu: &
A B A&B
0 0 0
0 1 0
1 0 0
1 1 1
Phép OR
Kí hiệu: |
A B A|B
0 0 0
0 1 1
1 0 1
19
1 1 1
Phép NOT
Kí hiệu: ~
A ~A
0 1
1 0
Phép XOR
Kí hiệu: ^
A B A^B
0 0 0
0 1 1
1 0 1
1 1 0
20
10
4/12/2022
Ví dụ
Ví dụ A=4; B=A<<16
=> B = 4 / 22 = 1
Ví dụ A=4; B=A>>2
=> B = 4 / 22 = 1
21
22
11
4/12/2022
Dayled=0xF0;
Dayled=0xoF;
}
23
Ví dụ2 :Ghép nối LED đơn với chân P1.0 của vi điều khiển, viết
chương trình điều khiển LED sáng, tắt
Bắt đầu
*/==================Bo tien xu li===================*/
#include<AT89x51.h> // Dinh kem file thu vien
Khởi tạo hệ thống
#define bat 1 // Dinh nghia gia tri bat den Led
#define tat 0 // Dinh nghia gia tri tat den Led
/*==================khai bao bien==================*/ Sáng Led
sbit Led = P1^0; // Khai bao bien Led kieu bit chan P1.0
Trễ
/*================= Khai bao hàm==================*/
void delay (int t) Tắt Led
{
….. Trễ
}
/*--------------------------------ham chinh--------------------------------*/
void main(void) Kếthúc
{
}
24
12
4/12/2022
Ví dụ:Ghép nối LED đơn với chân P1.0 của vi điều khiển, viết
chương trình điều khiển LED sáng, tắt
Bắt đầu
*/==================Bo tien xu li===================*/
#include<AT89x51.h> // Dinh kem file thu vien
Khởi tạo hệ thống
#define bat 1 // Dinh nghia gia tri bat den Led
#define tat 0 // Dinh nghia gia tri tat den Led
/*==================khai bao bien==================*/ Sáng Led
sbit Led = P1^0; // Khai bao bien Led kieu bit chan P1.0
Trễ
/*================= Khai bao hàm==================*/
void delay (int t) Tắt Led
{
….. Trễ
}
/*--------------------------------ham chinh--------------------------------*/
void main(void)
{
While (1)
{ Led = bat; // bat Led
delay (500);
Led = tat; // tat Led
delay (500);
}
}
25
a. Hàm trễ
void delay_us(int us)
Delay
{ while(us--)
{ Khởi tạo giá trị time
…
} Time≠0
} S
Time=Time-1
void delay_ms(unsigned int ms)
{
thoát
unsigned int x,y;
for (x=0;x<ms;x++);
}
void main()
{
while(1)
{ ….
delay_ms(100);
….
}
}
26
13
4/12/2022
b. Rẽ nhánh if dieu_kien
S
- Cấu trúc: Đ
Giải thích: nếu dieu_kien đúng thì xử lí các câu lệnh bên
trong còn sai thì nhảy qua.
27
c. Rẽ nhánh IF_ELSE
Cấu trúc:
if(dieu_kien)
{
// Đoạn chương trình 1 dieu_kien
S
} Đ
else
{ Đoạn chương trình 1 Đoạn chương trình 2
// Đoạn chương trình 2
}
28
14
4/12/2022
Ví dụ:
If (P0_0==0)
{ P1=0x55; P0_0=0
S
P2=P1; Đ
}
P1=55 P1=0xAA
else P2=P1 P2=P1
{ P1=0xAA;
P2=P1;
}
29
d. Lựa chọn:
switch(bien) Dung
bien= gia_tri_1 các câu lệnh 1
{
case gia_tri_1: {//các câu lệnh 1; break;} Sai thoát
case gia_tri_2: {//các câu lệnh 2; break;} Dung
bien= gia_tri_2 các câu lệnh 2
case gia_tri_3: {//các câu lệnh 3; break;}
……………………………………... Sai thoát
case gia_tri_n: {//các câu lệnh n; break;} Dung
bien= gia_tri_3 các câu lệnh 3
Sai thoát
}
thoát 30
thoát
15
4/12/2022
Ví dụ
switch (dem)
{ case 0: {P0=0x40;break;}
case 1: {P0=0x79;break;}
case 2: {P0=0x24;break;}
case 3: {P0=0x30;break;}
case 4: {P0=0x19;break;}
case 5: {P0=0x12;break;}
case 6: {P0=0x20;break;}
};
31
for(n=m;n<l;n=n+a) M<l
{ S
các câu lệnh xử lí 1 Đ
}
các câu lệnh xử lí 2 các câu lệnh xử lí 1
32
16
4/12/2022
Ví dụ 1: FOR(dem=0;dem<100;DEM++)
{ P0=~P0;
P1=0xAA;
}
Ví dụ 2: FOR(;;)
{ P0=~P0;
P1=0xAA;
}
33
34
17
4/12/2022
Ví dụ 1: while (P1_1==0)
{
P2=0xAA;
P3=0x55;
}
Ví dụ 2: while (1)// vòng lặp vô hạn
{
P2=0xAA;
P3=0x55;
}
35
18
4/12/2022
Ví dụ: Ghép nối LED dơn với chân P1.0 của vi điều khiển, viết
chương trình điều khiển LED nhấp nháy với thời gian trễ là 1s.
*/==================Bo tien xu li===================*/ START
#include<AT89x51.h> // Dinh kem file thu vien
#define bat 1 // Dinh nghia gia tri bat den Led
Khởi tạo hệ thống
#define tat 0 // Dinh nghia gia tri tat den Led
/*==================khai bao bien==================*/
Sáng Led
sbit Led = P1^0; // Khai bao bien Led kieu bit chan P1.0
Trễ 1S
/*================= Khai báo hàm==================*/
/*------------------------------ham tre -------------------------------------*/ Tắt Led
void delay(long time) Trễ 1S
{
while(time--);
}
/*--------------------------------ham chinh--------------------------------*/ Delay
void main(void)
{ Khởi tạo giá trị time
while(1)
{
Led = bat; // bat Led Time≠0
delay(25000); // tre 1s S
Led = tat; // tat Led Time=Time-1
delay(25000); //tre 1s
}
} thoát
37
Ví dụ 1: Một đèn Led được nối với chân P1.0 của vi điều
khiển. Một công tắc START nối với chân P3.0 và công
tắc STOP nối với chân P3.1 của vi điều khiển.
Xây dựng lưu đồ thuật toán và chương trình điều khiển
điều khiển để khi bật công tắc START thì Led sáng, khi
bật công tắc STOP thì Led tắt.
38
19
4/12/2022
39
Start
if(START==0)
Led = tat
{
Led = bat; Đ
Start = 0 Led = bat
}
S
if(STOP==0) Đ
Stop = 0 Led = tat
{ S
Led = tat;
}
40
20
4/12/2022
42
21
4/12/2022
43
44
22
4/12/2022
18 8951
C/T = 0: T
Thạch anh OSC ÷12
C/T = 1: C
TFx
19 THx: 8bit TLx: 8bit
T SW tràn
00…0 00…0
Tx C
(14/15)
0: SW hở
TRx
1: SW đóng
(12/13) GATE
INTx
TFx,C/T,GATE,TRx: các bit
18 8951
Thạch C/T = 0: T
OSC ÷12
anh C/T = 1: C
TFx
19 THx: 8bit TLx: 8bit
T SW tràn
00…0 00…0
Tx C
(14/15)
0: SW hở
GATE=0 TRx
1: SW đóng
(12/13)
INTx
46
23
4/12/2022
7 6 5 4 3 2 1 0
7 6 5 4 3 2 1 0
TIMER 1 TIMER 0
GATE, C/T: điều khiển trạng thái hoạt động cho Timer/Counter
M1, M0: chọn chế độ hoạt động cho Timer/Counter
48
24
4/12/2022
7 6 5 4 3 2 1 0
TIMER 1 TIMER 0
Bit C/T
Bit C/T = 0, bộ định thời nhận các xung đồng hồ từ bộ giao động thạch
anh của 8051.
Bit C/T = 1, bộ định thời được sử dụng như bộ đếm sự kiện và nhận các
xung đồng hồ từ nguồn bên ngoài Tx chuyển từ “1” về “0”
Chân Chân cổng Chức năng Mô tả
14 P3.4 T0 Đầu vào ngoài của bộ đếm 0
15 P3.5 T1 Đầu vào ngoài của bộ đếm 1
Bít GATE
GATE = 0 : Khởi động và dừng bộ định thời bằng phần mềm.
GATE = 1 : Khởi động và ngừng bộ định thời bằng phần cứng từ nguồn
ngoài bằng (xem ở chế độ ngắt.)
Khởi động bộ định thời: TRx=1;
Tắt bộ định thời: TRx=0;
49
50
25
4/12/2022
0110000011000
TRx
2021
51
TMOD = x x 0 1 x x 0 1
TRx
00000000 00000000 (B) THXTLX+1 11111111 11111111 +1
00000/0000(H) 65535 +1 /FFFF+1H
Công thức tính độ trễ thời gian theo tần số XTAL (f) Giá trị kết thúc=65536
26
4/12/2022
TRx OVERFLOW
THx : 8 BIT
THx xxxxxxxx
DDD/HH
53
PULSE INPUT
TL0 : 8 BIT TF0
OSC:12
TH0 : 8 BIT TF1
TR1
Trong chế độ này, TH1 và TL1 không được sử dụng, thay vào đó là TH0
và TL0 hoạt động như 2 bộ Timer/counter 8 bit. Tuy nhiên, xung cung cho
TH0 là từ bộ điều khiển của timer/counter1.
54
27
4/12/2022
Xóa cờ TFx
Khởi động
Timer/counter
TFx= 0
Giám sát cờ TFx=0
TFx= 1
Tắt Timer
~P1.0
56
28
4/12/2022
TMOD = x x 0 1 x x 0 1
TRx
00000000 00000000 (B) THXTLX+1 11111111 11111111 +1
00000/0000(H) 65535 +1 /FFFF+1H
Công thức tính độ trễ thời gian theo tần số XTAL (f) Giá trị kết thúc=65536
29
4/12/2022
Ví dụ: lập trình cho bộ định thời 1 hoạt động ở chế độ 1 (16 bit), có thời gian tràn là 500us (sử dụng
thạch 12Mhz).
Bước 1: Chọn chế độ hoạt động cho Timer 1, Mode1
TMOD=0x10
Bước 2: Nạp giá trị thanh ghi TH1, TL1
Vì bộ định thời đếm lên 1 đơn vị sau mỗi chu kỳ máy nên bộ định thời sẽ tràn sau 500 chu kỳ máy
|------------>|--------------------->|
Khai báo chế độ
0 X 65.535+1 timer/counter
=>x=65.536 – 500 = 65.036 =1111111000001100 B
00001100B =0Ch Định giá trị ban đầu
11111110B =FEh cho TLx, THx
MOV TH1,#11111110B;tách 8 bit đầu nạp cho TH1=FEh
MOV TL1,#00001100B;tách 8 bít sau nạp cho TL1 = 0Ch Xóa cờ TFx
Bước 3: Khởi động bộ định thời T1
TR1=1; Khởi động
Bước 4: Chờ bộ định thời tràn Timer/counter
while(){}
Bước 5: Dừng bộ định thời TFx= 0
Giám sát cờ TFx=0
TR1=0;
Bước 6: Xoá cờ TF cho vòng kế tiếp TFx= 1
TF1=0; Tắt Timer
Bước 7: Quay trở lại bước 2 để nạp lại TLx và THx
~P1.0
Bài tập: viết lại chương trình ASM của ví dụ trên dùng ngôn ngữ C 59
0 0 0 1 0 0 0 0
60
30
4/12/2022
Ví dụ
Tạo xung vuông (đèn sáng tắt) có chu kỳ 20.000us
Tạo một xung điều khiển (xung vuông) đèn sáng duy
trì ở 20.000us và tắt 20.000us
61
20mS=20.000us 50mS=50.000us
|---------->|--------------------->| |---------->|--------------------->|
0 X 65.535+1 0 X 65.535+1
X|<----20.000------->|65.536 X|<----50.000------->|65.536
=> X= 65536-20.000= 45536 => X= 65536-50.000= 15536
= B1E0 H = 3CB0H
TH1 =B1H ; TL1=E0H TH0 =3CH ; TL0=B0H
62
31
4/12/2022
7 6 5 4 3 2 1 0
TRx
TF1 TR1 TF0 TR0 IE1 IT1 IE0 IT0
TCON
Khởi động bộ định thời T0. Khởi động bộ định thời T1.
TR0=1; TR1=1;
Hoặc TCON|0x10; Hoặc TCON|0x40;
63
32
4/12/2022
Ví dụ C: lập trình cho bộ định thời 1 hoạt động ở chế độ 1 (16 bit), có thời gian tràn
là 500us (sử dụng thạch 12Mhz).
▪ Bước 1: Chọn chế độ hoạt động cho Timer 1
TMOD = 0x10
▪ Bước 2: Nạp giá trị tràn cho các thanh ghi TH1, TL1
Vì bộ định thời đếm lên 1 đơn vị sau mỗi chu kỳ máy nên bộ định thời sẽ tràn sau 500 chu
kỳ máy |------------>|--------------------->|65.535+1
0 X =>x=65.536 – 500 = 65.036 = FE0Ch
TH1=0x0FEh;tách 2 số đầu nạp cho TH
TH1=0x0Ch ;tách 2 số sau nạp cho TL
▪ Bước 3: Khởi động bộ định thời T1
TR1=1; Khởi động bộ định thời
▪ Bước 4: Chờ bộ định thời tràn
while(!TF0){} //Duy trì cho đến khi cờ TF0=1;
▪ Bước 5: Dừng bộ định thời (TR1 = 0)
TR1 = 0; Tắt bộ định thời
▪ Bước 6: Xoá cờ TF cho vòng kế tiếp
TF1 = 0;
▪ Bước 7: Quay lại Bước ????? nếu muốn tiếp tục vòng đếm tiếp theo
65
Ví dụ C: lập trình cho bộ định thời 1 hoạt động ở chế độ 1 (16 bit), có thời gian
tràn là 500us (sử dụng thạch 12Mhz).
Void main()
{ TMOD = 0x10;
while(1)
66
33
4/12/2022
Ví dụ C: lập trình để đèn nối vào chân P1.0 sáng tắt với chu kỳ 1000us (sử dụng
thạch 12Mhz).
Void main()
TMOD = 0x10
Khai báo chế độ
{
timer/counter
while(1)
{
Định giá trị ban
TH1=0x0FEh;tách 2 số đầu nạp cho TH đầu cho TLx, THx
Ví dụ C: lập trình để P1.0 đổi trạng thái sau mỗi thời gian tràn là 500us. Sử dụng
timer1 mode 1 Bắt đầu Delay_500u
34
4/12/2022
12Mhz
P3.0
Sinh viên tự
làm
VD: Tạo một sóng vuông với độ đầy xung 50% trên chân P1.5. Bộ định
thời Timer1 được dùng để tạo độ trễ thời gian:
35
4/12/2022
Tx C
(14/15)
0: SW hở
GATE=1 TRx
1: SW đóng
Pin 12/P3.2
(INT0)
Pin 13/P3.3
(INT1)
7 6 5 4 3 2 1 0
TMOD GATE C/T M1 M0 GATE C/T M1 M0
TMOD = 1 x x x 1 x x x
Nếu GATE = 1 (TMOD.7) thì việc khởi động và dừng bộ đếm/bộ định thời được
thực hiện từ bên ngoài qua chân: P3.2 (INT0) đối với Timer/counter 0 và P3.3 (INT1)
đối với Timer/counter 1.
71
72
36
4/12/2022
Ví dụ 1: lập trình cho bộ định thời 0 hoạt động ở chế độ 0 (13 bit), có thời gian
tràn là 500us (sử dụng thạch 12Mhz).
◼ Bước 1: Chọn chế độ hoạt động cho Timer 0
TMOD = 00000000B (0x00)
◼ Bước 2: Nạp giá trị tràn cho các thanh ghi TH0, TL0
Vì bộ định thời đếm lên 1 đơn vị sau mỗi chu kỳ máy nên bộ định thời sẽ tràn sau 500 chu
kỳ máy |------------>|--------------------->|
0 X 8.191+1 =>x=8192 – 500 = 7692 =1111000001100B
TH0=0xF0; tách 8 bit đầu nạp cho TH= 11110000B = F0h
TL0=0x0c; tách 5 bít sau nạp cho TL = 011000B = 0Ch
- Bước 3: Khởi động bộ định thời T0
TF0=0; Xóa cờ tràn
TR0=1; Khởi động bộ định thời
- Bước 4: Chờ bộ định thời tràn
while (!TF0){} ; chờ cho cờ TF0=1
- Bước 5: Dừng bộ định thời (TR0 = 0);Nếu tiếp tục muốn sử dụng bộ định
thời:, nạp lại giá trị cho TH0, TL0, khởi động lại (TR0 = 1).
- ….
Từ ví dụ được viết bằng ngôn ngữ ASM
sv viết lại sử dụng ngôn ngữ C
74
37
4/12/2022
75
38
4/12/2022
Ví dụ 1: Lập trình thay đổi trạng thái ngõ ra P0.0 để tạo xung
vuông có chu kỳ 2ms sử dụng Timer 0,Mode 0.
1ms=1000us
Ton=1ms Toff= 1ms
X= 8192- 1000= 7192= 11110000 11000B
T= 2ms
= E0 18H
Khai báo chế độ
timer/counter
Ví dụ 2: Lập trình thay đổi trạng thái ngõ ra P1.0 để tạo xung vuông có chu kỳ
2ms sử dụng Timer0,Mode0).
Delay
Bắt đầu
Void delay() Khai báo chế độ
{…. Delay timer/counter
}
P1.0=~P1.0 Định giá trị ban
đầu cho TLx, THx
Xóa cờ TFx
Khởi động
Void main() Timer/counter
{
while(1) TFx= 0
{ Giám sát cờ TFx=0
Delay();
TFx= 1
P0_1=~P1_0;đổi trạng thái
Tắt Timer
}
}
RET 78
39
4/12/2022
Ví dụ 2: Lập trình thay đổi trạng thái đèn trên chân P1.0 sáng
1ms, tắt 1ms. Sử dụng Timer1,Mode0, thạch anh 12Mhz.
Ví dụ 3: Lập trình thay đổi trạng thái ngõ ra P1.0 để tạo xung
vuông có chu kỳ 10ms sử dụng Timer0,Mode0 (sử dụng thạch
12Mhz). 2,5ms->7.942=1 1111 000 0 0110 B= 0xF8; 0x06
2,5ms 7,5ms
#include<at89x51.h> //khai báo thư viện 89x51
void Delay(int x, int y); //khi báo hàm con tạo trễ
main()
{ TMOD=0x00; //chọn timer0, chế độ 1, 16Bit
while(1) //vòng lặp vô hạn
{
P1_0=1;
Delay(x1, y1);
P1_0=0;
Delay(x2, y2);
}
}
void Delay(int x, int y)
{ TH0=x; //nạp giá trị cho TL0
TL0=y; //nạp giá trị cho TH0
….
80
}
40
4/12/2022
Ví dụ 3: Lập trình thay đổi trạng thái ngõ ra P1.0 để tạo xung
vuông có chu kỳ 1ms sử dụng Timer0,Mode0.
TRx OVERFLOW
THx : 8 BIT
THx xxxxxxxx
DDD/HH
82
41
4/12/2022
Chế độ 2 TH
1. Nạp thanh ghi giá trị TMOD để báo bộ định thời gian
nào (Timer0 hay Timer1) được sử dụng và chế độ làm việc nào
của chúng được chon.
2. Nạp lại thanh ghi TH và TL với giá trị đếm ban đầu.
3. Khởi động bộ định thời.
4. Duy trì kiểm tra cờ bộ định thời TF bằng cách sử dụng
một vòng lặp để xem nó đã được bật chưa. Thoát vòng lặp
khi TF lên cao.
5. Dừng bộ định thời.
6. Xoá cờ TF.
7. Quay trở lại bước 3. (Vì chế độ 2 là chế độ tự nạp lại.)
83
84
42
4/12/2022
Ví dụ 1: Viết chương trình xuất chuỗi xung 200uS ra loa (delay sử dụng timer1,
mode 2)
▪ Bước 1: Chọn chế độ hoạt động cho Timer 1
TMOD =0x20
▪ Bước 2: Nạp giá trị tràn cho các thanh ghi TH1, TL1
Vì bộ định thời đếm lên 1 đơn vị sau mỗi chu kỳ máy nên bộ định thời sẽ tràn sau 200 chu
kỳ máy |------------>|--------------------->|
0 X 255+1 =>x=256-200 = 56 = 01111000B=38H
TH1=0x38h
TL1=0x38h
▪ Bước 3: Khởi động bộ định thời T1
TF1=0; Xóa cờ tràn
TR1=1; Khởi động bộ định thời
▪ Bước 4: Chờ bộ định thời tràn
while (!TF1)
{}
▪ Bước 5: Dừng bộ định thời (TR1 = 0); Nếu tiếp tục vòng lặp: nạp lại giá trị
cho TH, TL, khởi động lại (TR1 = 1).
TR1=0; Dừng bộ định thời 85
(Mode0) Định giá trị ban Nạp giá trị ban đầu cho TLx, THx:
(Mode1) đầu cho TLx, THx Mode0: THX(8bit) TLX(5bit)
(Mode2) Mode1: THX(8bit) TLX(8bit)
Tắt Timer Mode2: THX(8bit) = TLX(8bit)
Mode0: 8191+1
Khởi động Mode1: 65535+1 ->
Timer/counter Mode2: 255+1
Với x= 1/0 86
43
4/12/2022
Tx C
(14/15)
0: SW hở
GATE=0 TRx
1: SW đóng
Pin 12/P3.2
(INT0)
Pin 13/P3.3
(INT1)
7 6 5 4 3 2 1 0
TMOD GATE C/T M1 M0 GATE C/T M1 M0
TMOD = 1 x x x 1 x x x
Chân Chân cổng Chức năng Mô tả
14 P3.4 T0 Đầu vào ngoài của bộ đếm 0
15 P3.5 T1 Đầu vào ngoài của bộ đếm 1 87
TMOD:
Nếu bit C/T = 0 thì bộ định thời nhận các xung đồng hồ từ bộ
giao động thạch anh của 8051.
Nếu bit C/T = 1 thì bộ định thời được sử dụng như bộ đếm
và nhận các xung đồng hồ từ nguồn bên ngoài của 8051.
Do vậy, nếu bit C/T = 1 thì bộ đếm tăng lên khi các xung được
đưa vào chân P3.4 (T0) đối với counter0 và chân P3.5 (T1)
đối với counter1.
88
44
4/12/2022
90
45
4/12/2022
91
ITx/Tcon 8951
IEx/Tcon
INT0(P3.2) 1
IEx
0
INT1(P3.3) EXx = 1: Đóng
ITx = 1: Sườn âm EXx = 0: Mở
ITx = 0: Mức thấp
TF/Tcon INTERRUP
T0(P3.4) Timer x
TLxTHx TFx
T1(P3.5) Counterx
ETx= 1: Đóng EA= 1: Đóng
ETx= 0: Mở EA = 0: Mở
TI
UART
RI ES = 1: Đóng
ES = 0: Mở
7 6 5 4 3 2 1 0 7 6 5 4 3 2 1 0
Tcon TF1 TR1 TF0 TR0 IE1 IT1 IE0 IT0 IE EA - - ES ET1 EX1 ET0 EX0
92
46
4/12/2022
Công việc 2
Công việc 2 Công việc a
Có nhấn
KT ct nhấn Công việc b
Không nhấn
Công việc n Công việc b
ĐK ngắt
ĐIỀU KHIỂN NGẮT (Hoạt động khi không có sự kiện ấn CT)
Điều khiển thăm dò
Công việc 1 Công việc 1
Công việc a Kiểm tra CT
Có nhấn
Công việc 2 Công việc a
KT ct nhấn Công việc b
Không nhấn
Công việc n +1 Công việc b
Công việc 2
Công việc a
Có nhấn RETI
Công việc n+
KT ct nhấn Công việc b
Hoạt động khi có sự kiện ấn ct
Không nhấn
Công việc 1
Có nhấn CT
Công việc n Công việc 2
Công việc a
Công việc a
Có nhấn
KT ct nhấn Công việc b
Công việc b
Không nhấn Công việc n +1
47
4/12/2022
95
48
4/12/2022
97
49
4/12/2022
IE
EA - - ES ET1 EX1 ET0 EX0 Giải thích Hex
0 x x x x x x x Cấm tất cả ngắt
1 Chưa sử dụng
1 Chưa sử dụng
1 0 0 1 0 0 0 0 Cho phép ngắt truyền 0x90
thông
1 0 0 0 1 0 0 0 Cho phép ngắt Timer 1 0x88
1 0 0 0 0 1 0 0 Cho phép ngắt ngoài 1 0x84
1 0 0 0 0 0 1 0 Cho phép ngắt Timer 0 0x82
1 0 0 0 0 0 0 1 Cho phép ngắt ngoài 0 0x81
1 x x 1 1 1 1 1
99
Ví dụ :
Hãy lập trình cho 8051:
a) Cho phép ngắt nối tiếp, ngắt Timer0 và ngắt phần cứng ngoài 1 (EX1)
b) Cấm ngắt Timer0
c) Cấm tất cả mọi ngắt chỉ bằng một lệnh duy nhất.
100
50
4/12/2022
#include<at89x51.h>
main()
{
//a)
IE=0x96; //1001 0110: lệnh này tương đương với 4 lệnh phía dưới
EA=1; //Cho phép sử dụng ngắt
ES=1; //Cho phép ngắt cổng nối tiếp
ET0=1; //Cho phép ngắt timer0
EX1=1; //Cho phép ngắt ngoài 1
//b)
ET0=0; //Cấm ngắt timer0
//c)
EA=0; //Cấm tất cả các ngắt
while(1)
{
//Chương trình chính
//…
}
}
101
- Khi các bít của thanh ghi IP không được tác động (=0): thứ tự ưu tiên của ngắt
được chọn lựa theo số Thứ tự ngắt.
- Khi cần ưu tiên ngắt, tác động đến các bít …. 102
51
4/12/2022
Bắt đầu
Công việc 2
Name (void) interrupt 1 Name (void) interrupt 3
Cờ ngắt TF0=1
52
4/12/2022
Sử dụng ngắt
105
Ví dụ: Viết chương trình điều khiển, thường xuyên thay đổi trạng thái trên chân
P1.0 sau khoản 200us và định kỳ sau 5.000us thì thay đỏi trạng thái trên chân
P1.1
#include <REG51.H> P1.1
sbit Led1=P1^0;
sbit Led2=P1^1; P1.0
int unsigned i;
void ngat_timer1_5000u(void) interrupt 3 {
Led2=~Led2;
TF1=0;
TH1=0xec;
TL1=0x78; }
void main(){
TMOD=0x10; //Timer1 mode1
EA=1;
ET1=1;
TH1=0xEC;
TL1=0x78;
TR1=1;
while(1){
for(i=0;i<12;i++){}
Led1=~Led1;
}
106
}
53
4/12/2022
Ví dụ: Viết chương trình điều khiển, thường xuyên thay đổi trạng thái trên chân
P1.0 và định kỳ sau 50.000us thì thay đỏi trạng thái trên chân P1.1
#include <REGX51.H>
sbit Led1= P1^0;
sbit Led2= P1^1;
void timer_delay(){
int i;
for (i=0;i<1000;i++) {};
}
// chuong trinh con phuc v? ngat timer 1//Tao chu ky 50.000us
void ngat_timer1 (void) interrupt 3{
TH1 = 0x3C;
TL1 = 0xB0;
TF1=0; // xoá co ngat
Led2=~Led2;
}
void main() {
TMOD = 0x10; //khai báo Mode 1 Timer 1 ->0001 0000B= 0x10
EA = 1; // cho phép ngat toan cuc
ET1= 1; // cho phep ngat Timer1
TR1=1; // Khoi dong timer
while(1){
Led1=~Led1;
timer_delay();
}
} 107
Viết chương trình điều khiển, thường xuyên thay đổi trạng thái trên chân P1.0 và định
kỳ sau 200us thì thay đổi trạng thái trên chân P1.1. Yêu cầu timer 0 mode 2 (mode 2:
Mode reload max 2^8=256)
#include <REGX51.H>
sbit Led1= P1^0;
sbit Led2= P1^1;
void timer_delay()
{ int i;
for (i=0;i<1000;i++)
{};
}
// chuong trinh con phuc v? ngat timer 1//Tao chu ky 200us -> Timer 0 Mode 2
void ngat_timer_2 (void) interrupt 1 // ngat Timer 0
{
Led2=~Led2;
}
void main()
{
TMOD = 0x02; //khai báo ch?n Timer 0 Mode 2->TMOD=0000 0010B= 0x02
//IE=0x82;
EA = 1; // cho phép ngat toan cuc
ET0= 1; // cho phep ngat Timer 0
TH0=TL0=0x38;
TR0=1; // Khoi dong timer
while(1)
{ Led1=~Led1;
timer_delay();
} 108
}
54
4/12/2022
Ví dụ C: lập trình để P1.0 đổi trạng thái sau mỗi thời gian tràn là 500us (sử dụng
thạch 12Mhz).
#include<at89x51.h> //khai báo thu viện cho VÐK 89x51
void ngat_timer1_500u(void) interrupt 3
{
P1.0=~P1.0;
TR1 = 0; //Tắt bộ định thời
TH1=0x0FEh;//nạp cho TH
TL1=0x0Ch ;//nạp cho TL
TR1=1; //Khởi động bộ định thời
}
Void main()
{ EA=1; //khai báo sử dụng ngắt
ET1=1; // khai báo sử dụng ngắt timer1
TMOD = 0x10;khai báo timer1 mode1
TH1=0x0FEh;//nạp cho TH
TL1=0x0Ch ;//nạp cho TL
TR1=1; //Khởi động bộ định thời
while(1)
{
}
} 109
Ví dụ C: lập trình để P3.0 đổi trạng thái sau mỗi thời gian tràn là 200us (sử dụng
thạch 12Mhz) sử dụng timer 0 mode2.
#include<at89x51.h> //khai báo thu viện cho VÐK 89x51
void ngat_timer0_200u(void) interrupt 1
{
TR0 = 0; //Tắt bộ định thời
P3.0=~P3.0;
TR0=1; //Khởi động bộ định thời
}
Void main()
{ EA=1; //khai báo sử dụng ngắt
ET0=1; // khai báo sử dụng ngắt timer1
TMOD = 0x02;khai báo timer1 mode1
TH0=0x038h;//nạp cho TH
TL0=0x038h ;//nạp cho TL
TR0=1; //Khởi động bộ định thời
while(1)
{
}
} 110
55
4/12/2022
VD1. Viết chương trình đảo trạng thái chân P1.0 với chu kỳ
khoảng 300us và chân P1.1 với chu kỳ chính xác 1ms
VD2. Viết chương trình điều khiển bóng đèn nhấp nháy
với chu kỳ 150 μs trên chân P0 để tạo ánh sáng trang trí
(viền), sử dụng P0.2 để tạo xung kích (50.000 μs) cho đồng
hồ đếm.
Thảo luận:
Xem xét yêu cầu độ chính xác của hai công việc trên.
Viết các chương trình con điều khiển hoạt động trên
111
Viết chương trình nhận liên tục dữ liệu 8 Bit ở cổng P0 và gửi nó đến
cổng P1 trong khi nó cùng lúc tạo ra một sóng vuông chu kỳ 200us trên
chân P2.1. Hãy sử dụng bộ Timer0 để tạo ra sóng vuông, tần số của
8051 là XTAL = 11.0592MHz.
Chu kỳ 200us, vậy nửa chu kỳ là 100ms.
Ta có: 100us/1,085us=92.
Suy ra giá trị cần nạp cho timer0 là: -92 <=> A4H. Ta
sử dụng timer0 8 bit.
112
56
4/12/2022
113
Ví dụ : Viết chương trình để tạo sóng vuông với mức cao kéo dài 1085us
và mức thấp dài 15us với giả thiết tần số XTAL = 11.0592MHz. Hãy sử
dụng bộ định thời Timer1.
114
57
4/12/2022
#include<at89x51.h>
bit a=0;
main()
{
TMOD=0x10; //chọn timer1, chế độ 1, 16Bit
TL1=0x18; //nạp giá trị cho TL1
TH1=0xFC; //nạp giá trị cho TH1
TR1=1; //khoi dong timer1
IE=0x88; //cho phép ngat timer1
while(1) //vòng lặp vô hạn
{
P1=~P0; //Cập nhật cổng P1
}
}
void songvuong(void) interrupt 3 //Khai báo trình phục vụ ngắt timer1
{
TR1=0; //Dừng timer1
if(a==0) //Nếu Xung vuông đang ở mức thấp
{
P2_1=1; //Bật xung vuông lên cao
a=1; //Đặt lại bit kiểm tra
TL1=0x18; //Nạp lại TL1: Ứng với mức trễ phần cao
TH1=0xFC; //Nạp lại TH1
}
Else //Nếu Xung vuông đang ở mức cao
{
P2_1=0; //Lật xung xuống thấp
a=0; //Đặt lại bit kiểm tra
TL1=0xF2; //Nạp lại TL1: Ứng với mức trễ phần thấp
TH1=0xFF; //Nạp lại TH1
}
TR1=1; //Khởi động lại timer1
//Không cần xóa cờ TF1, 8051 tự động xóa
}
115
58
4/12/2022
14
15
Ngắt ngoài (mức xung/sườn xung) xuất hiện khi: xuất hiện tín hiệu thích
hợp từ bên ngoài tác động vào chân chân P3.2(chân 12), Chân P3.3
(chân 13) :
Mức xung: chân P3.2(chân 12), Chân P3.3 (chân 13) có mức logic 0 (tồn tại
mức thấp khoảng 4 chu trình máy và phải về mức cao trước khi kết thúc vectơ
ngắt).
Sườn xung: chân P3.2(chân 12), Chân P3.3 (chân 13) chuyển từ mức
logic 1 về mức logic 0. 117
• Sườn xung:
ITx=1
Chương trình phục vụ ngắt
void <name>(void) interrupt 0 void <name>(void) interrupt 2
{ //chương trình phụ vụ ngắt ngoài 0 { //chương trình phụ vụ ngắt ngoài 1
} } 118
59
4/12/2022
Ví dụ: Viết chương trình điều khiển, thường xuyên thay đổi trạng thái trên chân
P1.0 và chỉ thay đổi trạng thái trên chân P1.1 khi có xung (mức 0) ở công tắc bên
ngoài -> dùng ngắt ngoài 0, ngắt theo mức xung
Pin 12/P3.2
Ví dụ: Viết chương trình điều khiển, thường xuyên thay đổi trạng thái trên chân
P1.0. Chỉ thay đổi trạng thái trên chân P1.1 về mức 0 khi có xung (mức 0) ở công
tắc 1 bên ngoài và thay đổi trạng thái trên chân P1.1 về mức 1 khi có xung (mức
0) ở công tắc 2 bên ngoài -> dùng 2 công tắc nối 2 ngắt ngoài 0 và 1, ngắt theo
sườn xung.
119
Ví dụ : Giả sử chân INT1 được nối đến công tắc bình thường ở mức
cao. Mỗi khi nó ấn xuống thấp phải bật đèn LED ở chân P1.3 (bình
thường Led tắt), khi nó được bật lên nó phải sáng vài giây. Chừng nào
công tắc được giữ ở trạng thái thấp đèn LED phải sáng liên tục.
#include<at89x51.h> //Khai báo thư viện cho VĐK 89x51
main() //Chương trình chính
{
IE=0x84; //cho phép ngắt ngoài 1; 10000100
while(1) //vòng lặp vô hạn
{ //không làm gì
}
}
void nn(void) interrupt 2 //Khai báo trình phục vụ ngắt ngoài 1
{ //(mặc định là ngắt theo mức)
int a=50000; //Biến đếm trễ
P1_3=0; //Cho Led sáng
while(a--){} //Trễ cho Led sáng vài giây
P1_3=1; //Tắt Led ,không cần xóa cờ ngắt
} 120
60
4/12/2022
122
61
4/12/2022
62