Timer’lar İle PWM Sinyali Üretme
İstenilen frekans ve Duty Cycle’da PWM sinyali üretmek için Timer’ları kullanabiliriz. Timer1 ile PWM sinyalin HIGH durumu, Timer0 ile PWM sinyalin LOW durumu kontrol ederiz. void setup() kısmında portu HIGH durumuna getirdik. Frekans 50hz ve Duty Cycle %5 olması için; Timer1’e 20ms olacak şekilde, Timer0’a da 1ms olacak şekilde değer verdik.
Program çalışmaya başladığında 1ms sonra Timer0 kesmesi oluşur ve port LOW yapılır. Ardından 19ms sonra Timer1 kesmesi oluşur ve port HIGH yapılır. Burada kayıtçılardan, Timer1’e 20ms olacak şekilde, Timer0’a da 1ms olacak şekilde yeniden değerler verilir ve senkronizasyon sağlanmış olur. Ardından 1ms sonra Timer0 kesmesi oluşur ve port LOW yapılır. Ardından yine 19ms sonra Timer1 kesmesi oluşur ve port HIGH yapılır. Yani Timer1 her 20ms de bir portu HIGH yaparken, Timer0 her 1 ms de bir portu LOW yapar.
Burada önemli bir nokta var. Timer0 her 1ms de bir porta LOW gönderirken 20. ms’ye geldiğimizde yine Timer0 portu LOW yapmaya çalışırken, Timer1 de portu HIGH yapmaya çalışır. Burada LOW ve HIGH çakışması olabilir ama kayıtçılara yüklenen değerler ile 1 ms ve 20 ms süreleri tam olarak virgülü virgülüne denk gelmediği için çakışma olmuyor. Fakat Timer0’a 156 değeri yüklendiğinde PWM’de bir karışıklık oluşuyor.
int i;
void setup()
{
pinMode(9, OUTPUT);
digitalWrite(9, HIGH); //ilk anda sinyal HIGH yapıldı.
cli(); //tüm kesmeler durduruldu
//timer1 kesmesi başlangıç ayarları yapılıyor. Bu ayara göre kesme süresi 20ms.
TCCR1A = 0;
TCCR1B = 0;
TCNT1 = 0; //timer1 başlangıç değeri sıfırlandı
OCR1A = 312; //timer1 bitiş/karşılaştırma değeri 312 olarak belirlendi
TCCR1B |= (1 << WGM12); //CTC(Clear Timer on Compare Match) mod açıldı
TCCR1B |= (1 << CS12) | (1 << CS10); //prescalar değeri 1024 yapıldı
TIMSK1 |= (1 << OCIE1A); //timer1 karşılaştırma kesmesi aktif edildi
//timer0 kesmesi başlangıç ayarları yapılıyor. Bu ayara göre kesme süresi 1ms.
TCCR0A = 0;
TCCR0B = 0;
TCNT0 = 0; //timer0 başlangıç değeri sıfırlandı
OCR0A = 120; //timer0 bitiş/karşılaştırma değeri 15 olarak belirlendi
TCCR0A |= (1 << WGM01); //CTC(Clear Timer on Compare Match) mod açıldı
TCCR0B |= (1 << CS02) | (1 << CS00); //prescalar değeri 1024 yapıldı
TIMSK0 |= (1 << OCIE0A); //timer0 karşılaştırma kesmesi aktif edildi
sei(); //tüm kesmelere izin verildi
}
void loop()
{
}
ISR(TIMER1_COMPA_vect)
{
digitalWrite(9, HIGH);
i = 1;
TCNT1 = 0; //timer1 başlangıç değeri sıfırlandı
OCR1A = 312; //timer1 bitiş/karşılaştırma değeri 312 olarak belirlendi
TCNT0 = 0; //timer0 başlangıç değeri sıfırlandı
OCR0A = 120; //timer0 bitiş/karşılaştırma değeri 15 olarak belirlendi
}
ISR(TIMER0_COMPA_vect)
{
digitalWrite(9, LOW);
}
0 comments:
Yorum Gönder