You are on page 1of 76

CHƯƠNG 5

BỘ ĐỊNH THỜI
Kiểm tra chuong 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 của Timer 0
3. Sơ đồ khối của Timer 0
4. Các bước để định thời gian Timer 0
5. Các bước để đếm sự kiện Counter 0
6. Bài tập Timer 0
7. Đặc điểm của Timer 1
8. Sơ đồ khối của Timer 1
9. Các bước để định thời gian Timer 1
10. Các bước để đếm sự kiện Counter 1
Nội dung chương 5
11. Bài tập Timer 1
12. Đặc điểm của Timer 2
13. Sơ đồ khối của Timer 2
14. Các bước để định thời gian Timer 2
15. 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:21:256) (÷1,÷2,÷4,÷8) (1:1,1:4,1:8)
(Resolution) Postscaler
(1:11:16)
Sự kiện ngắt và On overflow On overflow TMR2 matches
cờ ngắt FFh00h FFFFh0000h 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ừ
FFh00h
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

OPTION register 0 0 1 1:4

0 1 0 1:8
RBPU INTEDG TOCS TOSE PSA PS2 PS1 PS0
0 1 1 1:16

Prescaler Rate Select Bits 1 0 0 1:32

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

• Nếu xung clock bên ngoài (TOCKI) được sử dụng nó


sẽ được đồng bộ hóa với xung clock bên trong

•Timer 0 là có thể đọc hoặc ghi

•Cờ ngắt Timer 0 sẽ được set khi có hiện tượng tràn TMR0
(FF00)
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:

tdelay: thời gian cần định thời (us)


fOSC: tần số dao động thạch anh
Pre:hệ số chia tần trước prescaler(Pre=1,2,4...,256
[TMR0]: giá trị cần ghi vào thanh ghi TMR0

 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

a. TD = 100ms = dem * tdelay = 2 * 50ms


 dem = 2; TMR0=61; TMR0IF =0
PresT0 =1:256) PS2=1; PS1=1; PS0=1;
PSA=0 T0SE = 0 T0CS=0
b. TD = 500ms = dem * tdelay = 50 * 10ms
 dem = 50 ; TMR0=; TMR0IF =0
PresT0 =1:X) PS2=x; PS1=x; PS0=x;
PSA=0 T0SE = 0 T0CS=0
 [TMR0] = 256 – [ tdelay/Tcy*PresT0]
 = 256 – [1000us/1us*256) =

 [0] <= 256 – [ tdelay/Tcy*PresT0]


 PresT0 >= [ tdelay/ 256*Tcy]
= 1000us/ 256*1us =

TMR0 0……….………………. …..255


Các bước để đếm sự kiện Counter 0

 B1: Xóa giá trị trong thanh ghi TMR0 =0


 B2: Xóa cờ báo tràn( cờ ngắt) TMR0IF=0
 B3: Chọn chế độ hoạt động của Counter 0
• Chọn chế độ đếm sự kiện (Counter) T0CS =1
• Kích hoạt hoặc không cho phép ngắt GIE=0, TMR0IE=0
• Gán giá trị prescaler cho Timer 0 PSA =
• Chọn loại kích của nguồn xung bên ngoài T0SE=

 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

Cấu hình các PORT E: TMR0IF


output =1?

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
PrescalerWDT
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

Đặt giá trị ban đầu cho


bộ đếm(TMR0=0)

Xóa cờ báo tràn


Timer0
Code :ASM

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

Bài 1: Viết chương trình delay 4ms dùng


Timer 0 biết fOSC=4Mhz
Bài 2: Chỉ dùng Timer 0 viết chương trình
delay có thời gian lớn nhất biết fOSC=4Mhz.
Bài 3: Cho sơ đồ giống như ví dụ 2. Viết
chương trình khi nhấn nút SW0 thì số đếm
giảm từ 2000 hiển thị trên 8 led đơn.
Chữa bài 1- Viết chương trình delay 4ms
dùng Timer 0 biết fOSC=4Mhz
Chữa bài 2- Chỉ dùng Timer 0 viết chương trình
delay có thời gian lớn nhất biết fOSC=4Mhz.
Chữa bài 3-
Bài kiểm tra 9/4/2021

 Thiết kế mạch điều khiển 8 led nối với


