You are on page 1of 62

4/12/2022

4.1. Ngôn ngữ lập trình C cho vi


điều khiển
 Trong kỹ thuật lập trình vi điều khiển nói chung, ngôn
ngữ lập trình được sử dụng thường chia làm 2 loại:
▪ Ngôn ngữ bậc thấp
▪ Ngôn ngữ bậc cao

1
4/12/2022

 Khi sử dụng ngôn ngữ C người lập trình không cần


hiểu sâu sắc về cấu trúc của bộ vi điều khiển.
 Không phải mất thời gian tìm hiểu kiến trúc của vi
điều khiển đó.
 Có thể sử dụng lại các chương trình đã xây dựng
trước đó cũng dễ dàng hơn, có thể sử dụng toàn bộ
hoặc sửa chữa một phần.

4.1.1 Cấu trúc chương trình


1. Khai báo chỉ thị tiền xử lý
2. Khai báo các biến toàn cục
3. Khai báo nguyên mẫu các hàm
4. Xây dựng các hàm và chương trình chính

2
4/12/2022

#include<regx51.h>
#include<string.h> Khai báo biến toàn cục
#define Led1 P1_0

Unsigned char code Led_arr[3];


Unsigned char data dem; Khai báo nguyên mẫu hàm
Unsigned int xdata X;
Void delay(unsigned int n);
bit kiemtra(unsigned int a);
void delay(unsigned int n)
{
Khai báo biến cục bộ;
Mã chương trình trễ;
}
Void main()
Xây dựng các hàm và chương trình chính
{
Khai báo biến cục bộ;
Mã chương trình chính;
}
Bit kiemtra(unsigned int a)
{
Khai báo biến cục bô;
Mã chương trình kiểm tra biến a;
5
}

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:

<kiểu của hàm> <tên hàm>(danh sách tham số) ;


Kiểu của hàm: Là kiểu dữ liệu mà hàm trả về. Nếu không có giá trị trả về thì kiểu
của hàm là void.
Tên hàm: Là tên của hàm (tên hàm không được chứa ký tự đặt biệt, không được
bắt đầu bằng số).
Danh sách tham số: là danh sách các tham số dùng như các biến cục bộ. Nếu
có nhiều tham số, thì chúng sẽ được phân tách theo các dấu phẩy.
Ví dụ
int test(int); // Hàm test có tham số kiểu int và kiểu hàm là int
int rand(); // Không tham số, kiểu hàm (giá trị trả lại) là int
void write(float) ; //Hàm không trả lại giá trị (kiểu void).
6

3
4/12/2022

b. Định nghĩa hàm


Cấu trúc một hàm :
<kiểu hàm> <tên hàm>(danh sách tham số)
{ dãy lệnh của hàm ;
return (biểu thức trả về);
}
return là để truyền dữ liệu cho nơi gọi hàm.
Đối với hàm không có giá trị trả về (có kiểu trả về là void).
Đối với hàm có giá trị trả về thì kèm theo sau return là một
biểu thức.
Kiểu giá trị của biểu thức này chính là kiểu của hàm.
Khi gặp return chương trình tức khắc thoát khỏi hàm và trả lại
giá trị biểu thức sau return.
Có thể có nhiều câu lệnh return trong hàm.

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

4.1.3 Kiểu dữ liệu


a. Kiểu dữ liệu trong C
Kiểu Số Byte Khoảng giá trị
Char 1 -128 – +127
Unsigned char 1 0 – 255
Int 2 -32768 - +32767
Unsigned int 2 0 - 65535
Long 4 -2147483648 - +2147483647
Unsigned long 4 0 – 4294697295
Float 4

11

b. Kiểu dữ liệu trong Keil C


