PDA

View Full Version : Hỏi về timer0,1,2 của pic16f877A?


dvnccbmacbt
02-07-2007, 11:41 PM
Em chưa hiểu về cơ chế hoạt động của timer2 trong con pic16f877A.
Có bác nào giải thích giúp em với. Em dùng CCS C. Cụ thể như thế này. Nạp một giá trị ban đầu ( period ) cho nó và giá trị ( postscale ). Qua trình làm việc nó xử lý với 2 giá trị này này như thế nào? Có phải nó cũng bắt đầu đếm từ period đến 255, tràn và tiếp tục đếm từ period đến 255 và tràn cho đến khi nào số lần tràn bằng số postscale thì ngắt. Khi ngắt thì ta cũng thiết lập lại giá trị timer2 trong hàm ngắt.? Em hiểu như vậy có đúng không, các bác chỉ bảo cho?

Cho em hỏi thêm : Chế độ đếm đồng bộ và không đồng bộ ở timer1 là như thế nào? Em không hiểu gì cả? Chế độ đếm của timer0 là đồng bộ hay không đồng bộ? Các bác giúp em với. Cảm ơn các bác nhiều!

nhh
03-07-2007, 05:25 AM
Bạn xem chương trình đây thì rõ, lâu quá rồi, ko tìm thấy link cũ.

Jerry
04-07-2007, 04:35 PM
Timer 2 có 2 thanh ghi là PR2 và TMR2.
Khi chức năng timer của Timer2 được kích hoạt thì thanh ghi TMR2 sẽ đếm từ 0 cho đến khi "khớp" với giá trị đặt trước trong thanh ghi PR2 thì tràn. Lúc này nếu cho phép ngắt timer2 thì sẽ xảy ra 1 ngắt.

Hoạt động của timer2 còn liên quan đến prescaler và postscaler. Để cho bạn hiểu 1 cách đơn giản nhất thì có thể nói prescaler và postscaler là 1 hệ số nhân. timer 2 sẽ ngắt sau 1 khoảng thời gian = PR2*prescaler*postscaler. Ví dụ: PR2 = 124 (dec); prescaler = 10 (dec); postscaler = 16 (dec) thì timer2 sẽ tràn sau 1 khoảng thời gian là 124*10*16 = 19840 us (micro second)

dvnccbmacbt
05-07-2007, 11:10 AM
to Jerry: Cảm ơn bạn nhiều. cho mình hỏi thêm. Mình dùng CCS C. Câu lệnh set_timer2(value); có ý nghĩa gì? Giá trị value này được đưa và thanh ghi PR2 phải không?

3.Timer2

Thanh ghi tác động:

Các lệnh:

setup_TIMER_2(mode, period, postscale);
set_TIMER2(value); // xác định giá trị ban đầu (8bit) cho Timer2
get_TIMER2(); // trả về số nguyên 8bit


Với mode gồm (co the ket hop bang dau "|"):

T2_DISABLED
T2_DIV_BY_1
T2_DIV_BY_4
T2_DIV_BY_16

period là số nguyên từ 0-255, xác định giá trị xung reset
postscale là số nguyên 1-16, xác định reset bao nhiêu lần trước khi ngắt.

Jerry
07-07-2007, 04:50 PM
Lệnh set_TIMER2(value) chính là lệnh đặt giá trị cho PR2. Mình ít viết chương trình bằng C lắm. ASM thì mình thạo hơn. Cũng nhờ ASM nên mình hiểu khá kỹ về cấu trúc phần cứng của vi điều khiển PIC. Viết bằng C thì không hiểu nhiều về phần cứng đâu, tuy nhiên C có lợi thế khi xây dựng những project lớn

KHACTHO
04-12-2008, 07:14 PM
cho em hoi ve cái set_timer0(6)có ý nghĩa như thê nao mong cac bac giúp đơ.em cam on nhieu nha

tungtot_vl
05-12-2008, 02:18 PM
cho em hoi ve cái set_timer0(6)có ý nghĩa như thê nao mong cac bac giúp đơ.em cam on nhieu nha

set_timer0(6) là thiết lập giá trị đếm ban đầu của timer. khi đó biến đếm bắt đầu đếm từ 6 cho đến 255 thì tràn và nhảy vào ngắt, sau khi ngắt xong lại quay về giá trị đếm ban đầu là 6 để đếm tiếp

