Senin, 27 Juni 2011

TIMER DAN COUNTER AVR

Mungkin teman-teman semua sudah tau pengertian timer, jadi saya tidak akan menjelaskan panjang lebar mengenai pengertian timer. Sedangkan untuk counter  (pencacah/penghitung) berbeda dengan timer, perbedaan yang mendasar adalah pada sumber clocknya. Jika timer, sumber clocknya berasal dari internal mikrokontroler dalam hal ini berasal dari kristal. Sedangkan untuk counter sumber clocknya berasal dari luar mikrokontroler (eksternal). Sebagai contoh counter, jika kita ingin menghitung banyaknya barang yang lewat pada konveyor, maka sumber clocknya berasal dari sensor yang mendeteksi barang saat melewatinya. Mungkin sampai disini Teman-teman sudah mengerti perbedaan yang mendasar antara timer dan counter.

>>>TIMER<<<
Pada ATmega8535 terdapat 3 buah timer, yaitu Timer0 (8 bit), Timer1 (16 bit) dan Timer2 (8 bit). Untuk perbedaan dan cara kerja masing-masing timer, teman-teman dapat membacanya pada datasheet. Disini saya akan coba membahas Timer0 dan Timer1 saja. Untuk lebih jelasnya silakan download datasheet ATmega8535 disini.

Perhitungan untuk Timero dan Timer1 adalah sebagai berikut:
Ttimer0 = Tosc*(256-TCNT0)*N   → (8 bit = 256)
Ttimer1 = Tosc*(65536-TCNT1)*N   → (16 bit = 65536)


Tosc = 1/Fosc   → pada aplikasi ini saya menggunakan kristal 12 MHz, sehingga:
Tosc = 1/12Mhz = 0,0000000833 detik

Dimana:
Ttimer0 = lamanya periode Timer0
Ttimer1 = lamanya periode Timer1
TCNT0 = Register Timer0
TCNT1 = Register Timer1
N = Skala clock (mempunyai nilai 1, 8, 64, 256 dan 1024)
Tosc = periode  clock
Fosc = frekuensi clock kristal

Sekarang saya akan membuat aplikasi timer yang ditampilkan pada LCD, cara kerjanya pada LCD akan menampilkan nilai awal yaitu 0 kemudian setelah 1 detik (menggunakan timer) nilai tersebut akan naik menjadi 1, kemudian 2 dan seterusnya, jika sudah sampai 100 maka akan diset kembali menjadi 0. Berikut adalah shematicnya:

Menggunakan Timer1:
Ttimer1 = Tosc*(65536-TCNT1)*N

Pada aplikasi diatas diinginkan lamanya timer adalah 1 detik  (Ttimer1 = 1 detik) dan jika saya menggunakan kristal 12 MHz dan menggunakan skala clock N = 1024, maka didapat:

1 = 0,0000000833*(65536-TCNT1)*1024
TCNT1= 53818 = D23A (dalam hexa)

Dari perhitungan diatas didapat nilai 53818 atau dalam hexa D23A, nilai tersebut harus diisikan pada register TCNT1 agar Timer 1 bernilai 1 detik.

Berikut adalah gambar untuk mensetting pada CodeVision CodeWizard AVR:
 Pada settingan diatas digunanakan nilai clock value yaitu 11.719 kHz, nilai tersebut didapat dari Fosc/N atau 12 Mhz/1024. Berikut adalah listing program lengkapnya:

unsigned char temp[6];
int data;

#include <mega16.h>
#include <stdlib.h>

#asm
   .equ __lcd_port=0×15 ;PORTC
#endasm
#include <lcd.h>

// Timer 1 overflow interrupt service routine
interrupt [TIM1_OVF] void timer1_ovf_isr(void)
{
TCNT1H=0xD23A >> 8;
TCNT1L=0xD23A & 0xff;
data++; //setelah 1 detik increament data
}

