Hỏi về ngắt timer1 [Lưu Trữ] – PIC Vietnam

View Full Version : Hỏi về ngắt timer1

Em đã bới tung cả diễn đàn(chủ yểu là ở “Cơ bản về vi điều khiển và PIC” và ” Các ngôn ngữ lập trình khác “) lên để tìm xem có nói về ngắt timer mà sao khó quá. Có chỗ mấy anh hỏi thì lại không có ai trả lời. Đề bài của em là trong CCS C dùng Timer1 tạo ra một thời gian là 1 giây. Ví dụ: #Int_TIMER1 void Time() { bien++; if (bien>=40) { Count=get_timer1(); set_timer1(0); St=1; bien=0; } } Em muốn hỏi cách tính làm sao tính ra chính sác 1 giây (tại sao lại là số 40 kia :(). Hầu hết các bài hướng dẫn đều hướng dẫn cách tính bằng ASM theo từng lênh. Có ai có thể hướng dẫn em cách tính không ạ?

Em đã bới tung cả diễn đàn(chủ yểu là ở “Cơ bản về vi điều khiển và PIC” và ” Các ngôn ngữ lập trình khác “) lên để tìm xem có nói về ngắt timer mà sao khó quá. Có chỗ mấy anh hỏi thì lại không có ai trả lời. Đề bài của em là trong CCS C dùng Timer1 tạo ra một thời gian là 1 giây. Ví dụ: #Int_TIMER1 void Time() { bien++; if (bien>=40) { Count=get_timer1(); set_timer1(0); St=1; bien=0; } } Em muốn hỏi cách tính làm sao tính ra chính sác 1 giây (tại sao lại là số 40 kia :(). Hầu hết các bài hướng dẫn đều hướng dẫn cách tính bằng ASM theo từng lênh. Có ai có thể hướng dẫn em cách tính không ạ? Theo mình để dễ dàng thì bạn nên hiểu như thế này , timer 1 la timer 16 bit nghia la no co thể đếm từ 0 đến 65535 . Khi đếm hết nó sẽ quay lại từ đầu là 0 , và lúc đó sẽ xảy ra ngắt . vd : giả sử cứ 1us timer đế lên 1 , vậy thì khi timer 1 tràn no sẽ đếm được 65535 um =65,535ms=0,065535 s . Vậy để xác định thời gian ngắt thì chỉ việc xác định timer đếm bao nhiêu thôi đúng ko? Bây giờ là cách xác định đây . Thời gian đếm lên của timer phụ thuộc vào chu kỳ lệnh của vi điều khiển . chu kỳ lệnh bằng bao nhiêu thì thời gian định thời của timer củng như vậy . Nếu thạch anh 4M thì chu kỳ lệnh của VDK =1um . Bậy giờ muốn 1s thì timer ngắt , nghia la sau 10^6 um . timer 1 phải ngắt , nhưng timer1 thì ko thể đếm đến 10^6. vậy ta phai sử dung chế độ prescale 1:8 . nghia la cứ 8 chu kỳ lệnh timer1 mới đếm lên 1 .. ==> 8*65535 = 524280 us . #int timer1 void ngat_timer1() { set_timer1(24280); // mặc định giá trị ban đầu cho timer la 24280 . dem++; // timer 1 tràn sau ==> 500 000 us = 0.5s if(dem==2) // 2* 500 000 =1s { ……………….// thực hiện hành động ; dem=0; } } void main setup_timer1(T1_INTERNAL|T1_DIV_BY_8); // cho timer 1 chay ở chế độ timer.Bột chia 8 set_timer1(24280) ; // mặc định số đếm ban đầu cho timer1 la 24280. enable_interrupts(int_timer1); // cho phép ngắt timer 1 enable_interrupts(global); // cho phép ngắt toàn cục while(true) { …………. }