lequocbao
06-12-2008, 11:35 AM
Vậy là muốn sử dụng timer0 thì mình chỉ cần:
setup_TIMER_2(mode, period, postscale);
khi gặp câu lệnh:
set_TIMER2(value);
là timer 0 sẽ bắt đầu đếm phải không bạn?

Cho mình hỏi luôn là mình sử dụng thạch anh 4Mhz mà muốn tính số lần ngắt trên 1s thì mình phải tính như thế nào?(mục đích là mình muốn khi kích hoạt timer0 sau 1s thì mình sẽ làm việc khác đó mà!)
Mình có tham khảo trong mục help(mình sử dụng ccs c) thì với thạch anh 20Mhz thì số lần ngắt trên 1s là 76 nhưng mình không hiểu lắm về cách tính ra con số 76.Đại khái là:
20000000/(4*256*256) =76

thanhviet
06-12-2008, 12:31 PM
cac bac nao giai thich dum cach chon TMOD trong 8051 dc ko , minh ko hieu o cho 20,02 ,10,01 ,13...vd:
MOV TMOD,#02( minh hieu la timer0 ,che do 2 roi) ,nhung con cai nay thi sao
MOV TMOD,#20(Cac so khac nh:10,01,13,

lequocbao
06-12-2008, 04:35 PM
Hỏi ở đây thì hơi bị lộn tiệm rồi đó nha!
Nhưng đang rãnh nên khuyến mãi luôn.
vd:
20 có nghĩa là 00100000 binary đó bạn.
thì tương ứng thanh ghi Tmod sẽ có 8bit : 4 bit cao dành cho timer0 và 4 bit thấp dành cho timer1(có thể ngược lại ,mình không nhớ chính xác)
4 bit đó là:CT\ , GATE,M0,M1.
CT\:hình như là chọn chức năng timer hay là counter gì đó.
GATE:quên chức năng của bit này rồi(pác nào nhớ nhắc hộ)
M0,M1:chọn chế độ cho timer.(có 4 chế độ)

Tóm lại là từng bit 1 có chức năng cụ thể.Nếu bạn muốn hiểu rõ thêm thì hôm sau mình tìm được tài liệu sẽ trả lời đầy đủ hơn.
Tại tài liệu để đâu không nhớ tìm chưa ra nên có cái nhớ cái không. bạn thông cảm hì hì...

trungduc
07-12-2008, 10:41 AM
Xin chào mọi người !
Tôi đang tìm hiểu về timer, cụ thể là dùng timer0 làm counter ( bsf option_reg,t0cs ) thế nhưng quan sát LED thì nó cứ đếm từ 0 -> 255 mà chẳng quan tâm gì đến nút nhấn ở chân RA4 (16f877a). Anh em nào có đoạn code kiểu này cho mình tham khảo với. Mình chỉ biết ASM thôi.
Xin cảm ơn!

tungtot_vl
07-12-2008, 05:33 PM
Vậy là muốn sử dụng timer0 thì mình chỉ cần:
setup_TIMER_2(mode, period, postscale);
khi gặp câu lệnh:
set_TIMER2(value);
là timer 0 sẽ bắt đầu đếm phải không bạn?

Cho mình hỏi luôn là mình sử dụng thạch anh 4Mhz mà muốn tính số lần ngắt trên 1s thì mình phải tính như thế nào?(mục đích là mình muốn khi kích hoạt timer0 sau 1s thì mình sẽ làm việc khác đó mà!)
Mình có tham khảo trong mục help(mình sử dụng ccs c) thì với thạch anh 20Mhz thì số lần ngắt trên 1s là 76 nhưng mình không hiểu lắm về cách tính ra con số 76.Đại khái là:
20000000/(4*256*256) =76
ngắt 1s
#include <16F877A.h>
#device 18F4680*=16 ADC=10
#fuses NOWDT,PUT,XT,NOPROTECT
#use delay(clock=4000000)
#use fast_io(c)
#byte portc=0x07
int16 count;
int8 a;
//Chuong trinh ngat TMR0
#int_timer0
void timer0()
{
set_timer0(56); // T = 2*(256 - 56)*1us = 400us (nếu dùng thạch anh 20M thi thay 1us thành 0,2us)
++count;
if(count == 2500) // 2500*400us = 1000000us = 1s
{
count=0;
rotate_left(&a,1);
}
}
//Chuong trinh dich led
void main()
{ set_tris_c(0);
enable_interrupts(int_timer0);
setup_timer_0(RTCC_INTERNAL|RTCC_DIV_2);
enable_interrupts(global);

a = 0x01;
while(true)
{
portc = a;
}
}