Kiểu Số bit
Bit 1
Sbit 1
Sfr 8
Sfr16 16
- bit : dùng để khai báo các biến có giá trị 0 hoặc một hay các biến logic trên
vùng RAM của vi điều khiển. Khi khai báo biến kiểu bit trình dịc Keil C sẽ mặc
định vùng nhớ sử dụng là BDATA.
`- sbit, sfr, sfr16: dùng để định nghĩa các cho các thanh ghi chức năng hoặc các
cổng trên vi điều khiển dùng để truy nhập các đoạn dữ liệu 1 bit, 8 bit, 16 bit

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ể.

 Khai báo biến con trỏ:


Loại con trỏ Kích thước
- Cú pháp: Kiểu_Dữ_liệu Vùng_nhớ *Tên_biến; Con trỏ tổng quát 3 byte
- Ví dụ: Con trỏ XDATA 2 byte
int *int_ptr; Con trỏ CODE 2 byte
Con trỏ DATA 1 byte
Con trỏ IDATA 1 byte
Con trỏ PDATA 1 byte

14

7
4/12/2022

4.1.4 Phép toán


a. Phép toán số học
Phép toán ý nghĩa Ví dụ
+ Phép cộng X=a+b
- Phép trừ X=a-b
* Phép nhân X=a*b
/ Phép chia lấy phần nguyên X=a/b
(a=9, b=2 → X=4)
% Phép chia lấy phần dư a%b
(a=9, b=2 → X=1)

15

b. Phép toán Logic

 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ệ.

Phép toán Ý nghĩa Ví dụ


&& AND hai toán hạng a&&b
(a < 10) && (b == 7);
|| OR hai toán hạng a||b
(a < 10) || (b == 7);
! NOT giá trị của toán hạng duy nhất !a
(S<10) hay (! (s >= 10))

16

8
4/12/2022

c. Phép toán so sánh


Toán tử quan hệ được dùng để kiểm tra mối quan hệ giữa hai biến, hay giữa một biến và
một hằng. Ví dụ,việc xét số lớn hơn của hai số, a và b, được thực hiện thông qua dấu lớn
hơn (>) giữa hai toán hạng a và b (a > b)
Phép toán ý nghĩa Ví dụ
> So sánh lớn hơn a>b
4>5 cho giá trị 0
>= So sánh lớn hơn hoặc bằng a>=b
6>=2 cho giá trị 1
< So sánh nhỏ hơn a<b
6<7 cho giá trị 1

<= So sánh nhỏ hơn hoặc bằng a<=b


8<=5 cho giá trị 0
== So sánh bằng nhau a==b
6==6 cho giá trị 1
!= So sánh khác nhau a!=b
9!=9 cho giá trị 0 17

d. Phép toán thao tác Bit


Phép toán Ý nghĩa Ví dụ
& Phép và (AND) Bit_1 & Bit_2
| Phép hoặc (OR) Bit_1 | Bit_2
! Phép đảo (NOT) !Bit_1
^ Phép hoặc loại trừ (XOR) Bit_1 ^ Bit_2
<< Dịch trái a<<3
tương tự x=a*23
>> Dịch phải a>>4
~ Lấy bù theo bit ~a

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

Phép dịch trái <<


Kí hiệu: <<
Phép dịch trái n bit tương đương với phép nhân cho 2n.

Ví dụ
Ví dụ A=4; B=A<<16
=> B = 4 / 22 = 1

Phép dịch phải >>


Kí hiệu: >>
Phép dịch phải n bit tương đương với phép chia cho 2n.

Ví dụ A=4; B=A>>2
=> B = 4 / 22 = 1

21

e. Phép toán kết hợp


Phép toán Ví dụ

+= a+=5 <=> a=a+5


-= a-=5 <=> a=a-5
*= a*=5 <=> a=a*5
/= a/=5 <=> a=a/5
%= a%=5 <=> a=a%5

22

11
4/12/2022

4.2 Chương trình ứng dụng


Ví dụ 1: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 Sáng Led
/*==================khai bao bien==================*/
sbit Led = P1^0; // Khai bao bien Led tại chân P1.0 Tắt Led
sfr Dayled=0x80; // Khai bao bien Dayled kieu tại P0
/*================= Khai bao hàm==================*/
/*--------------------------------ham chinh--------------------------------*/ Kết thúc
void main(void)
{ Led = bat; // bat Led

Led = tat; // tat Led

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
{

Led = bat; // bat Led


delay (500);
Led = tat; // tat Led
delay (500);

}
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: Đ

if (dieu_kien) Đoạn chương trình


{
// Đoạn chương trình
}

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
}

Giải thích: nếu dieu_kien đúng thì xử lí “Đoạn chương trình


1” bên trong còn sai thì xử lý “Đ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
}

bien= gia_tri_n các câu lệnh n

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

e. Vòng lặp FOR Khởi tạo n=m


Cấu trúc:

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

Giải thích: n=n+a


m,l,a là giá trị(m>l), n là biến.
Thực hiện lặp các câu lệnh x lần. các câu lệnh xử lí 2
Lưu ý: for(;;)// vòng lặp vô hạn

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

f. Vòng lặp WHILE


Cấu trúc:
while(dieu_kien)
{ dieu kien
S
// các câu lệnh 1 Đ
}
// các câu lệnh 2 các câu lệnh xử lí 1

Giả thích: thực hiện lặp các câu


lệnh xử lý 1 khi điều kiện đúng,
nếu điều kiện sai thì thoát các câu lệnh xử lí 2
khỏi vòng lặp.

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

g. Vòng lặp DO-WHILE


Cấu trúc: các câu lệnh xử lí 1
do
{
Đ
// các câu lệnh1
} Dieu_kien
while(dieu_kien); S
// các câu lệnh 2
các câu lệnh xử lí 2

Giải thích: thực hiện lặp các câu


lệnh 1, sau đó kiểm tra điều
kiện nếu đúng, nếu sai thì
thoát khỏi vòng lặp.
36

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

*/======================Bo tien xu li===================*/


#include<AT89x51.h> // Dinh kem file thu vien
#define bat 1 // Dinh nghia gia tri bat den Led
#define tat 0 // Dinh nghia gia tri tat den Led
/*==================khai bao bien==================*/
sbit Led = P1^0; // Khai bao bien Led kieu bit chan P1.0
sbit STOP = P3^0; // cong tac STOP de tat Led
sbit START = P3^1; // cong tac START de bat Led
/*=================== ham chinh==================*/
void main(void)
{ P3^0=1; //khai bao chan input
P3^1=1; //khai bao chan input
Led = tat; //ban dau tat Led
` while(1){
if(START==0)
{
Led = bat;
}
if(STOP==0)
{
Led = tat;
}
41
}
}

*/======================Bo tien xu li===================*/


#include<AT89x51.h> // Dinh kem file thu vien
#define bat 1 // Dinh nghia gia tri bat den Led
#define tat 0 // Dinh nghia gia tri tat den Led
/*==================khai bao bien==================*/
sbit Led = P1^0; // Khai bao bien Led kieu bit chan P1.0
sbit STOP = P3^0; // cong tac STOP de tat Led
sbit START = P3^1; // cong tac START de bat Led
/*=================== ham chinh==================*/
void main(void)
{ Led = tat; //ban dau tat Led
while(1){
if((START==0)&&(STOP==1))
{ Vẽ lưu đồ thuật toán từ
Led = bat; chương trình bên?????
}
if((START==1)&&(STOP==0))
{
Led = tat;
}
}
}

