Minggu, 28 Februari 2016

Menggunakan Timer dan Counter Microcontroller ATMega328

        ATMega328 memiliki 8 bit timer/counter dan 16 bit timer/counter. Masing-masing conter/timer memiliki prescaler 1, 8, 64, 256 dan 1024 dari pulsa clock. Selain itu counter/timer dapat mempergunakan pulsa clock dari eksternal (Osilator yg terpisah) yaitu melalui pin 6 (PD4) dan pin 11 (PD5). Kedua timer dan counter diperlengkapi dengan TOV0 (Timer Over Flow 0), OCF0A (Output Compare Flag 0A) dan OCF0B (Output Compare Flag 0B). pada 16 bit counter/timer mendapat tambahan ICF1 (Input Capture Flag 1).
Timer sebenarnya merupakan sebuah counter, yaitu UC menghitung pulsa clock yang berasal dari oscilator. Pulsa clock yang dihitung sudah melalui prescaler atau dengan kata lain, pulsa dari oscilator dibagi dengan prescale. Contoh frekuensi oscilator 1 MHz, dan prescaler diset 8, maka satu hitungan sama dengan (1/1 MHz) * 8 = 8 μdet. Prescaler diset melalui register TCCR1B (Timer Counter Control Register 1B). Sehingga untuk menset prescaler 8 maka CS11 = 1, CS10 dan CS12 diclearkan. Gambar 1 memperlihatkan register TCCR1B. Untuk memilih prescaler ditentukan oleh bit 0 sampai bit 2 pada register TCCR1B. Gambar 2 memperlihatkan harga bit bit tersebut untuk mensetting prescaler.
 Gambar 1. Register TCCR1B untuk 16 bit pada ATMega328

 Gambar 2. Mensetting prescaler 16 bit counter pada ATMega328
 
Jumlah pulsa clock yang telah dihitung, disimpan pada register TCNT1 untuk counter 16 bit atau TCNT0 untuk counter 8 bit. Jangkauan untuk 8 bit adalah 255 sedangkan pada 16 bit sebesar 65535. Berikut adalah potongan program untuk mengakses TCNT1






Definisi untuk jangkauan 16 bit counter adalah :



Bila counter telah mencapai TOP maka pulsa clock berikutnya akan menset TOV1 (bit 0 dari register TIFR1 = Timer Interrupt Flag Register menajdi bernilai 1). Bit TOV1 akan diclearkan secara otomatis jika ISR (interrupt service Routine) dijalankan. Nama ISR untuk TOV0 adalah ISR (TIMER0_OVF_vect) dan untuk TOV1 adalah ISR(TIMER1_OVF_vect). Nama nama Interrupt service routine diberikan pada bahan kuliah interrupt vector. Isi Register TIFR diperlihatkan pada gambar 3.
Contoh mempergunakan counter 8 bit. Jika TCNT0 diberi nilai 250, maka bit TOV0 akan menjadi satu (set) jika telah terjadi 56 pulsa clock. 

 Gambar 3. Isi Register TIFR1 pada ATMega328

Interrupt pada register TIFR dapat dinonaktifkan jika global interrupt yang terdapat pada register SREG didisable. Menclearkan bit ke-7 pada register SREG mengakibatkan seluruh interrupt pada ATMega328 menjadi tidak berfungsi. Maka global interrupt yang terdapat pada register SREG harus diset agar interrupt dapat berfungsi. Perintah untuk mengaktifkan global interrupt pada register SREG adalah sei(). Isi register SREG diberikan pada supplemen Bab ini.
Berikut adalah potongan program untuk menonaktifkan interrupt dan mengaktifkannya kembali.




 

Register berikutnya yang terkait pada pengaturan timer 16 bit adalah register TIMSK1 (Timer1 Interrupt Mask).
ICIE1 (Timer1 Input Capture Interrupt Enable). Bit ke-5 dari register TIMSK1 adalah bit ICIE1 yang bekerja jika global interrupt pada register SREG diset dan bit ICIE1 dalam keadaan set. Jika ICF1 yang terdapat pada register TIFR1 berubah menjadi set maka maka interrupt vektor akan dieksekusi. OCIE1B (Timer1, Output Compare B Match Interrupt Enable). Bit OCIE1B jika diset dan global interrupt dalam posisi set maka Interrupt vector akan dijalankan saat OCF1B yang terdapat pada register TIFR1 berubah menjadi set. Nama vektor interrupt OCF1B dalam keadaan set adalah TIMER1_COMPB_vect. Hal yang sama berlaku pada OCIE1A dengan nama vektor interrupt TIMER1_COMPA_vect
TOIE1 (Timer1 Overflow Interrupt Enable). Bit yang sangat penting untuk menjalankan vektor interrupt pada timer 16 bit adalah bit TOIE1. Agar vektor interrupt yang bernama TIMER1_OVF_vect dijalankan maka bit ini harus diset. Vektor TIMER1_OVF_vect akan dieksekusi jika isi register TCNT mengalami overflow yaitu berubah keadaan dari top ke bottom.
Pada gambar 1, Bit WGM12 dan WGM13 pada Register TCCR1B disetting berdasarkan kombinasi dari register TCCR1A yaitu pada bit WGM10 dan WGM11. WGM adalah Waveform Generation Mode. Isi Register TCCR1A diperlihatkan pada gambar 4, sedangkan kombinasi WGM diperlihatkan pada gambar 5.






