Pendahuluan
Dalam suatu pekerjaan atau aktivitas seringkali terjadi penyelaan atau penghentian akivitas untuk sementara waktu karena adanya suatu hal yang memerlukan perhatian ataupun penanganan. Interupsi adalah suatu kejadian dalam sistem komputer yang meminta pelayanan khusus pada CPU ketika CPU sedang melakukan pemrosesan.

Dalam merespon interupsi, CPU menunda eksekusi program saat itu dan melakukan percabangan ke Interrupt Service Routine (ISR, rutin layanan interupsi) atau disebut juga vektor interupsi. ISR adalah sebuah program yang melayani interupsi. Setelah eksekusi ISR, CPU kembali lagi ke program yang menginterupsi (penginterupsi), ini artinya CPU akan melanjutkan program yang tersisa ketika sebelum terjadi percabangan.
Pada proses interupsi, status CPU sebelum melayani ISR harus disimpan. Ketika akan kembali dari ISR, status yang tersimpan diambil (load) kembali ke CPU.
Sebuah mikrokontroler dapat melayani beberapa device. Terdapat 2 metode dalam melayaninya yaitu: interupsi dan polling.
Interupsi adalah metode di mana ketika suatu device ingin mendapatkan pelayanan dari mikrokontroler, maka device itu sendiri yang memintanya atau melakukan notifikasi dengan cara mengirimkan sebuah sinyal interupsi.

Ketika mikrokontroler menerima sinyal interupsi tersebut maka dengan serta merta mikrokontroler menghentikan aktivitas atau pekerjaan apa pun yang sedang dilakukan saat itu, dan kemudian segera melayani atau mengerjakan perintah yang diisyaratkan oleh device penginterupsi. Pekerjaan atau program yang harus dikerjakan oleh mikrokontroler ketika terjadi interupsi disebut interrupt service routine (ISR) atau disebut juga interrupt handler.
Pada metode polling, mikrokontroler yang melakukan pemantauan (monitoring) atau pemeriksaan secara proaktif terhadap sejumlah device yang kemungkinan akan mengajukan permintaan pelayanan maupun yang tidak. Sehingga sebagian waktu mikrokontroler akan terbuang untuk melakukan pemantauan terhadap sejumlah device walaupun device tersebut sebenarnya tidak sedang meminta/menginginkan layanan. Metode ini tidak efisien dibandingkan dengan metode interupsi.

Keuntungan lain dari metode interupsi adalah dapat melayani banyak device (tentunya tidak dalam waktu yang bersamaan), setiap device dapat memperoleh layanan dari mikrokontroler berdasarkan prioritas interupsi (interrupt priority) yang telah ditetapkan. Sedangkan metode polling tidak dapat mengetahui prioritas layanan karena dilakukan dengan cara round-robin. Pada metode interupsi, mikrokontroler dapat melakukan penghalangan (masking) atau mengabaikan interupsi tertentu yang tidak dapat dilakukan pada metode polling.
Pada kasus timer, anda dapat melihat efisiensi mikrokontroler antara menggunakan metode interupsi dengan metode polling. Misalnya, ketika anda menggunakan instruksi pengujian terhadap bit overflow pada timer: “while ((TIFR & (1<<TOV1)) == 0);”. Instruksi ini akan melakukan looping secara terus-menerus atau melakukan pemantauan terhadap bit TOV1 hingga terjadi roll-over pada timer. Selama melakukan pemantauan tersebut maka mikrokontroler tidak dapat melakukan pekerjaan lain. Jadi, jelas bahwa hal ini akan membuang waktu mikrokontroler yang seharusnya dapat digunakan untuk aktivitas/pekerjaan lain yang lebih bermanfaat.
Pada kasus timer ini, jika digunakan metode interupsi maka mikrokontroler dapat melakukan pekerjaan lain, dan ketika flag TOV1 muncul maka timer akan menginterupsi mikrokontroler apapun yang sedang dikerjakan mikrokontroler saat itu.
Interupsi AVR ATmega16/32/8535
Mikrokontroler AVR ATmega16 mempunyai 3 buah pin untuk melakukan interupsi eksternal, yaitu INT0, INT1 dan INT2. Interupsi eksternal ini dapat dibangkitkan jika pada pin interupsi terdapat tepi naik atau tepi turun ataupun level logika 0 (kecuali INT2 yang hanya dapat dipicu oleh tepi naik atau tepi turun). Ketika interupsi eksternal aktif dan dikonfigurasikan sebagai level triggered (hanya untuk INT0/INT1) interupsi akan memicu selama pin ditahan dalam level logika low.
Interupsi juga mempunyai prioritas pemrosesan. Jika terdapat dua interupsi yang terjadi secara bersamaan, maka interupsi yang mempunyai prioritas lebih tinggi yang akan dieksekusi. Urutan interupsi yang prioritasnya paling tinggi yaitu yang mempunyai alamat atau vektor interupsi yang terendah.

