ฉันคิดว่าการตั้งชื่อเวกเตอร์และหมุดทับซ้อนกันทำให้เกิดความสับสน
มันคือ!
เหตุผลที่มีพินภายนอก 8 แบบที่ต่างกันสำหรับเวกเตอร์ขัดจังหวะคือทำให้การวางเลย์เอาต์ PCB ง่ายขึ้นหรือใช้พินที่แตกต่างกันถ้ามีข้อขัดแย้งกับฟังก์ชั่นพินอื่น
ฉันคิดถูกต้องหรือไม่ ... วิธีเดียวในการพิจารณาว่าพินใดทำให้เกิดการขัดจังหวะคือการบันทึกสถานะหลังจากการขัดจังหวะแต่ละครั้งและเปรียบเทียบค่าก่อนหน้าและปัจจุบันของพินทั้งหมดที่เปิดใช้งานใน PCMSKn?
ค่อนข้างมากสมมติว่าคุณใส่ใจเพียง PB0 (PCINT0) และ PB1 (PCINT1) ดังนั้นการเปลี่ยนพินจะเปิดใช้งานมาสก์ PCMSK0 เป็น 0x03
// External Interrupt Setup
...
volatile u_int8 previousPins = 0;
volatile u_int8 pins = 0;
ISR(SIG_PIN_CHANGE0)
{
previousPins = pins; // Save the previous state so you can tell what changed
pins = (PINB & 0x03); // set pins to the value of PB0 and PB1
...
}
ดังนั้นถ้าpins
เป็น 0x01 คุณรู้ว่ามันเป็น PB0 ... และถ้าคุณต้องการที่จะรู้ว่าสิ่งที่เปลี่ยนแปลงที่คุณต้องการจะเปรียบเทียบกับpreviousPins
สวยมากว่าสิ่งที่คุณคิดว่า
เก็บไว้ในใจในบางกรณีpins
อาจไม่ถูกต้องถ้าขามีสถานะการเปลี่ยนแปลงตั้งแต่ขัดจังหวะ pins = (PINB & 0x03)
แต่ก่อน
อีกทางเลือกหนึ่งคือการใช้เวกเตอร์ขัดจังหวะแยกจากกันด้วยหนึ่งพินจากแต่ละเวกเตอร์เพื่อให้คุณทราบว่ามีการเปลี่ยนแปลงใด อีกครั้งนี้นอกจากนี้ยังมีปัญหาบางอย่างเช่นการจัดลำดับความสำคัญการขัดจังหวะและเมื่อ CPU เข้าสู่ ISR ที่ทั่วโลกขัดจังหวะเปิดใช้งานบิตI-bit
ในSREG
จะถูกล้างเพื่อให้การขัดจังหวะอื่น ๆ ทั้งหมดถูกปิดใช้งานแม้ว่าคุณสามารถตั้งค่าภายในขัดจังหวะถ้าคุณต้องการที่จะ ขัดจังหวะซ้อน
สำหรับข้อมูลเพิ่มเติมดูที่แอปของ Atmel โดยใช้ External Interrupts สำหรับ megaAVR Devices
ปรับปรุง
นี่เป็นตัวอย่างที่สมบูรณ์รหัสฉันเพิ่งพบที่นี่
#include <avr/io.h>
#include <stdint.h> // has to be added to use uint8_t
#include <avr/interrupt.h> // Needed to use interrupts
volatile uint8_t portbhistory = 0xFF; // default is high because the pull-up
int main(void)
{
DDRB &= ~((1 << DDB0) | (1 << DDB1) | (1 << DDB2)); // Clear the PB0, PB1, PB2 pin
// PB0,PB1,PB2 (PCINT0, PCINT1, PCINT2 pin) are now inputs
PORTB |= ((1 << PORTB0) | (1 << PORTB1) | (1 << PORTB2)); // turn On the Pull-up
// PB0, PB1 and PB2 are now inputs with pull-up enabled
PCICR |= (1 << PCIE0); // set PCIE0 to enable PCMSK0 scan
PCMSK0 |= (1 << PCINT0); // set PCINT0 to trigger an interrupt on state change
sei(); // turn on interrupts
while(1)
{
/*main program loop here */
}
}
ISR (PCINT0_vect)
{
uint8_t changedbits;
changedbits = PINB ^ portbhistory;
portbhistory = PINB;
if(changedbits & (1 << PB0))
{
/* PCINT0 changed */
}
if(changedbits & (1 << PB1))
{
/* PCINT1 changed */
}
if(changedbits & (1 << PB2))
{
/* PCINT2 changed */
}
}