Professional Documents
Culture Documents
Gui c5 - Timer
Gui c5 - Timer
BỘ ĐỊNH THỜI
Kiểm tra chương ngắt
1. Nêu tên các thanh ghi liên quan đến ngắt, chức
năng các bit trong thanh ghi INTCON?
2. Nêu các chân ngắt ngoài và các chân ngắt PORTB
của PIC16F887, có gì khác với PIC 16F877A?
3. Vẽ sơ đồ mạch nguyên lý, vẽ lưu đồ giải thuật và
viết chương trình điều khiển 8 LED nối với PORTD
theo yêu cầu: Khi có ngắt ngoài PORTD = 0xF0;
Biết ban đầu 8 LED tắt; Fosc = 4MHz
Nội dung chương 5
1. Timer
2. Đặc điểm, Sơ đồ khối của Timer 0
3. Các bước để định thời gian Timer 0
4. Các bước để đếm sự kiện Counter 0
5. Bài tập Timer 0
6. Đặc điểm, Sơ đồ khối của Timer 1
7. Các bước để định thời gian Timer 1
8. Các bước để đếm sự kiện Counter 1
9. Bài tập Timer 1
10. Đặc điểm, Sơ đồ khối của Timer 2
11. Các bước để định thời gian Timer 2
12. Bài tập Timer 2
Timers
Timer được sử dụng cho nhiều chức
năng:
Định thì để tạo sự kiện
Đếm sự kiện
Tạo dạng sóng v..v
PIC16F877 có 3 timers
– Timer0
– Timer1
– Timer2
So sánh các Timer
TIMER0 TIMER1 TIMER2
Kích thước 8-bits (TMR0) 16-bits 8-bits (TMR2)
thanh ghi (TMR1H:TMR1L)
Nguồn CLOCK Fosc/4 Fosc/4 Fosc/4
(bên trong)
Nguồn CLOCK T0CKI pin T1CKI pin or None
(bên ngoài) Timer 1 oscillator
(T1OSC)
CLOCK SCALING Prescaler 8-bits Prescaler 3-bits Prescaler
AVAILABLE (1:21:256) (÷1,÷2,÷4,÷8) (1:1,1:4,1:8)
(Resolution) Postscaler
(1:11:16)
Sự kiện ngắt và On overflow On overflow TMR2 matches
cờ ngắt FFh00h FFFFh0000h PR2
(TMR0IF in INTCON) (TMR1IF in PIR1) (TMR2IF in PIR2)
Đánh thức PIC từ NO YES NO
SLEEP
Đặc điểm của Timer 0
Là Timer/Counter 8 bit
Có thể đọc và ghi
Có bộ chia trước 8 bit có thể lập trình bằng
phần mềm
Có thể lựa chọn nguồn xung clock bên
trong hoặc bên ngoài
Cho phép lựa chọn tác động cạnh cho xung
clock bên ngoài
Xảy ra hiện tượng ngắt khi tràn từ
FFh00h
Sơ đồ khối Timer 0
DATA BUS
Fosc/4 8
synchronize
T0CKI
pin
scaled clock TMR0
TMR0
prescaler PS2 PS1 PS0 RATE
Watchdog Timer
WDT out
0 0 0 1:2
0 1 0 1:8
RBPU INTEDG TOCS TOSE PSA PS2 PS1 PS0
0 1 1 1:16
1 0 1 1:64
Prescaler Assignment
TMR0 Clock 1= prescaler assigned to WDT 1 1 0 1:128
Source Select 0= prescaler assigned to Timer 0
1 = TOCK1, 0 = Fosc/4 1 1 1 1:256
Source Edge Select
1 = increment TMR0 on high-to-low transition
0 = increment TMR0 on low-to-high transition
Sơ đồ khối Timer 0
DATA BUS
Fosc/4 8
synchronize
T0CKI
pin
scaled clock TMR0
prescaler
Watchdog Timer INTCON register
TMR0IF
•Cờ ngắt Timer 0 sẽ được set khi có hiện tượng tràn TMR0
(FF00)
Hoạt động
Các bước để định thời gian Timer 0
B1: Tính toán các giá trị cần đưa vào code:
Xác định được:
tdelay: thời gian cần định thời (us) TMR0 =
fOSC: tần số dao động thạch anh TMR0IF =
Pre:hệ số chia tần trước prescaler(Pre=1,2,4...,256
PSA =
PS2 =
[TMR0]: giá trị cần ghi vào thanh ghi TMR0
PS1 =
PS0 =
B2: Ghi vào TMR0 giá trị đã tính toán
T0SE =
B3: Xóa cờ báo tràn( cờ ngắt) TMR0IF T0CS =
B4: Chọn chế độ hoạt động của Timer 0
Nếu dùng ngắt:
• (chọn chế độ Timer, gán prescaler..)
GIE =
B5: Xác định thời điểm Timer 0 tràn bằng cách:
TMR0IE =
• Kiểm tra cờ TMR0IF( nếu dùng thăm dò)
• Xử lý ISR của Timer 0 (nếu dùng ngắt)
Ví dụ
Fosc=4MHz Tcy = 1us
TD = dem* Tdelay = dem * [256-TMR0] *4*(1/fosc)* PresT0
= dem* [256-TMR0] *4*(Tosc)* PresT0
= dem* [256-TMR0] *Tcy* PresT0
Tdelay min = 1 *Tcy* 2 = 2us
max = 256 *Tcy* 256= 65,536ms
B4: Đọc giá trị về và xử lý xung đếm trong thanh ghi TMR0.
Lưu ý:
Ví dụ mô phỏng
Lập trình khởi tạo cho timer0 để tạo thời gian trễ
t=[256-0] *1us*16=4096us=4,1ms=0.0041s
fosc= 4MHz
Xác định:
Giá trị ban đầu TMR0=0;
Hệ số chia trước 1:16 (ps2=0; ps1=1; ps0=1)
Khởi tạo giá trị cho Timer0 (hitech-C)
Timer0
;Xóa giá trị đếm cho Timer0
TMR0 incrementing
;Xóa TMR0
0
1 0
1 0
1 0
1 0
1 0 0 0
1 1 1
TMR0=0x00;
INTCON
;Xóa cờ ngắt Timer0 TMR0IF
TMR0IF=0; 0
1
;Thiết lập thanh ghi OPTION_REG ; Flag on overflow TMR0IF
;với xung clock bên trong với bộ
;chia tần 1:16 This interrupt flag will set on
BANKSEL OPTION_REG Timer0 overflow even if
MOVLW b’00000011’ interrupts are disabled
OPTION_REG=0x03 OPTION_REG
;Kiểm tra cờ tràn TMR0IF nếu tràn 0 0 0 0 0 0 1 1
;thì tiếp tục
TOCS PSA
PS<2:0>
while(!TMR0IF) {}
Selects Timer 0 Prescaler
Prescaler
Clock Source Assignment
<continue> (WDT or TMR0)
value = 1:16
(External or Internal)
Ví dụ 1:
Dựa vào sơ đồ viết lưu đồ giải thuật và viết chương
trình tạo sóng xung vuông có tần số 500Hz tại chân
RE1 và 2Hz tại chân RE2 dùng Timer 0 để định thời.
Ta có: Td1 = 1/500Hz = 2ms tdelayT0 = 1ms
Td2 = 1/2Hz = 500ms = 250 Td1
Sơ đồ giải
thuật: Begin
Đặt chế độ Timer0
Pre=4
Cấu hình các Timer0
PORT digital
PORTE=0 RE1=!RE1
LOOP1
COUNT=250 COUNT- -
LOOP2
TMR0=6 COUNT
=0?
TMRIF=0
RE2=!RE2
Code C: void main()
{
#include <xc.h> ANSEL=0x00;
#define _XTAL_FREQ 4000000 TRISE = 0b001; // E1& E2 la out
PORTE = 0;
unsigned char count; loop:
count=250;
while(count--)
{
TMR0=6;
T0CS=0;
TMR0IF=0;
PSA=0;
PS2=0;
PS1=0;
PS0=1;
while(!TMR0IF){}
RE1=!RE1;
}
RE2=!RE2;
goto loop;
}
Ví dụ 2: Dựa vào sơ đồ viết lưu đồ giải thuật và viết
chương trình điều khiển đếm số lần nhấn nút SW0
được nối với ngõ vào của counter 0 (T0CKI) và hiển
thị giá trị này trên 8 led đơn dùng counter 0.
Sơ đồ giải thuật:
Begin
Đặt chế độ Timer0:
Cấu hình các Mode: Counter
PORT digital Prescaler:1:2
PrescalerWDT
Cấu hình các PORT C:
output
Đọc giá trị từ bộ
đếm & xuất giá trị
Cấu hình chân nối lên LED
RA4: input
SV tự viết
Bài tập Timer0
Fosc/4
T1CKI
TMR1H TMR1L
pin
Enable
Fosc/4
Đối với nguồn xung clock bên ngoài lấy từ bộ dao động Timer1
(thạch anh gắn trên 2 chân T1OS1 và T1OS0)
Trong đó:
tdelay: thời gian cần định thời (us)
fOSC: tần số dao động thạch anh
fOSC(T1): tần số dao động Timer1
Pre:hệ số chia tần trước prescaler(Pre=1,2,4,8)
[TMR1]: giá trị cần ghi vào thanh ghi TMR1
B2: Ghi vào thanh ghi TMR1( gồm TMR1H:TMR1L) được xác định ở
trên
B3: Xóa cờ báo tràn (cờ ngắt) TMR1IF
B4: Chọn chế độ hoạt động của Timer1
• Chế độ định thời gian (Timer)
• Kích hoạt hoặc vô hiệu hóa các ngắt
• Chọn giá trị prescale
B5: Cho phép Timer1 bắt đầu hoạt động
B6: Xác định thời điểm Timer1 bị tràn bằng cách:
• Kiểm tra cờ TMR1IF( nếu dùng thăm dò)
• Xử lý ISR của Timer 1 (nếu dùng ngắt)
Các bước để đếm sự kiện Counter 1
TMR1IF=0; PIR1
1
0
;Cho phép ngắt Timer1
TMR1IF
TMR1IE=1; PIE1
1
;Cho phép ngắt toàn cục và ngắt ngoại vi TMR1IE
PEIE=1;
GIE=1; INTCON
1 1
GIE PEIE
Khởi tạo Timer1 (C)
TMR1H
;Xóa thanh ghi TMR1 0 0 0 0 0 0 0 0
TMR1H=0x00;
TMR1L
TMR1L=0x00 0 0OVERFLOW!!
0 0 INCREMENTING
TMR1H:TMR1L 0 0 0 0
T1CON=b’00000001’
TMR1IF N
=1?
Y
Code Hitech: while(!TMR1IF){}
#include<pic.h> RE1=RE1^1;
unsigned char count; }
void main (void) RE2=!RE2;
{
ADCON1=0x06; }
TRISE=0b001;
PORTE=0; }
while(1)
{
count=5;
while(count--)
{
TMR1IF = 0;
TMR1H =0X3C;
TMR1L = 0XB0;
T1CKPS0 = 0;
T1CKPS1 = 0;
TMR1CS = 0;
TMR1ON = 1;
Dùng ngắt: Code void main (void)
Hitech C:
{
#include<pic.h> ADCON1=0x06;
unsigned char count = 0x00; TRISE=0b001;
void interrupt Timer1_ISR(void) PORTE=0;
{
TMR1IF = 0; TMR1ON = 0;
TMR1L = 0XB0; TMR1H = 0X3C;
TMR1H = 0X3C; TMR1L = 0XB0;
RE1 = RE1 ^ 1;
count++; T1CKPS0 = 0;
if (count == 5) T1CKPS1 = 0;
{ TMR1CS = 0;
RE2 = RE2 ^ 1;
count = 0; TMR1IE = 1;
} TMR1IF = 0;
} PEIE = 1;
GIE = 1;
TMR1ON = 1;
while(1);
}
Ví dụ 4: Dựa vào sơ đồ viết chương trình điều
khiển tạo sóng xung vuông có chu kỳ 2s tại chân
RE1.
Sơ đồ giải thuật Begin
dùng “thăm dò” :
T1CON=b’00001111’
TMR1IF N
=1?
Y
RE1=!RE1
Code Hitech C:
#include<pic.h> while(!TMR1IF){}
#define _XTAL_FREQ 4000000 PORTE ^= 2;
void main() }
{ }
ADCON1=0x06;
TRISE=0b000;
PORTE=0;
while(1)
{
TMR1IF=0;
TMR1H=0x80;
TMR1L=0x00;
TMR1CS=1;
T1OSCEN=1;
T1SYNC=1;
T1CKPS0=0;
T1CKPS1=0;
TMR1ON=1;
Dùng ngắt: Code Hitech C:
void main()
#include<htc.h> {
….. ADCON1=0x06;
#define _XTAL_FREQ 4000000 TRISE=0b000;
PORTE=0;
void interrupt isr(void)
{ TMR1H=0x80;
if(TMR1IF && TMR1IE) TMR1L=0x00;
{
TMR1IF = 0; TMR1IF=0;
TMR1L = 0; TMR1CS=1;
TMR1H = 0x80; T1OSCEN=1;
PORTE ^= 2; T1SYNC=1;
} T1CKPS0=0;
} T1CKPS1=0;
TMR1ON=1;
TMR1IE=1;
PEIE=1;
GIE=1;
while(1);
}
Bài tập Timer1
TMR2
OUTPUT
TMR2
Prescaler
Fosc/4
1:1, 1:4, 1:16
Postscaler
COMPARATOR 1:1 1:16
PR2
Postscaler
COMPARATOR 1:1 1:16
PR2
Load Period PIR1
Register 1 1 1 1 1 0 0 0
1
TMR2IF
Timer2 Control Register (T2CON)
TOUTPS3 TOUTPS2 TOUTPS1 TOUTPS0 TMR2ON T2CKPS1 T2CKPS0
Flag set on first
match with
postscaler = 1:1
Khi sử dụng Timer2 cần chú ý:
Khi mới cấp nguồn thì PR2=0xFF
Prescaler và Postscaler sẽ bị xóa khi:
• Ghi dữ liệu vào TMR2
• Ghi dữ liệu vào T2CON
• Bất cứ sự kiện reset nào((WDT,POR,BOR)
Khi reset vi điều khiển thì Prescaler và Postscaler sẽ
bị xóa
TMR2 bị xóa khi ghi giá trị vào T2CON
TMR2 sẽ tăng giá trị từ 00h đến khi bằng PR2 sau đó
TMR2 sẽ được reset về 0 vào chu kỳ tăng kế tiếp
Sự kiện ngắt khi TMR2=PR2 không thể làm “đánh
thức” vi điều khiển khỏi chế độ “ngủ“.
Timer 2 ít dùng để định thời gian. Nó thường dùng cho
CCP để tạo xung PWM
Các bước để định thời gian Timer 2
B1: Tính toán các giá trị cần đưa vào code:
Đối với dao động nội:
Trong đó:
tdelay: thời gian cần định thời (us)
fOSC: tần số dao động thạch anh(Mhz)
Pre: hệ số chia tần trước Prescaler(Pre=1,4,16)
Post: hệ số chia tần sau Postscaler(Post=1,2,...,16)
RETFIE
Dùng ngắt: Code Hitech C:
#include<pic.h> void main (void)
#define _XTAL_FREQ 4000000 {
unsigned char count = 0x00; ADCON1=0x06;
TRISE=0b001;
void interrupt Timer2_ISR(void) PORTE=0;
{
TMR2IF = 0; PR2=249;
TMR2IF=0;
RE1 = RE1 ^ 1; TOUTPS3=0;
count++; TOUTPS2=1;
if (count == 10) TOUTPS1=0;
{ TOUTPS0=0;
RE2 = RE2 ^ 1; T2CKPS1=0;
count = 0; T2CKPS0=1;
}
} TMR2ON = 1;
TMR2IE=1;
PEIE=1;
GIE=1;
while(1);
}
Bài tập Timer2
Bài 2: Viết chương trình tạo xung 10Hz trên chân RB7
Bài 3: Viết chương trình tạo xung có tần số 20Hz trên chân
RB0, chu kỳ nhiệm vụ D=40%.
Bài 4: Viết chương trình đếm sự kiện tại chân T0CKI kết
quả được hiển thị số đếm trên 8 led nối với PORT B biết
xung clock tác động từ mức cao xuống thấp.