Interupsi Eksternal
Register MCUCR & MCUSCR
Pengaturan kondisi yang menyebabkan terjadinya interupsi eksternal diatur oleh register MCUCR (MCU Control Register) dan MCUCSR (MCU Control & Status Register).

- Bit 3, 2 – ISC11, ISC10: Interrupt Sense Control 1 Bit 1 and Bit 0. Bit-bit kontrol pengindra interupsi 1. Interupsi eksternal 1 diaktifkan oleh pin INT1 jika bit-I pada register SREG (Status Register) dan bit penghalang interupsi pada register GICR (General Interrupt Control Register) yang bersesuaian dalam keadaan set ‘1’.

- Bit 1, 0 – ISC01, ISC00: Interrupt Sense Control 0 Bit 1 and Bit 0. Bit-bit kontrol pengindra interupsi 0. Interupsi eksternal 0 diaktifkan oleh pin INT0 jika bit-I pada register SREG dan bit penghalang interupsi pada register GICR yang bersesuaian dalam keadaan set ‘1’.

.

- Bit 6 – ISC2: Interrupt Sense Control 2. Interupsi eksternal 2 asinkron diaktifkan melalui pin INT2 jika bit-I pada register SREG dan bit penghalang interupsi pada register GICR yang bersesuaian dalam keadaan set ‘1’

.
Register GICR
Pemilihan pengaktifan interupsi ekternal diatur oleh register interupsi umum GICR.

- Bit 7 – INT1: External Interrupt Request 1 Enable. Jika bit INT1 set ‘1’ dan bit-I pada register SREG set ‘1’, maka interupsi pin eksternal 1 diaktifkan. Jika sebaliknya bit INT1 = ‘0’ maka tidak aktif.
- Bit 6 – INT0: External Interrupt Request 0 Enable. Jika bit INT0 set ‘1’ dan bit-I pada register SREG set ‘1’, maka interupsi pin eksternal 0 diaktifkan. Jika sebaliknya bit INT0 = ‘0’ maka tidak aktif.
- Bit 5 – INT2: External Interrupt Request 2 Enable. Jika bit INT2 set ‘1’ dan bit-I pada register SREG set ‘1’, maka interupsi pin eksternal 2 diaktifkan. Jika sebaliknya bit INT2 = ‘0’ maka tidak aktif.
.
PEMROGRAMAN INTERUPSI DENGAN BAHASA C
Untuk mengatur interupsi WinAVR/ATMEL Studio/AVR GCC, hal yang perlu ditambahkan adalah:
- Interrupt Include File: Kita harus memasukkan interrupt header file jika kita ingin menggunakan interupsi dalam program. --> #include <avr\interrupt.h>
- cli() dan sei(): Pada pemrograman assembly instruksi CLI dan SEI berturut-turut meng-clear dan menge-set bit I dalam register SREG. Dalam WinAVR/ATMEL Studio/AVR GCC macro cli() dan sei() melakukan tugas yang sama.
- Penetapan ISR: untuk menulis ISR (Interrupt Service Routine) pada sebuah interupsi, maka digunakan struktur berikut:

untuk nama_vektor_interupsi kita harus menggunakan nama-nama ISR seperti yang diberikan pada Tabel. Misalnya, ISR berikut mengerjakan interupsi Timer0 compare match:

.

.
Contoh 1:
Program berikut adalah proses interupsi ekternal 0 – INT0 logika low (dengan low level). Rutin ISR menyalakan LED pada PORTA.0, PORTA.2, PORTA.4 dan PORTA.6. Saklar pada PORTD.2 (INT0) dalam keadaan normally high.

.
Program:

