การเขียนโปรแกรม Interrupt

การเขียนโปรแกรม Interrupt

ในการทำงานของ MCS-51 จะทำงานตามคำสั่ง (Instruction) ที่เราโปรแกรมเข้าไป โดยจะทำการประมวลผลคำสั่งต่อไปเรื่อยๆ ทำให้การทำงานของ MCS-51 ทำงานได้ทีละอย่าง ทีนี้มีคำถามว่าถ้าเราต้องการให้ MCS-51 ทำงาน 2 อย่างหรือหลายอย่างคู่ขนานกันไปได้ไหม คำตอบก็คือได้ครับ เราจะใช้กระบวนการที่เรียกว่า interrupt มาตอบสนองการทำงานแบบหลายๆอย่างคู่ขนานกันไป

ตัวอย่างเช่น ถ้าเราจะทำนาฬิกาจาก 7Segment จะต้องมีการ scan display อยู่ตลอดเวลา ด้วยคาบเวลาคงที่ ถ้า scan display อย่างเดียวก็ไม่มีปัญหาอะไร แต่ถ้าต้องอ่านค่าเวลาจาก RTC (Real Time Clock) ด้วย display คงจะกระตุกเพราะต้่องรอให้อ่านค่าเวลาจาก RTC เสร็จก่อน

การทำงานของ interrupt เริ่มจาก MCS-51 ประมวลผล instruction ที่ 1, 2, 3…. ไปเรื่อยๆ เมื่อมีสัญญาณ interrupt ขึ้นมา stack จะทำการจำตำแหน่งล่าสุดไว้ และกระโดดไปจัดการกับ interrupt (Interrupt service routine) เมื่อจัดการกับ interrupt service routine เสร็จแล้วก็จะอ่านค่าตำแหน่งจาก stack เพื่อกลับไปยังตำแหน่งเดิมที่กระโดดออกมา

รูปที่ 1

ในการสั่งให้ interrupt ทำงานทำได้ตามขั้นตอนดังนี้

  1. เซตบิต EA ที่รีจิสเตอร์ IE
  2. เซตบิต interrupt ที่ต้องการ
  3. เขียนการทำงานที่ interrupt service routine ซึ่ง interrupt แต่ละตัวจะมี vector address ต่างตำแหน่งกัน ดังตารางด้านล่าง
    Interrupt Source
    Vector Address
    IE0
    0003H
    TF0
    000BH
    IE1
    0013H
    TF1
    001BH
    RI & TI
    0023H
    TF2 & EXF2
    002BH

สำหรับขา INT0 และ INT1 จะต้องเซตให้ P3.2 และ P3.3 เป็น “1″ ก่อน

IE : Interrupt Enable register เป็น Register ที่จะ enable การทำงานของ interrupt แต่ละตัว

1 = Enable, 0 = Disable

7
6
5
4
3
2
1
0
EA
-
ET2
ES
ET1
EX1
ET0
EX0
  • EA IE.7 บิต enable/disable interrupt ทั้งหมด
  • ET2 IE.5 บิต enable/disable Timer 2
  • ES IE.4 บิต enable/disable Serial port
  • ET1 IE.3 บิต enable/disable Timer1
  • EX1 IE.2 บิต enable/disable External Interrupt 1
  • ET0 IE.1 บิต enable/disable Timer 0
  • EX0 IE.0 บิต enable/disableExternal Interrupt 1

การกำหนดความสำคัญ(Priority) ของ interrupt

ถ้ามีเหตุการณ์ interrupt เกิดขึ้นซ้อนกันเช่นกำลังอยู่ในโปรแกรม interrupt Timer 0 แล้วมี interrupt EX0 เกิดขึ้นในขณะที่ interrupt Timer 0 ยังไม่เสร็จ MCS-51 จะดูความสำคัญ (Priority) ของ interrupt ที่มาทีหลัง ว่ามี priority สำคัญกว่าหรือไม่ ถ้า interrupt ตัวที่มาทีหลังมี priority สูงกว่าก็จะกระโดดไปตอบสนอง interrupt ตัวหลัง

รูปที่ 2

โดยปกติแล้ว MCS-51 จะจัด priority เรียงจากสูงสุดไปต่ำสุดดังนี้

  • IE0
  • TF0
  • IE1
  • TF1
  • RI or TI
  • TF2 or EXF2

เราสามารถกำหนด priority ของ MCS-51 ได้ใหม่ได้ที่รีจีสเตอร์ IP

0 หมายถึง priority ต่ำสุด, 1 หมายถึง priority สูงสุด

7
6
5
4
3
2
1
0
-
-
PT2
PS
PT1
PX1
PT0
PX0
  • PT2 IP.5 กำหนดให้ Timer 2 interrupt มี priority สูงสุด
  • PS IP.4 กำหนดให้ Serial port interrupt มี priority สูงสุด
  • PT1 IP.3 กำหนดให้ Timer 1 interrupt มี priority สูงสุด
  • PX1 IP.2 กำหนดให้ External Interrupt 1 มี priority สูงสุด
  • PT0 IP.1 กำหนดให้ Timer 0 interrupt มี priority สูงสุด
  • PX0 IP.0 กำหนดให้ External Interrupt 0 มี priority สูงสุด

ในการเขียนโปรแกรม interrupt ในภาษา C (Keil) ไม่ได้กำหนดเป็น Vector address แบบภาษาแอซเซมบลี เราสามารถเขียนเป็น sub routine ได้เลย และจะมีตัวเลขต่อท้าย เช่น void timer0_handler() interrupt 1 ตัวเลขที่ต่อท้ายเป็นการกำหนดว่าจะตอบสนองที่ vector address ไหน

Interrupt Source
interrupt number
External interrupt 0 (IE0)
0
Time 0 (TF0)
1
External interrupt 1 (IE1)
2
Timer 1 (TF1)
3
Serial port
4