top of page

SysTick Timer Kullanımı ve Servo Uygulaması

Güncelleme tarihi: 18 Oca 2023



SysTick timer, Cortex-M çekirdeğinde bulunan temel zamanlayıcıdır. Yani başka bir deyişle bu timerı STM32 serilerinin üreticisi ST firması değil de çekirdek üreticisi ARM sağlar. Delay fonksiyonlarında kullanılır, işlemci kapasitesini harcamaz, güç tüketimi sağlar ve doğrudan çekirdek içine tasarlanmıştır. Diğer timerların farklı modları (input capture, output capture vs.) olduğu için normal delay fonksiyonlarında bu timerları kullanmak tercih edilmez, bu birden fazla çevre biriminin aynı anda çalıştığı gelişmiş sistemlerde, işlemci gücünü ve kaynaklarını boşa kullanmak gibi olur. Sistem zamanlayıcısı SysTick, 24 bitlik bir geri sayım zamanlayıcısıdır. Bunu Gerçek Zamanlı İşletim Sistemi (RTOS) tick timer veya basit bir sayaç olarak kullanılır 0 ile 16.777.215 arasında sayar.



SysTick timerı kullanmak için kütüphanesi oluşturulur ve projeye dahil edilerek tekrar yazılmak zorunda kalınmatan tekrar kullanılabilir. Kütüphane için 2 dosya gereklidir. Bunlardan biri .h uzantılı dosyadır, bu dosyada kartın kendi kütüphanesi ve .c uzantılı dosyada oluşturulan fonksiyonlar yer alır. Diğer dosya .c uzantılı dosyadır. Burada SysTick ayarlamaları yapılır ve .h uzantılı dosyanın buraya dahil edilmesi gerekmektedir. SystemCoreClock/1000 yapılma nedeni işlemci örneğin 1 snde 168 mHz ile çalışır, bu 1 saniyede 168 milyon clock darbesi demektir. 1000’e bölünüyor yani 1 saniye 1000’e bölünüyor 1 milisaniye oluyor, kesme süresi 1 ms oluyor. 1000'e bölünmesiyle 1 ms'lik bir sistem timer elde ediliyor. Yani 1 ms'de bir SysTick_Handler(void) fonksiyonu çağırılır. /1000 kısmı değiştirilerek istenilen zaman oluşturulabilir. /1000 yerine /1000000 yapılırsa 1us olur, /10 yapılırsa 100ms olur. Genel kullanımı /1000 yani 1ms olacak şekildedir.



Bu servo uygulamasında TIM2 ile servo kontrolü yapılmış ve PWM mode (output compare mode) olarak kullanılmıştır. PWM mode darbe pals genişlik modülasyonudur. PWM sinyalinin çalışma döngüsü (duty cycle) genişletilerek çıkış sinyali elde etmeyi sağlar. Duty cycle, BTJ veya MOSFET gibi anahtarlama elemanı olarak kullanılan transistörlerin açık/kapalı durumlarına yani anahtara basma sürelerine göre değişir. Duty cycle değiştirilerek çıkışlardaki voltaj değeri de değiştirilebilmektedir.


Duty Cycle şu formüle göre hesaplanır:

Bir anahtarlama süresi sonunda çıkış voltajı da şu şekilde hesaplanır:

STM’de frekans ve duty cycle hesaplama:





Örneğin 1 kHz çalışma frekansında prescelar 10 olarak ayarlanırsa timer clock 2.4 Mhz olur. 1 kHz= 2.4/(Timer Period+1)'den timer periodun 2399 olarak ayarlanması gerekir. Duty cycle %25 ise TIM pulse=((2399+1)*0.25/100)-1'den TIM pulse 599 bulunur.


Bu uygulamada prescelar 100 olarak ayarlanmış ve timer clock 0.24 Mhz olmuştur. Servonun datasheetinden hangi frekans kaç derece için gerekli o bilgiler öğrenilmiş ve oradan da gerekli timer pulse değerleri elde edilmiştir. Örneğin 0 derece için 1.5 ms çalışması gerekmektedir, hesaplamalar yapıldığında da 0 derece için TIM pulse 359 olarak elde edilir. 90 derece için 2 ms çalışması gerekir ve TIM pulse 480 , -90 derece için 1ms çalıştırılır TIM pulse 240 ayarlanır.









Kullanılan Malzemeler, Devre Şeması ve Kodlar:


  • Servo motor

  • Jumper Kablolar

  • STM32VL Discovery Kartı






#include "stm32f10x.h"                  // Device header
#include "stm32f10x_tim.h"             // Keil::Device:StdPeriph Drivers:TIM
#include "delay.h" // olusturulan sysTick timer için delay.h kütüphanesinin eklenmesi gerekir 



void gpioConfig(); // pinlerin ayarlanmasi için fonksiyon 
void timerConfig(); // timerin ayarlanmasi için fonksiyon 
void pwmConfig(uint16_t timerPulse); // pwm modunun ayarlanmasi icin fonksiyon 



