ATMEL PROGRAMLAMA 22 - Timer/Counter0 CTC (Clear Timer on Compare) Mode.


    CTC Mode Timer\Counter birimlerinin ençok kullanılan modudur. İki adet timer değerimiz olur. Bir tanesi bizim saydırmak istediğimiz değer,  diğeri de o anki değer (TCNT0). İstediğimiz sayma miktarını OCR0A registerına yükleriz . Her saykılda  TCNT0 değeri bir artar , OCR0A değeri ve TCNT0 değeri birbirine eşit olduğunda sayma işlemi (zamanlama) tamamlanmış olur .


     TCNT0 ve OCR0A eşitliğinde aynı zamanda OCF0A Flag aktif olur. Eğer kesme ayarları yapıldıysa ilgili kesme rutini çalıştırılır.  

örnek olrakbir önceki çalışmamızda Timer\Counter0 Normal Mode ile  yapmış oduğumuz 1ms'lik zamanlamayı şimdi CTC mode ile yapalım.  

Aşağıdaki tabloda 8Mhz frekansı ve  Timer\Counter0 prescaler değerlerine göre 1 ms için saydırma miktarları gösterilmiştir tabloyla ilgili hesaplamalar bir önceki konuda detaylı olarak anlatılmıştı .

 

Tablodan da anlaşılacağı gibi 1ms için prescaler değerimiz 64 ve sayma maximum değerimiz 125 olamalı bu şekilde 8x125=1000mikrosaniye=1ms elde etmiş oluruz. 
  
Bunun için Timer\Counter0 birimi için saat sinyali kaynağını ve prescaler değerini ayarlamalıyız. TCCR0B kaydedicisinin CS02,CS01 ve CS00 bitlerini ayarlarsak istediğimizi yapmış oluruz. prescaler değerimiz 64 olmalı




Tabloya göre  CS02=0, CS01=1 ve CS00=1 olmalıdır.

 TCCR0B &=~(1<<CS02);
 TCCR0B |=(1<<CS01);
 TCCR0B =(1<<CS00);


Timer\Counter0 birimini CTC mode çalıştırmak için WGM02, WGM01 ve WGM00 registerlarını aşağıdaki tabloda olduğu gibi düzenlememiz gerekiyor.



 
CTC mode için WGM02=0 ,  WGM01=1 ve  WGM00=0 yapılmalı  bunun için

TCCR0B &=~(1<<WGM02);
TCCR0A |=(1<<WGM01);
TCCR0A &=~(1<<WGM00);
komutları yazılır.


1sn aralıkla
programımız

#include <avr/io.h>
#define F_CPU 8000000ul
#include <util/delay.h>

 
void Timer0_ayar()
      {
         
  // CTC mod

    TCCR0B &=~(1<<WGM02);

    TCCR0A |=(1<<WGM01);

    TCCR0A &=~(1<<WGM00);
      //prescaler değeri 64
    TCCR0B &=~(1<<CS02);

    TCCR0B |=(1<<CS01);

    TCCR0B |=(1<<CS00);

 // maximum sayma değeri
     OCR0A=125;
 
      }
int main(void)
     {
       
        Timer0_ayar();
  
        for(;;)
            {
                if(TCNT0 ==OCR0A)
                      {
                         TCNT0=0;
                       }
            } 
  }
 
bu şekilde 1ms zaman ayarı yapan bir programımız oldu.  Biz bu 1ms'yi kullanarak 1000ms yani 1sn'lik zamanlama yapmak istersek ve her 1sn de bir bir ledin durum değiştirmesini istersek ne yapacağız.
Yapmamız gereken her 1ms de bir bir sayacın  değerini artırmaktır. Böylece  sayac 1000 defa  saydığında fark edip ledin konum değişmesini sağlayabiliriz.
 
Programımızda şu şekilde olacak:
 
#include <avr/io.h>
#define F_CPU 8000000ul
#include <util/delay.h>
#define led  PORTB0
int sayac=0;



void Timer0_ayar()
{
        // CTC mod ayarlanıyor

    TCCR0B &=~(1<<WGM02);

    TCCR0A |=(1<<WGM01);

    TCCR0A &=~(1<<WGM00);

  

    //prescaler değeri 64

    TCCR0B &=~(1<<CS02);

    TCCR0B |=(1<<CS01);

    TCCR0B |=(1<<CS00);

 // maximum sayma değeri
     OCR0A=125;
  
}

int main(void)
{
    DDRB|=(1<<led);
  
    Timer0_ayar();
  
    for(;;)
    {
        if(TCNT0 ==OCR0A)
        {
            sayac++;
            if(sayac==1000)
            {
                PORTB^=(1<<led);
                sayac=0;
            }
            TCNT0=0;
        }
    }
}
 
 
aynı işlemi Kesme ile yapalım
 
 #include <avr/io.h>
 #define F_CPU 8000000ul
 #include <util/delay.h>
 #include <avr/interrupt.h>
 #define led  PORTB0
 int sayac=0;

// Timer/Counter0 Output Compare interrupt routine
ISR(TIMER0_COMPA_vect){
   
     sayac++;
     if(sayac==1000)
     {
         PORTB^=(1<<led);
         sayac=0;
     }
   }
 void Timer0_ayar()
 {
   
     
     // CTC mod ayarlanıyor

     TCCR0B &=~(1<<WGM02);

     TCCR0A |=(1<<WGM01);

     TCCR0A &=~(1<<WGM00);

   

     //prescaler değeri 64

     TCCR0B &=~(1<<CS02);

     TCCR0B |=(1<<CS01);

     TCCR0B |=(1<<CS00);

     // maximum sayma değeri
     OCR0A=125;
   
 }

 int main(void)
 {
     DDRB|=(1<<led);
   
     //aktif olan tüm kesmeler durduruluyor
     cli();

     Timer0_ayar();
   
     // Timer/Counter0 Output Compare interrupt aktif ediliyor
     TIMSK0 |= (1 << OCIE0A);
   
     // bütün kesmeler aktif ediliyor.
       sei();

     for(;;);
    }
 
 
 

Yorumlar

  1. Hocam yazılarınızı ilgiyle takip ediyoruz.Devamı inşallah gelir.

    YanıtlaSil
  2. Teşekkürederim sağolun. İnşallah devamı gelecek :)

    YanıtlaSil

Yorum Gönder