6.   8051 Zamanlayıcı ve Sayıcılar

Zamanlayıcı ve sayıcılar aşağıdaki görevler için kullanılırlar.

   Zaman gecikmesi yaratmak için

   Pals zamanı veya zaman aralığı ölçmek için

   Pals veya oluşan olayları saymak için

   Çoklu işlem uygulamalarında (Multi-tasking)

   Kesme üretmek için

Standart 8051 iki zamanlayıcı/sayıcıya sahiptir. Bu zamanlayıcı/sayıcılar 8 bit veya 16 bit zamanlayıcı/sayıcı olarak kullanılabilir.  Aşağıda M1 ve M0 bitlerinin değerlerine bağlı olarak zamanlayıcı/sayıcıların hangi modlarda kullanılabileceği belirtilmektedir.

 TMOD

 M1 M0  FUNCTION                                                              

| 0  0  |    8 bit counter or 8 bit timer with / 32 scaler                 

| 0  1  |    16 bit timer/counter                                                 

| 1  0  |    8 bit timer counter with auto-reload to initial start for count up   

| 1  1  |    TC1 - disabled                                                       

   TH0 - TH0 is an 8 bit timer incremented by setting TR1.Interrupts  are channelled to .001Bh                                         

  TL0 - is an 8 bit timer/counter controlled by TMOD and TCON         

Zamanlayıcı/sayıcı  çalıştır bitleri TR1 ve TR0, TCON registerinde bulunur. Bu bitlerden birisi  "1" yapıldığında,  bu bite  karşılık gelen sayıcı çalışmaya başlar.  Bu bitlerin değeri "0" yapıldığında zamanlama/sayma işlemleri de bitirilmiş olur.  Kesme kontrolü registerinde (IE) bulunan ET1 ve ET0 bitleri, zamanlayıcı taşmasında kesme üretilip üretilmeyeceğini belirlemekte kullanılır.  Bit değerinin "1" olması, zamanlayıcı/sayıcı taşmasının kesme üretmesi anlamına gelir.

TMOD registerindeki C/T biti, zamanlaycı/sayıcıyı, sayıcı modunda veya zamanlayıcı modunda çalıştırmak için kullanılır.  Bu bitin değeri "1" yapıldığında zamanlayıcı/sayıcı, 8051 entegrenin TX giriş pinindeki olayları saymak üzere konfigüre edilmiş olur.

Bu bitin değeri "0" olduğunda zamanlayıcı/sayıcı, zamanlayıcı modundadır ve sistem osilatöründen gelen sinyali 12'ye bölerek çalışır.

TMOD registerindeki GATE biti, "1" yapıldığında, zamanlayıcı/sayıcı n'in aktif olması için, INTn ve TRn bitleri "1" yapılmalıdır.  GATE biti "0" yapıldığında zamanlayıcı/sayıcı n,in aktif yapılması için, TRn bitinin "1" yapılması yeterlidir.  GATE biti zamanı ölçmekte, olayların zamanını ölçmekte, pals genişliğini ölçmekte kullanılır.  INTx hattı "1" olduğu sürede, bu değerler sayıcya geçirilir. Sistem osilatörünün frekansı 12'ye bölünerek zaman sayması gerçekleşir. Buna göre 12 MHz osilatör kullanan bir sistemde, zamanlayıcının frekansı 1 Mhz olur.

 

T0 Giriş Ucundan Pals Sayılması zamanlayıcı 0 (mod 1)

                             ; T0 ucuna gelen dış sinyallerin sayılması

 MOV TH0, #0          ; zamanlayıcı/sayıcıyı sıfırla

 MOV TL0, #0          ;

 MOV TMOD, #5       ; zamanlaycı/sayıcıyı sayma moduna getir.

                             ; C/T=1, Mod 1

 SETB TR0               ; zamanlayıcı/sayıcıyı başlat

 ; Sayılan olay sayısı herhangi bir anda TH0/TL0 registerlerinin okunmasıyla ; elde edilebilir. Sayma olayı, mikrokontrolcünün asıl yaptığı işten bağımsız ; olarak geri planda sayılır.

 Yukarıdaki program parçasında frekansı yüksek olayların sayılması sırasında önemli bir problem ortaya çıkabilir.  Örneğin zamanlayıcı 0'ın içeriği okunup, program tarafından kullanılamadan zamanlayıcı 0 taşmış olabilir.

 Ön Düzenleme Kullanılarak Pals sayılması (mod 0)

