Adından da anlaşılacağı gibi Timer modül, zamanı ölçmek veya doğru zaman gecikmesini oluşturmak için kullanılır. Mikrodenetleyici ayrıca döngüler çalıştırarak gerekli gecikmeleri üretebilir / ölçebilir, ancak zamanlayıcı / sayaç, CPU'yu diğer görevler için maksimum işleme süresi ayırmaya izin veren bu yedekli ve tekrarlayıcı görevi rahatlatır.

Zamanlayıcı, saat darbelerini saymak için yapılandırılabilen basit bir ikili sayaçtan başka bir şey değildir (Dahili / Harici). Maximum değerine ulaştığında, bir OverFlow (taşma) bayrağını ayarlayarak sıfıra geri sarar ve etkinleştirilirse kesmeyi oluşturur.

Pic16f877a, zamanlayıcı, sayıcı veya PWM üretimi için kullanılabilen üç boş zamanlayıcıya sahiptir.

Timer Size Control Register Count Register Min Delay Max Delay
TIMER0 8-bit OPTION_REG TMR0 0.2usec 13.107ms
TIMER1 16-bit T1CON TMR1H,TMR1L 0.2usec 104.857ms
TIMER2 8-bit T2CON TMR2 0.2usec 819usec

Timer Hesaplama

PIC Osilatör frekansı 4'e bölünür ve daha sonra denetleyiciye beslenir. Şimdi bu frekans, gecikme aralığını oluşturmak için presacalar ile bölünebilir. Zamanlayıcı sayımını bir arttırmak için geçen süre (zamanlayıcı keneti) aşağıdaki gibi belirlenebilir. 