portC của PIC 16f887 thực hiện theo yêu
cầu sau:
– Khi nhấn nhả sw1( nối với RB0) 8 led sáng
đuổi từ LSB  MSB.
– Khi nhấn nhả sw2( nối với RE0) 8 led sáng dần
từ LSB  MSB.
– Khi nhấn nhả sw3( nối với RA4) 8 led tắt.
Biết Fosc=8MHz ; thời gian chuyển giữa các
trạng thái là Td = 200ms.
Phải sử dụng module timer0 để định thời gian.
Đặc điểm của Timer 1
 Là Timer/Counter 16 bit gồm 2 thanh ghi
TMR1H và TMR1L có thể đọc và ghi
 Timer1 có thể hoạt động ở chế độ định thời
hay đếm được lựa bởi bit TMR1CS.
 Trong chế độ định thời T1 tăng giá trị ở mỗi
chu kỳ lệnh, chế độ đếm bộ đếm tăng mỗi khi
có cạnh clock ngõ vào bên ngoài
 Có bộ prescale chia tần 3 bit
 Xảy ra hiện tượng ngắt khi tràn từ
FFFFh0000h
 Có khả năng “đánh thức” vi điều khiển từ chế
độ “ngủ” nhờ có thêm bộ dao động bên ngoài.
Sơ đồ khối Timer1
T1OSI
T1
T1OS0 OSC
synchronize
prescaler

Fosc/4

T1CKI
TMR1H TMR1L
pin
Enable

Timer1 Control Register (T1CON) TMR1ON


T1GINV TMR1GE T1CKPS1 T1CKPS0 T1OSCEN T1SYNC TMR1CS TMR1ON

T1CKPS1 T1CKPS0 scale


1 1 1:8 Timer1 On
LP Oscillator Enable 1 = Enable Timer1
1 0 1:4
1 = T1OSC selected Chọn nguồn xung clock
0 1 1:2 0 = T1CKI can be used 1 = External (T1CKI)
0 0 1:1 0 = Internal (FOSC/4)
Sơ đồ khối Timer1
T1OSI
T1
T1OS0 OSC
synchronize
prescaler

Fosc/4

T1CKI TMR1H TMR1L


pin
Enable
Thanh ghi điều khiển (T1CON) TMR1ON

T1GINV TMR1GE T1CKPS1 T1CKPS0 T1OSCEN T1SYNC TMR1CS TMR1ON

Timer1 Gate Enable and Timer1 External Clock Input Synchronization


Timer1 Gate Invert are 1 = do not synchronize external clock input
available on some devices 0 = synchronize external clock input with
internal clock (Fosc/4)
Các bước để định thời gian Timer 1
 B1: Tính toán các giá trị cần đưa vào code:
Đối với dao động nội:

Đố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

TMR1H: Byte cao của [TMR1]


TMR1L: Byte thấp của [TMR1]

TMR1 =15536D = 3CB0H-> TMR1H =3CH =00111100B ;


TMR1L=B0H = 10110000B;
Các bước để định thời gian Timer 1

 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

 B1: Xóa giá trị trong thanh ghiTMR1


 B2: Xóa cờ báo tràn (cờ ngắt) TMR1IF
 B3: Chọn chế độ hoạt động của Counter 1
• Chế độ đếm sự kiện (Counter 1)
• Kích hoạt hoặc vô hiệu hóa các ngắt(tùy chọn)
• Chọn giá trị tỉ lệ của prescale
• Chọn tính năng đồng bộ hoặc không đồng bộ xung
 B4: Cho phép Counter 1 bắt đầu hoạt động
 B5: Đọc về và xử lý số đếm xung đếm được trong thanh ghi