Theo mình để dễ dàng thì bạn nên hiểu như thế này , timer 1 la timer 16 bit nghia la no co thể đếm từ 0 đến 65535 . Khi đếm hết nó sẽ quay lại từ đầu là 0 , và lúc đó sẽ xảy ra ngắt . vd : giả sử cứ 1us timer đế lên 1 , vậy thì khi timer 1 tràn no sẽ đếm được 65535 um =65,535ms=0,065535 s . Vậy để xác định thời gian ngắt thì chỉ việc xác định timer đếm bao nhiêu thôi đúng ko? Bây giờ là cách xác định đây . Thời gian đếm lên của timer phụ thuộc vào chu kỳ lệnh của vi điều khiển . chu kỳ lệnh bằng bao nhiêu thì thời gian định thời của timer củng như vậy . Nếu thạch anh 4M thì chu kỳ lệnh của VDK =1um . Bậy giờ muốn 1s thì timer ngắt , nghia la sau 10^6 um . timer 1 phải ngắt , nhưng timer1 thì ko thể đếm đến 10^6. vậy ta phai sử dung chế độ prescale 1:8 . nghia la cứ 8 chu kỳ lệnh timer1 mới đếm lên 1 .. ==> 8*65535 = 524280 us . #int timer1 void ngat_timer1() { set_timer1(24280); // mặc định giá trị ban đầu cho timer la 24280 . dem++; // timer 1 tràn sau ==> 500 000 us = 0.5s if(dem==2) // 2* 500 000 =1s { ……………….// thực hiện hành động ; dem=0; } } void main setup_timer1(T1_INTERNAL|T1_DIV_BY_8); // cho timer 1 chay ở chế độ timer.Bột chia 8 set_timer1(24280) ; // mặc định số đếm ban đầu cho timer1 la 24280. enable_interrupts(int_timer1); // cho phép ngắt timer 1 enable_interrupts(global); // cho phép ngắt toàn cục while(true) { …………. } woa!!đúng là đàn anh chỉ dạy rất dễ hiểu !!cảm ơn huynh nhé!!tiếp tục phát huy cho anh em được nhờ nhé!!! good luck!!!

Bác LE DUC ơi, cho em hỏi về ngắt T0, và T1. Nhưng ngắt T2 thì sao em khởi tạo như sau: Timer0: setup_timer_0(RTCC_INTERNAL|RTCC_DIV_2) setup_timer0(6) Timer1: setup_timer_1(T1_INTERNAL|T1_DIV_BY_8) ca hai thi chay tot, nhưng Timer2 thì pó tay, mỗi Timer co cách khởi tạo khac nhau. Bác Reply em nhé. Cảm ơn bác nhiều

Em đã bới tung cả diễn đàn(chủ yểu là ở “Cơ bản về vi điều khiển và PIC” và ” Các ngôn ngữ lập trình khác “) lên để tìm xem có nói về ngắt timer mà sao khó quá. Có chỗ mấy anh hỏi thì lại không có ai trả lời. Đề bài của em là trong CCS C dùng Timer1 tạo ra một thời gian là 1 giây. Ví dụ: #Int_TIMER1 void Time() { bien++; if (bien>=40) { Count=get_timer1(); set_timer1(0); St=1; bien=0; } } Em muốn hỏi cách tính làm sao tính ra chính sác 1 giây (tại sao lại là số 40 kia :(). Hầu hết các bài hướng dẫn đều hướng dẫn cách tính bằng ASM theo từng lênh. Có ai có thể hướng dẫn em cách tính không ạ? Đây có thể là cái bạn cần

em mới vào nghề,có bài sau muốn hỏi.em đang đọc về ngắt của con dspic,thử lập trình ngắt cho nháy đèn led từ 0-9 cho nó.chương trình của em gặp vấn đề thì phải,vì khi em thay đổi giá trị của PR1 thì thời gian nháy vẫn thế.nó vẫn nháy loạn lên.vậy mong các anh sửa giúp em với,và tư vấn cho em chút it về ngắt,khi nào dùng ngắt trong,khi nào dùng ngắt ngoài.sau đây là đoạn chương trình của em viết cho C30: #define __dsPIC33FJ12MC202__ #include <p33fj12mc202.h> int led[10]={0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x6 7}; int i; void _ISR _T1Interrupt(void) { _T1IF = 0; } main() { TMR1=0; PR1=0x2625A; //cho phep ngat sau 1 giay T1CON=0x8030; //chon ti le dem trc la 256 _T1IF=0; //xoa co ngat TMR1 _T1IE=1; //cho phep ngat TRISB=0xff00; while(1) { for (i=0;i<10;i++) { PORTB=led[i]; } } }