Gambar 4. Isi register TCCR1A untuk counter 16 bit pada ATMega328




Bit ke-4 sampai ke-7 (COM1B0,COM1B1, COM1A0, COM1A1) pada register TCCR1A adalah Compare Output Mode pada channel A dan channel B. Pada microcontroller ATMega328 terletak pada pin PB1 dan PB2 (OC1A dan OC1B). Hal yang patut dicatat dalam hal ini adalah Data Direction Register yang berkaitan dengan pin tersebut (OC1A atau OC1B) harus diset agar driver output menjadi enable.


 


Berikut adalah contoh program yang tampa mempergunakan interrupt vector.
//program menyalakan 7 buah LED di PORTB dan 7 buah LED diPORTD
// Untuk selengkapnya program dan video dapat dilihat diwebsite
//https://newbiehack.com/TimersandCountersDefaultandBasicUsage.aspx
#include <avr/io.h>
int main(void)
{
DDRB = 0b01111111;              //mensetting agar PORTB seluruhnya menjadi output
PORTB = 0b00000000;           //Seluruh PORTB bernilai low
DDRD = 0b01111111;              // Mensetting PORTD seluruhnya output
PORTD = 0b00000000;            // Seluruh PORTD bernilai low
TCCR1B |= 1<<CS10 | 1<<CS11;                 // Prescaler 64.
int LEDNumber[2];
while(1)
{
if (TCNT1 > 2232)                          //menghitung pulsa clock sampai 2232
{
TCNT1 = 0;                               // menolkan isi register TCNT1.
PORTB = 1<<LEDNumber[0];
LEDNumber[0] ++;
if (LEDNumber[0] > 6)
{
LEDNumber[0] = 0;
PORTD = 1<<LEDNumber[1];
LEDNumber[1] ++;
if (LEDNumber[1] > 6)
LEDNumber[1] = 0;
}
}
}
}

Berikut adalah contoh program counter 8 bit dengan mempergunakan interrupt timer overflow dengan nama vektor interrupt TIMER0_OVF_vect.
//Id: TOV0_sevenseg.c,ATmega8,8MHz,10Des2011,sidiknur@yahoo.com
#include <avr/io.h>
#include <avr/interrupt.h>
#include "sevenseg.h"
#include "_74595.h"

#define DIGIT_NUM 3                  //jumlah digit seven segment
#define CHIP_NUM 2                  //jumlah IC 74595
uint8_t sevenseg_buf[DIGIT_NUM];
void sevenseg_buf_put(uint8_t data, uint8_t *buf);
void timer0_ovf_1ms_init(void);

int main(void){
uint8_t data;
DDRB = 0x00;
PORTB = 0xff;
_74595_init();
timer0_ovf_1ms_init();
while(1){
data = PINB;
sevenseg_buf_put(data,sevenseg_buf);
}
return 0;
}

void sevenseg_buf_put(uint8_t data, uint8_t *buf){
uint8_t temp;
temp = data/100;
buf[0] = sevenseg_pattern(temp);
data -= temp*100;
temp = data/10;
buf[1] = sevenseg_pattern(temp);
temp = data%10;
buf[2] = sevenseg_pattern(temp);
}

#define T0V0_PRELOAD_1MS (0xff + 1 - 125)
//menginisialisasi timer0 overflow tiap 1ms
void timer0_ovf_1ms_init(void)
{
TCNT0 = T0V0_PRELOAD_1MS;                           //memberi nilai pada register TCNT0 = 131
TCCR0 = _BV(CS01) | _BV(CS00);                         //prescaler 64
TIMSK |= _BV(TOIE0);                                             //mengaktifkan timer0 overflow interrupt.
Sei(); // global interrupt pd sreg diaktifkan
}

//vektor interupsi timer0 overflow
ISR(TIMER0_OVF_vect)
{
static uint8_t digit = 0;
uint8_t buf[CHIP_NUM];

TCNT0 = T0V0_PRELOAD_1MS;
buf[1] = sevenseg_buf[digit];
buf[0] = ~_BV(digit);
_74595_put(buf,CHIP_NUM);
if(++digit>=DIGIT_NUM)
digit = 0;
}


Contoh program berikut mempergunakan OCIEnx ( Output Compare Match Interrupt Enable) dengan vektor interrupt bernama TIMERn_COMPx_vect.

#include <avr/io.h>
#include <avr/interrupt.h>

int main(void)
{
sei();

DDRB |= 1<<PINB0;

TCCR1B |= 1<<CS10 | 1<<CS11 | 1<<WGM12;
TIMSK1 |= 1<<OCIE1A;                                  // Mengaktifkan interrupt pada output compare match
OCR1A = 15624;                                             //membandingkan dengan TCNT.
                                                           //Jika isi TCNT = 15624 maka Output Compare Interrupt akan aktif
while(1)
{
}
}

ISR(TIMER1_COMPA_vect)
{
PORTB ^= 1<<PINB0;
}

Tidak ada komentar:

Posting Komentar