STM8 Programlama -IAR- #6 (Clock Ayarları)

Merhabalar,
Bu yazımızda MCU’nun clock ayarlarını ayrıntılı bir şekilde inceleyeceğiz. CLK_CCO çıkışını kullanarak lojik analizör ile inceleyeceğiz. ST firmasının STM8 ailesinde aşağıda da görüldüğü gibi esnek clock ayarları yapabilmek mümkün. CPU çalışma frekansı ile çevre birimleri çalışma fekanslarını ayrı ayrı ayarlamak mümkün. Osilatör kaynaklarımızı daha önceki yazılarımızda incelemiştik kısaca hatırlaycak olursak
– HSE (High Speed External)
– HSI (High Speed Internal (RC))
– LSI (Low Speed Internal)

MCU Turkey – STM8S – İlk Uygulamalar (Clock ve GPIO Konfigürasyonu)

Mikrodenetleyicinin clock kaynağını (HSI) High-Speed dahili osilatör olarak seçeceğiz. Bu durumda Master Clock Switch fHSIDIV olarak seçilmelidir. Bu kaynağın 4 adet ön bölücü değeri vardır. Bu değerler 16 MHz olan HSI osilatör kaynağını (/8/4/2/1) seçnekleri arasından seçeceğimiz değere böler ve bölünmüş clock fMASTER hattına geçiş yapar. Şemadan da görüldüğü gibi TIMER,I2C,SPI,ADC,AWU,CAN,UART çevre birimleri bu hattan doğrudan beslenir. Dolayısıyla HSIDIV ön bölücü değerimizin sonucunda bu çevre birimlerinin clock kaynağının sağlandığını unutmayalım.
HSIDIV’i ayarladıktan sonra CPUDIV ön bölücü değeri için 8 seçenek mevcut (/1/2/4/8/16/32/64/128). CPUDIV ön bölücü değerine göre ise fCPU frekansı belirlenmiş olur.

Örnek; Osilatör kaynağımız HSI (16MHz) olsun. HSIDIV=/2, CPUDIV=/4 olduğunu varsayalım.
O halde fMASTER= 16/2 = 8 MHz olacaktır. Buda demek oluyor ki çevre birimlerinin çalışma frekansı ve CPUDIV giriş frekansı 8MHz’dir.

fCPU = 8/4 = 2MHz olacaktır. Buda mikrodenetleyimizin çekirdeği 2MHz ile koşacağı anlamına gelir. Saniyede 2 milyon işlem yapabilir diyebiliriz.

Şimdi kod IAR derleyicisi için kodlarımıza geçelim. Öncelikle main.c dosyamızda stm8s_clk.h kütüphanesini dahil etmeliyiz.

#include "stm8s_clk.h"

Daha sonra kullanacağımız osilatör kaynağını aktif etmeliyiz (HSI).

CLK_HSECmd(DISABLE);
CLK_LSICmd(DISABLE);
CLK_HSICmd(ENABLE);

Osilatör hazır olana kadar, ilgili osilatörün bayrağı SET olana kadar CLK_GetFlagStatus(); fonksiyonundan aldığımız cevaba göre while dönüsü ile bekleme yapıyoruz. Fonksiyonun parametreleri şu şekildedir;

typedef enum {
CLK_FLAG_LSIRDY = (uint16_t)0x0110, /*!< Low speed internal oscillator ready Flag */
CLK_FLAG_HSIRDY = (uint16_t)0x0102, /*!< High speed internal oscillator ready Flag */
CLK_FLAG_HSERDY = (uint16_t)0x0202, /*!< High speed external oscillator ready Flag */
CLK_FLAG_SWIF = (uint16_t)0x0308, /*!< Clock switch interrupt Flag */
CLK_FLAG_SWBSY = (uint16_t)0x0301, /*!< Switch busy Flag */
CLK_FLAG_CSSD = (uint16_t)0x0408, /*!< Clock security system detection Flag */
CLK_FLAG_AUX = (uint16_t)0x0402, /*!< Auxiliary oscillator connected to master clock */
CLK_FLAG_CCOBSY = (uint16_t)0x0504, /*!< Configurable clock output busy */
CLK_FLAG_CCORDY = (uint16_t)0x0502 /*!< Configurable clock output ready */
}CLK_Flag_TypeDef;