42

21
4/12/2022

Ví dụ: Sử dụng vi điều khiển để điều khiển động cơ DC.


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ì động cơ chạy,
khi bật công tắc STOP thì động cơ dừng.

43

4.3 ĐIỀU KHIỂN CÁC


THANH GHI CÓ CHỨC NĂNG ĐẶC BIỆT
(SFR: Special Function Registers)

44

22
4/12/2022

4.3.1. CÁC THANH GHI ĐIỀU KHIỂN TIMER/COUNTER:


Vi điều khiển 8951 có 2 timer/counter: TIMER0/COUNTER0 và
TIMER1/COUNTER1
Cấu trúc của một bộ timer/counter: Timer

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

 THx, TLx: 2 thanh ghi 8 bit


Tx, INTx: chân 8951
45

Cấu trúc của một bộ timer/counter: Counter

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

b. Thanh ghi điều khiển timer: TCON


Là thanh ghi 8 bit, truy xuất (ghi/đọc) byte hoặc bit
- Truy xuất byte: TCON= 0xgiá trị ;
- Truy xuất bit: <TÊN BIT>=giá trị;

7 6 5 4 3 2 1 0

TF1 TR1 TF0 TR0 IE1 IT1 IE0 IT0

TF1: báo trạng thái tràn cho bộ Timer/Counter1


TR1: điều khiển cấp xung cho bộ Timer/Counter1
TF0: báo trạng thái tràn cho bộ Timer/Counter0
TR0: điều khiển cấp xung cho bộ Timer/Counter0
IE1: báo trạng thái ngắt ngoài 1
IT1: cho phép tác động ngắt ngoài 1 bằng cạnh xuống (default IT1 = 0, tác động ngắt
bằng mức thấp)
IE0: báo trạng thái ngắt ngoài 0
IT0:cho phép tác động ngắt ngoài 0 bằng cạnh xuống (default IT0 = 0, tác động ngắt
bằng mức thấp)
47

c. Thanh ghi chế độ timer: TMOD


Là thanh ghi 8 bit, truy xuất (ghi/đọc) byte
TMOD=0xgiá trị;

7 6 5 4 3 2 1 0

GATE C/T M1 M0 GATE C/T M1 M0

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

M1 M0 Chế độ Mô tả


0 0 0 Timer/Counter 13 bit
0 1 1 Timer/Counter 16 bit
1 0 2 Timer/Counter 8 bit, auto reload
1 1 3 Timer/Counter 8 bit

48

24
4/12/2022

7 6 5 4 3 2 1 0

TCON GATE C/T M1 M0 GATE C/T M1 M0

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

c. Thanh ghi Timer: THx,TLx


Các thanh ghi của bộ Timer 0
Thanh ghi 16 bit của bộ Timer 0 được truy cập như byte thấp và byte cao:
Thanh ghi byte thấp được gọi là TL0 (Timer0 Low byte).
Thanh ghi byte cao được gọi là TH0 (Timer0 High byte).

Hình 1: Các thanh ghi của bộ Timer 0


Các thanh ghi của bộ Timer 1

Hình 2: Các thanh ghi của bộ Timer 1.

50

25
4/12/2022

4.3.2 Hoạt động của các chế độ timer

a. Chế độ 0: 13 bit


TMOD GATE C/T M1 M0 GATE C/T M1 M0

÷12 THx (8 BIT) TLx (5 BIT) TFx

0110000011000

TRx

00000000 00000 00000000 00001 00000000 00010 11111111 11111 +1


0/0H 1/1H 2/2H 8191 +1/1FFF+1H

Giá trị kết thúc=8192

2021

51

4.3.2 Hoạt động của các chế độ timer


7 6 5 4 3 2 1 0
b Chế độ 1: 16 bit TMOD GATE C/T M1 M0 GATE C/T M1 M0

TMOD = x x 0 1 x x 0 1

÷12 THx (8 BIT) TLx (8 BIT) TFx

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

a) Tính theo số Hex b) Tính theo số thập phân


(FFFF - YYXX + 1)*12/f (ms) trong Chuyển đổi các giá trị YYXX của
đó YYXX là các giá trị khởi tạo của TH, TL về số thập phân để nhận một
TH, TL tương ứng. Lưu ý rằng các số thập phân NNNNN sau đó lấy
giá trị YYXX là theo số Hex. (65536 – NNNNN)*12/f (ms).
52

26
4/12/2022

c. Chế độ 2: 8 bit AUTORELOAD 7 6 5 4 3 2 1 0

TMOD GATE C/T M1 M0 GATE C/T M1 M0

÷12 TLx : 8 BIT TFx

TRx OVERFLOW

THx : 8 BIT

TLx xxxxxxxx 11111111+1


DDD/HH
256 /FF+1H

Nạp THx vào TLx

THx xxxxxxxx
DDD/HH
53

HOẠT ĐỘNG CỦA CÁC CHẾ ĐỘ TIMER/COUNTER

d. Chế độ 3: 8 bit

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

4.3.3 Lập trình điều khiển Timer


a.Chế độ 1
 1. Nạp giá trị TMOD cho thanh ghi báo độ định thời nào
(Timer0 hay Timer1) được sử dụng và chế độ nào được chọn.
 2. Nạp các thanh ghi TLx và THx với các giá trị đếm ban
