การขัดจังหวะ (Interrupt) เป็นคุณสมบัติอย่างหนึ่งของไมโครโปรเซสเซอร์ที่ช่วยให้การประมวลผลข้อมูลเป็นไปอย่างมีประสิทธิภาพมากขึ้น โดยเป็นการหยุดการทำงานที่ดำเนินอยู่ในปัจจุบันชั่วคราว เพื่อไปจัดการกับเหตุการณ์สำคัญบางอย่างที่เกิดขึ้น เช่น การกดปุ่มบนแป้นพิมพ์ การมาถึงของข้อมูลจากอุปกรณ์ภายนอก เป็นต้น เมื่อจัดการกับเหตุการณ์สำคัญเสร็จแล้ว ไมโครโปรเซสเซอร์จะกลับมาทำงานที่ดำเนินอยู่เดิมต่อไป
การขัดจังหวะสามารถแบ่งออกได้เป็น 2 ประเภทหลักๆ คือ
- การขัดจังหวะจากอุปกรณ์ภายนอก (External Interrupt) เป็นการขัดจังหวะที่เกิดจากอุปกรณ์ภายนอก เช่น การกดปุ่มบนแป้นพิมพ์ การมาถึงของข้อมูลจากอุปกรณ์ภายนอก เป็นต้น
- การขัดจังหวะจากซอฟต์แวร์ (Software Interrupt) เป็นการขัดจังหวะที่เกิดจากซอฟต์แวร์ เช่น การเรียกใช้ฟังก์ชัน interrupt ในโปรแกรม
หลักการทำงานของการขัดจังหวะ มีดังนี้
- อุปกรณ์ภายนอกหรือซอฟต์แวร์จะส่งสัญญาณขัดจังหวะไปยังไมโครโปรเซสเซอร์
- ไมโครโปรเซสเซอร์จะหยุดการทำงานที่ดำเนินอยู่ในปัจจุบันชั่วคราว
- ไมโครโปรเซสเซอร์จะบันทึกค่าสถานะการทำงานปัจจุบันลงในหน่วยความจำ
- ไมโครโปรเซสเซอร์จะเปลี่ยนเส้นทางการประมวลผลไปยังโปรแกรมย่อยการขัดจังหวะ
- โปรแกรมย่อยการขัดจังหวะจะจัดการกับเหตุการณ์สำคัญที่เกิดขึ้น
- โปรแกรมย่อยการขัดจังหวะจะส่งสัญญาณกลับไปยังไมโครโปรเซสเซอร์
- ไมโครโปรเซสเซอร์จะกลับมาทำงานที่ดำเนินอยู่เดิม
การขัดจังหวะช่วยให้การประมวลผลข้อมูลเป็นไปอย่างมีประสิทธิภาพมากขึ้น โดยช่วยลดเวลาในการรอคอยของอุปกรณ์ภายนอกหรือซอฟต์แวร์ เนื่องจากไมโครโปรเซสเซอร์จะไม่รอให้ทำงานที่ดำเนินอยู่ในปัจจุบันเสร็จสิ้นก่อนจึงไปจัดการกับเหตุการณ์สำคัญที่เกิดขึ้น
นอกจากนี้ การขัดจังหวะยังช่วยให้สามารถจัดการกับเหตุการณ์สำคัญต่างๆ ได้อย่างทันท่วงที เช่น การกดปุ่มบนแป้นพิมพ์ การมาถึงของข้อมูลจากอุปกรณ์ภายนอก เป็นต้น
ไมโครคอนโทรลเลอร์ ESP32 พัฒนาโดย Espressif Systems มีระบบขัดจังหวะที่ยืดหยุ่นมาก IRAM_ATTR เป็นคำหลักที่ใช้ระบุว่าควรวางฟังก์ชันเฉพาะไว้ใน RAM ภายในของ ESP32 เพื่อการดำเนินการที่รวดเร็วยิ่งขึ้น โดยเฉพาะอย่างยิ่งที่สำคัญอย่างยิ่งสำหรับ Interrupt Service Routines (ISR) เพื่อให้แน่ใจว่าฟังก์ชันดังกล่าวสามารถทำงานได้อย่างรวดเร็วและไม่ถูกขัดจังหวะโดยการทำงานของหน่วยความจำแฟลช .
จำนวน "ชุดการขัดจังหวะ" ที่สามารถรองรับได้:
- จำนวนการขัดจังหวะของฮาร์ดแวร์: ESP32 มีพิน GPIO จำนวนหนึ่ง ซึ่งส่วนใหญ่สามารถกำหนดค่าให้เป็นแหล่งสัญญาณขัดจังหวะภายนอกได้ ตามทฤษฎีแล้ว หมายความว่า GPIO เกือบทุกพินสามารถมีรูทีนขัดจังหวะของตัวเองได้ อย่างไรก็ตาม จำนวนที่แน่นอนอาจน้อยกว่าเล็กน้อย เนื่องจากพินบางตัวอาจมีฟังก์ชันพิเศษหรืออาจไม่ปรากฏบนทุกโมดูล
- การขัดจังหวะที่ใช้ร่วมกัน: เป็นไปได้ที่พิน GPIO หลายอันจะแชร์รูทีนขัดจังหวะเดียว ซึ่งทำได้โดยการตรวจสอบว่าพินใดที่ทำให้เกิดการขัดจังหวะภายใน ISR
- การขัดจังหวะของซอฟต์แวร์และการแจ้งเตือนงาน: นอกเหนือจากการขัดจังหวะด้วยฮาร์ดแวร์แล้ว ESP32 ยังรองรับการขัดจังหวะที่เรียกใช้ซอฟต์แวร์และการแจ้งเตือนงานอีกด้วย สิ่งเหล่านี้ใช้ภายในสภาพแวดล้อม FreeRTOS ที่กรอบงาน ESP-IDF ใช้ โดยทั่วไปแล้วจะไม่ถูกระบุว่าเป็น "การขัดจังหวะ" ในความหมายของไมโครคอนโทรลเลอร์แบบดั้งเดิม แต่มีจุดประสงค์ที่คล้ายกัน
- ข้อจำกัดของ RAM ภายใน (IRAM): แม้ว่าคุณจะสามารถกำหนด ISR ได้จำนวนมาก แต่โปรดจำไว้ว่า IRAM ของ ESP32 นั้นมีจำกัด หากคุณวางฟังก์ชันมากเกินไปหรือฟังก์ชันขนาดใหญ่ใน IRAM โดยใช้ IRAM_ATTR พื้นที่ว่างของคุณอาจหมด คุณต้องจัดการพื้นที่นี้อย่างรอบคอบเพื่อให้แน่ใจว่า ISR ที่สำคัญและฟังก์ชันที่สำคัญอื่นๆ สามารถเหมาะสมได้
ดังนั้น แม้ว่าจะไม่มี "จำนวนชุดของการขัดจังหวะ" ที่เข้มงวดซึ่ง ESP32 สามารถรองรับได้ แต่จำนวนดังกล่าวก็ถูกกำหนดโดยพิน GPIO ที่มีอยู่ซึ่งสามารถตั้งค่าเป็นแหล่งการขัดจังหวะ กลไกการขัดจังหวะระดับซอฟต์แวร์อื่นๆ และความพร้อมใช้งานของ IRAM ช่องว่าง.
อ้างอิงถึงการใช้IRAM_ATTR คำหลักสำหรับรูทีนการบริการขัดจังหวะ (ISR) บน ESP32 โดยทั่วไปจะทำเพื่อให้แน่ใจว่า ISR ถูกจัดเก็บไว้ใน RAM ภายใน (IRAM) ของ ESP32 เพื่อให้สามารถดำเนินการได้อย่างรวดเร็วและไม่ได้รับผลกระทบจากการทำงานของแฟลชที่อาจเกิดขึ้น
อธิบายให้ชัดเจนกว่านี้:
เมื่อเกิดการขัดจังหวะระบบจะต้องตอบสนองทันที อย่างไรก็ตาม ใน ESP32 หากโค้ดของคุณดำเนินการจากหน่วยความจำแฟลช อาจเกิดข้อขัดแย้งได้หากการดำเนินการอื่น เช่น การเขียนหรืออ่านแฟลชเกิดขึ้นพร้อมกัน เมื่อ ISR ไม่ได้อยู่ใน IRAM และกำลังดำเนินการแฟลชเมื่อเกิดการขัดจังหวะ การตอบสนองของการขัดจังหวะอาจล่าช้า ซึ่งอาจนำไปสู่การพลาดการขัดจังหวะหรือปัญหาอื่นๆ
เพื่อป้องกันสิ่งนี้ ควรวางโค้ดสำคัญเช่น ISR ไว้ใน IRAM เพื่อให้แน่ใจว่าการตอบสนองของการขัดจังหวะจะเกิดขึ้นทันที และไม่ต้องรอการทำงานของแฟลชใดๆ
นี่เป็นตัวอย่างง่ายๆ ของวิธีที่คุณอาจใช้IRAM_ATTR ด้วย ISR:
void IRAM_ATTR handleInterrupt() {
// Your ISR code here
}
โดยการวางIRAM_ATTR ก่อนคำจำกัดความฟังก์ชัน ISR คุณกำลังสั่งให้ ESP-IDF (กรอบการพัฒนาอย่างเป็นทางการสำหรับ ESP32) เพื่อวางจัดการขัดจังหวะ ทำงานใน RAM ภายใน ช่วยให้มั่นใจถึงการดำเนินการที่รวดเร็วเมื่อเกิดการขัดจังหวะ
อย่างไรก็ตาม โปรดทราบว่า IRAM มีขนาดจำกัด ดังนั้นให้ใช้IRAM_ATTR อย่างรอบคอบและเฉพาะสำหรับฟังก์ชันที่ความเร็วในการดำเนินการเป็นสิ่งสำคัญ เช่น ISR หากคุณใช้งานมากเกินไป พื้นที่ IRAM ของคุณจะหมด ซึ่งจะส่งผลให้เกิดข้อผิดพลาดในการคอมไพล์
ตัวอย่าง 5 buttons
// Define 5 buttons
struct Button {
const uint8_t PIN;
uint32_t numberKeyPresses;
bool pressed;
};
Button buttons[] = {
{18, 0, false},
{19, 0, false},
{20, 0, false},
{21, 0, false},
{22, 0, false}
};
// ISR for all buttons
void IRAM_ATTR handleInterrupt() {
for (int i = 0; i < 5; i++) {
if (digitalRead(buttons[i].PIN) == LOW) { // If button is pressed
buttons[i].numberKeyPresses++;
buttons[i].pressed = true;
}
}
}
void setup() {
Serial.begin(115200);
// Attach interrupt for all buttons
for (int i = 0; i < 5; i++) {
pinMode(buttons[i].PIN, INPUT_PULLUP);
attachInterrupt(buttons[i].PIN, handleInterrupt, FALLING);
}
}
void loop() {
for (int i = 0; i < 5; i++) {
if (buttons[i].pressed) {
Serial.printf("Button %d has been pressed %u times\n", i + 1, buttons[i].numberKeyPresses);
buttons[i].pressed = false;
}
}
}
อธิบาย Code นี้:
- อาร์เรย์ปุ่ม ใช้สำหรับเก็บข้อมูลทั้ง 5 ปุ่ม
- รูทีนบริการขัดจังหวะครั้งเดียวจัดการขัดจังหวะ ใช้สำหรับปุ่มทั้งหมด ภายใน ISR นี้ จะมีการตรวจสอบแต่ละปุ่มเพื่อดูว่าปุ่มใดถูกกด
- ในระหว่างติดตั้งแต่ละปุ่มจะถูกเตรียมใช้งานเป็นอินพุตพร้อมกับตัวต้านทานแบบดึงขึ้นภายใน และเชื่อมโยงกับรูทีนบริการขัดจังหวะ
- Loop ฟังก์ชั่นตรวจสอบสถานะของปุ่มแต่ละปุ่ม และหากกด จะแสดงผลจำนวนครั้งที่กด
ตรวจสอบให้แน่ใจว่า Pin ที่คุณใช้ (18, 19, 20, 21, 22 ในตัวอย่างนี้) พร้อมใช้งานสำหรับจุดประสงค์นี้บนบอร์ด/โมดูล ESP32 เฉพาะของคุณ ถ้าไม่คุณสามารถเปลี่ยนเป็นหมุดอื่นที่เหมาะสมได้
REF .
https://lastminuteengineers.com/handling-esp32-gpio-interrupts-tutorial/