
STM32 mikrodenetleyiciler timer sayısı ve özellikleri bakımdan bir çok avantaja sahiptir. Arduino kullanarak devre hazırladığım yani mikrodenetleyici mimarisine çok uzak olduğum dönemlerde Timerlar hakkında hiçbirşey duymamış görmemiştim. Daha sonra ilk AVR programlama öğrenmeye çalıştığım zamanlarda Timer larla tanıştım. İlk yorumlarıma ve önyargılarıma göre benim için çok da önemli bir birim olmamıştı. Daha sonra fark ettimki Timer lar Arduino da kullandığım o kütüphanelerin bir çoğunda çok önemli bir yere sahip. Basit bir delay fonksiyonundan tutun servo motor sürmeye kadar bir çok şeyin içinde timerlar varmış. :)Muhtemelen şuanda henüz öğrenmediğim farklı özellikleri vardır. Bunları öğrendikçe ve anladıkça sizlere anlatmaya devam edeceğim.
Systick Timer Nedir ?
Yukarıda da bahsettiğim gibi STM32 mikrodenetleyiciler timer sayısı bakımından gayet avantajlı fakat Systick Timer ı diğerlerinden ayıran küçük bir detay var. Systick Timer ı diğerlerinden ayıran en önemli şey çip üreticisi STM32 tarafından değilde çipte kullanılan çekirdek üreticisi ARM tarafından sağlanmasıdır. Daha öncede mikrodenetleyicilerin bir mcu etrafına çevrebilirimlerinin bağlanmasıyla oluştuğundan bahsetmiştim. Timerlarda bu çevre birimlerine dahil ,STM32 tarafından sağlanan bir çok timer vardır fakat systick timer arm tarafından doğrudan çekirdek içerisinde tasarlanmıştır. Hatta Systick Timer registerları gibi bilgiler STM32 tarafından sağlanan belgelerde değilde ARM ın sunduğu dökümanlardadır.
Şimdi gelelim, Neden Systick Timer ?
Systick timerlar ile ilgili araştırma yapmaya başladığımda genellikle “basit zaman hesaplama gibi işlemler için genel timer kaynaklarımızı kullanmamıza gerek kalmıyor” gibi yaklaşımlara rastladım. Fakat henüz çok fazla timer kullanacağım seviyelerde komplike projeler yapmadığım için bu yaklaşım benim için çok anlam ifade etmemişti. Benim systick timer kullanmamın en önemli sebebi basit yapısı ve kullanım kolaylığı. Böyle bir yorum yapmam ne kadar doğru bilmiyorum ama basit yapısından kaynaklı güç tüketiminin de daha az olacağını düşünebiliriz.
Systick timer içerisinde bir adet 24 bit geriye doğru sayan sayıcıya sahiptir. Bu sayıcının hangi frekansta çalıştığını yani hangi hızda saydığını bildiğimiz için zaman hesaplama işlemini bu sayıcı sayesinde yaparız. Örneğin ; Sayıcımız 1 Hz de çalışsın bu demek oluyor ki her saniyede 1 geriye sayacak. Sayıcının ilk okunan değer ile son okunan değeri arasındaki fark bize geçen zamanı saniye cinsinden verecektir. Fakat, bu uygulamada ben bu prensib üzerine değilde kesmeye girme süresine göre zamanı hesaplayacağım.
Böyle basit bir işlem için kesme kullanmak çok önem arz etmesede bu yazı için böyle bir yol tercih ettim daha sonrada kesme kullanmadan yani yukarıda verdiğim örnekteki gibi delay yapacağımız bir yazı yazacağım.
Systick Timer Yazmaçları

ENABLE(0) : Bu biti 1 yapmak sayıcıyı aktif hale getirir.
TICKINT(1) : Bu biti 1 yapmak sayıcı 0 a ulaştığı zaman oluşacak kesmeyi aktif eder.
CLKSOURCE(2) : Bu bit 1 iken sayıcı frekansı doğrudan AHB hattının frekansına eşittir. Bu bit 0 yapıldığında ise sayıcı AHB/8 frekansta çalışmaktadır.
COUNTFLAG(16) : Sayıcı 0 a ulaştığı zaman 1 konumuna geçer. Kesme kullanılmasa bile bu bayrak kontrol edilerek sayıcının 0 olma durumu kontrol edilebilir.

RELOAD(23:0) : Sayıcının hangi değerden 0 a doğru sayacağını belirlediğimiz bitler. Sayıcı her 0 a ulaştığında tekrar RELOAD değerine eşitlenecektir ve tekrar 0 a kadar eksilerek sayacaktır. Sayma işlemine 0 da dahil olduğu için sayma sayısının 1 eksiğini atamalıyız.

CURRENT(23:0) : Sayıcının o anlık değerini okuyabileceğimiz veya yazabileceğimiz bitler.
Benim AHB frekansım 100 Mhz ve systick frekansı olarak AHB/8 i seçiyorum. Böylece Systick frekansım 1,25 Mhz oluyor. Bu demek oluyor ki sayıcım her 0,08 mikrosaniyede bir sayacak.
Delay fonksiyonum milisaniye cinsinden bekleme yapacağı için ihtiyacım olan zaman 1 ms .Sayıcımın Reload değerine 12499 değerini atadığım zaman bu değerden 0 a ulaşması 1 milisaniye olmaktadır. Yani en kısa tabir ile systick timer ım her 1 milisaniyede bir kez kesmeye girecek ve bende kesme içerisindeki milisaniye değerini tuttuğum değişkenimi 1 arttıracağım.
void systickinit(void)
{
SysTick->CTRL |= SysTick_CTRL_ENABLE_Msk; // Sayıcıyı aktif et
SysTick->LOAD = 12499; // Reload değerini ata
SysTick->VAL=0; // sayıcıyı sıfırla
SysTick->CTRL |= SysTick_CTRL_TICKINT_Msk; // kesmeyi aktif et
SysTick->CTRL &= ~(1<<2); //Systick clock source = AHB/8
NVIC_EnableIRQ(SysTick_IRQn); // NVIC tarafında kesmeyi aç
NVIC_SetPriority (SysTick_IRQn,0); //kesme önceliğini ayarla
}
void SysTick_Handler(void) // kesme oluştuğunda girilecek fonksiyon
{
millis++; // millis değerini 1 arttır
}
void delayms(int ms) // milisaniye cinsinden delay fonksiyonu
{
int delay = millis+ms;
while(millis<delay);
}
Note : millis değişkenimi kesme fonksiyonu içerisinde kullanacağım için volatile olarak atamam gerekiyor.