• LinkedIn
  • Join Us on Google Plus!
  • Subcribe to Our RSS Feed

Senin, 05 Oktober 2015

Menangani Interupsi pada Mikrokontroler AVR

00.20 // by Imam Firmansyah // No comments

Mikrokontroler tanpa interrupsi tidak akan bernilai apa apa. Rutin Interupsi dipanggil saat ada input yang menginterupsi alur program normal. Interrupsi tidak lebih dari subrutin yang menahan aliran program normal saat program tersebut di eksekusi. Setelah subrutin interrupt selesai, maka akan kembali ke titik terakhir program normal. Beberapa subrutin dipanggil interupt handler yang disebabkan oleh beberapa toggle pin eksternal atau beberapa nilai register seperti timer yang overflow dan lain sebagainya.

Mengapa interupsi begitu penting ? untuk kasus tanpa interupsi kamu akan melakukan looping untuk mencek satu atau lebih event yang terjadi. Operasi ini disebut polling. Namun polling mempunyai banyak kekurangan seperti program yang melakukan loop membutuhkan resources dari tugas yang mungkin perlu diselesaikan. Inilah mengapa mikrokontroler datang dengan banyak sumber interupsi. Sebagai ganti mengecek sebuah event, mikrokontroler mempunyai kemampuan  untuk menginterupsi program utama dan melompat ke subrutin interupsi dan kemudian kembali lagi ke pogram utama.

Apa yang terjadi saat interupsi terjadi? Setelah ada event interupsi mikrokontroler akan berhenti pada program utama, menyimpan informasi ke stack dan memberikan resourcenya ke subrutin interupsi. Saat subrutin interupsi selesai, alur program kembali ke titik terakhir program utama saat terhenti dan program terus berjalan.

Dalam Bahasa assembly program kamu biasanya akan mulai dengan table interupsi : 



Table ini mengindikasikan dimana semua subrutin interupsi diletakan. Setelah interupsi tertentu terjadi. Program pointer akan melompat ke lokasi subrutin interupsi.
Untuk contoh misalnya saat kamu memberi power ke mikrokontroler pointer akan melompat ke lokasi alamat $000 dimana itu merupakan lokasi RESET. Dalam bahasa C berarti akan di lokasikan ke fungsi main().
Compiler C akan membuat table ini saat mengkompilasi source code. Namun bagaimana akan menjabarkan penanganan rutin interupsi di Bahasa C menggunakan toolset WinAVR. Disepanjang waktu saat compiler di perbaiki terus menerus, disanan tidak ada perjanjian bagaimana untuk menangani kode interupsi. Sebagai compiler dia akan mencoba untuk tetap tidak bergantung pada detail mesin, setiap compiler di desain dengan metodenya sendiri sendiri. AVR-GCC tidak terkecuali. Disana setiap interupsi di pointing dengan nama yang telah didefinisikan sebelumnya – kamu akan menemukannya di file header definisi mikrokontroler seperti iom8.h
Pertama tama include library interupsi sehingga compiler mengerti makro perintah interupsi:
#include <avr/interrupt.h>
Semua interupsi kemudian dapat dijabarkan menggunakan perintah makro : ISR(), sebagai contoh :

ISR(ADC_vect)
{
//Kode kamu disini
}

Subrutin tersebut merupakan penanganan konversi ADC setelah selesai melakukan konversi. Perintah makro ISR() cukup mudah untuk menangani semua interupsi yang terjadi. Hanya membuat rutin seperti berikut :

ISR(_vector_default)
{
//Kode kamu disini
}

Jika kamu ingin untuk menjabarkan sebuah interupsi yang kosong pada kasus tertentu (menempatkan perintah “reti” di table interupsi)  kamu dapat menggunakan perintah berikut :
 EMPTY_INTERRUPT(ADC_vect)
Kasus ini akan diperlukan ketika kamu tidak memerlukan kode apapun yang diimplementasikan saat interupsi terjadi. perintah tersebut diatas perlu untuk dideklarasikan sehingga saat trigger interupsi terjadi tidak akan menjalankan kode BADISR_vect (yang mana secara default akan merestart program)

Berikut merupakan contoh program sederhana untuk menangani interupsi pada mikrokontroler.

#include <avr\io.h>
#include <avr\iom8.h>
#include <avr\interrupt.h>

#define outp(a, b) b = a
#define inp(a) a
uint8_t led;
typedef unsigned char  u08;
ISR(INT0_vect) { /* subrutin untuk int0 */
    led =  0x01;
   }
ISR(INT1_vect) {    /* subrutin untuk  int1 */
    led =  0x00;
   }
int main(void) {

    outp(0x01, DDRB);      /* PORTB.0 sebagai output (LED) */
    outp(0x00, DDRD);      /* PORTD sebagai input(saklar) */
    outp((1<<INT0)|(1<<INT1), GIMSK); // mengaktifkan eksternal int0, int1
    sei();       /* mengaktifkan interupsi*/
    led =  0x01;
    for (;;) {
    outp(led, PORTB);
    }                      /* looping seterusnya */
}

Di awal versi dari WinAVR makro yang digunakan yaitu SIGNAL(). Sekarang makro tersebut sama dengan ISR() dan tidak digunakan kembali.

Makro penanganan interupsi yang menarik lainnya yaitu ISR_ALIAS(vector, target_vector). Ini digunakan saat kamu membutuhkan untuk memindahkan satu vector ke vector yang lain. Ini cara dimana kamu dapat menangani banyak interupsi dengan single implementasi. Berikut contohnya :


ISR(INT0_vect)
    {
        PORTB = 42;
    }
 
    ISR_ALIAS(INT1_vect, INT0_vect);

dapat juga diartikan sebagai ISR yang di-link kan ke ISR yang lain yang ditentukan oleh parameter target vektor. pada contoh kode diatas, jika ada interupsi di INT1 maka akan di-link kan ke subrutin INT0, dimana akan membuat PORTB bernilai 42.



Referensi :


0 komentar:

Posting Komentar