- COUNTER/TIMER , apaan seh ?
adalah fasilitas di microcontroller untuk melakukan counter/perhitungan tanpa perlu menambahkan code di looping main program ( auto), sehingga nilai dari counter ( BIASANYA register TCNT) dapat di olah/manfaatkan sewaktu2
- JENIS COUNTER APA AJA ?
secara umum Counter /Timer terdiri dari:
- Timer Biasa (8 bit & 16 bit)
- Clear Timer on Compare (CTC)
- Overflow Timer
- Output Compare
- PWM timer ( bahasan tersendiri)
Kita bahas yang paling sering digunakan timer biasa dan timer CTC
- Counter 8 bit & 16 Bit
jadi ingat, 8 bit itu maximum nilai yg didapat 0 - 255, 16 bit = 0 - 65534 , jadi hanya beda di range nilai saja
semisal kita pakai IC attiny2313 dengan clock default 1MHZ, jadi jika kita dapat ambil matematika sederhana
resolusi = 1/input clock = 1/1Mhz = 1 micro second
jadi jika kita inisialisasi counter dengan Full Sped , clock=input (16bit / counter 1) TCCR1B|=(1<<CS10), maka jika kita ingin menghidupkan suatu led di portD dalam selang 1 detik, maka kita tunggu nilai Counter(TCNT1) = 1000000;
wah....kelebihan...nilai TCNT1 max= 65534, jadi kita perlu membagi counter dengan variabel yg laen...semisal kita pake variable a; jadi ketika TCTN1 = 10000; Maka TCTN1=0 ; a++; (ditambah), berulang seterusnya sampe nilai a= 100; maka LED di PORTD dihidupkan/toogle
Code:
#include <avr/io.h> int main (void) { DDRD |= (1 << PD0); // Set LED di portD0 TCCR1B |= (1 << CS10); // Set up counter dengan full speed int a; variable a=0; //nilai awal dari variable while (1) { if(TCNT1 == 10000) { a++; TCNT1=0; } if(a == 100) { PORTD ^= (1 << PD0); // Toggle the LED a=0; } } }
- PRESCALER
Jika di pembahasan sebelumnya, kita menggunakan variabel sebagai pembagi counter yg berlebih, AVR memberikan suatu solusi dengan melakukan pembagian clock menjadi faktor 1/8, 1/64, 1/256, dan 1/1024
jadi jika ada pembagian hasilnya resolusi akan menjadi berkurang :
1(full speed) = 1 micro secon
1/8 = 8 micro secon
1/64 = 64 us
1/256= 256 us
1/1024=1024us
nah...kita sekarang bisa membagi clock sesuai keinginan, dan menyederhanakan perhitungan
semisal kita ingin mendelay LED 1 detik, maka kita coba jika prescale 1/8 maka untuk mencari 1 detik nilai TCNT1 = 125000, masih lewat, prescale 1/64 maka nilai TCNT1 = 15625 ...nahh nilainya ga lewat....ketemu dehh....jadi kita sederhanakan script sebelumnya menjadi :
Code:
#define F_CPU 1000000UL //clock dari avr #include <avr/io.h> int main (void) { DDRD |= (1 << PD0); // Set LED di portD0 TCCR1B |= (1 << CS11); // Set up counter dengan prescale 64 //Baca datasheet untuk mencari konfigurasi prescaler yg laen while (1) { if(TCNT1 == 15624) // nilai max 1 detik, perhitungan mulai 0 maka nilai dikurangi 1 dari 15625 { PORTD ^= (1 << PD0); // Toggle the LED TCNT1=0; } } }
selanjutnya AVR memberikan failitas CTC, yaitu kita menentukan nilai maximum dari TCNT1 dan secara otomatis akan mengclear nilai TCNT1. Nilai max dari TCNT1 diberikan melalui register OCR1A
setiap kali TCNT1 = OCR1A akan terjadi trigger interupt CTC, sehingga dapat dimanfaatkan untuk mentriger suatu output. codenya akan menjadi seperti ini
Code:
#define F_CPU 1000000UL //clock dari avr
#include <avr/io.h>
#include <avr/interrupt.h>
ISR(TIMER1_COMPA_vect) //vector interupt compare
{
PORTD ^= (1 << PD0); // Toggle the LED
}
int main (void)
{
DDRD |= (1 << PD0); // Set LED di portD0
TCCR1B |= (1 << CS11); // Set up counter dengan prescale 64
//Baca datasheet untuk mencari konfigurasi prescaler yg laen
TCCR1B |= (1 << WGM12); // Configure timer 1 for CTC mode
TIMSK |= (1 << OCIE1A); // Enable CTC interrupt
OCR1A = 15624; // nilai atas dari TCNT1, untuk perhitungan 1 detik
sei(); //hidupkan interupt
while (1)
{
}
}
untuk counter dengan nilai-nilai lainnya dapat menggunakan rumus matematika sederhana untuk menetukan OCR1A
OCR1A = [(Frekuensi AVR / Prescale) / frekuensi yg diinginkan ] - 1
atau
OCR1A = [(Frekuensi AVR / Prescale) * Periode yg di inginkan ] - 1
catatan : nilai prescale = 1,8,64,256,1024 bukan 1/prescale , untuk mempermudah saja
SELAMAT MENCOBA
0 komentar:
Posting Komentar