int main(){
   
	gpioConfig();
	timerConfig();
	DelayInit(); // stsTickin ayarlari ve update edilmesi 
	
	
	uint16_t servoArray[]={359,480,240}; //0,90 ve 180 derece için belirlenmis TIM pulselar için olusturulan array
	
	
while(1){



  for(int i=0; i<=2; i++){ // while içinde önce 0 sonra 90 ve sonra 180 dereceye gidecek belli bir bekleme bulunmakta arada 
	   pwmConfig(servoArray[i]);
		 delayms(1000);
	   
	}
	
	 
}


}


void gpioConfig(){
	
	GPIO_InitTypeDef GPIOInitStructure; 
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE); // A portunun 0. pini servonun sinyal pinine baglanacak, A portu için clock hatti aktif ediliyor
	
	GPIOInitStructure.GPIO_Mode=GPIO_Mode_AF_PP; // Pin modu seçildi, timer kullanilacagi için af ayarlandi
	GPIOInitStructure.GPIO_Pin=GPIO_Pin_0; // 0. pin belirlendi
	GPIOInitStructure.GPIO_Speed=GPIO_Speed_50MHz;// hiz ayarlandi 
	
  GPIO_Init(GPIOA,&GPIOInitStructure); // pin konfigürasyonunun yapildigi bildirildi


}
void timerConfig(){
	
	
	 TIM_TimeBaseInitTypeDef TIMERInitStructure; 
	 RCC_APB1PeriphClockCmd (RCC_APB1Periph_TIM2, ENABLE); //A0 için TIM2 kullanilacak, APB1 clock hattina bagli. CH1 de sonra aktif edilmeli 
    	
	 TIMERInitStructure.TIM_ClockDivision=TIM_CKD_DIV1; // clock bölümü yapiliyor 
	 TIMERInitStructure.TIM_CounterMode=TIM_CounterMode_Up; // yukari dogru sayan counter mode seçildi
	 TIMERInitStructure.TIM_Prescaler=100; //prescaler 100 olarak ayarlandi
	 TIMERInitStructure.TIM_Period=4799; // 50 hz frekans için hesaplamalardan period 4799 olarak bulundu 
	
	 TIM_TimeBaseInit (TIM2,&TIMERInitStructure); //timer için ayarlamalarin yapildigi bildirildi
	 TIM_Cmd(TIM2, ENABLE);
	
	


}
void pwmConfig(uint16_t timerPulse){
  
	 TIM_OCInitTypeDef TIMOC_InitStructure; 
	 
   TIMOC_InitStructure.TIM_OCMode=TIM_OCMode_PWM1; //timerin output conpara modunda kullanilacagi ve %75lik duty cycle ile calisacagi bildiriliyor. PWM2 olsa %25lik duty cycle ile calisirdi
   TIMOC_InitStructure.TIM_OutputState=TIM_OutputState_Enable; // output durumu için karsilastirma yapilacak enable edildi
   TIMOC_InitStructure.TIM_OCPolarity=TIM_OCPolarity_High;
   TIMOC_InitStructure.TIM_Pulse=timerPulse; // TIM pulselera göre servonun dereceler kontrol edilecek
  
   TIM_OC1Init(TIM2,&TIMOC_InitStructure); // output compare modu için ayarlama yapildigi bildiriliyor. Channel 1'e bagli A0'sa bulunan TIM2. 
   TIM_OC1PreloadConfig(TIM2,TIM_OCPreload_Enable);
	
}


Systick için oluşturulan .c ve .h kodları:




#include "delay.h" //.c dosyasina olusturulan .h uzantili dosya eklenmelidir 


static __IO uint32_t counter; // counter volatile olarak tanimlandi 


void SysTick_Handler(){ // Systick için kesme fonksiyonu 
  
   if(counter>0){
		 counter--;
	 }
}
void delayms (uint32_t time){ // delay fonksiyonu 


  counter=time; // time countera ataniyor 
	while(counter); //counter 0 olana kadar time bitene kadar yani çalisacak

}
void DelayInit(void){ //initialize donksiyonu 
   
	 SystemCoreClockUpdate(); // çekirdegin saati update ediliyor
	 SysTick_Config(SystemCoreClock/1000); //1000e bölerek 1 ms olacak sekilde ayarlaniyor sysTick 
   

}





#ifndef __DELAY_H
#define __DELAY_H

#ifdef __cplusplus
extern "C" {  // C kodunun C++ ile kullanilabilmesini saglar.

#endif

 

#include "stm32f10x.h" //kartin headeri ekleniyor 

void DelayInit(void); // .c uzantili dosyada kullanilan fonskiyon
void delayms(uint32_t time); // .c uzantili dosyada kullanilan fonskiyon

#ifdef __cplusplus
}

#endif

#endif

Son Paylaşımlar

banner300900.gif
banner300900.gif
bottom of page