Bác LE DUC ơi, cho em hỏi về ngắt T0, và T1. Nhưng ngắt T2 thì sao em khởi tạo như sau: Timer0: setup_timer_0(RTCC_INTERNAL|RTCC_DIV_2) setup_timer0(6) Timer1: setup_timer_1(T1_INTERNAL|T1_DIV_BY_8) ca hai thi chay tot, nhưng Timer2 thì pó tay, mỗi Timer co cách khởi tạo khac nhau. Bác Reply em nhé. Cảm ơn bác nhiều Nếu bạn cũng khai báo TIMER2 như vậy thì không ra đâu.vì timer2 khia báo hoàn toàn khác với timer0 và 1 cụ thể: setup_TIMER2(mode, period, postscale); set_TIMER2(value);//xác định giá trị đầu(8bit) cho timer2 get_TIMER2(); //trả về trị số nguyên 8 bit mode gồm: T2_DISABLE T2_DIV_BY_1 T2_DIV_BY_4 T2_DIV_BY_16 period :số nguyên tu 0-255 postcale:số nguyên 0-16

Theo mình để dễ dàng thì bạn nên hiểu như thế này , timer 1 la timer 16 bit nghia la no co thể đếm từ 0 đến 65535 . Khi đếm hết nó sẽ quay lại từ đầu là 0 , và lúc đó sẽ xảy ra ngắt . vd : giả sử cứ 1us timer đế lên 1 , vậy thì khi timer 1 tràn no sẽ đếm được 65535 um =65,535ms=0,065535 s . Vậy để xác định thời gian ngắt thì chỉ việc xác định timer đếm bao nhiêu thôi đúng ko? Bây giờ là cách xác định đây . Thời gian đếm lên của timer phụ thuộc vào chu kỳ lệnh của vi điều khiển . chu kỳ lệnh bằng bao nhiêu thì thời gian định thời của timer củng như vậy . Nếu thạch anh 4M thì chu kỳ lệnh của VDK =1um . Bậy giờ muốn 1s thì timer ngắt , nghia la sau 10^6 um . timer 1 phải ngắt , nhưng timer1 thì ko thể đếm đến 10^6. vậy ta phai sử dung chế độ prescale 1:8 . nghia la cứ 8 chu kỳ lệnh timer1 mới đếm lên 1 .. ==> 8*65535 = 524280 us . #int timer1 void ngat_timer1() { set_timer1(24280); // mặc định giá trị ban đầu cho timer la 24280 . dem++; // timer 1 tràn sau ==> 500 000 us = 0.5s if(dem==2) // 2* 500 000 =1s { ……………….// thực hiện hành động ; dem=0; } } void main setup_timer1(T1_INTERNAL|T1_DIV_BY_8); // cho timer 1 chay ở chế độ timer.Bột chia 8 set_timer1(24280) ; // mặc định số đếm ban đầu cho timer1 la 24280. enable_interrupts(int_timer1); // cho phép ngắt timer 1 enable_interrupts(global); // cho phép ngắt toàn cục while(true) { …………. } Em thấy chỗ set giá trị cho timer1 sai thì phải, chổ này theo e tính toán thì phải là: set_timer1(3035); (65535 – 3035)*1us*8 = 500000us

Mình cũng nghĩ như bạn alycuong là cái set_timer1(3035). Thế thì mỗi lần ngắt Timer nó sẽ đếm được 0.5s do đó cần 2 lần ngắt timer để đếm được 1s. Nhưng ko hiểu sao mình mô phỏng thấy 1s gì mà nhanh khiếp. Mọi người xem hộ mình cái code nhé: #include <16F877A.h> #include <def_877A.h> #fuses NOWDT,PUT,XT,NOPROTECT #use delay(clock=4000000) int16 count; //bien dem /*Khoi tao port*/ void PortInit() { TRISD = 0x00; //PORTD la cong xuat PORTD = 0xFF; //Keo chan PORTD len tro khang cao } /*Khoi tao Timer1*/ void Timer1Init() { set_timer1(3035); setup_timer_1(RTCC_INTERNAL|RTCC_DIV_8); //Chon tan so Timer1 la Internal va chia tan 8 enable_interrupts(int_timer1); //Cho phep ngat tran Timer1 enable_interrupts(global); //Cho phep ngat toan cuc count = 0; } //Chuong trinh ngat TMR0 #int_timer1 void interrupt_timer1() { set_timer1(3035); ++count; if(count == 2) // { count=0; PORTD^=0xFF; //Dao tat ca bit portD } } //Chuong trinh chinh void main(void) { PortInit(); //khoi tao port Timer1Init(); //khoi tao timer1 while(1) { interrupt_timer1(); } }

