IAR ile STM8S – TIMER

Bu yazıda Timer’lara giriş yaparak artık zamanlama sorunlarının üstesinden rahatça gelebileceğiz. Daha önce STM32F0 Derslerinde sayaçları incelemiştik. Kısaca özetleyecek olursak. Belirlenen değere kadar saydıkların da bize bir kesme üretirler böylece ana programdan bağımsız olarak periyodik bir kesme sinyalimiz olur. Bu MCU’lar da  zaman yönetimi konusunu çözerek bize bir hayli fayda sağlar. Bunun dışında PWM çıkışları, Capture girişleri, Encoder girişleri gibi bir takım ekstra özellikleri de vardır. Bunlar daha sonraki yazılarda değineceğiz. Şimdi STM8S’in içindeki sayaç bloğunu inceleyerek işe başlayalım.

Öncelikle MCU’ların içinde birden fazla sayıcı olabileceğini ve her sayacın kendine özgü özellikleri olduğunu unutmayalım. STM8S003F3P6 adlı MCU’da TIM1, TIM2, TIM4 olmak üzere 3 adet sayaç bulunmaktadır. Bunu kontrolcü’nün veri kağıdından bulabilirsiniz.


Resimde görüldüğü üzere her sayaç farklı özelliklere sahiptir. Biz genelde PWM çıkışı kullanmadığımız taktirde 8 bit olan daha basit sayaçları zamanlama işlemi için seçeriz. Bu bize sonraki uygulamalarda PWM için seçenek bırakır. Yayınlanan “Reference Manuel” den detayları bilgilere ulaşarak TIM4’ün yapısını inceleyebiliriz.


Görüldüğü gibi tek yapmamız gereken ön bölücü “PRESCALER” ve periyot “PERIOD” değerlerini yüklememiz. Bu işlemi yaptıktan sonra sayacın taşma kesmesini aktif etmemiz yeterli olacaktır.

TIM4 sayacı için tanımlanan 8 farklı ön bölücü değeri şu şekildedir;

/** TIM4 Prescaler */
typedef enum
{
  TIM4_PRESCALER_1  = ((uint8_t)0x00),
  TIM4_PRESCALER_2    = ((uint8_t)0x01),
  TIM4_PRESCALER_4    = ((uint8_t)0x02),
  TIM4_PRESCALER_8     = ((uint8_t)0x03),
  TIM4_PRESCALER_16   = ((uint8_t)0x04),
  TIM4_PRESCALER_32     = ((uint8_t)0x05),
  TIM4_PRESCALER_64    = ((uint8_t)0x06),
  TIM4_PRESCALER_128   = ((uint8_t)0x07)
} TIM4_Prescaler_TypeDef;

Ben kesmeyi 1 mili saniye civarı ayarlamak istiyorum. Öncelikle dahili osilatör (HSI) kullanacağım için 16 MHz / 128 işlemini yaptıktan sonra t yerine 0.001 değerini koyarak periyot değerini elde edebiliriz. Bu frekans sayacın frekansı oluyor.


Buradan Period değerini 124 olarak hesaplanır.

TIM4_TimeBaseInit(TIM4_PRESCALER_128, 124);
TIM4_ClearFlag(TIM4_FLAG_UPDATE);
TIM4_ITConfig(TIM4_IT_UPDATE, ENABLE);

enableInterrupts();

TIM4_Cmd(ENABLE);

Genel kesmeleri de aktif ederek sayacı çalışır hale getirdik. Bundan sonra yapmamız gereken kesme fonksiyonunu hazırlamak. Burada ST bize hazır bir kesme dosyası vererek kolaylık sağlamış. Bu dosyayı kütüphaneye eklemek yeterli.  STM8S_StdPeriph_Lib içinde bulunan stm8s_it.c adlı dosyayı projeye eklemek yeterli. Bu dosya içinde TIM4_UPD_OVF_IRQHandler kesmesini kullanacağız. Unutmadan burada bir önemli nokta kesme bayrağını temizlemek. Eğer bunu yapmazsak ikinci kez kesme alamayız.