TMR1(TMR1H:TMR1L)
Thiết lập ngắt Timer1 (ASM)
TMR1H TMR1L
Main Code
1 0
0
Start 1 01 0 1 0
1 01 0 1 0
1 0
1 0
1 1
0 1 1
0 0 1
0 1 1
0 0
;Xóa cờ ngắt Timer1 TMR1IF
BANKSEL PIR1
BCF PIR1, TMR1IF PIR1
1
0
;Cho phép ngắt Timer1
BANKSEL PIE1 TMR1IF
BSF PIE1, TMR1IE PIE1
1
;Cho phép ngắt toàn cục và ngắt ngoại vi TMR1IE
BSF INTCON, PEIE
BSF INTCON, GIE INTCON
1 1
GIE PEIE
Khởi tạo Timer1(ASM)
TMR1H
;Xóa thanh ghi TMR1 0 0 0 0 0 0 0 0
BANKSEL TMR1H
CLRF TMR1H
TMR1L
CLRF TMR1L 0 0OVERFLOW!!
0 0 INCREMENTING
TMR1H:TMR1L 0 0 0 0
;Xóa cờ ngắt TMR1IF trong thanh ghi PIR1
BANKSEL PIR1
BCF PIR1,TMR1IF
PIR1 (Peripheral Interrupt Request)
;Setup T1CON register for internal clock
;with 1:8 prescaler, Timer1 is stopped
0 0 0 0 0 0 0 0
1
;and T1 osc is disabled
MOVLW b’00110000’ TMR1IF
MOVWF T1CON
T1CON (Timer1 Control)
;Bật Timer 1
BSF T1CON, TMR1ON 0 0 1 1 0 0 0 1
0

;Kiểm tra cờ ngắt Timer 1 Input clock


BTFSS PIR1, TMR1IF prescale bits Timer1 TMR1ON
GOTO $-1 (T1CKPS<1:0>) oscillator Clock source
enable bit select bit
(T1OSCEN) (TMR1CS)
 Ví dụ mô phỏng
Lập trình khởi tạo cho timer1 để tạo thời
gian trễ td=
fosc= 4MHz
Xác định:
Giá trị ban đầu TMR1H= ..;
TMR1L= ..;

Hệ số chia trước 1:8


Thiết lập ngắt Timer1 (Hitech-C)
TMR1H TMR1L
Main Code
1 0
0
Start 1 01 01 01 01 0 1 0
1 0
1 0
1 1
0 1 1
0 0 1
0 1 1
0 0
;Xóa cờ ngắt Timer1 TMR1IF

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

;Xóa cờ ngắt TMR1IF trong thanh ghi PIR1

TMR1IF=0; PIR1 (Peripheral Interrupt Request)


;Setup T1CON register for internal clock
;with 1:8 prescaler, Timer1 is stopped
0 0 0 0 0 0 0 0
1
;and T1 osc is disabled
TMR1IF
T1CON=0xC0;
T1CON (Timer1 Control)
;Bật Timer 1
TMR1ON=1; 0 0 1 1 0 0 0 1
0

;Kiểm tra cờ ngắt Timer 1 Input clock


while(!TMR1IF) {} prescale bits Timer1 TMR1ON
(T1CKPS<1:0>) oscillator Clock source
enable bit select bit
(T1OSCEN) (TMR1CS)
Viết CT Delay_2s sử dụng Timer1
 Tính toán:  Với Timer1:
t_delay = 2s = 2000000 + Chọn tỉ lệ chia tần
us; f_xtal = 8 MHz  trước prescale là 8
t_xung=0.5 us + Chọn dung lượng
Số lượng xung cần đếm Timer1 là 50000
đếm: n_xung=4000000 + Số lần đếm cờ báo tràn
Timer1 là 10
void Delay_2s (void)
{
T1CON=0B00110000;
TMR1H=(65536-50000)/256;
TMR1L=(65536-50000)%256;
unsigned char nIF=0;
TMR1IF=0; TMR1ON=1;
while (nIF <10)
{
TMR1IF=0;
TMR1H=(65536-50000)/256;
TMR1L=(65536-
50000)%256;
nIF ++;
}
TMR1ON=0;
}
Ví dụ 3: 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ỳ 100ms tại
chân RE1 và 500ms tại chân RE2
Sơ đồ giải thuật
dùng “thăm dò” : Begin
RE1=!RE1
Cấu hình các
PORT digital,
PORTE: output count - -

