Trích:
Nguyên văn bởi hunter800
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.