tick = (Prescalar/(Fosc/4)
tick = (Prescalar/(20Mhz/4))
$$tick = (Prescalar * 4)/Fosc$$

Şimdi gerekli gecikme için Zamanlayıcı değeri aşağıdaki gibi hesaplanabilir.

Delay = TimerCount * tick
Count = (Delay/tick)
RegValue = TimerMax- Count 
RegValue = TimerMax-(Delay/tick) = TimerMax - (Delay/((Prescalar *4)/Fosc))
$$RegValue = TimerMax-((Delay * Fosc)/(Prescalar*4))$$

Aşağıdaki tablo, üç Zamanlayıcı için de formül sunmaktadır.

Timer Size Formula for delay calculation
TIMER0 8-bit $$RegValue = 256-((Delay * Fosc)/(Prescalar*4))$$
TIMER1 16-bit $$RegValue = 65536-((Delay * Fosc)/(Prescalar*4))$$
TIMER2 8-bit $$RegValue = 256-((Delay * Fosc)/(Prescalar*4))$$

TIMER0 MODÜLÜ

TMR0 modülü aşağıdaki özelliklere sahip bir 8 bit zamanlayıcı / sayaçtır:

  • 8 bit zamanlayıcı / sayaç
  • Okunabilir ve yazılabilir
  • 8-bit yazılım ile programlanabilir prescaler
  • Dahili veya harici saat seçme
  • Taşma sırasında FFh'den 00h'ye kesilme
  • Harici saat için kenar seçimi

TIMER0 Yazaçları (Registers)

Aşağıdaki tabloda PIC16f877A Timer0 modülü ile ilişkili yazaçlar gösterilmektedir.

Register Açıklama
OPTION_REG Bu register TIMER0 ın prescaler değerini atamak, Clock kaynağını belirtmek vb. işlemleri ayarlamak için kullanılır.
TMR0

Bu register, prescalar konfigürasyonuna bağlı olarak artırılacak olan zamanlayıcı sayım değerini tutar.

INTCON

Bu register ise Timer0 taşma bayrağını (TMR0IF) ve buna karşılık gelen Inetrrupt Enable bayrağını (TMR0IE) içerir.

OPTION_REG              
7 6 5 4 3 2 1 0
RBPU INTEDG T0CS T0SE PSA PS2 PS1 PS0

RBPU: Zamanlayıcılar için NA
INTEDG: Zamanlayıcılar için NA
T0CS: TMR0 Saat Kaynağı Seçme biti
        - T0CKI pini üzerinde geçiş
        - Dahili komut çevrimi saati (CLKO)

T0SE: TMR0 Kaynak Kenarı Seçme biti
        - T0CKI piminde yüksekten alta düşük geçişte artım
        - T0CKI piminde düşükten yükseğe geçişte artım

PSA: Önceden Ayırıcı Atama biti
        - Prescaler WDT'ye atanır
        0 - Prescaler Timer0'a atanır

PS2: PS0: Önceden Ayırma Oranı Seçme bitleri 

Not: Timer0 modülü ile Watchdog Timer arasında karşılıklı olarak yalnızca paylaşılan tek bir prescaler mevcuttur. Timer0 modülü için bir prescaler ataması, Watchdog Zamanlayıcı için prescaler bulunmadığı anlamına gelir ve tersi de demektir. Bu prescaler'e erişilemiyor ancak OPTION_REG'in PS2: PS0 bitlerini kullanarak yapılandırılabilir.

INTCON              
7 6 5 4 3 2 1 0
GIE PIE TMR0IE INTE RBIE TMR0IF INTF RBIF

GIE: Genel Kesme Etkinleştirme biti
       1 - Tüm maskelenmemiş kesmeleri etkinleştirir
       0 - Tüm kesmeleri devre dışı bırakır

PIE: Çevresel Kesme Etkinleştirme biti
       1 - Tüm maskesiz çevresel kesmeleri etkinleştirir
       0 - Tüm çevresel kesmeleri devre dışı bırakır

TMR0IE: TMR0 Taşma Kesme Etkinleştirme biti
       1 - TMR0 kesmesini etkinleştirir
       0 - TMR0 kesmesini devre dışı bırakır

INTE: Zamanlayıcılar için NA
RBIE: Zamanlayıcılar için NA
TMR0IF: TMR0 Taşma Kesme Bayrağı biti
       1 - TMR0 kaydı taşmıştır (yazılımda silinmelidir)
       0 - TMR0 kaydı taşmadı

INTF: Zamanlayıcılar için NA
RBIF: Zamanlayıcılar için NA

@8Mhz osilatör ile 1ms gecikme süresi üretmek için hesap yaparsak:
Yazaç değeri = 256-(Delay * Fosc)/(Prescalar*4))
Yazaç değeri = 256-((1ms * 8Mhz)/(8*4))
Yazaç değeri = 256-250
Yazaç değeri = 6 (0x06)

TIMER0 Modülü 1ms frekanslı sinyal üreten XC8 C kodu:

#include<pic16f877a.h>

char cikis = 0;

void interrupt timer_0()
{  
    if(TMR0IF==1)
    {
        cikis=~cikis;   // cikis değişkeninin tümleyenini alarak LED'i yakıp söndürüyoruz.
        
        TMR0 = 7;       // Hesapladığımız Timer0 yazaç değeri, 
                        // (Not: Timer yazaç değeri (6+1) 7 olarak atadık. 
                        // Çünkü Timer0 TMR0 yazaç arttırımı başlatmak için
                        // 2 komut cycle'a ihtiyaç duyar.
        TMR0IF=0;       // Timer kesme bayrağını temizledik.
    } 
}


void main()
{    
    TRISD=0x00;         //PORTD'yi LEDleri yakmak için çıkış olarak ayarlıyoruz.

    OPTION_REG = 0x02;  // prescaler değerini 8 olarak atadık.
    TMR0=0x06;          // 1ms için yazaç değerini 6 olarak hesaplamıştık.
    TMR0IE=1;           //PIE1 yazacında Timer kesmesini aktif ediyoruz.
    GIE=1;              //Global kesmeyi aktif ediyoruz.
    PEIE=1;             //Çevresel kesmeyi aktif ediyoruz.
    while(1)
    {
        PORTD = cikis;
    }
}


TIMER1 MODÜLÜ