.
/*
* INTERUPSI 1.c
*
* Created: 03/02/2023 8:23:21
* Author : DELL
*/
#include <avr/io.h>
#include <avr/interrupt.h>
int main ()
{
DDRA = 0xff; //PORTA sebagai output
PORTA = 0xff; //semua LED padam
DDRD = 0x00; //PORTD sebagai input
PORTD = 0xff; //pull-up aktif
GICR = 0x40; //enable INT0
MCUCR = 0x00; //;inisialisasi untuk level low pada masukan PD2
sei(); //enable interrupt
while(1); //tunggu di sini
}
ISR(INT0_vect) //ISR untuk interupsi eksternal-0
{
PORTA = 0b10101010; //menyalakan LED portA0, portA2, portA4, portA6
}
.
Video Demo:
.
.
Contoh 2:
Program berikut adalah proses interupsi ekternal 0 – INT0 falling edge (dengan peralihan tepi ‘1’ ke ‘0’- tepi turun). Rutin ISR menyalakan LED pada PortA.0 secara toggle. Saklar pada PORTD.2 (INT0) dalam keadaan normally high.

Program:

.
/*
* INTERUPSI 2.c
*
* Created: 03/02/2023 8:27:20
* Author : DELL
*/
#include <avr/io.h>
#include <avr/interrupt.h>
int main ()
{
DDRA = 0xff; //PORTA sebagai output
PORTA = 0xff; //semua LED padam
DDRD = 0x00; //PORTD sebagai input
PORTD = 0xff; //pull-up aktif
GICR = 0x40; //enable INT0
MCUCR = 0x02; //inisialisasi untuk falling edge pada masukan PD2
sei(); //enable interrupt
while(1); //tunggu di sini
}
ISR(INT0_vect) //ISR untuk interupsi eksternal-0
{
PORTA ^= 1<<0; //toggle LED portA0
}
.
Video Demo:
.
Interupsi Timer AVR ATmega32/16/8535
ROLLOVER TIMER FLAG DAN INTERUPSI
Sebelum ini telah dibahas bab tentang bagaimana menggunakan Timer 0, 1 dan 2 dengan metode polling, saat ini akan dibahas penggunaan metode interupsi pada pemrograman Timer AVR. Pada metode polling, Timer overflow flag dibangkitkan saat terjadinya rollover. Di bab tersebut telah diperlihatkan bagaimana memantau timer flag dengan instruksi “while ((TIFR & (1<<TOV1)) == 0);”. Artinya, anda harus menunggu hingga flag TOV1 dibangkitkan. Masalah yang ditimbulkan dengan cara ini adalah mikrokontroler akan terpaku/terikat pada pemantauan TOV1 sampai dibangkitkan, sehingga mikrokontroler tidak dapat mengerjakan yang lainnya.
Dengan menggunakan interupsi maka hal tersebut tidak akan terjadi (mikrokontroler bisa mengerjakan yang lain). Jika interupsi timer pada register interupsi di-enable, maka TOV1 dibangkitkan saat timer rollover dan mikrokontroler melompat ke tabel vektor interupsi untuk mengerjakan ISR.
Untuk menggunakan metode interupsi sebagai pengganti polling, maka pertama kita harus meng-enable interupsi karena semua interupsi dalam keadaan masking (terhalang). Bit TOIEx meng-enable interupsi untuk Timer. Bit TOIEx berada dalam register TIMSK sedangkan bit TOVx ada dalam register TIFR.

.
Contoh 3:
Program berikut adalah interupsi Timer 0 yang membangkitkan gelombang kotak (7,15 us) pada PORTB.5. Dan dalam waktu yang sama kondisi 8 saklar pada PORTC dikirim ke 8 LED melalui PORTA berdasarkan gambar sirkuit berikut:

Program:

.
/*
* INTERUPSI 3.c
*
* Created: 03/02/2023 8:37:11
* Author : DELL
*/
#include <avr/io.h>
#include <avr/interrupt.h>
int main ()
{
DDRB = 0x20; //PORTB5 sebagai output
DDRC = 0x00; //PORTC sebagai input
DDRA = 0xff; //PORTA sebagai output
PORTA = 0xff; //semua LED padam
PORTC = 0xff; //pull-up aktif
TCCR0 = 0x01;
TIMSK = 0x01; //;interupsi Timer0 overflow di-enable
sei(); //enable interrupt
while(1) //tunggu di sini
PORTA = PINC;
}
ISR(TIMER0_OVF_vect) //ISR untuk interupsi Timer0 overflow
{
PORTB ^= 0x20; //toggle PORTB5
TCNT0 = -32;
}
.
Video Demo:
.
.
Contoh 4:
Gunakan interupsi Timer0 dan Timer1 untuk membangkitkan gelombang kotak pada PORTB.0 dan PORTB.1. Dan dalam waktu yang sama kondisi 8 saklar pada PORTC dikirim ke 8 LED melalui PORTA berdasarkan gambar sirkuit berikut:

Program:

.
/*
* INTERUPSI 4.c
*
* Created: 03/02/2023 9:16:19
* Author : DELL
*/
#include <avr/io.h>
#include <avr/interrupt.h>
int main ()
{
DDRB = 0x21; //PORTB0 dan PORTB5 sebagai output
DDRC = 0x00; //PORTD sebagai input
DDRA = 0xff; //PORTA sebagai output
PORTA = 0xff; //semua LED padam
PORTC = 0xff; //pull-up aktif
TIMSK = 0x05; //interupsi Timer0 dan Timerl overflow di-enable
TCNT0 = -160; //nilai timer 20 us
TCCR0 = 0x01; //normal, intenal clock, tanpa prescaler (N=1)
TCNT1L = (-640); //byte bawah
TCNT1H = (-640) >> 8; //byte atas
TCCR1A = 0x00;
TCCR1B = 0x01;
sei(); //enable interrupt
while(1) //tunggu di sini
PORTA = PINC;
}
ISR(TIMER0_OVF_vect) //ISR untuk interupsi Timer0 overflow
{
PORTB ^= 0x01; //toggle PORTB0
TCNT0 = -160;
}
ISR(TIMER1_OVF_vect) //ISR untuk interupsi Timerl overflow
{
PORTB ^= 0x20; //toggle PORTB5
TCNT1L = (-640); //byte bawah
TCNT1H = (-640) >> 8; //byte atas
}
Video Demo:
.
.
Contoh 5:
Program berikut ini mempunyai dua interupsi.
- PORTD (LED active high) mencacah naik setiap Timer1 mengalami overflow. Dan setiap satu detik terjadi overflow.
- Pulsa diumpankan dari Timer0, di mana Timer0 digunakan sebagai counter dan mencacah naik. Ketika counter mencapai cacahan 200, maka PORTB.0 akan toggle
- Kondisi Push button pada PORTC ditampilkan pada LED (active low) yang terhubung pada PORTA

.
/*
* INTERUPSI 5.c
*
* Created: 03/02/2023 9:53:56
* Author : DELL
*/
#include <avr/io.h>
#include <avr/interrupt.h>
int main ()
{
DDRA = 0xff; //PORTA dan PORTD sebagai output
PORTA = 0xFF;
DDRC = 0x00; //PORTC sebagai input
PORTC = 0xFF;
DDRD = 0xff;
DDRB |= 0x01; //PORTB0 sebagai input
TCCR0 = 0x01; //normal, tanpa prescaler (N=1)
TCNT0 = -200; //isikan timer dengan -200
TCNT1L = (-31250) & 0xFF; //overflow setalah 31250 clock
TCNT1H = (-31250) >> 8; //byte atas
TCCR1A = 0x00; //mode normal
TCCR1B = 0x04; //internal clock, prescaler 256
TIMSK = 0x05; //interupsi Timer0 dan Timerl overflow di-enable
sei(); //enable interrupt
while(1) //tunggu di sini
PORTA = PINC;
}
ISR(TIMER0_OVF_vect) //ISR untuk interupsi Timer0 overflow
{
PORTB ^= 0x01; //toggle PORTB0
TCNT0 = -200;
}
ISR(TIMER1_OVF_vect) //ISR untuk interupsi Timerl overflow
{
PORTD++; //increment PORTD
TCNT1L = (-31250) & 0xFF; //overflow setalah 31250 clock
TCNT1H = (-31250)>>8; //byte atas
}
Video Demo:
Berikut ini link semua program di atas:
https://drive.google.com/file/d/1I5L2sSynygHlODA0dNel8ybgY6Y-6YGg/view?usp=sharing