Öndüzenleme mod 0 kullanılarak, girişte oluşan palslar  32 ye bölünebilir. Bu sayede çok hızlı olayların sayılması kolaylaşmış olacaktır. Zamanlayıcı/sayıcı girişte 32 olay oluştuğunda 1 artacaktır.

                               ;T0 ucunda oluşan olayları 32'ye bölerek say

 MOV TH0, #0            ; zamanlayıcı/sayıcıyı sıfırla.

 MOV TL0, #0            ;

 MOV TMOD, #4         ; zamanlayıcı 0 sayıcı modunda , C/T=1, Mod 0

 SETB TR0                 ; zamanlayıcı/sayıcıyı başlat

 Zaman dilimi yaratmak  Mod 1: 16 bit zamanlayıcı/sayıcı

 Zamanlayıcı/sayıcılar, işlemcinin servisine gerek duymadan geri planda çalışabildiklerinden, zamanlayıcı/sayıcılar kullanılarak zaman dilimi yaratmak ve gerçek zamanı saydırmak olanaklıdır.

 Eğer zamanlayıcı/sayıcının her iki registeri, 00h değeriyle yüklenirse, bir taşma meydana gelmeden önce, zamanlayıcı/sayıcı 65,536 sayma gerçekleştirecektir.  12 Mhz lik entegre osilatörü kullanılan bir devrede, bu yaklaşık olarak 66 milisaniyelik (65,536 mikrosaniye) zaman dilimine karşılık gelir.  Pek çok uygulamada genelde daha uzun zaman gecikmelerine gereksinim olduğundan, zamanlayıcı/sayıcı registerlerine ilave olarak bir 8 bit hafıza elemanı daha kullanılır.  Bu hafıza elemanın değeri her taşmada "1" azaltılarak gereken zaman dilimi yaratılır. TH0 ve TL0 registerlerinin başlangıç değerleri isteğe göre seçilebildiğinden hassas zaman dilimleri yaratmak olanaklıdır.  Örneğin TH0'a 80h, TL0'a 00h değerlerinin yüklenmesiyle zamanlayıcı sayıcı her 32,768 saymada taşacaktır. Taşma gerçekleştikten sonra, register değerleri tekrar 80h ve 00h değerleriyle yüklenmelidir. Aşağıdaki program parçası, gerçek gün zamanını ölçmek için zamanlayıcı/sayıcının nasıl kullanılabileceğini göstermektedir.

org 0000h                       		; program başlangıç adresi
JMP Anaprogram 
org 000Bh                       		; zamanlayıcı 0 kesme adresi
JMP TC0kesme                 		; zamanlayıcı 0 kesme programına git
org 0100h                      		; ana döngü başlangıcı
Anaprogram:
CALL Baslangıc              		; RTC ilk değerlerini ver
dongu: sjmp dongu        		; ana programın yapığı is
                
; R0 : uzun zaman dilimi yaratmak için kullanılan değişken
;TH0 ve TL0  0000h değerine ulaşınca kesme oluşturmak üzere programlansın
 