đầu.
 3. Khởi động bộ định thời.
 4. Duy trì kiểm tra cờ bộ định thời TFx bằng một vòng lặp
để xem nó được bật lên 1 không. Thoát vòng lặp khi TFx được
lên cao.
 5. Dừng bộ định thời.
 6. Xoá cờ TFx cho vòng kế tiếp.
 7. Quay trở lại bước 2 để nạp lại TLx và THx.
55

Khai báo chế độ


timer/counter

Định giá trị ban


đầu cho TLx, THx

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

4.3.2 Hoạt động của các chế độ timer


7 6 5 4 3 2 1 0
b Chế độ 1: 16 bit TMOD GATE C/T M1 M0 GATE C/T M1 M0

TMOD = x x 0 1 x x 0 1

÷12 THx (8 BIT) TLx (8 BIT) TFx

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

a) Tính theo số Hex b) Tính theo số thập phân


(FFFF - YYXX + 1)*12/f (ms) trong Chuyển đổi các giá trị YYXX của
đó YYXX là các giá trị khởi tạo của TH, TL về số thập phân để nhận một
TH, TL tương ứng. Lưu ý rằng các số thập phân NNNNN sau đó lấy
giá trị YYXX là theo số Hex. (65536 – NNNNN)*12/f (ms).
57

 Tính giá trị nạp THx, TLx


 Tìm giá trị nạp cho THx,TLx để sau 20ms cờ TF1=1
20mS=20.000us
|---------->|--------------------->|
0 X 65.535+1
X|<----20.000------->|65.536
=> X= 65536-20.000= 45536= B1E0 H
TH1 =0xB1 ; TL1=0xE0
 Tìm giá trị nạp cho THx,TLx để sau 50ms cờ TF0=1
50mS=50.000us
|---------->|--------------------->|
0 X 65.535+1
X|<----50.000------->|65.536
=> X= 65536-50.000= 15536= 3CB0H
TH0 =0x3C ; TL0=0xB0
58

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

1.Nạp giá trị TMOD.


2. Nạp các thanh ghi TL và TH với các giá trị đếm
Tmod ban đầu.
3. Khởi động bộ định thời.
4. Duy trì kiểm tra cờ bộ định thời TF bằng một
vòng lặp để xem nó được bật lên 1 không. Thoát
vòng lặp khi TF được lên cao.
5. Dừng bộ định thời.
6. Xoá cờ TF cho vòng kế tiếp.
7. Quay trở lại bước 2 để nạp lại TL và TH.
TMOD
Timer 1 Timer 0
G C/T M1 M0 G C/T M1 M0
0 0 0 0 0 0 0 1

Tmod=0x01; Timer 0 mode 1 (Bộ định thời 16bit)

0 0 0 1 0 0 0 0

Tmod=0x10; Timer 1 mode 1 (Bộ định thời 16bit)

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

1.Nạp giá trị TMOD.


2. Nạp các thanh ghi TL và TH với các 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 một
vòng lặp để xem nó được bật lên 1 không. Thoát
vòng lặp khi TF được lên cao.
5. Dừng bộ định thời.
6. Xoá cờ TF cho vòng kế tiếp.
7. Quay trở lại bước 2 để nạp lại TL và TH.

Tìm giá trị nạp cho THx,TLx để sau 50ms cờ TF0=1

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

1.Nạp giá trị TMOD.


2. Nạp các thanh ghi TL và TH với các 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 một
vòng lặp để xem nó được bật lên 1 không. Thoát
vòng lặp khi TF được lên cao.
5. Dừng bộ định thời.
6. Xoá cờ TF cho vòng kế tiếp.
7. Quay trở lại bước 2 để nạp lại TL và TH.

÷12 THx (8 BIT) TLx (8 BIT) TFx

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

1.Nạp giá trị TMOD.


2. Nạp các thanh ghi TL và TH với các 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 một
vòng lặp để xem nó được bật lên 1 không.
Thoát vòng lặp khi TF được lên cao.
5. Dừng bộ định thời.
6. Xoá cờ TF cho vòng kế tiếp.
7. Quay trở lại bước 2 để nạp lại TL và TH.
Đ
TFx=0 7 6 5 4 3 2 1 0
S TCON TF1 TR1 TF0 TR0 IE1 IT1 IE0 IT0

Dừng bộ định thời

while(!TF1){} //Duy trì kiểm tra cờ TF1


TR1=0; //Dừng bộ định thời
TF1=0 // Xoá cờ TF
Hoặc TCON ? . . ;
64

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)

{ TH1=0x0FEh;tách 2 số đầu nạp cho TH


TH1=0x0Ch ;tách 2 số sau nạp cho TL

TR1=1; Khởi động bộ định thời


while(!TF0){} //Duy trì cho đến khi cờ TF0=1;
P0_1=~P1_0;
TR1 = 0; Tắt bộ định thời

TF1 =0; Xóa cờ bộ định thời


}
}

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

TH1=0x0Ch ;tách 2 số sau nạp cho TL Xóa cờ TFx


TR1=1; Khởi động bộ định thời
Khởi động
while(!TF0){} //Duy trì cho đến khi cờTimer/counter
TF0=1;
P0_1=~P1_0;
TFx= 0
TR1 = 0; Tắt bộ định thời Giám sát cờ TFx=0

TF1 =0; Xóa cờ bộ định thời TFx= 1


} Tắt Timer
}
~P1.0
67

 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

 Void Delay_500u() Delay_500u Khai báo chế độ


