Professional Documents
Culture Documents
BỘ ĐỊNH THỜI
Kiểm tra chuong ngắt
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)
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:
B2: Ghi vào thanh ghi TMR0 giá trị đã tính toán
B3: Xóa cờ báo tràn( cờ ngắt) TMR0IF
B4: Chọn chế độ hoạt động của Timer 0 (chọn chế độ Timer, gán
prescaler..)
B5: Xác định thời điểm Timer 0 bị tràn bằng cách:
• 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)
Fosc=4MHz Tcy = 1us
TD = dem* Tdelay = [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=41ms=0.041s
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-ASM
Timer0
;Xóa giá trị đếm cho Timer0
TMR0 incrementing
;Xóa TMR0
BANKSEL TMR0 0
1 0
1 0
1 0
1 0
1 0 0 0
1 1 1
CLRF TMR0
INTCON
;Xóa cờ ngắt Timer0 TMR0IF
BCF INTCON,TMR0IF 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
MOVWF OPTION_REG 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
BTFSS INTCON,TMR0IF
PS<2:0>
GOTO $-1
Selects Timer 0 Prescaler
Prescaler
Clock Source Assignment
<continue> value = 1:16
(External or Internal) (WDT or TMR0)
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> value = 1:16
(External or Internal) (WDT or TMR0)
Ví dụ 1: Dựa vào sơ đồ 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.
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:
processor 16f877a LOOP2
#include <p16f877a.inc> BANKSEL TMR0
MOVLW .6
COUNT EQU 0x30 MOVWF TMR0
ORG 0x0000 BCF INTCON,TMR0IF
GOTO start
start BANKSEL OPTION_REG
BANKSEL ADCON1 MOVLW b'00000001';1:4
MOVLW .6 MOVWF OPTION_REG
MOVWF ADCON1
BTFSS INTCON,TMR0IF
BANKSEL TRISE GOTO $-1
CLRF TRISE BANKSEL PORTE
MOVLW B'010'
BANKSEL PORTE XORWF PORTE,1
CLRF PORTE DECFSZ COUNT,1
LOOP1 GOTO LOOP2
BANKSEL COUNT MOVLW B'100'
MOVLW .250 XORWF PORTE,1
MOVWF COUNT GOTO LOOP1
END
Code Hitech
C:
#include<htc.h>
PSA=0;
#define _XTAL_FREQ 4000000
PS2=0;
unsigned char count;
PS1=0;
void main()
PS0=1;
{
while(!TMR0IF){}
ADCON1=0x06;
RE1=!RE1;
TRISE = 0b001; // E1& E2 la out
}
//TRISE1=0; & TRISE2=0
RE2=!RE2;
PORTE = 0;
goto loop;
loop:
}
count=250;
while(count--)
{
TMR0=6;
T0CS=0;
TMR0IF=0;
Ví dụ 2: Dựa vào sơ đồ 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
processor 16f877a
CLRWDT
#include <p16f877a.inc>
BANKSEL OPTION_REG
BSF OPTION_REG,T0CS
COUNT EQU 0x30
BSF OPTION_REG,T0SE
ORG 0x0000
BSF OPTION_REG,PSA
GOTO start
CLRWDT
start
MOVLW B'11111000'
BANKSEL ADCON1
ANDWF OPTION_REG,W
MOVLW .6
IORLW B'00000000'
MOVWF ADCON1
MOVWF OPTION_REG
BANKSEL 0
BANKSEL TRISC
loop
CLRF TRISC
MOVF TMR0,w
BSF TRISA,TRISA4
MOVWF PORTC
GOTO loop
END
BANKSEL TMR0
MOVLW .0
MOVWF TMR0
BCF INTCON,TMR0IF
Code Hitech-C
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 (Hitech-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 MOVLW LOW .15536
assembly: MOVWF TMR1L
processor 16f877a
#include <p16f877a.inc>
BANKSEL PIR1
COUNT EQU 0x30 BCF PIR1,TMR1IF
ORG 0x0000
GOTO start BSF T1CON,T1CKPS0
start BCF T1CON,T1CKPS1
BANKSEL ADCON1 BCF T1CON,TMR1CS
MOVLW .6 BSF T1CON,TMR1ON
MOVWF ADCON1
BTFSS PIR1,TMR1IF
BANKSEL TRISE GOTO $-1
CLRF TRISE MOVLW B'010'
LOOP XORWF PORTE,1
BANKSEL COUNT BANKSEL COUNT
MOVLW .5 DECFSZ COUNT,1
MOVWF COUNT GOTO LOOP1
LOOP1 MOVLW B'100'
MOVLW HIGH .15536 XORWF PORTE,1
MOVWF TMR1H GOTO LOOP
END
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 MOVWF TMR1H
assembly:
MOVLW LOW .15536
processor 16f877a MOVWF TMR1L
#include <p16f877a.inc>
BSF T1CON,T1CKPS0
COUNT EQU 0x30 BCF T1CON,T1CKPS1
ORG 0x0000 BCF T1CON,TMR1CS
GOTO start BSF T1CON,TMR1ON
ORG 0x0004
GOTO ISR_T1 BANKSEL PIE1
start BSF PIE1,TMR1IE
BANKSEL ADCON1 BSF INTCON,PEIE
MOVLW .6 BSF INTCON,GIE
MOVWF ADCON1 GOTO $
BANKSEL TRISE
CLRF TRISE
BANKSEL COUNT
MOVLW .5
MOVWF COUNT
MOVLW HIGH .15536
Dùng ngắt: Code
assembly:
ISR_T1
BANKSEL PIR1
BCF PIR1,TMR1IF
MOVLW HIGH .15536
MOVWF TMR1H
MOVLW LOW .15536
MOVWF TMR1L
MOVLW B'010'
XORWF PORTE,1
BANKSEL COUNT
DECFSZ COUNT,1
GOTO EXIT_ISR
MOVLW B'100'
XORWF PORTE,1
MOVLW .5
MOVWF COUNT
EXIT_ISR
RETFIE
END
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
assembly:
processor 16f877a BSF T1CON,TMR1CS
#include <p16f877a.inc> BSF T1CON,T1OSCEN
BSF T1CON,T1SYNC
ORG 0x0000 BCF T1CON,T1CKPS0
GOTO start BCF T1CON,T1CKPS1
start BSF T1CON,TMR1ON
BANKSEL ADCON1
MOVLW .6 BTFSS PIR1,TMR1IF
MOVWF ADCON1 GOTO $-1
BANKSEL TRISE MOVLW B'010'
CLRF TRISE XORWF PORTE,1
BANKSEL PORTE GOTO LOOP
CLRF PORTE END
LOOP
BCF PIR1,TMR1IF
MOVLW 0x80
MOVWF TMR1H
CLRF TMR1L
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 assembly: BCF T1CON,T1CKPS0
processor 16f877a BCF T1CON,T1CKPS1
#include <p16f877a.inc> BSF T1CON,TMR1CS
BSF T1CON,T1SYNC
COUNT EQU 0x30 BSF T1CON,T1OSCEN
ORG 0x0000 BSF T1CON,TMR1ON
GOTO start
ORG 0x0004 BANKSEL PIE1
GOTO ISR_T1 BSF PIE1,TMR1IE
BSF INTCON,PEIE
start
BSF INTCON,GIE
BANKSEL ADCON1
GOTO $
MOVLW .6
ISR_T1
MOVWF ADCON1 BANKSEL PIR1
BCF PIR1,TMR1IF
BANKSEL TRISE
CLRF TRISE MOVLW 0x80
MOVWF TMR1H
BANKSEL TMR1H CLRF TMR1L
MOVLW 0x80 MOVLW B'010'
MOVWF TMR1H XORWF PORTE,1
CLRF TMR1L RETFIE
BCF PIR1,TMR1IF END
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
Postscaler
COMPARATOR 1:1 1:16
PR2
Timer2 ON
1 = Timer2 enabled
TOUTPS3
Sơ đồ khối củaTimer2
TOUTPS2 TOUTPS1 TOUTPS0 SCALE
0 0 0 0 1:1
0 0 0 1 1:2
0 0 1 0 1:3 TMR2
0 0 1 1 1:4 OUTPUT
0 1 0 0
TMR21:5
0 Prescaler
1 0 1 1:6
01:1, 1:4,
1 1:16 1 0 1:7
Fosc/4 0 1 1 1 1:8
1 0 0 0 1:9
Postscaler
1
1
0
0
0
1
1
0
COMPARATOR
1:10
1 1 1 1 1:16
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 assembly: BANKSEL COUNT ;0
processor 16f877a MOVLW .10
#include <p16f877a.inc> MOVWF COUNT
CLRF PORTE
COUNT EQU 0x30
ORG 0x0000 BCF PIR1,TMR2IF
GOTO start MOVLW B'01110111'
ORG 0x0004 MOVWF T2CON
GOTO ISR_T2
start BANKSEL PIE1
BANKSEL ADCON1;1 BSF PIE1,TMR2IE
MOVLW .6 BSF INTCON,PEIE
MOVWF ADCON1 BSF INTCON,GIE
GOTO $
CLRF TRISE
MOVLW .249
MOVWF PR2
Dùng ngắt: Code assembly:
ISR_T2
BANKSEL PIR1
BCF PIR1,TMR2IF
MOVLW B'010'
XORWF PORTE,1
DECFSZ COUNT,1
GOTO EXIT_ISR
MOVLW B'100'
XORWF PORTE,1
MOVLW .10
MOVWF COUNT
EXIT_ISR
RETFIE
END
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