tungtot_vl
07-12-2008, 05:33 PM
tự tìm hiểu nhé

KHACTHO
09-12-2008, 11:24 AM
Trích:
Nguyên văn bởi lequocbao View Post
Vậy là muốn sử dụng timer0 thì mình chỉ cần:
setup_TIMER_2(mode, period, postscale);
khi gặp câu lệnh:
set_TIMER2(value);
là timer 0 sẽ bắt đầu đếm phải không bạn?

Cho mình hỏi luôn là mình sử dụng thạch anh 4Mhz mà muốn tính số lần ngắt trên 1s thì mình phải tính như thế nào?(mục đích là mình muốn khi kích hoạt timer0 sau 1s thì mình sẽ làm việc khác đó mà!)
Mình có tham khảo trong mục help(mình sử dụng ccs c) thì với thạch anh 20Mhz thì số lần ngắt trên 1s là 76 nhưng mình không hiểu lắm về cách tính ra con số 76.Đại khái là:
20000000/(4*256*256) =76
ngắt 1s
#include <16F877A.h>
#device 18F4680*=16 ADC=10
#fuses NOWDT,PUT,XT,NOPROTECT
#use delay(clock=4000000)
#use fast_io(c)
#byte portc=0x07
int16 count;
int8 a;
//Chuong trinh ngat TMR0
#int_timer0
void timer0()
{
set_timer0(56); // T = 2*(256 - 56)*1us = 400us (nếu dùng thạch anh 20M thi thay 1us thành 0,2us)
++count;
if(count == 2500) // 2500*400us = 1000000us = 1s
{
count=0;
rotate_left(&a,1);
}
}
//Chuong trinh dich led
void main()
{ set_tris_c(0);
enable_interrupts(int_timer0);
setup_timer_0(RTCC_INTERNAL|RTCC_DIV_2);
enable_interrupts(global);

a = 0x01;
while(true)
{
portc = a;
}
}
tungtot_vl vẫn chưa có mặt trong diễn đàn
NHƯ VẬY CON SỐ 2 Ở (T=2*(256-56)*1US)Ơ ĐÂU RA VẬY

gghh
09-12-2008, 07:04 PM
delay 1s dùng thạch anh 4Mhz
#INCLUDE<16F877A.H>
#INCLUDE<DEF_16F877A.H>
#USE DELAY(CLOCK=4000000)
#INT8 H;
#INT_TIMER1
VOID NGAT_TIMER1()
{
SET_TIMER1(15536);
H++;
IF(H==20) //20*50000us = 1000000us = 1s
{
lệnh;
H=0;
}
}
void main()
{
SETUP_TIMER_1(T1_INTERNAL);
ENABLE_INTERRUPTS(GLOBAL);
ENABLE_INTERRUPTS(INT_TIMER1);
SET_TIMER1(15536); //T_dinhthoi = (65536-15536)*1us = 50000us
while(1)
{
lệnh;
}
}

lequocbao
10-12-2008, 01:04 PM
Tại sao mình phải set_timer1(15536); tới 02 lần luôn vậy bạn?
Còn nữa ,nếu mình muốn dừng ngắt thì phải dùng khai báo:
disable_interrupt(global); phải không?nếu đúng thì mình phải đặt khai báo đó ở chổ nào?

tungtot_vl
10-12-2008, 05:05 PM
NHƯ VẬY CON SỐ 2 Ở (T=2*(256-56)*1US)Ơ ĐÂU RA VẬY[/QUOTE]

setup_timer_0(RTCC_INTERNAL|RTCC_DIV_2);

lequocbao
11-12-2008, 04:37 PM
Pác tungtot_vl ơi!: pác coi hộ lại giúp cái ngắt timer0 1s của pác sao mà khi mở nguồn thì khoảng 30s sau ngắt mới làm việc vậy pác.Sau khi ngắt đã làm việc thì nhấn reset thì ngắt làm việc lại liền còn cúp nguốn thì chịu khó đợi 30s nữa.Vậy là nó bị trục trặc chổ nào phải không pác?