INTERRUPT_HANDLER(TIM4_UPD_OVF_IRQHandler, 23)
{
   if (TIM4_GetITStatus(TIM4_IT_UPDATE) == SET)
   {
      TIM4_ClearITPendingBit(TIM4_IT_UPDATE);

      GPIO_WriteReverse(LED_GPIO, LED_PIN);
   }
}

Kullanmış olduğumuz if yapısı sadece sayacın taşma kesmesi olup olmadığını anlamak için. Bunun sebebi bir sayacın birden fazla kesmesi olmasıdır. TIM4 ile ilgili tüm kesmeler bu fonksiyona gireceği için taşma kesmesini bu şekilde ayırt edebiliriz.  Sonuç olarak elimizde 1 mili saniye aralıklar ile terslenen bir çıkış var. Son olarak Logic Analyzer ile bunu doğrulayarak işlemiş tamamlayalım.


Harika! Her şey yolunda gözüküyor. Bu görüntü bize bir şeyi hatırlatıyor ? Bu bir sonraki yazının konusu olsun.

Kodlarımızın son hali şu şekilde.

#include "stm8s.h"

#define LED_GPIO        (GPIOB)
#define LED_PIN         ((GPIO_Pin_TypeDef)GPIO_PIN_5)

#define TIM4_PERIOD     (124)

static void SYSTEM_Config(void);
static void CLK_Config(void);
static void GPIO_Config(void);
static void TIM4_Config(void);

void main(void)
{
   SYSTEM_Config();
   
   for (;;)
   {

   }
}

static void SYSTEM_Config(void)
{
   CLK_Config();
   GPIO_Config();
   TIM4_Config();
}

static void CLK_Config(void)
{
   CLK_DeInit();
   CLK_HSECmd(DISABLE);
   CLK_HSICmd(ENABLE);
   CLK_ClockSwitchConfig(CLK_SWITCHMODE_AUTO, CLK_SOURCE_HSI, DISABLE, CLK_CURRENTCLOCKSTATE_DISABLE);
   CLK_SYSCLKConfig(CLK_PRESCALER_HSIDIV1);
   CLK_SYSCLKConfig(CLK_PRESCALER_CPUDIV1);
}

static void GPIO_Config(void)
{
   GPIO_Init(GPIOB, GPIO_PIN_5, GPIO_MODE_OUT_PP_LOW_FAST);
}

static void TIM4_Config(void)
{
   /* TIM4 configuration:
   - TIM4CLK is set to 16 MHz, the TIM4 Prescaler is equal to 128 so the TIM1 counter
   clock used is 16 MHz / 128 = 125 000 Hz
   - With 125 000 Hz we can generate time base:
   max time base is 2.048 ms if TIM4_PERIOD = 255 --> (255 + 1) / 125000 = 2.048 ms
   min time base is 0.016 ms if TIM4_PERIOD = 1   --> (  1 + 1) / 125000 = 0.016 ms
   - In this example we need to generate a time base equal to 1 ms
   so TIM4_PERIOD = (0.001 * 125000 - 1) = 124 */

   /* Time base configuration */
   TIM4_TimeBaseInit(TIM4_PRESCALER_128, TIM4_PERIOD);
   /* Clear TIM4 update flag */
   TIM4_ClearFlag(TIM4_FLAG_UPDATE);
   /* Enable update interrupt */
   TIM4_ITConfig(TIM4_IT_UPDATE, ENABLE);

   /* enable interrupts */
   enableInterrupts();

   /* Enable TIM4 */
   TIM4_Cmd(ENABLE);
}

#ifdef USE_FULL_ASSERT
void assert_failed(uint8_t* file, uint32_t line)
{ 
   while (1);
}
#endif

Toparlayacak olursak…

STM8S kullanarak sayaçları kullanmak bir hayli kolay. Uygun fiyatı, rahat geliştirme ortamı ve kolay geliştirilebilirliği açısından 8 bit tarafından büyük ilgi görmekte olan bu denetleyiciler bir çok projemizde yer almaya devam edecek…

 

You may also like...

Bir yanıt yazın