Zamanlayıcı TMR1 modülü aşağıdaki özelliklere sahip 16 bit zamanlayıcı / sayaçtır:

  • İki 8-Bit kayıt TMR1H / TMR1L'ye sahip 16-bit zamanlayıcı / sayaç
  • Okunabilir ve yazılabilir
  • 1: 8'e kadar programlanabilir prescaler
  • Dahili veya harici saat seçme
  • FFFFh'den 00h'ye taşma üzerine kesme
  • Harici saat için kenar seçimi

Timer1 Yazaçları 

Aşağıdaki tabloda PIC16f877A Timer1 modülü ile ilişkili yazaçlar gösterilmektedir.

Register Açıklama
T1CON: Bu register TIMER1 in prescaler değerini atamak, Clock kaynağını belirtmek vb. işlemleri ayarlamak için kullanılır.
TMRIH Bu register zamanlayıcı değerinin yüksek 8 bitini tutar. TMR1H ve TMR1L, çift olarak, 0000'den FFFFh'e kadar değeri artar.
TMRIL Bu kayıt, zamanlayıcı değerinin düşük 8 bitini tutar. TMR1H ve TMR1L, çift olarak, 0000'den FFFFh'e kadar değeri artar.
PIR1 Bu register Timer1 in taşma bayrağını (TMR1IF) barındırır.
PIE1 Bu register Timer1 in Kesme bayrağını (TMR1IE) barındırır.
T1CON              
7 6 5 4 3 2 1 0
T1CKPS1 T1CKPS0 T1OSCEN T1SYNC TMR1CS TMR1ON

T1CKPS1: T1CKPS0: Timer1 Giriş Saati prescaler Bit seçimi
        11 = 1: 8 prescaler değer
        10 = 1: 4 prescaler değer
        01 = 1: 2 prescaler değer
        00 = 1: 1 prescaler değer

T1OSCEN: Timer1 Osilatör Etkinleştirme Kontrol biti
        1-Osilatör etkinleştirildi
        0-Osilatör kapalı

T1SYNC: Timer1 Harici Saat Girişi Eşitleme Kontrol biti
        1-Harici saat girişini senkronize etmeyin
        0-Harici saat girişini senkronize edin

TMR1CS: Timer1 Saat Kaynağı Seçme biti
        1-RC0 / T1OSO / T1CKI piminden harici saat (yükselen kenar)
        0-Dahili saat (FOSC / 4)

TMR1ON: Zamanlayıcı1 Bitte
        1-Timer1'i etkinleştirir
        0-Timer1'i durdurur

@8Mhz osilatör ile 100ms gecikme süresi üretmek için hesap yaparsak:
YazaçDeğeri = 65536-(Delay * Fosc)/(Prescalar*4))
YazaçDeğeri = 65536-((100ms * 8Mhz)/(8*4))
YazaçDeğeri = 40536 = 0x9E58

TIMER1 Modülü 100ms frekanslı sinyal üreten XC8 C kodu:

#include<pic16f877a.h>

char cikis = 0;

void interrupt timer_isr()
{  
    if(TMR1IF==1)
    {
        cikis=~cikis;   // LED'ler yakıp söndürmek için cikis degerinin tümleyenini alıyoruz
        TMR1H=0x9E;     // 100 ms gecikme için TMR1H değeri atadık
        TMR1L=0x58;     // aynı şekilde TMR1L değerini atadık.
        TMR1IF=0;       // Timer1 kesme bitini temizledik.
    } 
}


void main()
{    
    TRISD=0x00;     //PORTD'yi çıkış olarak ayarladık.

    T1CON = 0x31;    // Timer1 prescaler'ini 8 olarak atadık.
    TMR1H = 0x9E;
    TMR1L = 0x58;       
    TMR1IE=1;       //PIE1 yazacındaki Timer kesme bayrağını aktifleştirdik. 
    GIE=1;          //Global kesmeyi aktikleştirdik.
    PEIE=1;         //Çevresel kesmeyi aktifleştirdik.
    TMR1ON = 1;     //Timer1 i aktifleştirdik.

    while(1)
    {
        PORTD = cikis;
    }
}