การขัดจังหวะประเภท "การเปลี่ยนพิน" มีสองประเภท การขัดจังหวะภายนอกซึ่งมีสองอย่างใน Uno พวกเขาเรียกว่า 0 และ 1 แต่พวกเขาอ้างถึงหมุดดิจิตอล 2 และ 3 บนกระดาน เหล่านี้สามารถกำหนดค่าให้ตรวจจับเพิ่มขึ้นลดลงเปลี่ยน (เพิ่มขึ้นหรือลดลง) หรือต่ำ
นอกจากนั้นยังเป็นการขัดจังหวะ "การเปลี่ยนพิน" ซึ่งตรวจจับการเปลี่ยนแปลงสถานะพินใน 20 พินใด ๆ (A0 ถึง A5 และ D0 ถึง D13) การขัดจังหวะการเปลี่ยนพินเหล่านี้ยังเป็นไปตามฮาร์ดแวร์ดังนั้นในตัวมันเองจะเร็วเท่ากับการขัดจังหวะภายนอก
ทั้งสองชนิดมีการใช้งานในระดับรีจิสเตอร์เล็กน้อย แต่ IDE มาตรฐานประกอบด้วย attachInterrupt (n) และ detachInterrupt (n) ซึ่งทำให้อินเตอร์เฟซเข้ากับอินเตอร์รัปต์ภายนอกได้ง่าย คุณยังสามารถใช้Pin Change Libraryเพื่อทำให้การขัดจังหวะการเปลี่ยนพินง่ายขึ้น
อย่างไรก็ตามการล้างไลบรารีเป็นเวลาหนึ่งนาทีเราสามารถสร้างการขัดจังหวะการเปลี่ยนพินได้เร็วหรือเร็วกว่าอินเตอร์รัปต์ภายนอก สำหรับสิ่งหนึ่งแม้ว่าการเปลี่ยนพินจะหยุดการทำงานของแบทช์ แต่คุณไม่จำเป็นต้องเปิดใช้งานแบทช์ทั้งหมด ตัวอย่างเช่นหากคุณต้องการตรวจจับการเปลี่ยนแปลงในพิน D4 สิ่งนี้จะพอเพียง:
ตัวอย่างร่าง:
ISR (PCINT2_vect)
{
// handle pin change interrupt for D0 to D7 here
if (PIND & bit (4)) // if it was high
PORTD |= bit (5); // turn on D5
else
PORTD &= ~bit (5); // turn off D5
} // end of PCINT2_vect
void setup ()
{
// pin change interrupt (example for D4)
PCMSK2 |= bit (PCINT20); // want pin 4
PCIFR |= bit (PCIF2); // clear any outstanding interrupts
PCICR |= bit (PCIE2); // enable pin change interrupts for D0 to D7
pinMode (4, INPUT_PULLUP);
pinMode (5, OUTPUT);
} // end of setup
void loop ()
{
}
การทดสอบของฉันระบุว่าใช้เวลา 1.6 fors สำหรับพิน "ทดสอบ" (พิน 5) เพื่อตอบสนองต่อการเปลี่ยนแปลงของหมุดขัดจังหวะ (ขา 4)
ตอนนี้ถ้าคุณใช้วิธีง่ายๆ (สันหลังยาว) และใช้ attachInterrupt () คุณจะพบว่าผลลัพธ์ช้าลงไม่เร็วขึ้น
รหัสตัวอย่าง:
void myInterrupt ()
{
if (PIND & bit (2)) // if it was high
PORTD |= bit (5); // turn on D5
else
PORTD &= ~bit (5); // turn off D5
} // end of myInterrupt
void setup ()
{
attachInterrupt (0, myInterrupt, CHANGE);
pinMode (2, INPUT_PULLUP);
pinMode (5, OUTPUT);
} // end of setup
void loop ()
{
}
สิ่งนี้ใช้เวลา 3.7 tos ในการเปลี่ยนพินการทดสอบมากกว่า 1.6 aboves ด้านบน ทำไม? เนื่องจากรหัสที่คอมไพเลอร์จำเป็นต้องสร้างสำหรับตัวจัดการขัดจังหวะ "ทั่วไป" จึงต้องบันทึกการลงทะเบียนที่เป็นไปได้ทั้งหมด (ดันพวกมัน) เมื่อเข้าสู่ ISR แล้วกู้คืนพวกมัน (ป๊อปพวกเขา) ก่อนกลับมา นอกจากนี้ยังมีค่าใช้จ่ายในการเรียกใช้ฟังก์ชั่นอื่น
ตอนนี้เราสามารถแก้ไขได้โดยหลีกเลี่ยง attachInterrupt () และทำมันเอง:
ISR (INT0_vect)
{
if (PIND & bit (2)) // if it was high
PORTD |= bit (5); // turn on D5
else
PORTD &= ~bit (5); // turn off D5
} // end of INT0_vect
void setup ()
{
// activate external interrupt 0
EICRA &= ~(bit(ISC00) | bit (ISC01)); // clear existing flags
EICRA |= bit (ISC00); // set wanted flags (any change interrupt)
EIFR = bit (INTF0); // clear flag for interrupt 0
EIMSK |= bit (INT0); // enable it
pinMode (2, INPUT_PULLUP);
pinMode (5, OUTPUT);
} // end of setup
void loop ()
{
}
นั่นคือความเร็วที่เร็วที่สุดของพวกเขาทั้งหมดที่ 1.52 --s - ดูเหมือนว่าหนึ่งรอบนาฬิกาได้รับการบันทึกไว้ที่ไหนสักแห่ง
มีข้อแม้หนึ่งประการสำหรับการอินเตอร์รัปต์การเปลี่ยนพิน พวกมันจะถูกแบทช์ดังนั้นถ้าคุณต้องการที่จะขัดจังหวะด้วยหมุดจำนวนมากคุณต้องทดสอบภายในอินเทอร์รัปต์ที่เปลี่ยนไป คุณสามารถทำได้โดยการบันทึกสถานะพินก่อนหน้าและเปรียบเทียบกับสถานะพินใหม่ นี่ไม่จำเป็นว่าช้ามากนัก แต่ยิ่งคุณต้องตรวจสอบพินมากเท่าไหร่ก็ยิ่งช้า
กระบวนการคือ:
- A0 ถึง A5
- D0 ถึง D7
- D8 ถึง D13
หากคุณต้องการหมุดขัดจังหวะอีกสองสามตัวคุณสามารถหลีกเลี่ยงการทดสอบใด ๆ ได้โดยเพียงเลือกใช้พินจากแบตช์ต่าง ๆ (เช่น D4 และ D8)
รายละเอียดเพิ่มเติมได้ที่http://www.gammon.com.au/interrupts