Void delay()
 { TMOD = 0x10; timer/counter
{….
TH1=0x0FEh;nạp cho TH
} P1.0=~P1.0
TH1=0x0Ch ;nạp cho TL Định giá trị ban
TR1=1; Khởi động bộ định thời đầu cho TLx, THx
while(!TF0){} //chờ đến khi TF0=1;
TR1 = 0; Tắt bộ định thời
Xóa cờ TFx
TF1 =0; Xóa cờ bộ định thời
 } Chỉ ra điểm
sai trong Khởi động
 Void main() chương trình Timer/counter
 { này
while(1) TFx= 0
Giám sát cờ TFx=0
{
Delay_500u(); TFx= 1
P0_1=~P1_0;đổi trạng thái Tắt Timer
}
} RET 68

34
4/12/2022

Ví dụ: Viết chương trình tạo xung vuông 1kHz ở chân


P3.0 với độ đầy xung là 66%, sử dụng timer 1, mode 1.
8951

12Mhz
P3.0

Sinh viên tự
làm

Ghi chú: Độ rỗng của một dãy xung là tỉ


số giữa chu kỳ lặp lại T đối với độ rộng
xung ton và được ký hiệu là: Q = T / ton
Trị số nghịch đảo của Q được gọi là hệ
số đầy của xung và nó được tính theo
69
công thức: n = ton / T.

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:

#include<at89x51.h> //khai báo thư viện cho VĐK 89x51


void delay(void); //khi báo nguyên mẫu hàm con tạo trễ
main()
{
TMOD=0x20; //chọn timer1, chế độ 2, 8Bit, tự nạp lại
TH1=0xC8; //nạp giá trị cho TH1
TL1=0xC8; //nạp giá trị cho TL1
P1_5=1;
Tính chu kỳ
//khởi tạo chân P1_5 ở mức cao
while(1) //vòng lặp vô hạn xung trên chân
{ P1.5 ???
delay(); //gọi chương trình con tạo trễ
P1_5=~P1_5; //đảo tín hiệu chân P1_5
}
}
void delay(void) //định nghĩa hàm delay
{
TR1=1; //khởi động timer1
while(!TF1){} //vòng lặp kiểm tra cờ TF1
TR1=0; //ngừng timer1
TF1=0; //xóa cờ TF1
}
70

35
4/12/2022

Trường hợp khi bit GATE = 1 trong TMOD


18 8951
C/T = 0: T
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ở
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

 Viết chương trình mô tả hệ thống rót (chiết) sản phẩm.


Khi có hộp/chai được đưa đến hệ thống (P3.3=0) sẽ điều
khiển van rót mở (P1.0=0) trong khoảng 60ms rồi đóng lại

72

36
4/12/2022

4.3.3 Lập trình điều khiển Timer


b. Chế độ 0
 1. Nạp giá trị TMOD cho thanh ghi báo độ định thời X
(Timer0 hay Timer1) được sử dụng và chế độ nào được
chọn.
 2. Nạp các thanh ghi TLx (5bit) và THx (8bit) với các
giá trị đếm ban đầu.
 3. Khởi động bộ định thời (Xóa cờ TFx).
 4. Duy trì kiểm tra cờ bộ định thời TFx bằng một vòng
lặp để xem nó được bật lên 1 không. Thoát vòng lặp
khi TFx được lên cao.
 5. Dừng bộ định thời.
 6. Xoá cờ TFx cho vòng kế tiếp.
 7. Quay trở lại bước 2 để nạp lại TLx và THx.
73

 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

Tính giá trị nạp THx, TLx


 Tìm giá trị nạp cho THx,TLx để sau 0,5ms cờ TF0=1
0,5mS=500µs
|---------->|--------------------->|
0 X 8191+1
X|<--------500------->|8192
=> X= 8192- 500= 7692= 1111000001100B
TL0= 01100B= 0CH
TH0 =11110000B=F0H

75

Tính giá trị nạp THx, TLx


 Tìm giá trị nạp cho THx,TLx để sau 5ms cờ TF1=1
5mS=5000µs
|---------->|--------------------->|
0 X 8191+1
X|<--------5000------>|8192
=> X= 8192- 5000=3192=1100011 11000B
TL1= 11000B= 18H
TH1 =1100011B=63H
void main(){

Time=8192-5000;
TL1=Time&1F; //nạp 5 bit thấp cho TL1
TH1=Time>>5; //nạp 8 bit cao cho TH1
….
} 76

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

#include<at89x51.h> //khai báo thư viện 89x51


Định giá trị ban đầu cho main()
THx(8bit), TLx(5bit) {
TMOD=0x00; //chọn timer0, chế độ 1, 16Bit
while(1) //vòng lặp vô hạn
Xóa cờ TFx {
P1_0=~P1_0; //đảo tín hiệu chân P1_0
Khởi động Timer/counter TH0=0xE0; //nạp giá trị cho TL0
TL0=0x18; //nạp giá trị cho TH0
TF0=0; //xóa cờ TF0
TR0=1; //khởi động timer0
Giám sát cờ TFx=0 while(!TF0){} //chờ tràn (TF0=1)
TFx= 0 TR0=0; //ngừng timer0
TFx= 1
}
Tắt Timer }
77

 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.

Sáng=1ms Tắt= 1ms