crazy_baby
18-12-2008, 05:20 PM
các pro xem giúp em cái code này với .mạch đồng hồ , hh:mm:ss , dùng ngắt timer0 nhưng không hiểu tại sao lại không xảy ra ngắt . code nè :
#include<16f877a.h>
#include<def_877a.h>
#FUSES NOWDT, HS, NOPUT, NOPROTECT, NODEBUG, NOBROWNOUT, NOLVP, NOCPD, NOWRT
#device *=16 ADC=8
#use delay(clock=20000000)
int16 count;
int8 h10,h1,m10,m1,s10,s1,i;//khai bao bien gio,phut,giay
#int_TIMER0
void timer0()
{
set_timer0(6);
++count;
if(count==5000)
{
++s1;
if(s1==9){
s1=0;
++s10;
if(s10==5)
{
s10=0;
++m1;

if(m1==9){
++m10;
m1=0;
if(m10==5){
m10=0;
++h1;
if(h1==2){h1=0;
++h10;
if(h10==1){h10=0;}
}
}
}

}
}
count=0;

}



}
void main()
{
trisd=0x00;
trise=0x00;
s1=0;
s10=0;
m1=0;
m10=0;
h1=0;
h10=0;
enable_interrupts(int_timer0);
setup_timer_0(RTCC_INTERNAL|RTCC_DIV_4);
enable_interrupts(global);


while(1)
{
i=0;
for(i=0;i<=5;i++)
{
porte=i;
switch(i)
{
case 0: portd=h10;break;
case 1: portd=h1;break;
case 2: portd=m10;break;
case 3: portd=m1;break;
case 4: portd=s10;break;
case 5: portd=s1;break;
}
}
}


}

hoaphonglan
03-01-2009, 08:49 PM
khi su dung timer ban phai chon ty le chia tang so trong timer roi moi tinh theo chu moi khi timer giam ung voi 1 nhip dem cua bo chia tang ma ban chon(tuy theo timer co ty le chia tang so 1/1 ;1/4/..

namqn: xin nhắc bạn viết bài bằng tiếng Việt có dấu. Bạn tham khảo luồng sau về cách gõ tiếng Việt trên diễn đàn: http://www.picvietnam.com/forum/showthread.php?t=862.

lexuantien
18-03-2009, 04:22 AM
Pác tungtot_vl ơi!: pác coi hộ lại giúp cái ngắt timer0 1s của pác sao mà khi mở nguồn thì khoảng 30s sau ngắt mới làm việc vậy pác.Sau khi ngắt đã làm việc thì nhấn reset thì ngắt làm việc lại liền còn cúp nguốn thì chịu khó đợi 30s nữa.Vậy là nó bị trục trặc chổ nào phải không pác?
mình thấy mạch vẫn chạy ổn mà bạn , bạn coi lại cái mạch của bạn thử coi!

lexuantien
18-03-2009, 04:42 AM
Tại sao mình phải set_timer1(15536); tới 02 lần luôn vậy bạn?
Còn nữa ,nếu mình muốn dừng ngắt thì phải dùng khai báo:
disable_interrupt(global); phải không?nếu đúng thì mình phải đặt khai báo đó ở chổ nào?
Mình cũng từng viết chương trình điều khiển led giống vậy , mình trả lời bạn trong giới hạn hiểu biết của mình thôi:

1. Vì sao phải set_timer1(15536); tới 02 lần ?
set_timer1(15536); trong hàm void main(void) là để tính thời gian bắt đầu đếm của Timer0 . Còn set_timer1(15536); trong hàm void interrupt_timer0() thì sau khi tính giá trị xong thì nó sẽ gán giá trị của set_timer1(15536); vào hàm này.
2. Khai báo disable_interrupt(global); được hiểu là cấm ngắt . Còn đặt ở đâu thì bạn tham khỏa trong đoạn Code sau:

#include <16F877A.h>
#fuses NOWDT,PUT,XT,NOPROTECT
#use delay(clock=4000000)
#byte PORTB = 0x06

int16 count;
int8 a;
//Chuong trinh ngat TMR0
#int_timer0
void interrupt_timer0()
{
set_timer0(6);
++count;
if(count == 2000) // 2000*500us = 500000us = 1s
{
count=0;
rotate_left(&a,1);
}
}
//Chuong trinh chinh
void main(void)
{
set_tris_b(0);
enable_interrupts(int_timer0);
setup_timer_0(RTCC_INTERNAL|RTCC_DIV_2); // so 2 la o cho T_dinhthi=2*(256-6)*1us = 500 us
enable_interrupts(global);
set_timer0(6);// T_dinhthi = 2*(256 - 6)*1us = 500us
a = 0x01;
disable_interrupts(global);
while(true)
{
PORTB = a;
}
}