|
Tài trợ cho PIC Vietnam |
Cơ bản về vi điều khiển và PIC Những bài hướng dẫn cơ bản nhất để làm quen với vi điều khiển PIC |
|
Ðiều Chỉnh | Xếp Bài |
|
14-05-2009, 11:31 PM | #1 |
Nhập môn đệ tử
Tham gia ngày: Aug 2008
Bài gửi: 10
: |
hỏi về ngắt ngoài để đếm xung
Chào các bạn ! mình sử dụng pic6f877a để đếm xung ngoài đo tốc độ của một cái trục, mỗi khi cái trục quay vòng thì có 1 xung (từ mức cao xuống mức thấp).Có một vấn đề là mình phải dùng chân nào để đếm xung, và khai báo trong chương trình (mình dùng ccs) như thế nào.Vì hiện giờ mình đã sử dụng các chân T0CKI,T1CKI,các chân portb, RD5->RD7 trong mạch.Vậy ngoài các chân trên có còn cách nào đọc xung vào không, và khai báo cụ thể trong chương trình ra sao các bạn có thể chỉ giúp mình không?
|
15-05-2009, 10:48 AM | #2 |
Đệ tử 6 túi
Tham gia ngày: Jul 2007
Bài gửi: 146
: |
tùy tốc độ của cái trục đó, bạn có thể dùng chân ngắt ngoài để xử lý nếu nó quá nhanh, còn nếu mà nó quay chậm, cứ dùng 1 chân I/O bất kỳ rồi rùng timer quét cũng OK.
__________________
mạch nạp - kit phát triển - linh kiện điện tử www.PNLabvn.com |
15-05-2009, 01:23 PM | #3 |
Nhập môn đệ tử
Tham gia ngày: Aug 2008
Bài gửi: 10
: |
bạn có thể nói cụ thể hơn quét timer là sao không? mình mới sử dụng pic nên còn gà lắm.
|
15-05-2009, 01:59 PM | #4 |
Đệ tử 6 túi
Tham gia ngày: Oct 2008
Nơi Cư Ngụ: HCM
Bài gửi: 137
: |
là dùng timer2(cái còn lại duy nhất mà bạn chưa dùng) sau khoảng thời gian do bạn tự tính rồi đếm số vòng quay của trục rùi suy ra tốc độ của nó.
Nếu trục quay tương đối chậm thì bạn dùng bất kỳ chân i/o nào còn lại của pic cũng được miễn là bạn set nó là input. nếu trục chạy quá nhanh thì bạn chịu khó chế cho nó 01 bộ bánh răng giảm tốc rồi từ công thức tỉ số truyền tương ứng tính ra số vòng quay của trục.
__________________
A&A |
15-05-2009, 05:27 PM | #5 |
Đệ tử 6 túi
Tham gia ngày: Jul 2007
Bài gửi: 146
: |
bạn định thời cho timer một khoảng tràn ngắn, đủ để ít nhất là 2 lần khi có 1 chuyển mức từ trục (nguyên tắc để ko mất xung) , rồi bạn kiểm tra cái chân bạn nối trạng thái của trục mà chân này bạn đã để là input nhé, kiểm tra xem nó có chuyển mức ko, nếu có thì đếm, bạn đếm 1 biến khác ở mỗi lần timer tràn, chia 2 cái này cho nhau là ra tốc độ.
__________________
mạch nạp - kit phát triển - linh kiện điện tử www.PNLabvn.com |
15-05-2009, 05:50 PM | #6 |
Nhập môn đệ tử
Tham gia ngày: Aug 2008
Bài gửi: 10
: |
mình đã sử dụng 1 chân là input rồi.Cái trục của mình quay cũng chậm thôi (khoảng 0.5-2s/vòng).Tuy nhiên mình thử đưa vào thì số nó chạy liên tục.Nghĩa là cứ mức 1 thì nó tăng biến đếm liên tục, nếu ko có xung thì giá trị vào là 1.Trong chương trình phải viết như thế nào để khi có sự thay đổi trạng thái của chân input thì biến đếm mới tăng?mình dùng ccs để viết.Hiện giờ mình chỉ cần làm sao tính được số xung trong khoảng thời gian delta t là ổn.MÌnh sử dụng chân rc5 làm input. đoạn code mình như thế này,giá trị x sau đó xuất ra led 7 đoạn.
void docxung() { if (input(PIN_C5)==0) count=count+1; x=count; else x=count; } |
15-05-2009, 06:34 PM | #7 | |
Đệ tử 6 túi
Tham gia ngày: Oct 2008
Nơi Cư Ngụ: HCM
Bài gửi: 137
: |
Trích:
đo tốc độ của trục nghĩa là bạn đếm liên tục số vòng quay của trục trong khoảng thời gian nhất định gọi là thời gian lấy mẩu(có chu kỳ nha bạn -->dùng ngắt timer) rồi sau khoảng thời gian đó bạn lấy số vòng quay đó chia cho thời gian mà bạn lấy mẩu sẽ ra tốc độ của trục. vd: bạn đếm liên tục ngõ vào rc5 trong khoảng 1s được 5 vòng thì tốc độ trục khi đó là 5 vòng/s. bạn nghiên cứu lại có nếu vẫn chưa thông thì cứ post lên mọi người sẽ hổ trợ bạn!
__________________
A&A |
|
15-05-2009, 06:55 PM | #8 |
Nhập môn đệ tử
Tham gia ngày: Aug 2008
Bài gửi: 10
: |
đúng như bạn nói, bảng led tăng liên tục khi cấp nguồn, mình chỉ đang thắc mắc là dùng lệnh gì để "chốt" giá trị count khi nó quay hết 1 vòng, nghĩa là chỉ khi có sự thay đổi giá trị của chân input thì biến đếm mới tăng,mình chưa viết đoạn timer định thì sau 1 khoảng thời gian.đoạn code trên mình viết để hiển thị ra bảng led thôi chứ không phải giá trị cuối cùng mình tính ra ,nhưng nếu có giá trị đó thì có thể tính dc tốc độ.Tuy nhiên mình đang khúc mắc ở trên như đã nói đó.
|
16-05-2009, 12:26 AM | #9 |
Đệ tử 3 túi
Tham gia ngày: Nov 2007
Bài gửi: 48
: |
void docxung()
{ if (input(PIN_C5)==0) // them doan nay ne ban while(input(PIN_C5)==0); // ko làm gì đến khi rc5 lên 1 /// count=count+1; x=count; else x=count; } /// nghĩa là khi đã vào trạng thái tích cực mức 0, thì chờ cho nó hết trạng thái đó rồi mới tăng biến đếm. đó là cách giải quyết vần đề bạn thắc mắc, còn đo tốc độ thì đúng như cách lequocbao nói. |
16-05-2009, 11:56 AM | #10 |
Nhập môn đệ tử
Tham gia ngày: Aug 2008
Bài gửi: 10
: |
mình đã thử đoạn code trên nhưng không được bạn ơi.doạn code trên khi có chân input chuyển về 0 thì bảng led tăng liên tục.Vì trục quay chậm cho nên mỗi khi có xung xuống thì mất 1 khoảng thời gian nó mới chuyển mức(khoảng nửa giây), mà trong khoảng thời gian đó biến count tăng liên tục(vài chục giá trị) theo như code trên, như vậy là không đúng.Cái mình cần là làm sao khi thay đổi thì nó chỉ tăng lên 1 đơn vị thôi, và chờ cho tới khi tiếp tục thay đổi trạng thái .Mình chưa cần quan tâm tới chiều quay mà chỉ cần đếm được số lần thay đổi trạng thái chân input trước đã.
|
16-05-2009, 12:07 PM | #11 |
Nhập môn đệ tử
Tham gia ngày: Aug 2008
Bài gửi: 10
: |
À mình đã giả quyết được rồi, đoạn code như sau
void docxung() { if (input(PIN_C5)==0) { while(input(PIN_C5)==0); // ko lam gi cho toi khi thay doi muc /// count=count+1; x=count; break; } else { x=count; break;} } vì không thoát ra khỏi vòng lặp sau khi tăng biến count, nên biến sẽ tăng liên tục. Nhân tiện hỏi các bạn luôn là mình định dùng timer0 để đếm giá trị xung vào(số vòng quay) trong vòng 10s chẳng hạn, vậy mình phải đặt đoạn code trên ở chỗ nào, và giá trị khai báo cho timer cụ thể ra sao? |
17-05-2009, 12:06 PM | #12 | |
Đệ tử 6 túi
Tham gia ngày: Oct 2008
Nơi Cư Ngụ: HCM
Bài gửi: 137
: |
Trích:
vd: như bạn nói là pin_c5 sẽ ở mức logic 0 là khoảng 0.5s ,mà tạm tính thời gian để pic quét toàn bộ chương trình là 0.1s(vd thôi nha bạn hì hì) thì có phải là sau 0.5s biến count sẽ tăng lên 5 đơn vị (vì điều kiện để tăng biến count là pin_c5==0 vẫn thõa mãn ở 4 lần quét chưong trình còn lại)đúng không nào?trong khi bạn chỉ muốn là count chỉ tăng 1 đơn vị bạn chịu khó post toàn bộ code chương trình lên đây rùi mọi người sẽ hướng dẫn cho bạn là nên "nhét" đoạn code của bạn vào chổ nào!
__________________
A&A thay đổi nội dung bởi: lequocbao, 17-05-2009 lúc 12:18 PM. |
|
17-05-2009, 07:21 PM | #13 |
Nhập môn đệ tử
Tham gia ngày: Aug 2008
Bài gửi: 10
: |
chương trình hiện tại mình kết hợp như sau
#include <16F877A.h> #priority EXT,TIMER1,timer0 #fuses NOWDT,PUT,XT,NOPROTECT,NOLVP,HS #device *=16 #use delay(clock=20000000) #use fast_io(b) #use fast_io(d) #use fast_io(c) #byte portb=0x06 #byte portd=0x08 #byte portc=0x07 #byte PORTB = 0x06 unsigned char led1,led2,led3; int16 count=0 ; int32 dem=0; int16 xung=0; int32 vantoc=0; int32 x=0; int32 timer=0; void convert_bcd(int32 x); void display(); #int_timer0 void interrupt_timer0() { set_timer0(6); { ++dem; if(dem >= 20000)// 20000*500us = 10s dem=0; {if (input(PIN_C5)==0) { while(input(PIN_C5)==0); count=count+1; xung=count; break;} else { xung=count; break;} } } vantoc=(xung/10);//tinh ra van toc (xung/giay) } //void docxung() void convert_bcd(int32 x) { led1 = x / 100; x = x %100; led2 = x / 10; led3 = x % 10; } void display() { char maled7[] = {0x7e,0x18,0xec,0xe6,0xd2,0xb6,0xbe,0x62,0xfe,0xf6 }; portb = (maled7[led3]); output_low(PIN_D5); delay_us(90); output_high(pin_D5); portb = (maled7[led2]); output_low(PIN_D6); delay_us(90); output_high(pin_D6); portb = (maled7[led1]); output_low(PIN_D7); delay_us(90); output_high(pin_D7); } //Chuong trinh chinh void main(void) { set_tris_b(0); set_tris_d(0x00); set_tris_c(0xFf);// dau vao la C7,C6,C5,C4,xung vao chan c5 enable_interrupts(int_timer0); setup_timer_0(RTCC_INTERNAL|RTCC_DIV_2); enable_interrupts(global); set_timer0(6);// T_dinhthi =delay= 2*(256 - 6)*1us = 500us //INitTIMER0=6;prescaler=2(do RTCC_div_2 while(true) { // hien thi so xung ra led 7 doan x=xung; convert_bcd(x); display(); } } chương trình như trên ý định của mình là xuất ra 3 led 7 đoạn giá trị xung đếm được sau 10s(dùng timer0 delay 10s , trong thời gian đó đếm số xung).Tuy nhiên khi nạp vào chip thì chạy không đúng, mỗi khi có xung thì nó tăng 1 giá trị, trên bảng led (3 led 7 đoạn) giá trị tăng dần chứ không đúng ý đồ.MÌnh đã thử đặt đoạn chương trình đoc xung vào nhiều chỗ nhưng chưa đúng.Mong các bạn giúp đỡ vì thời gian với mình cũng không còn nhiều. |
18-05-2009, 02:19 PM | #14 | |
Đệ tử 6 túi
Tham gia ngày: Oct 2008
Nơi Cư Ngụ: HCM
Bài gửi: 137
: |
Trích:
+chương trình chính: -đọc liên tục chân rc5 nếu có sự thay đổi mức logic từ 1 sang 0 thì biến count tăng 1. - quét 3 led 7 đoạn với tham số truyền là x. - sau 1s thì xảy ra ngắt timer.(theo mình bạn nên kiểm tra tốc độ sau 1s or 0.5s là hợp lý hơn, do trục quay tương đối chậm nên hiển thị led 7 đoạn là vòng/s nha). +chương trình phục vụ ngắt timervd sau 1s) - lấy biến x=count; - xóa biến count; -trở về chương trình chính. bạn tham khảo thử đoạn code trên mình đã sữa lại,còn nữa bạn chú ý các dấu {} nha,mình thấy bạn bỏ tứ tung hết.Còn nữa nếu không có gì đặt biệt thì bạn nên gom 2 hàm convert_bcd(x) và display() lại 1 lun cho gọn khi lập trình.khi đó bạn chỉ cần gọi hàm convert_bcd_display(x); là ok rùi.
__________________
A&A thay đổi nội dung bởi: lequocbao, 18-05-2009 lúc 02:25 PM. |
|
18-05-2009, 10:40 PM | #15 |
Nhập môn đệ tử
Tham gia ngày: Aug 2008
Bài gửi: 10
: |
Cảm ơn bạn, mình đã giải quyết được vấn đề rồi.Nhưng vẫn còn một vài vấn đề nhỏ
Chương trình hoàn chỉnh như sau : #include <16F877A.h> #priority EXT,TIMER1,timer0 #fuses NOWDT,PUT,XT,NOPROTECT,NOLVP,HS #device *=16 #use delay(clock=20000000) #use fast_io(b) #use fast_io(d) #use fast_io(c) #byte portb=0x06 #byte portd=0x08 #byte portc=0x07 #byte PORTB = 0x06 unsigned char led1,led2,led3; int16 count=0 ; int32 dem=0; float vantoc; int32 x=0; void convert_bcd(int32 x); void docxung(); #int_timer0 void interrupt_timer0() { set_timer0(6); ++dem; if(dem ==18200)// 5s { dem=0; x=count; count=0; } }//ket thuc ngat timer void convert_bcd(int32 x) { led1 = x / 100; x = x %100; led2 = x / 10; led3 = x % 10; { char maled7[] = {0x7e,0x18,0xec,0xe6,0xd2,0xb6,0xbe,0x62,0xfe,0xf6 }; portb = (maled7[led3]); output_low(PIN_D5); delay_us(90); output_high(pin_D5); portb = (maled7[led2]); output_low(PIN_D6); delay_us(90); output_high(pin_D6); portb = (maled7[led1]); output_low(PIN_D7); delay_us(90); output_high(pin_D7); } } void docxung() { if(input(pin_c5)==0) { count++; while(input(pin_c5)==0) convert_bcd(x); } } void main(void) { set_tris_b(0); set_tris_d(0x00); set_tris_c(0xFf);// dau vao la C7,C6,C5,C4,xung vao chan c5 enable_interrupts(int_timer0); setup_timer_0(RTCC_INTERNAL|RTCC_DIV_2); enable_interrupts(global); set_timer0(6);// T_dinhthi =delay= 2*(256 - 6)*0.2us = 100us count=0; while(true) { docxung(); convert_bcd(x); }} Mình muốn hiển thị giá trị của vận tốc ra xung/s (hay vòng/s).Nhưng giá trị này tính ra theo thực tế phải là dạng số thực chứ không phải là số nguyên (3 led hiển thị giá trị số nguyên).MÌnh định chuyển giá trị đó sao cho nhìn trên led 7 đoạn có thể thấy được giá trị.Ví dụ 1.52 vòng/s thì hiển thị trên led là 152 chẳng hạn.Mình thêm đoạn như sau: vantoc=(count/10); x=vantoc*100; Tuy nhiên mình thấy hiển thị trên led không đúng.Không biết phải sử dụng các biến như thế nào để có được kết quả chính xác. Ngoài ra mình sử dụng công thức T_dinhthi =delay= 2*(256 - 6)*0.2us = 100us khi đó để có 10s thì giá trị của biến dem là 100000, nhưng mình thử lại thì không đúng, phải là 20000, vì mình dùng thạch anh 20mhz .Như vậy giá trị trên phải là 500us (T_dinhthi =delay= 2*(256 - 6)*1us = 500us) cho thạch anh 4mhz ?Thực tế là mình dùng đồng hồ bấm giờ tính ra như trên(viết 1 đoạn chương trình ngắn dịch led bằng timer thử nghiệm và dùng đồng hồ bấm giây kiểm tra.) Ai có thể giải thích tại sao chỉ dùm mình với . |
|
|