Có ai giúp em cái này với. Em dùng ngắt timer1 để thử tạo 1 xung trên chân bất kì của PIC8F26K22 để kiểm tra độ chính xác nhưng ko rõ lỗi ở đâu nữa. Thạch anh:16MHz Code của em đây ah #bit Pulse=getenv(“SFR:PORTB”).0 #INT_TIMER1 void Timer1_Isr(void) { set_timer1(65410);//Tràn sau 125 chu kỳ timer Pulse ^=1;//Đảo trạng thái chân PORTB.0 } void main(void) { setup_timer_1(T1_INTERNAL|T1_DIV_BY_8); set_timer1(65410); enable_interrupts(INT_TIMER1); enable_interrupts(global); while(true); } Theo như tính toán của em thì nó phải ra cái xung 2KHz, nhưng mạch thật đo bằng đồng hồ đo tần số là:1.888KHz, mô phỏng ISIS là 1.901KHz Có ai chỉ ra chỗ thiếu sót giúp em với. Thank

tdmh.2508

em có code xuất tần số mà không hiểu đoạn này anh nào pro giúp mình với

//===========================
#int_ext
void dem_xung()
{
so_xung++;
}

#INT_TIMER1
void tao_tre_1s() // Trinh phuc vu ngat tran TIMER1
{
set_timer1(3036); //(65536-3036).1us.8=50 000us
count_t1++; //tran sau 500 000us=0.5us
if(count_t1==2) // 2*500 000=1s
{
tan_so = so_xung;
so_xung = 0;
count_t1 = 0;

}
}
//=====================

chương trình
#include <16f877a.h>
#fuses XT,NOWDT,NOPROTECT,NOLVP
#use delay(clock=4000000)
#use fast_io(d)
#use fast_io(e)
#byte portd=0x08
#bit rs=0x09.0
#bit rw=0x09.1
#bit e=0x09.2
#bit rb0=0x06.0

int16 so_xung,tan_so,count_t1;
int16 tramnghin,chucnghin,nghin,tram,chuc,dv;
int16 u[10]={0x30,0x31,0x32,0x33,0x34,0x35,0x36,0x37,0x38,0x3 9};

#int_ext
void dem_xung()
{
so_xung++;
}

#INT_TIMER1
void tao_tre_1s() // Trinh phuc vu ngat tran TIMER1
{
set_timer1(3036); //(65536-3036).1us.8=50 000us
count_t1++; //tran sau 500 000us=0.5us
if(count_t1==2) // 2*500 000=1s
{
tan_so = so_xung;
so_xung = 0;
count_t1 = 0;

}
}

void ghi_ir()
{
e=1;rs=0;rw=0;e=0;
delay_ms(3);
}
void ghi_dr()
{
e=1;rs=1;rw=0;e=0;
delay_ms(3);
}

void main()
{
{
set_tris_d(0);
set_tris_e(0b000);

enable_interrupts(global);
enable_interrupts(int_ext);
ext_int_edge (H_to_L);
enable_interrupts(INT_TIMER1);
setup_timer_1(T1_INTERNAL|T1_DIV_BY_8);
set_timer1(3036);

portd=0x01;
ghi_ir();
portd=0x0c;
ghi_ir();
portd=0x38;// 2 dong
ghi_ir();

PORTD=0X80;
GHI_IR();
PORTD=”T”;
GHI_DR();
PORTD=”a”;
GHI_DR();
PORTD=”n”;
GHI_DR();
PORTD=” “;
GHI_DR();
PORTD=”S”;
GHI_DR();
PORTD=”o”;
GHI_DR();
PORTD=”:”;
GHI_DR();
}

while(1)
{
tramnghin=tan_so/100000;
chucnghin=(tan_so/10000)%10;
nghin=(tan_so/1000)%10;
tram=(tan_so/100)%10;
chuc=(tan_so/10)%10;
dv=tan_so%10;

portd=0x87;
ghi_ir();
portd=u[tramnghin];
ghi_dr();
portd=u[chucnghin];
ghi_dr();
portd=u[nghin];
ghi_dr();
portd=u[tram];
ghi_dr();
portd=u[chuc];
ghi_dr();
portd=u[dv];
ghi_dr();
portd=”H”;
ghi_dr();
portd=”z”;
ghi_dr();

}
}

Rate this post

Viết một bình luận