#include<at89x51.h> //khai báo thư viện 89x51
T= 2ms void delay(void); //khai báo hàm con tạo trễ
main()
Khai báo chế độ {
P1_0=1; //khởi tạo chân P1_0 ở mức cao
timer/counter
TMOD=0x00; //chọn timer0, chế độ 1, 16Bit
while(1) //vòng lặp vô hạn
Định giá trị ban đầu cho {
THx(8bit), TLx(8bit) delay(); //chương trình con tạo trễ
P1_0=~P1_0; //đảo tín hiệu chân P1_5
}
Xóa cờ TFx }
void delay(void) //định nghĩa hàm delay
{
Khởi động Timer/counter
TH1=0xE0; //nạp giá trị cho TL0
TL1=0x18; //nạp giá trị cho TH0
TFx= 0 TF1=0; //xóa cờ TF0
Giám sát cờ TFx=0 TR1=1; //khởi động timer0
while(!TF1){} //chờ tràn (TF0=1)
TFx= 1 TR1=0; //ngừng timer0
Tắt Timer {
79

 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

7,5ms->7.442=1 1101 000 1 0010 B= 0xE8, 0x12

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.

#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
0,25ms 0,75ms while(1) //vòng lặp vô hạn
{
P1_0=1;
Delay(0xF8, 0x06);
P1_0=0; //đảo tín hiệu chân P1_5
Delay(0xE8, 0x12);
}
}
void Delay(int x, int y) //định nghĩa hàm delay
{ TH0=x; //nạp giá trị cho TL0
TL0=y; //nạp giá trị cho TH0
TF0=0; //xóa cờ TF0
TR0=1; //khởi động timer0
while(!TF0){} //chờ tràn (TF0=1)
TR0=0; //ngừng timer0
}
81

4.3.3 Lập trình điều khiển Timer


c. Chế độ 2 7 6 5 4 3 2 1 0

TMOD GATE C/T M1 M0 GATE C/T M1 M0

÷12 TLx : 8 BIT TFx

TRx OVERFLOW

THx : 8 BIT

TLx xxxxxxxx 11111111+1


DDD/HH
256 /FF+1H

Nạp THx vào TLx

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

Các bước lập trình cho chế độ 2


 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 THx và TLx 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 TFx 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 TFx lên cao.
 5. Dừng bộ định thời.
 6. Xoá cờ TFx.
 7. Quay trở lại bước 3. Vì chế độ 2 là chế độ tự nạp lại.

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

Tóm tắt sử dụng thanh ghi định thời

Tác động thanh ghi Tmode:


Khai báo chế độ |---TIMER1----||-----TIMER0----|
timer/counter G|C/T|M1|M0| G|C/T|M1|M0

(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

TFx= 0 TRx=1 (TFx= 0 )


Giám sát cờ TFx=0
TFx= 0 TFx = 1
TFx= 1
TRx= 0 ; (TFx= 0 )

Với x= 1/0 86

43
4/12/2022

4.3.4. Bộ đếm (Counter)


18 8951
C/T = 0: T
÷12 TMOD
OSC 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
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

4.3.4. Bộ đếm (Counter)


7 6 5 4 3 2 1 0

TMOD GATE C/T M1 M0 GATE C/T M1 M0

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.

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

88

44
4/12/2022

VD: Chương trình sử dụng bộ đếm 1, đếm các xung ở


chân P3.5 và hiển thị số đếm được (trong thanh ghi TL1) lên
cổng P2:
#include<at89x51.h> //khai báo thư viện 89x51
main() //chương trình chính
{
TMOD=0x60; //0x60=0110 000 : C/T=1, bộ đếm 1, chế độ
2 tự nạp
TH1=0x00; //xóa bộ đếm ban đầu
P3_5=1; //set chân vào cho bộ đếm
TR1=1; //khởi động bộ đếm 1
while(1) //vòng lặp vô hạn
{
P2=TL1; //hiển thị số đếm được ra cổng P2
}
}
89

 Sử dụng counter để đếm sản phẩm chạy tên băng


truyền, khi đủ 25 s ản ph ẩm thì xuất tất cả tín hiệu ở
Port 2 lên mức 1 trong 1s.

90

45
4/12/2022

Ngắt trong 8051 4.4 Ngắt


1. RESET: Khi chân RESET được kích hoạt từ 8051, bộ đếm
chương trình nhảy về địa chỉ 0000H.
2. 2 ngắt dành cho các bộ định thời: 1 cho Timer0 và 1
cho Timer1. Địa chỉ tương ứng của các ngắt này
là 000BH và 001BH.
3. 2 ngắt dành cho các ngắt phần cứng bên ngoài: chân 12
(P3.2) và 13 (P3.3) của cổng P3 là các ngắt phần cứng bên
ngoài INT0 và INT1 tương ứng. Địa chỉ tương ứng của các ngắt
ngoài này là 0003H và 0013H.
4. Truyền thông nối tiếp: có 1 ngắt chung cho cả nhận và
truyền dữ liệu nối tiếp. Địa chỉ của ngắt này trong bảng vector
ngắt là 0023H.

91

4.4.1. ĐIỀU KHIỂN NGẮT

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

ĐIỀU KHIỂN NGẮT


Công việc 1 Điều khiển thăm dò
Điều khiển thăm dò Công việc a
Có nhấn
KT ct nhấn Công việc b
Công việc 1 Không nhấn

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

Công việc n+1 Công việc a


Công việc n
Công việc a
KT ct nhấn Có nhấn
Có nhấn KT ct nhấn Công việc b
Không nhấn Không nhấn
Công việc n+ Công việc n+
93

Đ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

Công việc n+ RETI


Công việc n 94

47
4/12/2022

Khi một ngắt xuất hiện và được CPU chấp


nhận, chương trình chính bị ngắt. Các thao
tác sau đây xảy ra: Công việc 1
- Hoàn tất việc thực thi lệnh hiện hành Có ngắt
- Cất bộ đếm chương trình (PC-chứa Công việc 2
địa chỉ câu lệnh được thực thi tiếp theo) vào Công việc a
Stack.
- Trạng thái của ngắt hiện hành được Công việc n +1 Công việc b
lưu giữ lại
- Bộ đếm chương trình PC sẽ nạp địa
Công việc n RETI
chỉ của chương trình con phục vụ ngắt và
chuyển đến thực hiện chương trình con phục
vụ ngắt .
- Thực hiện xong sẽ quay về chương
trình chính tại vị trí nó bị ngắt (nạp lại giá trị
thanh ghi PC từ Stack) và thực hiện tiếp
chương trình chính.

95

• Ngắt ( interrupt ) là sự xảy ra của một điều kiện ( một sự


kiện) làm cho chương trình hiện hành bị tạm ngưng để thực
hiện một chương trình khác (chương trình con phục vụ ngắt
hay còn gọi là véc tơ ngắt).
• Các ngắt cho phép hệ thống đáp ứng một sự kiện theo cách không đồng bộ và xử
lý sự kiện trong khi một chương trình khác đang thực thi.
• Một hệ thống được điều khiển bởi ngắt cho ta cảm giác CPU đang làm nhiều công
việc đồng thời (đa nhiệm).
Phân biệt sự giống và khác nhau giữa “ngắt” và “gọi chương trình con”:
• Giống nhau:
Khi xảy ra điều kiện tương ứng thì CPU sẽ tạm dừng chương trình hiện hành để thực
thi một chương trình khác (chương trình con / chương trình xử lý ngắt) rồi sau đó
(sau khi xử lý xong chương trình con / chương trình xử lý ngắt) thì CPU sẽ qquay về
để thực thi tiếp tục chương trình dang dở trước đó - đang bị tạm dừng.
• Khác nhau: Ngắt Chương trình con
Thời điểm xảy ra sự Không biết trước (hay xảy ra Biết trước (hay xảy ra đồng
kiện không đồng bộ với chương bộ với chương trình chính)
trình chính).
Nguyên nhân dẫn Do các tín hiệu điều khiển Do lệnh gọi chương trình
đến sự kiện từ Timer, Serial port và bên con (ACALL, LCALL).
ngoài chip. 96

48
4/12/2022

4.4.2 Chương trình con phục vụ


ngắt (Trình phục vụ ngắt-ISR)
Số
Cờ Địa chỉ
thứ Bắt đầu
Ngắt ngắt phục
tự
(I) vụ ngắt
(X)
Công việc 1
Reset - 0000h -
Ngắt ngoài 0 IE0 0003h 0 Công việc 2
Ngắt Timer 0 TF0 000Bh 1 Name (void) interrupt X
Cờ ngắt Ix=1
Ngắt ngoài 1 IE1 0013h 2
Ngắt Timer 1 TF1 001Bh 3 Chương trình phục vụ
Ngắt truyền RI/TI 0023h 4 Công việc n +1 ngắt
thông
Công việc n RETI

97

Void Name (void) interrupt X Bắt đầu


{
Công việc 1
//chương trình phục vụ ngắt
}
Công việc 2
Void main (void) Name (void) interrupt X
{ Cờ ngắt Ix=1

//chương trình chính Chương trình phục vụ


} Công việc n +1 ngắt
Địa chỉ Số
Cờ
phục thứ Công việc n
Ngắt ngắt RETI
vụ ngắt tự
(I)
IA (X)
Reset - 0000h -
Ngắt ngoài 0 IE0 0003h 0 Đia chỉ phục vụ ngắt (Interrupt Address):
= (X * 8) + 3
Ngắt Timer 0 TF0 000Bh 1
X: là số thứ tự của ngắt ;
Ngắt ngoài 1 IE1 0013h 2
Ngắt Timer 1 TF1 001Bh 3
Ngắt truyền RI/TI 0023h 4 98
thông

49
4/12/2022

IE – Interrupt Enable Register


EA - ET2 ES ET1 EX1 ET0 EX0

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

 EA = 0 thì không có ngắt nào được đáp ứng cho dù bit


tương ứng của nó trongIE có giá trị cao. Bit D7 - EA của
thanh ghi IE phải được bật lên cao để cho phép các bit còn
lại của thanh ghi hoạt động được.
 EA = 1 thì tất cả mọi ngắt đều được phép và sẽ được đáp
ứng nếu các bit tương ứng của chúng trong IE có mức
cao.

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

Thanh ghi IP (Interrupt priority):


Là thanh ghi 8 bit, có thể truy xuất byte
7 6 5 4 3 2 1 0
-- -- -- PS PT1 PX1 PT0 PX0

Địa chỉ Thứ tự


Cờ
Ngắt Ưu tiên phục vụ Ngắt (chưa
ngắt
ngắt ưu tiên)

PS= 1 Ngắt truyền thông RI/TI 0023h 4


PT1=1 Ngắt Timer 1 TF1 001Bh 3
PX1=1 Ngắt ngoài 1 IE1 0013h 2
PT0=1 Ngắt Timer 0 TF0 000Bh 1
PX0=1 Ngắt ngoài 0 IE0 0003h 0

- 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

4.4.3 Lập trình các ngắt bộ định thời


TF0 Ngắt Timer 0 TF1 Ngắt Timer 1
1 000BH 1 001BH
Nhảy đến Nhảy đến

Bắt đầu

Công việc 1 Cờ ngắt TF1=1

Công việc 2
Name (void) interrupt 1 Name (void) interrupt 3
Cờ ngắt TF0=1

Chương trình phục vụ Chương trình phục vụ


Công việc n +1 ngắt ngắt

Công việc n RETI RETI


103

Các bước lập trình ngắt timer


 Bước 1: Chọn chế độ hoạt động của timer như ở phần lập
trình cho timer (TMOD)
 Bước 2: Cho phép ngắt:
 Cho phép ngắt do timer
ET0 = 1; // Nếu sử dụng ngắt timer 0
ET1 = 1; // Nếu sử dụng ngắt timer 1
 Cho phép ngắt toàn cục
EA = 1; // Bắt buộc phải có khi sử dụng bất cứ ngắt nào.
 Bước 3: Viết chương trình phục vụ ngắt Timer.
Chương trình phục vụ ngắt do timer được đặt ở các vector ngắt
Lưu ý: Không cần xóa cờ TFx.
void <name>(void) interrupt 1 void <name>(void) interrupt 3
{ //chương trình phụ vụ ngắt Timer 0 { //chương trình phụ vụ ngắt Timer 1
} }
• Bước 4: Xem xét chu kỳ ngắt tiếp theo.
104

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

#include<at89x51.h> //khai báo thu viện cho VÐK 89x51


main(){
TMOD=0x02; //chọn timer0, chế độ 2, 8Bit tự nạp lại
TL0=0xA4; //nạp giá trị cho TL0
TH0=0xA4; //nạp giá trị cho TH0
TR0=1; //khởi động timer0
IE=0x82; //cho phép ngắt timer0
while(1) { //vòng lặp vô hạn
P1=~P0; //Cập nhật giá trị cho cổng P1 từ P0.
}
}
void songvuong(void) interrupt 1{ //Khai báo trình phục vụ ngắt T0
TR0=0; //Ngừng timer0
P2_1=~P2_1; //Đảo trạng thái chân P2_1.
TR0=1; //Khởi động timer0
//Không cần xóa cờ TF0,
}

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.

Vì 1085us/1.085us=1000 nên ta cần sử dụng chế độ 1 của


bộ định thời Timer1.
Các giá trị cần nạp cho timer1 là:
1085/1.085=1000 , -1000 # FC18H
15/1.085 =14 , -14 # FFF2H

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

4.4.4. Lập trình ngắt ngoài


(Pin 14)
(Pin 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 Công việc 1
động vào chân chân P3.2(chân 12), Chân P3.3 Có ngắt
(chân 13): Công việc 2
Mức xung: chân P3.2(chân 12), Chân P3.3 (chân 13)
Công việc a
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 khi kết thúc vectơ
ngắt). Công việc n +1 Công việc b
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. Công việc n RETI
116

58
4/12/2022

4.4.4 Lập trình các ngắt phần cứng bên ngoài

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

Lập trình ngắt ngoài 8051


Pin 12/P3.2
Pin 13/P3.3
• Khai báo có ngắt ngoài
 Cho phép ngắt ngoài
EX0 = 1; // Nếu sử dụng ngắt ngoài 0
7 6 5 4 3 2 1 0
EX1 = 1; // Nếu sử dụng ngắt ngoài 1
Tcon TF1 TR1 TF0 TR0 IE1 IT1 IE0 IT0
 Cho phép ngắt toàn cục
EA = 1; // Bắt buộc phải có khi sử dụng bất cứ ngắt
nào.
• Khai báo mức ngắt
• Mức xung (mặc định): 7 6 5 4 3 2 1 0

ITx=0 IE EA - - ES ET1 EX1 ET0 EX0

• 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.

Pin 12/P3.2 Pin 13/P3.3


CT1 CT2

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

#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
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
}
121