void main(void)
{
// Timer/Counter 1 initialization
// Clock source: System Clock
// Clock value: 11.719 kHz
// Mode: Normal top=FFFFh
// OC1A output: Discon.
// OC1B output: Discon.
// Noise Canceler: Off
// Input Capture on Falling Edge
// Timer 1 Overflow Interrupt: On
// Input Capture Interrupt: Off
// Compare A Match Interrupt: Off
// Compare B Match Interrupt: Off
TCCR1A=0×00;
TCCR1B=0×05;
TCNT1H=0xD2;
TCNT1L=0x3A;
ICR1H=0×00;
ICR1L=0×00;
OCR1AH=0×00;
OCR1AL=0×00;
OCR1BH=0×00;
OCR1BL=0×00;

// Timer(s)/Counter(s) Interrupt(s) initialization
TIMSK=0×04;

// Analog Comparator initialization
// Analog Comparator: Off
// Analog Comparator Input Capture by Timer/Counter 1: Off
ACSR=0×80;
SFIOR=0×00;

// LCD module initialization
lcd_init(16);

// Global enable interrupts
#asm(“sei”)

while (1)
      {  
      if (data==100)
      {
        lcd_clear();
        data=0;
      }    
      lcd_gotoxy(0,0);
      lcd_putsf(“ElectrO-cOntrOl”);
      itoa(data,temp); //menampilkan di LCD
      lcd_gotoxy(0,1);
      lcd_puts(temp);
      };
}

Menggunakan Timer0:
Ttimer0 = Tosc*(256-TCNT0)*N

Dengan menggunakan Timer0, untuk aplikasi yang sama seperti diatas, sebenarnya timer0 ini tidak dapat menghasilkan periode timer selama 1 detik dikarenakan keterbatasan jumlah bit yaitu hanya 8 bit (256) saja. Tetapi kita masih dapat memanupulasi program agar dapat menghasilkan timer selama 1 detik, caranya dengan membuat timer selama 10 ms kemudian dilakukan pengulangan sebanyak 100 kali, maka akan dihasilkan timer selama 1 detik.

10 ms * 100= 1 detik

Pada aplikasi ini diinginkan lamanya timer adalah 10 ms  (Ttimer0=10 ms=0.01 s) dan jika saya menggunakan kristal 12 MHz dan menggunakan skala clock N = 1024, maka didapat:

0.01 = 0,0000000833*(256-TCNT0)*1024
TCNT0= 138 = 8A (dalam hexa)

Dari perhitungan diatas didapat nilai 138 atau dalam hexa 8A, nilai tersebut harus diisikan pada register TCNT0 agar Timer 0 bernilai 10 mili detik.

Berikut adalah gambar untuk mensetting pada CodeVision CodeWizard AVR:

Pada settingan diatas digunanakan nilai clock value yaitu 11.719 kHz, nilai tersebut didapat dari Fosc/N atau 12 Mhz/1024. Berikut adalah listing program lengkapnya:

unsigned char temp[6], loop=0;
int data;

#include <mega16.h>
#include <stdlib.h>

#asm
   .equ __lcd_port=0×15 ;PORTC
#endasm
#include <lcd.h>

// Timer 0 overflow interrupt service routine
interrupt [TIM0_OVF] void timer0_ovf_isr(void)
{
// Reinitialize Timer 0 value
TCNT0=0x8A;
loop++;
if (loop>=100)
    {
    data++;
    loop=0;
    }
}

void main(void)
{
// Timer/Counter 0 initialization
// Clock source: System Clock
// Clock value: 11.719 kHz
// Mode: Normal top=FFh
// OC0 output: Disconnected
TCCR0=0×05;
TCNT0=0x8A;
OCR0=0×00;

// Timer(s)/Counter(s) Interrupt(s) initialization
TIMSK=0×01;

// Analog Comparator initialization
// Analog Comparator: Off
// Analog Comparator Input Capture by Timer/Counter 1: Off
ACSR=0×80;
SFIOR=0×00;

// LCD module initialization
lcd_init(16);

// Global enable interrupts
#asm(“sei”)

while (1)
      {
      if (data==100)
        {
        lcd_clear();
        data=0;
        }    
      lcd_gotoxy(0,0);
      lcd_putsf(“ElectrO-cOntrOl”);
      itoa(data,temp); //menampilkan di LCD
      lcd_gotoxy(0,1);
      lcd_puts(temp);
      };
}

>>>COUNTER<<<
Untuk aplikasi counter lebih mudah dibandingkan dengan timer, karena kita tidak harus lagi menghitung untuk mendapatkan nilai dari register TCNT, tetapi secara otomatis register TCNT yang akan mencacah jika ada input yang masuk.