Osilatör kaynağımız HSI olduğu için CLK_FLAG_HSIRDY seçmeliyiz.

while(CLK_GetFlagStatus(CLK_FLAG_HSIRDY) == 0);

Yukarıda bahsettiğimiz ön bölücü değerlerini ayarlıyoruz. Parametrelerin sonlarındaki rakamı yukarıdaki ilgili değerlerle değiştirerek istediğimiz çalışma frekansını elde edebiliriz.

CLK_HSIPrescalerConfig(CLK_PRESCALER_HSIDIV1); //fMASTER
CLK_SYSCLKConfig(CLK_PRESCALER_CPUDIV1); //fCPU

Clock ayarlarmaları için bir diğer durum ise CLK_ClockSwitchConfig() fonkisyonudur. Bu özellik mikrodenetleyici çalışıyorken clock kaynağını manuel veya otomatik değiştirmeye olanak sağlar. İşlem otomatik olarak seçilir ise; ana osilatörde herhangi bir problem oluşursa seçeceğimiz alternatif osilatör kaynağı devreye alınacak ve istersek ana osilatörü pasif edebileceğiz. Örnek fonksiyon ve parametre açıklamaları;

CLK_ClockSwitchConfig(CLK_SWITCHMODE_AUTO, CLK_SOURCE_HSI,
DISABLE, CLK_CURRENTCLOCKSTATE_ENABLE);
/**
  * CLK_SWITCHMODE_AUTO/_MANUEL : işlemin otomatik veya ellemi seçileceğini
  * CLK_SOURCE_HSI/_LSI/_HSE    : Alterantif olarak seçilecek kaynağı(yedek)
  * DISABLE/ENABLE : Otomatik veya manuel farketmeksizin böyle bir işlem 
  *gerçekleştiğinde kesme oluşmasını istiyorsak ENABLE olması gerekir.
  * CLK_CURRENTCLOCKSTATE_ENABLE/DISABLE : İşlem gerçekleşirse ana kaynağı 
  *pasif konuma getireceksek DISABLE seçmeliyiz.
  */

Değinmek istediğim bir diğer nokta ise bu kütüphanedeki CCO (Configurable Clock Output) özelliğidir. Bu özelliklik ile birlikte mikrodenetleyicinin ilgili pininden (PC4/CLK_CCO) aşağıdaki seçeneklerden istediğimiz clock sinyalini elde edebiliriz. Geliştirdiğimiz sistemde herhangi bir osilatör kaynağına ihtiyaç duymamız halinde bu özelliği kullanabiliriz. Ayrıca ilgili osilatör kaynağı freknasını CCO ile gözlemlemek mümkündür.

typedef enum {
  CLK_OUTPUT_HSI      = (uint8_t)0x00, /*!< Clock Output HSI */
  CLK_OUTPUT_LSI      = (uint8_t)0x02, /*!< Clock Output LSI */
  CLK_OUTPUT_HSE      = (uint8_t)0x04, /*!< Clock Output HSE */
  CLK_OUTPUT_CPU      = (uint8_t)0x08, /*!< Clock Output CPU */
  CLK_OUTPUT_CPUDIV2  = (uint8_t)0x0A, /*!< Clock Output CPU/2 */
  CLK_OUTPUT_CPUDIV4  = (uint8_t)0x0C, /*!< Clock Output CPU/4 */
  CLK_OUTPUT_CPUDIV8  = (uint8_t)0x0E, /*!< Clock Output CPU/8 */
  CLK_OUTPUT_CPUDIV16 = (uint8_t)0x10, /*!< Clock Output CPU/16 */
  CLK_OUTPUT_CPUDIV32 = (uint8_t)0x12, /*!< Clock Output CPU/32 */
  CLK_OUTPUT_CPUDIV64 = (uint8_t)0x14, /*!< Clock Output CPU/64 */
  CLK_OUTPUT_HSIRC    = (uint8_t)0x16, /*!< Clock Output HSI RC */
  CLK_OUTPUT_MASTER   = (uint8_t)0x18, /*!< Clock Output Master */
  CLK_OUTPUT_OTHERS   = (uint8_t)0x1A  /*!< Clock Output OTHER */
} CLK_Output_TypeDef;