Cấu hình các PORT E:


output N count
LOOP =0?
count=5
Y
RE2=!RE2
TMR1IF=0
TMR1=15536

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ò” :

Cấu hình các


PORT digital

Cấu hình PORT E:


output
LOOP
TMR1IF=0
TMR1=0x8000

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

Bài 1: Viết chương trình delay 100ms dùng


Timer1 biết fOSC=4Mhz
Bài 2: Chỉ dùng Timer1 viết chương trình
delay có thời gian lớn nhất biết fOSC=4Mhz
Bài 3: Viết chương trình delay 10s dùng
Timer 1 sử dụng bộ dao động bên ngoài gắn
trên 2 chân RC1/T1OSI, RC2/T1OSO có
f =32768 Hz
Đặc điểm của Timer 2
 Là Timer 8 bit có bộ prescale và postscale
 Được sử dụng như bộ tạo xung có PWM
cho chế độ hoạt động PWM của khối CCP
 Thanh ghi TMR2 có thể đọc ghi và xóa khi
bị reset
 Có bộ chia tần số trước prescale với bit
điều khiển T2CKPS1:T2CKPS2
 Ngõ ra TMR2 đi qua bộ postscale 4 bit để
tạo ra yêu cầu ngắt TMR2 được chốt trong
cờ TMR2IF(PIR1<1>)
 Tạo tín hiệu ngắt khi giá trị TMR2 bằng PR2
 Chỉ sử dụng nguồn xung clock bên trong
Sơ đồ khối củaTimer2
T2CKPS1 T2CKPS2 Scale
0 0 1:1 TMR2
0 1 1:4 OUTPUT
1 X 1:16 TMR2
Prescaler
Fosc/4
1:1, 1:4, 1:16

Postscaler
COMPARATOR 1:1  1:16

PR2

Timer2 Control Register (T2CON)


TOUTPS3 TOUTPS2 TOUTPS1 TOUTPS0 TMR2ON T2CKPS1 T2CKPS0

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:11 1:1  1:16


1 0 1 1 1:12
1 1 0 0 PR2 1:13
1 1 0 1 1:14
1 1 1 0 1:15

1 1 1 1 1:16

Timer2 Control Register (T2CON)


TOUTPS3 TOUTPS2 TOUTPS1 TOUTPS0 TMR2ON T2CKPS1 T2CKPS0

T2CKPS1 T2CKPS0 Scale


0 0 1:1 Timer2 ON
0 1 1:4 1 = Timer2 enabled
1 X 1:16
Sơ đồ khối củaTimer2
Start Timer2
Counting TMR2
OUTPUT
TMR2
Prescaler
1 1 1 1 0
1 1
0 0
1 1
0
Fosc/4
1:1, 1:4, 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)

[TMR2]: giá trị cần ghi vào thanh ghi TMR2


[PR2]: giá trị cần ghi vào thanh ghi PR2
Các bước để định thời gian Timer 2
B2: Ghi vào thanh ghi PR2 giá trị đã tính toán
B3: Xóa cờ báo tràn (cờ ngắt) TMR2IF
B4: Chọn chế độ hoạt động của Timer 2
 Kích hoạt hoặc vô hiệu hóa các ngắt
 Chọn giá trị Pre
 Chọn giá trị Post
B5: Cho phép Timer 2 bắt đầu hoạt động
B6: Xác định thời điểm Timer 2 bị tràn bằng
cách:
 Kiểm tra cờ TMR2IF (dùng thăm dò)
 Xử lý ISR của Timer 2 (nếu dùng ngắt)
