Interupsi
Sebuah Mikrokontroler dapat melayani beberapa perangkat. Untuk melakukan hal itu, terdapat dua cara yaitu interupsi atau polling. Pada metode interupsi, kapanpun sebuah perangkat membutuhkan pelayanannya, perangkat tersebut akan mengingatkan mikrokontroler dengan cara mengirimkan sebuah sinyal interupsi. Pada saat menerima sinyal interupsi, mikrokontroler akan menyela apapun yang sedang dilakukannya dan melayani perangkat tersebut. Program yang bekerjasama dengan interupsi dinamakan Interrupt Service Routine (ISR) atau Interrupt Handler.
Keuntungan dari interupsi adalah mikrokontroler dapat melayani banyak perangkat; tentunya tidak pada waktu yang sama, setiap perangkat bias mendapat perhatian dari mikrokontroller berdasarkan dengan prioritas yang diberikan kepadanya. Yang lebih penting, pada metode interupsi sebuah mikrokontroler dapat mengabaikan sebuah perangkat yang meminta service. Jadi dalam situasi untuk tidak memaksa sebuah mikrokontroler bekerja, interupsi digunakan.
Interrupt Service Routine
Untuk setiap interupsi, harus selalu ada Interrupt Service Routine (ISR). Ketika interupsi sedang diminta, mikrokontroler akan menjalankan Interrupt Service Routine. Untuk setiap interupsi, selalu ada lokasi pada memory yang menyimpan alamat dari ISR itu sendiri.
Langkah-langkah dalam mengeksekusi Interupsi
Pada saat mengaktifkan sebuah interupsi, mikrokontroler melewati tahap-tahap berikut ini:
Mikrokontroler menyelesaikan instruksi yang sedang dieksekusinya dan menyimpan alamat dari instruksi selanjutnya dari tumpukan instruksi-instruksi yang ada.
MIkrokontroler juga menyimpan status saat ini dari setiap interupsi didalamnya.
Mikrokontroler langsung mengakses ke lokasi memori yang menyimpan alamat dari ISR.
Setelah mendapat alamat dari ISR, mikrokontroler mulai mengeksekusi interrupt subroutine sampai mencapai instruksi terakhir dari subroutine tersebut atau disebut dengan RETI (return from interrupt)
Pada saat mengeksekusi instruksi dari RETI, mikrokontroler akan kembali ke tempat dimana dia disela terakhir kali. Pertama, mikrokontroler mendapatkan alamat Program Counter (PC) dari tumpukan instruksi yang ada dengan cara memunculkan dua bit teratas dari tumpukan instruksi kedalam PC. Kemudian mikrokontroler mulai mengeksekusinya dari alamat yang didapatnya.
Struktur Interupsi
Gambar Struktur sistem interupsi pada mikrokontroler
Fasilitas interupsi yang disediakan oleh mikrokontroler ada 5 buah interupsi, yang masing-masing dikelompokkan menjadi interupsi timer, eksternal dan serial. Kapan masing-masing interupsi dilayani, bergantung pada posisi saklar. Sebagai contoh, bila diinginkan layanan interupsi TIMER 0 (TF0) , maka posisi saklar ET0, dan EA harus ditutup yang dilakukan secara software, agar layanan TIMER 0 ini mendapatkan prioritas utama maka saklar PT0 harus diposisikan ke UP.
Timer dan Counter
Timer/Counter dalam mikrokontroler merupakan fasilitas yang salah satu fungsinya dapat digunakan sebagai pewaktu atau cacahan suatu event. Sumber clock atau pemicau dapat dibangkitkan dari sinyal eksternal maupun internal.
Jika sumber sinyal pemicu atau clock berasal dari internal maka Timer/Counter berfungsi sebagai pewaktu atau timer dan jika sumber sinyal berasal dari luar maka disebut sebagai pencacah atau counter.
Mikrokontroler ATMega16 memiliki 3 buah timer yaitu Timer0, Timer1 dan Timer2. Timer0 dan Timer2 memiliki kapasitas 8-bit sedangkan Timer1 memiliki kapasitas 16-bit. Apa yang dimaksud timer 8 bit dan 16 bit?
Timer 8-bit adalah pewaktu yang bisa mencacah atau menghitung hingga maksimal nilai 0xFF heksa (dalam biner = 11111111).
Timer 16-bit sama seperti timer 8-bit, hanya saja nilai maksimalnya mencapai 0xFFFF.
Gambar 1. Diagram blok TIMERn (n diganti dengan 1) Register
Timer1 yang akan kita libatkan di awal ini adalah:
TCCR1B
TCNT1
TIMSK
TIFR
Register TCCR1B, ditunjukkan pada Gambar 2, merupakan tempat pengaturan clock yang intinya agar Timer/Counter1 bisa bekerja, maka register TCCR1B ini jangan sampai diisi dengan 0x00 (dikosongkan).
Gambar 2. Register TCCR1B
Kenapa tidak boleh berisi 0x00 atau semua bit pada TCCR1B nol semua? Coba perhatikan Tabel 1. Sumber clock bisa berasal dari internal mulai dari prescaler 1 hingga 1024 atau bisa juga dari sumber eksternal, semua bisa diatur sesuai atau mengikuti aturan pada Tabel 1.
Apa nilai praskalar itu? Timer1 (juga timer/counter lainnya) membutuhkan sumber detak atau clock source. Biasanya sumber detak yang biasa kita pakai berasal dari XTAL. Besarnya maksimum sama dengan XTAL yang digunakan dan minimum XTAL/1024. Nah nilai pembagi atau 1024 inilah yang disebur nilai praskalar atau prescaler.
Apa yang terjadi jika semua bit di TCCR1B nol semua? Artinya bit 0, 1 dan 2 juga nol semua, perhatikan Gambar 2, itu artinya CS12=0, CS11=0 dan CS10=0 dan itu menurut Tabel 1 “No clock source (Timer/Counter stopped)” Timer berhenti bekerja! Atau tidak bekerja!
Tabel 1. Konfigurasi sumber clock atau detak pada TCCR1B
Register TCNT1 merupakan register pencacah, artinya nilai di dalamnya akan dinaikkan setiap kali ada pemicu, bisa tepi naik atau tepi turun. Jika sumbernya dari dalam (internal) pencacahan dilakukan pada saat tepi naik. Register ini akan mencacah naik dari 0x0000 sampai nilai max 0xFFFF kemudian di-reset kembali lagi ke 0x0000.
Overflow (melimpah) terjadi saat kondisi dari 0xFFFF ke 0x0000, sehingga mengakibatkan bit TOV1 pada register TIFR akan di-set (diberi logika 1). Kondisi overflow juga bisa digunakan untuk menjalankan interrupsi.
Register TIMSK, yang ditunjukkan pada Gambar 3, merupakan register tempat pengaturan interupsi overflow dari Timer/Counter1 yang ingin diaktifkan atau tidak. Dengan memberikan logika 1 pada bit TOIE1 (bit-2 pada TIMSK), maka interupsi Timer/Counter1 aktif dengan catatan bit interupsi global diaktifkan (bit-7 di register Status SREG, perhatikan Gambar 4).
Perhatikan juga bit-bit lain yang berkaitan dengan masing-masing Timer:
Timer/Counter-0: OCIE0 dan TOIE0 – masing-masing bit 1 dan 0;
Timer/Counter-1: TICIE1, OCIE1A, OCIE1B dan TOIE1 – masing-masing bit 5, 4, 3 dan
2;
Timer/Counter-2: OCIE2 dan TOIE2 – masing-masing bit 7 dan 6;
Gambar
3
. Register
TIMSK
Gambar 4 Register SREG
Penjelasan register SREG:
I – Global Interrupt Enable: digunakan untuk mengaktifkan interupsi menyeluruh (global); T – Bit copy storage
H – Half Carry Flag
S – Sign bit
V – Two‟s Complement Overflow Flag
N – Negative flag
Z – Zero flag
C – Carry flag
Sedangkan register TIFR (Timer/Counter Interrupt Flag Register), sebagaimana ditunjukkan pada Gambar 5, digunakan sebagai indikator atau penanda apakah sudah terjadi overflow atau belum. Pada Timer/Counter1, kondisi overflow ditandai dengan logika 1 pada bit TOV1 (bit-2) pada register TIFR.
Gambar 5. Register TIFR
Persamaan untuk mencari waktu jeda yang ingin digunakan adalah berdasarkan nilai awal yang harus dimasukkan ke dalam TCNT1, gunakan persamaan berikut:
TCNT1 = (1+0xFFFF) - (waktu *( XTAL / praskalar) )
Waktu waktu yang diinginkan
XTAL frekuensi kristal yang dipakai
praskalar nilai prescaler.
Pemrograman Timer dan Counter
Pemrograman Timer1
Dengan menggunakan program AVR Timer, kita dapat mencari nilai dari TCNT1. Langkah-langkah menggunakan programnya:
Frekuensi kristal: 11,0592MHz atau ditulis 11.059.200 Hz;
Pilih nilai prescale sebesar 1024;
Isikan Timer1 Interrupts per second (berapa kali interupsi/detik) sebesar 1 kali;
Hasilnya ditampilkan pada gambar 6:
Gambar 6. Contoh Penggunaan ATMega Timer Calculator untuk TIMER1
Listing programnya:
Penjelasannya:
Baris 1 – 5 merupakan deklarasi untuk definisi kristal yang digunakan, yaitu 11.0592MHz. Pustaka apa saja yang digunakan (baris 2 dan 3) dan alias untuk PORTB sebagai led (baris 5);
Baris 7- 10 merupakan subrutin untuk inisialisasi PORTB sebagai luaran (baris 9). Perhatikan bahwa DDRB diberi logika 1 semua (=0xFF atau 255 desimal);
Baris-15 merupakan pengisian register TCCR1B agar digunakan nilai prescale sebesar 1024, artinya nilai kristal 11,0592MHz dibagi dengan 1024, sekaligus mengaktifkan Timer1;
Baris-16 memberikan nilai awal pada TCNT1 sesuai dengan perhitungan atau kalkulasi yang telah dilakukan sebelumnya, yaitu mengisi dengan nilai awal 54.736 (desimal) atau 0xD5D0 (heksadesimal);
Baris-17 menunggu hingga terjadi overflow – ini merupakan proses pooling bukan interupsi;
Jika sudah terjadi overflow atau melimpah, maka flag TOV1 di-reset (baris 18) dan Timer1 dimatikan (baris 19).
Pemrograman Timer2
Dengan menggunakan program AVR Timer, kita dapat mencari nilai dari TCNT1. Langkah-langkah menggunakan programnya:
Frekuensi kristal: 11,0592MHz atau ditulis 11.059.200 Hz;
Pilih nilai prescale sebesar 1024;
Untuk 10 milidetik diisi 100 kali interupsi per detik.
Gambar 7. Contoh Penggunaan ATMega Timer Calculator untuk TIMER2
Listing Programnya
#define F_CPU 11059200UL
#include "avr/io.h"
#define led PORTB
void init_devices()
{
DDRB=255;
}
//gunakan AVR Delay calculator untuk menghitung //tundaan 10 milidetik dengan frek kristal 11.0592MHz void delay10ms()
{
TCCR2=0B00000111; //prescaler 1024
TCNT2=0x94; //isi ulang 0x94 agar 1 detik
while(!(TIFR&(1<<TOV2)));
TIFR=64; //TOV2 di-nolkan dengan menuliskan "1" pada bit ybs
TCCR2=0B00000000;
}
void delay1detik()
{
unsigned char ulang;
for(ulang=0; ulang<100; ulang++)
{
delay10ms();
}
}
int main()
{ init_devices(); for(;;) { led=255; delay1detik(); led=0; delay1detik(); } }
Penjelasan:
Terdapat 2 subrutin yaitu delay10ms() dan delay1detik();
Kenapa tidak langsung dilakukan tundaan 1 detik? Mengapa harus melakukan pengulangan 100 kali subrutin delay10ms()?;
Timer2 merupakan timer 8bit, artina dengan kemampuan seperti itu tidak bias dilakukan langsung tundaan 11 detik, cara yang paling mudah untuk mendapat tundaan 1 detik atau 1000 milidetik adalah mengulang 100 kali tundaan 10 milidetik;
Perhatikan register TCCR2 bit 0,1, dan 2 pada Gambar 8. Kemudian perhatikan juga tabel 2 untuk semua kemungkinan nilai CS22, CS21 dan CS20.
Nilai prescale yang digunakan, mengikuti Tabel 2, perhatikan pada baris 14 adalah sebesar 1024 atau nilai clock dibagi dengan nilai prescale tersebut;
Agar terjadi penundaan sekitar 10 milidetik, maka nilai register TCNT2 diberi nilai sebesar 94 heksadesimal atau 148 desimal;
Gambar
8
.
Register
TCCR2
Baris 16 digunakan untuk menunggu terjadinya overflow pada Timer2, kemudian bit overflow tersebut direset (baris 17).
Timer2 kemudian dihentikan dengan memberi nilai 0 atau 0x00 pada register TCCR2.
Tabel 2. Konfigurasi sumber clock atau detak pada TCCR2
Pemrograman Timer0
Pengaturan pewaktuan menggunakan AVRTimer0Calc ditunjukkan pada Gambar 9. Untuk penundaan 10 milidetik sebanyak 100 kali, parameter-nya sama seperti Timer2.
Gambar 9. Contoh penggunaan ATMega Timer Calculator – TIMER0
Listing Program
#define F_CPU 11059200UL
#include "avr/io.h"
#define led PORTB
void init_devices()
{
DDRB=255;
}
//gunakan AVR Delay calculator untuk menghitung //tundaan 10 milidetik dengan frek kristal 11.0592MHz void
delay10ms()
{
TCCR0=0B00000101; //prescaler 1024
TCNT0=0x94; //isi ulang 0x94 agar 1 detik while(!(TIFR&(1<<TOV0)));
TIFR=1; //TOV0 di-nolkan dengan menuliskan "1" pada bit ybs TCCR0=0B00000000;
}
void delay1detik()
{
unsigned char ulang;
for(ulang=0; ulang<100; ulang++)
{
delay10ms();
}
}
int main()
{
init_devices(); for(;;)
{
led=255; delay1detik(); led=0;
delay1detik();
}
}
Pemrograman Counter
#define F_CPU 11059200UL
#include "avr/io.h"
#include "avr/interrupt.h" // saatnya menggunakan interupsi
#define led PORTC
#define pencacah PORTD
volatile unsigned int cacah; // sbg volatile agar tetap global
// di dalam ISR
ISR(TIMER0_OVF_vect) {
TCNT0=0xFB; // isi ulang 0xFB agar 5 kali saja
++cacah; // setara dengan -5 (negatif 5)
}
// -- untuk aktivasi interupsi TIMER0 –
void enable_timer0()
{TIMSK|=(1<<TOIE0);}
// -- untuk deaktivasi interupsi TIMER0 –
void disable_timer0()
{TIMSK&=~(1<<TOIE0);}
void init_devices()
{
DDRC=255;
DDRD=255;
}
int main()
{
init_devices();
// Inisialisasi Timer/Counter 0
// Sumber detak: pin T0 Rising Edge
// Mode: Normal top=FFh
TCCR0=0x06;
// Luaran OC0 output: tidak dihubungkan
OCR0=0x00;
// Nilai awal dari Timer/Counter 0 (-5 desimal)
TCNT0=0xFB;
enable_timer0();
sei();
cacah=1;
while(1)
{
led = cacah;
pencacah = TCNT0;
}
}
Real-Time Clock