![]() |
|
![]() |
#1 |
Đệ tử 7 túi
Tham gia ngày: Jul 2007
Nơi Cư Ngụ: Đà Nẵng
Bài gửi: 188
: |
Lúng túng với Interrupts - nhờ trợ giúp
Code:
#include <16F877A.h> #include <DEFINE_16F877A.h> #include <DEFINE_16F87x.h> #fuses NOWDT,XT,NOPROTECT,NOLVP,PUT #use delay(clock=4000000) #define RS RC0 #define RW RC1 #define E RC2 #define LCD PORTD #define mo_khoa RA0 #define kichSCR RA1 #define OK RA2 #define CANCEL RA3 const unsigned char num[] = {' ','0','1','2','3','4','5','6','7','8','9'} ; const unsigned char pass[] = {' ','3','9','5','2','6','1','0'} ; // password unsigned char key[] ; unsigned char a = 0 ; // bien tang cac so nhap vao key [a++] unsigned char i ; // bien hien thi cac so da nhan , sau khi nhan OK //---------------------------- void delay_ms_MAIN(unsigned int j) { unsigned int k , l; for( k=0 ; k<=j;k++) { l = j ; while(l!=0) l-- ; } } //---------------------------- void delay_ms_INT(unsigned int j) { unsigned int k , l; for( k=0 ; k<=j;k++) { l = j ; while(l!=0) l-- ; } } void ham_DK_MAIN() { RS = 0 ; RW = 0 ; E =1 ; E=0 ; delay_ms_MAIN(2);} void ham_HienThi_MAIN() { RS = 1 ; RW = 0 ; E =1 ; E=0 ; delay_ms_MAIN(1);} //---------------- void ham_DK_INT() { RS = 0 ; RW = 0 ; E =1 ; E=0 ; delay_ms_INT(2);} void ham_HienThi_INT() { RS = 1 ; RW = 0 ; E =1 ; E=0 ; delay_ms_INT(1);} //---------------------- void quetphim_hienthi() { PORTB = 0b11101111 ; if(RB0==0) { delay_ms_INT(20) ; while (RB0==0) continue ; delay_ms_INT(20); LCD = num[1] ; ham_HienThi_INT(); key[a++] = num[1]; // key[a++] = '0' } ; if(RB1==0) { delay_ms_INT(20) ; while (RB1==0) continue ; delay_ms_INT(20); LCD = num[2] ; ham_HienThi_INT(); key[a++] = num[2]; // key[a++] = '1' } ; if(RB2==0) { delay_ms_INT(20) ; while (RB2==0) continue ; delay_ms_INT(20); LCD = num[3] ; ham_HienThi_INT(); key[a++] = num[3]; // key[a++] = '2' } ; PORTB = 0b11011111 ; if(RB0==0) { delay_ms_INT(20) ; while (RB0==0) continue ; delay_ms_INT(20); LCD = num[4] ; ham_HienThi_INT(); key[a++] = num[4]; // key[a++] = '3' } ; if(RB1==0) { delay_ms_INT(20) ; while (RB1==0) continue ; delay_ms_INT(20); LCD = num[5] ; ham_HienThi_INT(); key[a++] = num[5]; // key[a++] = '4' } ; if(RB2==0) { delay_ms_INT(20) ; while (RB2==0) continue ; delay_ms_INT(20); LCD = num[6] ; ham_HienThi_INT(); key[a++] = num[6]; // key[a++] = '5' } ; PORTB = 0b10111111 ; if(RB0==0) { delay_ms_INT(20) ; while (RB0==0) continue ; delay_ms_INT(20); LCD = num[7] ; ham_HienThi_INT(); key[a++] = num[7]; // key[a++] = '6' } ; if(RB1==0) { delay_ms_INT(20) ; while (RB1==0) continue ; delay_ms_INT(20); LCD = num[8] ; ham_HienThi_INT(); key[a++] = num[8]; // key[a++] = '7' } ; if(RB2==0) { delay_ms_INT(20) ; while (RB2==0) continue ; delay_ms_INT(20); LCD = num[9] ; ham_HienThi_INT(); key[a++] = num[9]; // key[a++] = '8' } ; PORTB = 0b01111111 ; if(RB0==0) { delay_ms_INT(20) ; while (RB0==0) continue ; delay_ms_INT(20); LCD = num[10] ; ham_HienThi_INT(); key[a++] = num[10]; // key[a++] = '9' } ; } #int_RB void ngat_RB() { while(OK!=0) { quetphim_hienthi();} delay_ms_INT(20); RBIF =0; } main() { set_tris_A(0b00001100); output_A(0b001100); set_tris_B(0x0F); output_B(0x0F); // port B = keypad set_tris_C(0); set_tris_D(0); delay_ms_MAIN(100); // thoi gian LCD khoi dong LCD = 0x38 ; ham_DK_MAIN(); // modify LCD 2 dong matrix 5x7 LCD = 0x0C ; ham_DK_MAIN(); // tat con tro bat hien thi enable_interrupts(global); enable_interrupts(int_RB); ext_int_edge(H_to_L); while(1) { LCD = 0xC4 ; ham_DK_MAIN(); // hien chu dong 2 cot 5 LCD = 'R' ; ham_HienThi_MAIN(); LCD = 'e' ; ham_HienThi_MAIN(); LCD = 'a' ; ham_HienThi_MAIN(); LCD = 'd' ; ham_HienThi_MAIN(); LCD = 'y' ; ham_HienThi_MAIN(); LCD = '!' ; ham_HienThi_MAIN(); } ; } ![]() hiện tượng xảy ra thế này - khi cho dòng lệnh enable_interrupts(global) - cho phép ngắt - thì LCD ko hiện dòng chữ gì cả ? ngay cả khi ta reset để cố tình cho ct chỉ chạy trong MAIN (tức là phải có dòng "ready!' - khi disable_interrupts(global) thì dòng "ready!" hiện ra ( có thể hiểu là ct chạy đúng theo ý đồ ) tại sao vậy ? - chả lẽ set_tris các port bị sai so với phần cứng ? - hay khởi tạo ngắt chưa đúng , nên ct nhảy ngắt lung tung ? |
![]() |
![]() |
![]() |
#2 |
...Damned...
Tham gia ngày: Apr 2006
Nơi Cư Ngụ: Hồ Chí Minh
Bài gửi: 522
: |
Nếu bạn debug = ICD2 thì INT_RB sẽ hoạt động ko đúng, vi lúc này 2 chân RB6 RB7 do ICD2 điều khiển.
Trong hàm phục vụ ngắt bạn không cần xóa cờ ngắt, trình dịch tự sinh mã làm điều này cho bạn. Bạn có thể sử dụng thư viện giao tiếp LCD của CCS C(trong thư mục /drivers) |
![]() |
![]() |
![]() |
#3 |
Đệ tử 7 túi
Tham gia ngày: Jul 2007
Nơi Cư Ngụ: Đà Nẵng
Bài gửi: 188
: |
- thư viện LCD trong PICC/drivers là giao tiếp 4 bit , mình đang giao tiếp 8 bit
- mới nhập môn nên ko hiểu ICD2 là cái gì , đc biết nó là mạch debug ngoài , ko biết có đúng ko ? nhưng mình đang test ct trên mạch thật . Do đó , điều thắc mắc bây giờ là : cần chỉnh lại ct chỗ nào để chạy đúng ý đồ( ý đồ : khi có ngắt thì quét phím & hiển thị số đã bấm ; khi ko có ngắt thì hiện dòng READY! ) hay phải thay đổi lại phần cứng ? |
![]() |
![]() |
![]() |
#4 |
Đệ tử 4 túi
Tham gia ngày: Jul 2006
Nơi Cư Ngụ: Bốn biển là nhà
Bài gửi: 69
: |
Bạn coi lại chân RA2==OK, bạn dùng CCS thì khi chạy, sau khi enable interrupts thì chuơng trình sẽ nhảy vào ISR liền. Khi đó nếu RA2=1 thì chuơng trình chỉ chạy trong phần ISR ( int_RB) mà thôi, chưa kịp tới vòng while(1) để hiển thị chữ ready.
__________________
YM: electronicltv |
![]() |
![]() |
![]() |
#5 | |
Đệ tử 7 túi
Tham gia ngày: Jul 2007
Nơi Cư Ngụ: Đà Nẵng
Bài gửi: 188
: |
Trích:
cách giải thích của bien_van_khat có vẻ đúng . Mình nghĩ hơi nông cạn ! hic.... |
|
![]() |
![]() |
![]() |
#6 |
...Damned...
Tham gia ngày: Apr 2006
Nơi Cư Ngụ: Hồ Chí Minh
Bài gửi: 522
: |
Thực tế nếu ko xài ICD2, theo mình với chương trình như trên ngắt RB không bao giờ xảy ra vì bạn cấu hình PORTB<4:7> là output. Do 4 chân này không được pull-up hoặc pull-down nên cho dù cấu hình là input bạn cũng không thể dùng ngắt INT_RB theo đúng ý đồ được.
Chương trình của bạn viết khá rối rắm nên mình mới khuyên dùng thư viện của CCS, ví dụ Code:
ext_int_edge(H_to_L); Để kiểm tra nguyên nhân bạn thử disable INT_RB xem. |
![]() |
![]() |
![]() |
#7 | |
Đệ tử 7 túi
Tham gia ngày: Jul 2007
Nơi Cư Ngụ: Đà Nẵng
Bài gửi: 188
: |
Trích:
uhm ! đúng như bạn nói , khi mình disable int_RB thì mọi chuyện hoạt động bình thường Bây giờ : - cho 4 con trở 10k kéo xuống ở chân RB4 - RB7 . - còn cấu hình cho ngắt khi thay đổi mức trên RB , mình phải chữa lại ntn ? ĐÚng là mình chưa nghĩ thấu đáo vấn đề ! |
|
![]() |
![]() |
![]() |
#8 |
Đệ tử 7 túi
Tham gia ngày: Jul 2007
Nơi Cư Ngụ: Đà Nẵng
Bài gửi: 188
: |
Code:
#use delay(clock=4000000) #use fast_io(b) #use fast_io(c) int a; const unsigned char dig[]={0b00111111,0b00000110, 0b01011011,0b01001111,\ 0b01100110,0b01101101,0b01111101,0b00000111,0b01111111,0b01101111,0b01110111,\ 0b01111100,0b00111001,0b01011110,0b11111001,0b11110001}; // ma hoa digital duoi dang mang // Chuong trinh ngat #int_RB void ngat_RB() { if((RBIF)&&(RBIE)) { { if(RB4&&RB0) a=dig[0]; } { if(RB4&&RB1) a=dig[4]; } { if(RB4&&RB2) a=dig[8]; } { if(RB4&&RB3) a=dig[12]; } //....... { if(RB5&&RB0) a=dig[1]; } { if(RB5&&RB1) a=dig[5]; } { if(RB5&&RB2) a=dig[9]; } { if(RB5&&RB3) a=dig[13]; } //........ { if(RB6&&RB0) a=dig[2]; } { if(RB6&&RB1) a=dig[6]; } { if(RB6&&RB2) a=dig[10]; } { if(RB6&&RB3) a=dig[14]; } //........ { if(RB7&&RB0) a=dig[3]; } { if(RB7&&RB1) a=dig[7]; } { if(RB7&&RB2) a=dig[11]; } { if(RB7&&RB3) a=dig[15]; } RBIF=0; //Xoa co ngat RB } } // Chuong trinh chinh main() { set_tris_b(0b11110000); set_tris_c(0); enable_interrupts(global); enable_interrupts(int_RB); ext_int_edge(H_to_L); portb=0; portc=0; while(true) { portb=1; portb=2; portb=4; portb=8; portc=a; } } ![]() đây là mạch & code của anh nnh - có phải mắc mạch quét phím kiểu này thì mới dùng đc INT_RB ? ah có vẻ bây giờ mình đã phân biệt đc : ngắt có thay đổi mức trên RB & ngắt ngoài trên RB . Ko biết mình hiểu như thế đã trọn vẹn chưa ? |
![]() |
![]() |
![]() |
#9 |
...Damned...
Tham gia ngày: Apr 2006
Nơi Cư Ngụ: Hồ Chí Minh
Bài gửi: 522
: |
Sơ đồ cũng như code bạn vừa đưa ra ở đây cũng có vấn đề, mình nghĩ rằng nó chỉ hoạt động đúng khi mô phỏng còn khi chạy thực tế mạch sẽ không ko hoạt động như ý đồ.
Thứ 1 về pull-up hoặc pull-down. Khi hoạt động thực tế, bạn không bao giờ được để Input pin lơ lửng như thế. Khi ở mode input, trở kháng vào của chân IO là trở kháng vào của cực Gate của MOSFET. Do trở kháng vào này cực kỳ lớn nên chỉ cần một sự biến thiên điện trường nhỏ cũng đủ gây nên một xung điện áp trên mạch vào, điện áp này đủ khả năng để đầu ra của Smith trigger thay đổi trạng thái, hoặc khiến mạch vào TTL chuyển mức. Nói tóm lại là tín hiệu đọc trên PORT sẽ nhảy tùm lum dù ko có phím bấm. Vậy nên dùng pull-up hay pull-down? Thiết kế input ko nên sử dụng pull-down, vì nếu pull-down, tức là khi idle, mức logic=0, vậy để chuyển mức logic thành 1, bạn cần phải đưa lên nguồn Vdd qua một điện trở hạn dòng (ko hạn dòng sẽ làm hư IO pin). Như vậy rõ ràng một mạch vào cần 2 điện trở là ko hiệu quả về linh kiện, chưa nói đến hiệu quả về thiết kế nếu IO pin cần hạn dòng nhiều, bạn phải tính toán giá trị điện trở cho phù hợp. Sử dụng pull-up vừa tiết kiệm vừa đơn giản. Thứ 2, ngắt thay đổi mức trên PORTB bạn có thể coi trong datasheet của 16F877A, đây là ngắt xảy ra khi mức logic trên PORTB<4:7> thay đổi (từ 0->1 hoặc từ 1->0). Bạn nên để ý là với 877A chỉ có 4 bit cao của PORTB là có chức năng này thôi nhé, và chỉ xảy ra khi chân đó là input. Với mạch của bạn rõ ràng vấn đề nằm ở ngắt INT_RB, bạn có thể mắc thêm 4 con 10K lên Vdd, hoặc gọi hàm Code:
port_b_pullups(TRUE); |
![]() |
![]() |
![]() |
#10 |
Đệ tử 7 túi
Tham gia ngày: Jul 2007
Nơi Cư Ngụ: Đà Nẵng
Bài gửi: 188
: |
![]() ![]() Code:
#int_RB void ngat_RB() { while(OK!=0) { quetphim_hienthi();} delay_ms(20); } main() { set_tris_A(0b00001100); output_A(0b001100); set_tris_B(0xF0); // port B = keypad set_tris_C(0); set_tris_D(0); delay_ms(100); // thoi gian LCD khoi dong enable_interrupts(global); enable_interrupts(int_RB); ext_int_edge(H_to_L); lcd_int() ; while(1) { // cho hiển thị dòng "READY!" } ; } - LCD giao tiếp 4 bit ( để lợi dụng thư viện CCS) - ma trận phím để sd INT_RB - cách viết code như vậy đã đúng : khi có ngắt thay đổi mức trên RB4-RB7 thì tạo ngắt & ct nhảy vào quetphim_hienthi() ; ko thì hiện dòng READY ! |
![]() |
![]() |
![]() |
#11 |
Đệ tử 7 túi
Tham gia ngày: Jul 2007
Nơi Cư Ngụ: Đà Nẵng
Bài gửi: 188
: |
các bạn cho ý kiến về mạch + ct để mình hoàn thiện trước khi đi in . Chắc cái mạch mình đang test ... vứt đi rùi ! Làm lại mạch mới thôi ... cũng tốn kha khá đấy chứ nhẩy ? hic !
|
![]() |
![]() |
![]() |
|
|