Baslangıc:MOV R0, #20h          	; R0 * 33ms  = 1sec
                MOV SAN, #00h        	;
                MOV DAK, #00h        	;
                MOV SAAT,  #00h     	;	   
                MOV TH0,  #80h       	; 
                MOV TL0,  #00h        	; kesmeler arasında 33ms
                MOV TMOD, #01       	;C/T=0, mod 1 (16bit zamanlayıcı)
                MOV TCON, #10h      	;zamanlayıcı 0'ı başlat
                MOV IE,   #82h         	;tüm kesmeleri aktifle biti "1"
                                             	;zamanlayıcı "0" kesmesi aktif
                RET			;Zamanlayıcı 0 olduğunda devreye girecek kesme programı

TC0kesme: DEC R0                	;sayıcı değişkeni azalt
                 MOV A, R0           	;akümülatore al
                 JNZ TC0CIK         	;sıfır değilse geri don
                 MOV R0, #20h      	;R0'ın ilk değerini tekrar yükle
                 INC SAN              	;saniye  = saniye + 1
                 MOV A, SAN         	;
                 SUBB A, #60        	;saniye  >= 60 ?
                 JNZ TC0Cık          	;
                 MOV SAN, #00      	;saniye = 0
                 INC DAK               	;dakika = dakika + 1
                 MOV A, DAK          	;dakika >= 60 ?
                 SUBB A, #60         	;
                 JNZ TC0CIK          	;
                 MOV DAK, #00      	;dakika = 0
                 INC SAAT             	;saat = saat + 1
                 MOV A, SAAT        	;saat >= 24 ?
                 SUBB A, #24         	;
                 JNZ TC0CIK          	;
                 MOV SAAT, #00    	;saat = 0
TC0CIK:     MOV TH0, #80h      	; 
                 MOV TL0, #00h     	;
                 CLR TF0               	;
                 RETI                    	;

 SAN EQU R2                          	;
 DAK EQU R3                          	;
 SAAT EQU R4                        	;
 End

Zaman Dilimi Yaratmak Mod 2: 8 bit Otomatik Yeniden-yükleme

(Auto-Reload)


Bir önceki örnekte, zamanlayıcı registerleri kesme programı içerisinde yeniden yüklenmek zorundaydı. Zamanlayıcı otomatik yeniden yükleme modunda kullanarak THx  registerindeki değerin otomatik olarak TLx değerine yüklenmesi olanaklıdır. THx yeniden yükleme değeri olarak adlandırılır ve TLx'de  normal zamanlayıcı görevini görmektedir. Bu yöntemin tek dezavantajı, sayma işleminin yalnızca 8 bit olmasııdır (Önceki örnekte 16 bit olduğuna dikkat ediniz). Aşağıda gün zamanı ölçümünün bu modda nasıl yapılabileceği bir örnekle verilmiştir.


org 0000h                        		; program başlangıç adresi
JMP Anaprogram
 
org 0Bh                            		; zamanlayıcı 0 kesme adresi
JMP TC0kesme                   	; zamanlayıcı 0 kesme programına git
 
org 100h                           	; ana döngü başlangıcı
Anaprogram:
CALL Baslangıc                 		; RTC ilk değerlerini ver
dongu: sjmp dongu          		; ana programın yaptığı iş
 
; R0 : uzun zaman dilimi yaratmak için kullanılan değişken
;TH0 ve TL0  0000h değerine ulaşınca kesme oluşturmak üzere ;programlansın
                
Baslangıc:MOV R0, #20h          	; R0 * 33ms  = 1sec
             MOV R1, #80h         	; R0 azaltılmadan önce kaç döngü
             MOV SAN, #00h        	;
             MOV DAK, #00h        	;
             MOV SAAT,  #00h     	;
             MOV TH0,  #00h       	; 256 kere
             MOV TL0,  #00h       	; kesmeler arasında 33ms
             MOV TMOD, #02       	;C/T=0, mod 2
             MOV TCON, #10h      	;zamanlayıcı 0'i başlat
             MOV  IE,   #82h         	;tüm kesmeleri aktifle biti "1"
                                                	;zamanlayıcı "0" kesmesi aktif
             RET			;Zamanlayıcı 0 olduğunda devreye girecek kesme programı