Berikut adalah aplikasi counter untuk menghitung dan ditampilkan pada LCD, input yang digunakan berasal dari pushbutton. Berikut adalah schematicnya:


Counter0
Input untuk counter0 berasal dari pin T0 atau PB0. Counter0 hanya mampu mencacah sampai dengan nilai 256 dikarenakan counter 8 bit. Berikut adalah setting pada CodeVision CodeWizard AVR:


Berikut adalah listing program lengkap:

unsigned char temp[6];
int data;

#include <mega16.h>
#include <stdlib.h>

#asm
   .equ __lcd_port=0×15 ;PORTC
#endasm
#include <lcd.h>

void main(void)
{
// Timer/Counter 0 initialization
// Clock source: T0 pin Falling Edge
// Mode: Normal top=FFh
// OC0 output: Disconnected
TCCR0=0×06;
TCNT0=0×00;
OCR0=0×00;

// Analog Comparator initialization
// Analog Comparator: Off
// Analog Comparator Input Capture by Timer/Counter 1: Off
ACSR=0×80;
SFIOR=0×00;

// LCD module initialization
lcd_init(16);

while (1)
      {
      data=TCNT0;//hasil  counter (TCNT0) dipindah ke data      
      if (data>=256)
        {
        lcd_clear();
        }           
      lcd_gotoxy(0,0);
      lcd_putsf(“ElectrO-cOntrOl”);
      itoa(data,temp); //menampilkan di LCD
      lcd_gotoxy(0,1);
      lcd_puts(temp);
      };
}

Counter1
Counter1 tidak jauh berbeda dengan counter0, hanya saja maksimum pencacahan counter1 sampai 65536 dikarenakan counter 16 bit, dan input untuk counter1 berasal dari pin T1 atau PB1. Untuk settingan dan program pada CodeVision AVR hampir sama dengan counter0, jadi tidak akan saya jelaskan lagi disini.

12 komentar:

  1. mau tanya nih,saya menggunakan optocoupler sebagai sensor penghitung putaran untuk ditampilkan di LCD. bagaimana code program agar mikrokontroler dapat menghitung ketika output sensor dalam keadaan high??

    BalasHapus
  2. pada dasarnya untuk fitur Counter dan external interupt tidak dapat membaca kondisi suatu logika (high atau low), tetapi hanya dapat membaca perubahan logika atau transisi, seperti falling edge (transisi dari high ke low) dan rising edge (transisi dari low ke high). jika anda membaca kondisi high saja maka tidak ada bedanya kan ketika anda membaca perubahan logika (transisi)? jadi pembacaan suatu kondisi logika tidak jauh berbeda dengan pembacaan transisi logika...!

    BalasHapus
  3. jadi apabila saya menggunakan rising edge, apa programnya sama saja dengan listing program diatas?

    BalasHapus
  4. program diatas saya pakai falling edge.. klo mau pake rising edge anda tinggal mengubahnya saja pada codewizard---->kemudian pilih clock source pada fitur counter yg digunakan

    BalasHapus
  5. terimakasih banyak atas informasinya

    BalasHapus
  6. salam kenal mas bro
    tutorial anda sangat berguna khususnya bagi saya yang ingin belajar mengenai mikrokontroler

    BalasHapus
  7. mas,, apa bedanya falling edge dan rising edge?? apa keuntungan dan kerugian masing-masing?? jika saya ingin mengukur kecepatan motor dc dengan sensor optocoupler,, sebaiknya menggunakan falling edge atau rising edge?? mengapa?? mohon dijelaskan.. terimakasih...

    BalasHapus
  8. Thanks mas.., Info'y kerent abiz.

    BalasHapus
  9. MAS kalo mau menggunakan 2 sensor optocopler supaya bisa digunain secara bersamaan, progamnya kyak gimna mas...??

    BalasHapus
  10. kenapa ya kalau menggunakan counter dengantimer kadang tidak presisi

    BalasHapus
  11. mas kalo sensor yang saya gunakan ldr apa bisa? lalu rising edge atau failing edge maksudnya apa? bila dalam pengcounteran ada penambahan atau pengurangan itu gmana ya mas?0 thq ^^

    BalasHapus
  12. Arigatou,,
    sangat membantu nih Min,, :)

    BalasHapus