Ví dụ mô phỏng
Khởi tạo Timer2 (ASM) Timer2
Incrementing
TMR2 (Timer2 Counter)
;Disable the Timer2 interrupts in the PIE1
;Cấm ngắt Timer2 trong thanh ghi PIE1 0
1 0
1 0
1 0
1 0
1 0 1 0
1 0 1
;Xóa cờ ngắt TMR2IF trong thanh ghi PIR1
BANKSEL PIE1 PR2 (Period Register Timer2)
BCF
BANKSEL
PIE1,TMR2IE
PIR1
1 0 0 0 0 0 0 0
BCF PIR1,TMR2IF PIE1 (Peripheral Interrupt Enable)
;Setup thanh ghi T2CON Postscaler = 1:15,
;Prescaler = 1:16, Timer2 off 0
MOVLW b’01110010’ TMR2IE
MOVWF T2CON PIR1 (Peripheral Interrupt Request)
;Xóa thanh ghi TMR2
BANKSEL TMR2 1
0
CLRF TMR2 TMR2IF
;Khởi tạo giá trị PR2 Flag is set
BANKSEL PR2
MOVLW b’10000000’ T2CON (Timer2 Control)
MOVWF PR2
;Timer2 bắt đầu đếm lên 0 1 1 1 0 0
1 1 0
BANKSEL T2CON
BSF T2CON,TMR2ON
TMR2ON
;Kiểm tra cờ ngắt TMR2IF Postscaler = 1:15
BTFSS PIR1,TMR2IF (TOUTPS<3:0>) Prescaler = 1:16
GOTO $-1
(T2CKPS<1:0>)
Khởi tạo Timer2 (Hitech-C) Timer2
Incrementing
TMR2 (Timer2 Counter)
;Disable the Timer2 interrupts in the PIE1
;Cấm ngắt Timer2 trong thanh ghi PIE1 0
1 0
1 0
1 0
1 0
1 0 1 0
1 0 1
;Xóa cờ ngắt TMR2IF trong thanh ghi PIR1
PR2 (Period Register Timer2)
TMR2IE=0;
1 0 0 0 0 0 0 0
TMR2IF=0; PIE1 (Peripheral Interrupt Enable)
;Setup thanh ghi T2CON Postscaler = 1:15,
;Prescaler = 1:16, Timer2 off 0
TMR2IE
T2CON=0x76; PIR1 (Peripheral Interrupt Request)
;Xóa thanh ghi TMR2
1
0
TMR2=0; TMR2IF
;Khởi tạo giá trị PR2 Flag is set
T2CON (Timer2 Control)
PR2=0x80
;Timer2 bắt đầu đếm lên 0 1 1 1 0 0
1 1 0
TMR2ON=1;
TMR2ON
;Kiểm tra cờ ngắt TMR2IF Postscaler = 1:15
while (!TMR2IF) (TOUTPS<3:0>) Prescaler = 1:16
{}
(T2CKPS<1:0>)
Ví dụ 5: Dựa vào sơ đồ viết chương trình điều
khiển tạo sóng xung vuông có tần số 10Hz và
100Hz tại chân RE1 và RE2.
Sơ đồ giải thuật Begin
dùng ngắt : ISR:

Cấu hình các TMR2IF=0


PORT digital

Cấu hình PORT E: RE1=!RE1


output, PORTE=0
count++
TMR1IF=0
PR2=249, count=0
count N
T2CON=b’00100001’ =10?
(Pre=1:4,Post=1:5) Y
count=0
TMR2IE=1
PEIE=1 RE2=!RE2
GIE=1

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

Bài 1: Viết chương trình delay 1ms dùng


Timer2 biết fOSC=4Mhz
Bài 2: Chỉ dùng Timer2 viết chương trình
delay có thời gian lớn nhất biết fOSC=4Mhz
Bài tập tổng hợp
Bài 1: Viết chương trình delay 1s dùng
Timer0, Timer1, Timer2 biết fOSC=4Mhz
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.

You might also like