TC0KESME:  DEC R1                    	;her 80h seferde R0'i azalt
                 MOV A, R1                	;akumulatore al
                 JNZ TC0CIK               	;sıfır değilse geri don
                 MOV R1, #80h          	;R1'i tekrar yükle
                 DEC R0                    	;
                 MOV A, R0                	;
                 JNZ TC0CIK               	;
                 MOV R0, #20h           	; R0 ilk değerini tekrar yükle
                 INC SAN                   	;saniye  = saniye + 1
                 MOV A, SAN               	;
                 SUBB A, #60              	;saniye  >= 60 ?
                 JNZ TC0CIK               	;
                 MOV SAN, #00           	;saniye = 0
                 INC DAK                   	;dakika = dakika + 1
                 MOV A, DAK               	;dakika >= 60 ?
                 SUBB A, #60              	;
                 JNZ TC0CIK               	;
                 MOV DAK, #00           	;dakika = 0
                 INC SAAT                  	;saat = saat + 1
                 MOV A, SAAT             	;saat >= 24 ?
                 SUBB A, #24              	;  
                 JNZ TC0CIK               	; 
                 MOV SAAT, #00        	;saat = 0
TC0CIK:   MOV TH0, #80h            	;
                 MOV TL0, #00h          	;
                 CLR TF0                    	;
                 RETI                        	;
 
SAN   EQU      R2                        	;
DAK   EQU      R3                        	;
SAAT EQU      R4                         	;
END 

Zamanlayıcı/Sayıcının Mod 3 de kullanımı
Bu modda zamanlayıcı/sayıcının TH0 ve TL0 registerleri iki bağımsız sayıcı olarak kullanılır. TCON ve TMOD registerlerindeki bit kontrolleri TH0 registerindeki taşmaları kontrol eder.  Kesme oluşumu TH0'ın taşması ile meydana gelir. 

Pals Genişliği veya olay zamanı ölçme (Gating)
Zamanlayıcı/sayıcı Mod 3 kullanılarak, pals genişliği, geçen zaman ve durum sayımı gerçekleştirilebilir. Kapılama biti (Gating) aktiflendiğinde, zamanlayıcı yalnızca, INTx girişi "1" olduğu sürece aktif kalır. Bu sayede, INTx  girişindeki bir sinyalin aktif olduğu zaman miktarını bulmak mümkündür.  Aşağıdaki örnek, böyle bir uygulamayı anlatmaktadır. 

 org 0000h               		; program başlangıç adresi
 JMP AnaProgram
 org 000Bh               		; Zamanlayıcı 0 kesme adresi
 SETB F0                   		; F0 bitini tasma olduğunu belirtmek üzere aktifle
 RETI                        		; kesmeden dönüş
 
 org 001Bh               		; Zamanlayıcı 1 kesme adresi
 RETI                        		; Kesmeden dönüş
 
Anaprogram: CALL BaslangIc
lp1:          JNB P3.2, lp1             	;INT0 düşükse döngü
lp2:          JB P3.2, lp2              	;INT0 yüksekse döngü
 
;Bu noktada, TL0 içerisinde, INT0 yüksek olduğu süredeki sayma değeri bulunmaktadır.
;Bu değer kolaylıkla zaman bilgisine çevrilebilir.
 
lp3: JB F0, Hata       		; F0 "1" se Hata
CALL Cevır               		;Tl0 daki değeri zaman bilgisine cevir
CLR F0                      		; F0'i temizle
JMP lp1                     		; tekrar don
 
 
BaslangIc: MOV TH0, #0h        	;
                 MOV TL0, #0h        	;
                 MOV TMOD, #07h    	;C/T=1, Mod 3, Timer 0
                 MOV TCON, #10h    	;zamanlayıcıyı başlat
                 MOV IE, #82h         	;Kesmeleri aktifle
                 CLR F0                  	;F= bayrağını temizle
                 RET			;
                
Hata:       JMP HataIsleme
CevIr:
RET				;
end