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);
để sử dụng weak pull-up bên trong chip.