AVR : cara membuat timer 1 detik



Kelihatannya memang sepele tapi untuk melakukan ini ada beberapa hal yang harus kita pahami. Oh iya, sebelum kita lanjut lebih jauh lagi alasan kenapa saya tiba-tiba membuat tutor yang kelihatannya sangat sepele ini utamanya adalah untuk pengingat untuk diri saya sendiri...dan juga berbagi kepada para pembaca sekalian.


Terlebih dahulu, saya akan memberitahukan kalau dalam tutor kali ini saya memakai Atmega16a.
Ok, jadi dalam tiap operasi yang di lakukan micro controller selalu di pengaruhi oleh clock ratenya. Apa itu clock rate ? mungkin link ini bisa menjawabnya. Intinya clock rate itu kecepatan micro controller mengeksekusi tiap pekerjaannya dan besaran untuk clock rate ini adalah hertz. Pada data sheet atmega16 (yang mana spesifikasinya sama seperti atmega16a hanya saja di versi "a" ada revisi, yang di revisi saya sendiri kurang tahu) yang bisa di akses disini (silahkan baca bagian default clock source) terlihat kalau clock rate atmega16 defaultnya adalah 1 Mhz. 1 Mhz artinya 1.000.000 hertz dengan kata lain dalam 1 detik, atmega16 bisa mengeksekusi sampai 1.000.000 pekerjaan.

Selain itu, avr punya timer register yang mana tiap 1 periode (periode adalah (1/frekuensi) detik) bit di dalam register ini akan bertambah 1 nilainya. Avr punya 3 register timer yang bertambah tiap 1 periode yaitu TCNT0 (ukuran 8 bit), TCNT1 (ukuran 16 bit) dan TCNT2 (ukuran 8 bit). ukuran 8 bit artinya timer tersebut mempunya batas nilai 2 pangkat 8 atau 256, tapi karena hitungan awal di sini di mulai dari 0 maka sampai 255 saja sedangkan untuk yang ukuran 16 bit artinya mempunyai batas nilai sampai 65535. ketika batas nilai ini di lewati maka yang terjadi adalah timer overflow.

Dengan mengetahui fakta-fakta ini, untuk menghitung 1 detik dengan memanfaatkan fitur interrupt pada avr dengan 2 metode, yang pertama interrupt tiap saat terjadi time overflow terjadi dan yang kedua interrupt ketika nilai di register timer (di TCNT0, TCNT1 atau TCNT2) cocok, maka interrupt terjadi dan nilai dari register itu akan tereset ke 0 lagi (metode CTC). Oh iya apa itu interrupt ? bisa di lihat disini. Intinya ketika suatu event yang di harapkan terjadi, maka interrupt akan tertrigger dan kemudian akan mengeksekusi function yang mengikuti interrupt itu.

Kali ini kita akan mengguunakan metode ke-2 atau CTC. Untuk source codenya bisa di akses disini. Dalam testing kali ini saya memakai 7 segment common katoda.
dan koneksinya dengan pin-pin avr :
a = PD0
b = PD1
c = PD2
d = PD3
e = PD4
f = PD5
g = PD6
dan sebelum di koneksikan ke 7 segment d gunakan resistor 220 ohm untuk mengamankan led di 7 segment pada tiap kaki-kai 7 segment.

jadi alur program ini di mulai dengan menginisiasi semua pin di PORTD sebagai output
DDRD = 0xFF;
kemudian di ikuti dengan menginisiasi timer.
 void init_timer1 ()
{
    // Timer Mode 4: Clear Timer on Compare match (CTC)
    TCCR1B |= (1<<WGM12);
    // Initialize Timer staring value
    TCNT1 = 0;
    // Set Compare value for 1s overflow
    OCR1A = 15625;
    // Enable Timer Compare A Match interrupt
    TIMSK |= (1<<OCIE1A);
    // Start Timer & Clock Select: Prescale I/O clock by 64
    TCCR1B |= (1<<CS10);
    TCCR1B |= (1<<CS11);
}
 Disitu terlihat pada saat menginisiasi timer, mula-mula program akan menset bit pada register TCCR1B untuk mengatifkan mode CTC, kemudian di ikuti dengan menginisiasi nilai TCNT1 sebagai 0. OCR1A adalah nilai yang akan di bandingkan kecocokannya dengan TCNT1 jadi, saat nilai TCNT1 = 15625 maka interrupt akan tertrigger dan menjalankan fungsi didalamnya.
ISR (TIMER1_COMPA_vect)
{  
    counter++;
    if (counter > 9)
        counter = 0;
    if (counter == 0)
        nol(4);
    else if (counter == 1)
        satu(4);
    else if (counter == 2)
        dua(4);
    else if (counter == 3)
        tiga(4);
    else if (counter == 4)
        empat(4);
    else if (counter == 5)
        lima(4);
    else if (counter == 6)
        enam(4);
    else if (counter == 7)
        tujuh(4);
    else if (counter == 8)
        delapan(4);
    else if (counter == 9)
        sembilan(4);
    else if (counter == 0)
        nol(4);
}
Yang di lakukan dalam fungsi ini hanya menunjukkan angka 0 - 9 bergantian tiap detik. Yang perlu di perhatikan disini adalah kenapa nilai OCR1A di inisiasi sebagai 15625 ? Ini ada hubungannya dengan setting bit pada register TCCR1B yang efeknya akan men-prescale I/O clock 64 kali. Maksudnya adalah membuat seolah-olah clock rate dari avr menurun 1/64 kali lipat, jadi yang awalnya 1Mhz menjadi 15625 hz. Yang mana artinya ketika 1 detik berlalu TCNT1 nilainya sudah bertambah 15625, jadi otomatis ketika nilai TCNT1 dibandingkan dengan nilai OCR1A dan cocok maka interrupt terjadi dan itu terjadi pas saat 1 detik.

Setelah menginisiasi timer, dilanjutkan dengan meng-enable global interrupt yang keterangannya sudah ada di source code fungsi apa yang membuat itu. Setelah itu agar program berjalan selamanya selama masih ada power di avr, maka di buat loop infinite pada kode.

Untuk mengenal lebih dalam mengenai settingan register-regiter di avr silahkan baca-baca lagi di datasheetnya dan di forum-forum avr jika ada kesulitan saat membaca datasheet. Berikut beberapa dokumentasi percobaan kali ini :
Sejatinya percobaan kecil-kecilan ini untuk membuat project saya kali ini yaitu jam digital (dengan alarm mungkin). Oke cukup sekian, jika ada saran atau kritik silahkan sampaikan di komentar.

referensi :
http://maxembedded.com/2011/06/avr-timers-timer1/
http://www.atmel.com/images/atmel-8154-8-bit-avr-atmega16a_datasheet.pdf
http://www.atmel.com/webdoc/AVRLibcReferenceManual/group__avr__interrupts.html
https://en.wikipedia.org/wiki/Clock_rate
http://electronics.stackexchange.com/questions/178227/12-hours-delay-with-atmega16a

Komentar