PIC Vietnam

PIC Vietnam (http://www.picvietnam.com/forum/index.php)
-   Các ngôn ngữ lập trình khác (CCS C, HT PIC,...) (http://www.picvietnam.com/forum/forumdisplay.php?f=12)
-   -   ngắt timer CCS (http://www.picvietnam.com/forum/showthread.php?t=5986)

hunter800 22-03-2010 03:37 PM

ngắt timer CCS
 
hix ai giải thích dùm mình chương trình ngắt này với!Mình thực sự rất cố gắng đọc nhưng chuă hiểu lắm!thanks

#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);
enable_interrupts(global);
set_timer0(6);// T_dinhthi = 2*(256 - 6)*1us = 500us
a = 0x01;

while(true)
{
PORTB = a;
}
}

trai_xq 22-03-2010 06:00 PM

Trích:

Nguyên văn bởi hunter800 (Post 34297)
hix ai giải thích dùm mình chương trình ngắt này với!Mình thực sự rất cố gắng đọc nhưng chuă hiểu lắm!thanks

#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);
enable_interrupts(global);
set_timer0(6);// T_dinhthi = 2*(256 - 6)*1us = 500us
a = 0x01;

while(true)
{
PORTB = a;
}
}

+set_tris_b(0);//định nghĩa portb là đầu ra số(nêu như ở vòng lặp while bạn khai báo
output_b(a); thì câu lệnh set_tris_b(0); là không cần thiết.
+enable_interrupts(int_timer0);//mới bắt đầu chương trình, bạn cho timer0 làm việc(bắt đầu tính
+setup_timer_0(RTCC_INTERNAL|RTCC_DIV_2); //chỉ lệ chia tần số
timer0 8bit, đêm từ 0-->255, và sau đó tràng đếm lại từ 0. Mỗi lần tràn như vậy là được bạn tính thời gian như sau:
-bạn dùng thạch anh 4M=4000000hz. như vậy mỗi lần tràn thì được thời gian là Ttimer0=255*4/(4.000.000) (s)=255micro s. Nhân 4 bởi vì một chu kì lệnh của VDk=4 chu kì xung của thạch anh. Mục đích của chúng ta là để tạo ra một giây, như thế thì phải làm sao?
+setup_timer_0(RTCC_INTERNAL|RTCC_DIV_2); //lệnh này sẻ nâng giải tần của timer0 lên 2 lần nữa. nghĩa là khi có lện này ttimer0 sẻ được tính lại sau mổi lần tràn như sau:
Ttimer0=( 255*4/(4.000.000) )* 2(s) = 510micro s
+enable_interrupts(global);//cho ngắt toàn bộ(lệnh này không cần nếu như bạn chỉ có ngắt timer0)
+set_timer0(6);//đắt giá trị đầu cho timer0 là 6, nghĩa là timer bây giờ tăng từ 6 chư không phải là 0 nữa. Chổ này thôi tôi nghĩ có sự nhầm lẫn là set_timer0(5); là đùng hơn, vì sao phải làm vậy bạn biết không? tất ca cũng chỉ vì cho dễ tính và chẵn số thôi. Nếu đặt như vậy thì thời gian timer0 sẻ được tính lại như sau:
Ttimer0=( (255-5)*4/(4.000.000) )* 2(s) = 500micro s
+như vậy bạn phải cần mấy lần tràn mới được 1s? có phải là 2000 lần không
vì 2000*500=1000000micro s=1s ok!
+Đoạn chương trình này sẽ thể vấn đề đó:
#int_timer0
void interrupt_timer0()
{
set_timer0(5);
++count;
if(count == 2000) // 2000*500us = 500000us = 1s
{
count=0;//nếu đã được 2000 nghìn lần tràn(đã được 1s) thì cho tràn lại từ đầu
rotate_left(&a,1);//tương ưng với lệnh a=a<<1; nghĩ là dịc trái một bit, sau 1s
//bởi vì bạn đã cho a=0x01<=> a=0b00000001; trong chương trình main
}
}
//------------------
Sở dĩ tôi giúp bạn vì ngày xưa tôi cũng có gặp khó khăn này rồi.

v1t2m3 17-02-2011 09:18 PM

Thank!!!
 
Cảm ơn bác trai_xp, bác viết quá cặn kẽ, không thể nào không hiểu trừ phi không muốn hiểu.

babadada 01-03-2011 10:49 PM

may wa gặp bài này cuả bác em đã hiểu thưa bác ...thank bác

iVoVa 13-03-2011 05:15 AM

Theo mình để tính được giá trị cần nạp vào thanh ghi TMRO thì mình tính theo công thức này . T_out = ((4*Prescaler)*(256-TMR0)x Count)/4000000. ( Timer 16bit thì thay 256 = 65536 )
Mình nên cho Prescaler là 256 .
Cho Count là 1 trước. T_out là thời gian trễ mình cần tạo ( ví dụ T_out = 0.5s).
Thay vào để tính được TMR0.
Nếu TMR0 ko đủ để biểu diễn giá trị vừa tính ra ( vượt quá 8 bit ) thì ta xem mức độ lớn hơn như thế nào để tăng biến count lên cho phù hợp và tính lại từ đầu.
( Hiện nay các PIC18 timer 0 có thể sử dụng đến 16 bit hoặc 8 bit , trong CCS C Complier khi sử dụng hàm set_timer0(xxx) thì mình xem mã ASM thấy nó mặc định sử dụng là timer 16 bit.

Delfy_Coltech 14-03-2011 09:34 PM

Code:

setup_timer1(TMR_INTERNAL | TMR_DIV_BY_8, 4096);
Thế còn dòng setup Timer1 thế này các bạn giải thích giùm?
Thanks!

nguyenminh545 25-11-2011 08:20 AM

cám ơn rất nhiều

madampi.12 21-12-2011 02:25 PM

[QUOTE=trai_xq;34303]+set_tris_b(0);//định nghĩa portb là đầu ra số(nêu như ở vòng lặp while bạn khai báo
output_b(a); thì câu lệnh set_tris_b(0); là không cần thiết.
+enable_interrupts(int_timer0);//mới bắt đầu chương trình, bạn cho timer0 làm việc(bắt đầu tính
+setup_timer_0(RTCC_INTERNAL|RTCC_DIV_2); //chỉ lệ chia tần số
timer0 8bit, đêm từ 0-->255, và sau đó tràng đếm lại từ 0. Mỗi lần tràn như vậy là được bạn tính thời gian như sau:
-bạn dùng thạch anh 4M=4000000hz. như vậy mỗi lần tràn thì được thời gian là Ttimer0=255*4/(4.000.000) (s)=255micro s. Nhân 4 bởi vì một chu kì lệnh của VDk=4 chu kì xung của thạch anh. Mục đích của chúng ta là để tạo ra một giây, như thế thì phải làm sao?
+setup_timer_0(RTCC_INTERNAL|RTCC_DIV_2); //lệnh này sẻ nâng giải tần của timer0 lên 2 lần nữa. nghĩa là khi có lện này ttimer0 sẻ được tính lại sau mổi lần tràn như sau:
Ttimer0=( 255*4/(4.000.000) )* 2(s) = 510micro s
+enable_interrupts(global);//cho ngắt toàn bộ(lệnh này không cần nếu như bạn chỉ có ngắt timer0)
+set_timer0(6);//đắt giá trị đầu cho timer0 là 6, nghĩa là timer bây giờ tăng từ 6 chư không phải là 0 nữa. Chổ này thôi tôi nghĩ có sự nhầm lẫn là set_timer0(5); là đùng hơn, vì sao phải làm vậy bạn biết không? tất ca cũng chỉ vì cho dễ tính và chẵn số thôi. Nếu đặt như vậy thì thời gian timer0 sẻ được tính lại như sau:
Ttimer0=( (255-5)*4/(4.000.000) )* 2(s) = 500micro s
+như vậy bạn phải cần mấy lần tràn mới được 1s? có phải là 2000 lần không
vì 2000*500=1000000micro s=1s ok!
+Đoạn chương trình này sẽ thể vấn đề đó:
#int_timer0
void interrupt_timer0()
{
set_timer0(5);
++count;
if(count == 2000) // 2000*500us = 500000us = 1s
{
count=0;//nếu đã được 2000 nghìn lần tràn(đã được 1s) thì cho tràn lại từ đầu
rotate_left(&a,1);//tương ưng với lệnh a=a<<1; nghĩ là dịc trái một bit, sau 1s
//bởi vì bạn đã cho a=0x01<=> a=0b00000001; trong chương trình main
}
}
//------------------
Sở dĩ tôi giúp bạn vì ngày xưa tôi cũng có gặp khó khăn này rồi.[
thank

kyanh911 24-03-2012 04:57 PM

còn vụ counter thì sao các bác? có bác nào xài chưa


Múi giờ GMT. Hiện tại là 01:43 PM.

Tên diễn đàn: vBulletin Version 3.8.11
Được sáng lập bởi Đoàn Hiệp.
Copyright © PIC Vietnam