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<<CS02);
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);
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);
{
// 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;
TCCR0B &=~(1<<CS02);
TCCR0B |=(1<<CS01);
TCCR0B |=(1<<CS00);
// maximum sayma değeri
OCR0A=125;
}
int main(void)
{
for(;;)
#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;
}
}
}
Timer0_ayar();
// Timer/Counter0 Output Compare interrupt aktif ediliyor
TIMSK0 |= (1 << OCIE0A);
// bütün kesmeler aktif ediliyor.
sei();
for(;;);
}
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:
#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;
#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();
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(;;);
}
Hocam yazılarınızı ilgiyle takip ediyoruz.Devamı inşallah gelir.
YanıtlaSilTeşekkürederim sağolun. İnşallah devamı gelecek :)
YanıtlaSil