Lập trình bộ định thời
(TIMER)
Giới thiệu bộ định thời
1. Các thanh ghi của bộ định thời
- Timer 0: TH0, TL0
- Timer 1: TH1, TL1
- Các thanh ghi trạng thái và cài đặt
chế độ hoạt động cho các bộ định thời:
+ TCON: Điều khiển
+ TMOD: Chọn chế độ
Vị trí của các bộ định thời trong
sơ đồ khối của chip 89X51/52
Các bộ định thời
VỊ TRÍ CÁC THANH GHI CỦA BỘ ĐỊNH THỜI
TRONG VÙNG NHỚ ĐẶC BIỆT- SFR
Thanh ghi TMOD: Timer Mode
Chọn chế độ hoạt động
TMOD
D7 D6
D5
GATE
M1
C/T
Chọn chế độ hoạt động
cho TIMER1
D4
D3
D2
GATE
M0
D1
D0
M1
C/T
M0
Chọn chế độ hoạt động
cho TIMER0
Bit M0, M1 – của thanh ghi TMOD
TMOD
GATE C/T M1
M0
M1
M0
Chế độ
0
0
1
1
0
1
0
1
0
1
2
3
GATE C/T M1
M0
Mô tả
Chế độ định thời 13 bit
Chế độ định thời 16 bit
Chế độ tự động nạp lại 8-bit
Chế độ định thời chia xẻ
Thanh ghi TCON – Timer/Counter
Control Register
TCON
D7
D6
TF1
D5
TF0
TR1
Cờ ngắt
của
Timer1
D4
D3
IE1
TR0
Cờ ngắt
của
Timer0
D2
D1
IE0
IT1
Cờ ngắt
ngoài 1
D0
IT0
Cờ ngắt
ngoài 0
Chế độ hoạt động của Timer
- Chế độ 0: Chế độ định thời 13 bit
- Chế độ 1: Chế độ định thời 16 bit
- THx, TLx chứa giá trị đếm hiện tại của bộ định thời
- Chế độ 2: Chế độ tự nạp lại 8-bit
- Byte thấp giữ giá trị đếm hiện tại
- Byte cao giữ giá trị nạp lại
- Chế độ 3: Chế độ định thời chia xẻ
Lập trình cho bộ định thời Timer 0
• Ví dụ 1: lập trình cho bộ định thời 0 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 0
TMOD = 00000001B (0x01)
– 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 khi nạp vào TH0, TL0 giá trị bằng 65536
– 500 = 65036 tương đương 0FE0Ch
TH0 = 0xFE; //
MOV TH0, #0FEh
TL0 = 0X0C; //
MOV TL0, #0Ch
- Bước 3: Khởi động bộ định thời T0
TF0 = 0; // (CLR TF0) Xóa cờ tràn
TR0 = 1; // (SETB TR0) Khởi động bộ định thời
- Bước 4: Chờ bộ định thời tràn
while(!TF0) continue; // JNB TF0, $
- Bước 5: Nếu tiếp tục muốn sử dụng bộ định thời: Dừng bộ định
thời (TR0 = 0), nạp lại giá trị cho TH0, TL0, khởi động lại (TR0 = 1).
TMOD
GATE
C/T
M1
M0
GATE
C/T
M1
M0
Chương trình hồn chỉnh ví dụ 1
C
TMOD = 00000001B
TH0 = 0xFE;
TL0 = 0x0C;
TF0 = 0; // Xóa cờ tràn
// Khởi động bộ định thời
TR0 = 1;
// Chờ cờ tràn bật 1
while(!TF0) continue;
// Dừng bộ định thời
TR0 = 0;
// Nạp lại giá trị
TH0 = 0xFE;
TL0 = 0x0C;
...
// Khởi động bộ định thời
TR0 = 1;
ASM
MOV
TMOD, #00000001B
MOV
TH0, #0FEh
MOV
TL0, #0Ch
CLR
TF0; Xóa cờ tràn
;Khởi động bộ định thời
SETB
TR1
; Chờ cờ tràn bật 1
JNB TF0, $
; Dừng bộ định thời
CLR
TR0
; Nạp lại giá trị
MOV
TH0, #0FEh;
MOV
TL0, #0Ch;
...
// Khởi động bộ định thời
SETB
TR0
Lập trình cho bộ định thời Timer 0 – (tip)
• Ví dụ 2: lập trình cho bộ định thời 0 hoạt động ở chế độ 2, 8-bit tự
nạp lại, có thời gian tràn là 200us (sử dụng thạch 12Mhz).
– Bước 1: Chọn chế độ hoạt động cho Timer 0
TMOD = 00000010B (0x02)
– Bước 2: Nạp giá trị tràn cho các thanh ghi TH0, TL0
Ở chế độ 2, thanh ghi TH0 sẽ giữ giá trị nạp lại, vậy
TH0 = 255 - 200;
//
MOV TH0, #55
TL0 = 255 - 200;
//
MOV TL0, #55
- Bước 3: Khởi động bộ định thời T0
+ TF0 = 0; // (CLR TF0) Xóa cờ tràn
+ TR0 = 1; // (SETB TR0) Khởi động bộ định thời
- Bước 4: Chờ bộ định thời tràn
- while(!TF0) continue; // JNB TF0, $
- Bước 5: Xóa cờ tràn (TF0 = 0), tiếp tục đợi cờ tràn bật 1 do thanh
ghi TL0 tự động được nạp lại.
Chương trình hồn chỉnh ví dụ 2
C
TMOD = 0x02;
TH0 = 55;
TL0 = 55;
TF0 = 0; // Xóa cờ tràn
// Khởi động bộ định thời
TR0 = 1;
// Chờ cờ tràn bật 1
while(!TF0) continue;
// Dừng bộ định thời
TR0 = 0;
...
// Khởi động bộ định thời
TR0 = 1;
ASM
MOV
TMOD, #00000010B
MOV
TH0, #55
MOV
TL0, #55
CLR
TF0; Xóa cờ tràn
;Khởi động bộ định thời
SETB
TR1
; Chờ cờ tràn bật 1
JNB TF0, $
; Dừng bộ định thời
CLR
TR0
...
// Khởi động bộ định thời
SETB
TR0
Tạo trễ sử dụng Timer
MAIN:
MOV
MOV
MOV
AGAIN:
CPL
CALL
JMP
TMOD, #00000010B
TH0, #55
TL0, #55
P1.0
DELAY
AGAIN
DELAY:
CLR
TF0; Xóa cờ tràn
;Khởi động bộ định thời
SETB
TR1
; Chờ cờ tràn bật 1
JNB
TF0, $
; Dừng bộ định thời
CLR
TR0
RET
void main() {
TMOD = 0x02;
while(1) {
P1_0 = !P1_0;
delay(55);
}
void delay(unsigned char us){
TH0 = us;
TL0 = us;
TF0 = 0 ; Xóa cờ tràn
;Khởi động bộ định thời
TR1 = 1;
; Chờ cờ tràn bật 1
while(!TF0) continue;
; Dừng bộ định thời
TR0 = 0;
}
NGẮT
• Giới thiệu ngắt
• Các loại ngắt và bảng vector ngắt:
•
•
•
•
•
•
•
Reset hệ thống
Ngắt ngồi 0
Timer 0
Ngắt ngồi 1
Timer 1
Cổng nối tiếp
Timer 2
RST Địa chỉ vector ngắt
IE0
TF0
IE1
TF1
RI hoặc TI
TF2 hoặc EXF2
• Các thanh ghi cấu hình ngắt
• Lập trình ngắt
0000H
0003H
000BH
0013H
001BH
0023H
002BH
Xử lý của CPU đối với 1 ngắt
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:
- Hoàn tất việc thực thi lệnh hiện hành
- Cất bộ đếm chương trình (PC) vào stack
- Trạng thái của ngắt hiện hành được lưu giữ lại
- Bộ đếm chương trình PC sẽ nạp địa chỉ của chương trình con
phục vụ ngắt và đi thực hiện.
- Thực hiện xong sẽ quay về chương trình chính tại vị trí nó bị
ngắt và thực hiện tiếp chương trình chính.
Thanh ghi cho phép ngắt IE
(Interrupt Enable Register)
IE
D7
D6
D5
EA
D4
ET2
ES
Cho phép
ngắt do
Timer 2
Khơng sử
dụng
D2
ET1
Cho phép
ngắt tồn
cục
D3
D1
ET0
EX1
Cho phép
ngắt do
Timer 1
Cho phép
ngắt do port
nối tiếp
D0
EX0
Cho phép
ngắt do
Timer 0
Cho phép
ngắt
ngoài 1
Cho phép
ngắt
ngoài 0
Thanh ghi ưu tiên ngắt IP
(Interrupt Priority Register)
IP
D7
D6
D5
D4
D3
PT2
Không sử
dụng
D2
PT1
Không sử
dụng
PS
Ưu tiên
ngắt cho
Timer 2
D1
PT0
PX1
Ưu tiên
ngắt cho
Timer 1
Ưu tiên ngắt
do port nối
tiếp
D0
PX0
Ưu tiên
ngắt cho
Timer 0
Ưu tiên
ngắt
ngoài 1
Ưu tiên
ngắt
ngoài 0
LẬP TRÌNH NGẮT
1. Lập trình với ngắt timer
– Timer 0
– Timer 1
2. Lập trình với ngắt ngồi
– Ngắt ngồi 0
– Ngắt ngoài 1
– Ngắt ngoài theo sườn xuống và theo mức 0
3. Ưu tiên ngắt
– Thứ tự ưu tiên thực hiện các ngắt
– Lập trình theo đổi ưu tiên các ngắt
1. Lập trình ngắt timer
IE – Interrupt Enable Register
EA
-
ET2
ES
ET1
EX1
ET0
EX0
• Bước 1: Chọn chế độ hoạt động của timer như ở phần lập
trình cho timer
• 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 ngt toàn cc
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
000Bh (Timer 0)
001Bh (Timer 1).
Các chương trình con phục vụ ngắt cũng giống như các chương trình con khác,
tuy nhiên nó được kết thúc bằng lệnh RETI (Return from Interrupt) thay vì lệnh
RET.
Ví dụ 1: Viết chương trình nháy LED nối ở chân P1.0 với chu kỳ 500us
sử dụng ngắt timer 0. Sử dụng thạch anh 12Mhz.
ASM
C
ORG 0000H
LJMP MAIN
ORG 001BH
LJMP T0_ISR
ORG 0030H
MAIN:
MOV TMOD, #00000010B; Chế độ 2
MOV TH0, #55
MOV TL0, #55
CLR TF0; Xóa cờ tràn
SETB ET0
SETB EA
SETB TR0; Khởi động Timer 0
JMP $
T0_ISR:
CPL P1.0
RETI
void main() {
TMOD = 0x02; // Timer 0 ở chế độ 2
TH0 = 5;
TL0 = 5; // Nạp giá trị cho TH0,
TF0 = 0;
// Xóa cờ tràn
ET0 = 1;
EA =1;
TR0 = 1;
// Khởi động Timer 0
while(1) continue;
}
void T0_ISR() interrupt 1 {
P1_0 = !P1_0;
}