#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
IT1=1; //Thiết lập ngắt ngoài 1 theo sườn âm
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
}

122

61
4/12/2022

 Chương 1: so sánh VXL, VĐK


 Chương 2: 89c51
 Chân nguồn?; Mass?
 Reset: vị trí, chức năng, mức tác động, reset 2mmanual auto
 Chân 29, 30, 31 : chức năng-> khi sử dụng chương trình trong rom nội/ngoại
 Chân 18, 19 giao động, thạch anh xxMH->MC ?
 Bộ nhớ (ram) bộ nhớ, thanh ghi-> Rn, A, B, Px, SP, PC, DPTR: chức năng, đọ lớn (8
bit/16bit), khi có hoạt động reset
 Chương 3 :
 Phân biệt các chế độ địa chỉ
 Chú ý không cho phép trong mỗi chế độ địa chỉ, độ lướn toán hạng đích, nguồn…
 Ý nghĩa câu lệnh setb, clr, jb, jnb, cjne, djnz, inc, dec, jmp, nop, call…
 Chỉ ra các câu lênh sai, lý do sai.
 Ứng dụng
 Chương 4:
 Thời gian thực hiện
 Vòng lặp: tính số lần lặp, thời gian duy trì…
 Ứng dụng
 Chương 5:
 Ngôn ngữ C vòng lặp, điều kiện
 Timer/ Counter-> hoạt đọng từng Timer x mode y->T0/T1 Mode 0; T0/T1 Mode 1;
T0/T1 Mode 2: bước lập trình, cài đặt chế độ (TMOD); cài đặt giá trị tràn (THx, TLx)
 Ngắt:ngắt Timer0/1; ngoài 0/1 bước lập trình, vecto ngắt
 Ứng dụng
123

62

You might also like