CCO’yu kullanabilmek için ilgili CLK_CCO pin konfigürasyonunu (STM8S103F3 için PC4 pini) input pull-up veya output push-pull moduna getirmeliyiz (push-pull,pull-up için buraya).

CLK_CCOConfig(CLK_OUTPUT_CPU);
CLK_CCOCmd(ENABLE);

PC4 pini için gerekli ayarlamayı yaptıktan sonra PC4 pininden CPU çalışma frekansındaki sinyali almış olacağız.

Konuyu şöyle bir toparlarsak….. Yapacağımız uygulamalarda kartımızın üzerinde harici bir kristal osilatör olmadığı için dahili HSI osilatörü kullanacağız. Bu osilatör kaynağı ile ilgili bir ön yargınız/şüpheniz olmasın bu birim gayet sağlıklı çalışmaktadır. Buna göre ilerideki uygulamalarda kullanabileceğimiz bir clock ayarı için kodumuz şöyle olur;

CLK_DeInit();	
CLK_HSECmd(DISABLE);
CLK_LSICmd(DISABLE);
CLK_HSICmd(ENABLE);
while(CLK_GetFlagStatus(CLK_FLAG_HSIRDY) == 0);

CLK_ClockSwitchCmd(ENABLE);
CLK_HSIPrescalerConfig(CLK_PRESCALER_HSIDIV2);
CLK_SYSCLKConfig(CLK_PRESCALER_CPUDIV1);

Bu kodu void main(void) döngüsünün hemen altına yazarak kullanabiliriz.

Aşağıda CLK_CCO ya ait uygulamanın kodları bulunmaktadır. Ayrıca proje dosyasını buradan indirebilirsiniz.

/**
  ******************************************************************************
  * @file    Project/main.c 
  * @author  N7A TECHNIC
  * @brief   Main program body
   ******************************************************************************
  *        www.n7a.web.tr
  ******************************************************************************
  */ 

/* Includes ------------------------------------------------------------------*/
#include "stm8s.h"
#include "stm8s_clk.h"
#include "stm8s_gpio.h"

/* Private defines -----------------------------------------------------------*/
/* Private function prototypes -----------------------------------------------*/
/* Private functions ---------------------------------------------------------*/

void main(void)
{
  /* Infinite loop */
  CLK_DeInit();
  CLK_HSECmd(DISABLE);
  CLK_LSICmd(DISABLE);
  CLK_HSICmd(ENABLE);
  
  while(CLK_GetFlagStatus(CLK_FLAG_HSIRDY)==0);
  
  CLK_ClockSwitchCmd(ENABLE);
  CLK_HSIPrescalerConfig(CLK_PRESCALER_HSIDIV4);
  CLK_SYSCLKConfig(CLK_PRESCALER_CPUDIV2);
  
  GPIO_Init(GPIOC,GPIO_PIN_4,GPIO_MODE_OUT_PP_LOW_FAST);
  
  CLK_CCOConfig(CLK_OUTPUT_CPU);
  CLK_CCOCmd(ENABLE);
  
  while (1)
  {
  }
}

#ifdef USE_FULL_ASSERT

void assert_failed(u8* file, u32 line)
{ 
  /* User can add his own implementation to report the file name and line number,
     ex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */

  /* Infinite loop */
  while (1)
  {
  }
}
#endif


/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/

Teorik Eğitim:

Uygulama:

Bir yanıt yazın

E-posta adresiniz yayınlanmayacak. Gerekli alanlar * ile işaretlenmişlerdir

Whatsapp Hattı