Stm32F4 Std_Lib Timer kullanımı (Örnek)

Başlatan Klein, 31 Ekim 2012, 03:10:06

Klein

STD_LIB kullanarak Timer ayarlama.
Proje CooCox IDE kullanarak yazıldı. KEil ile derlemek istenirse , daha önceden nasıl yapılacağını anlatmıştım. Bir farkı yok zaten. CoIDE'de kütüphane eklemek için arayüz var oraden seçtiğinizde projenize ekleniyor. Keilde ise kullanacağınız kütüphanenin *.c dosyasını proje yöneticisinden projeye dahil ediyorsunuz. Eğer Stm32F4xx_conf.h dosyasında  #include "kullanacağınız kütüphane.h"  satırı comment yapılmış ise açıyorsunuz, ya da benim yaptığım gibi,#include direktifi ile projenin başlığında ekliyorsunuz. Hangi kütüphanelerin eklenmiş olduğu #include satırlarında görülüyor, kısa bir açıklama yapayım.

"stm32f4xx.h"             bazı peripherial ayarlarını içerir.
"stm32f4xx_gpio.h"     GPIO ayarları
"stm32f4xx_rcc.h"       RCC ayarları.
"stm32f4xx_tim.h"       Timer ayarları
"misc.h"                      NVIC ayarları

Kod:
#include "stm32f4xx.h"
#include "stm32f4xx_gpio.h"
#include "stm32f4xx_rcc.h"
#include "stm32f4xx_usart.h"
#include "stm32f4xx_tim.h"
#include "misc.h"

GPIO_InitTypeDef GPIO_Init_Struct;
uint8_t timer_update=0;
uint32_t ledtime=0;

void init_tim7(void){
TIM_TimeBaseInitTypeDef TIM_TBInitStruct;
NVIC_InitTypeDef NVIC_InitStructure;

	RCC_APB1PeriphClockCmd(RCC_APB1ENR_TIM7EN,ENABLE); // Timer saat kaynağını aç
	TIM_TBInitStruct.TIM_Prescaler = 4199; // ÖnBölücü (PSC) değeri 4199 
	TIM_TBInitStruct.TIM_Period =1; // Otomatik geri yükleme (ARR) eşiği 1
	TIM_TimeBaseInit(TIM7,&TIM_TBInitStruct); // Timeri init et

	TIM_ITConfig(TIM7, TIM_IT_Update, ENABLE); // Timer Update olayında interrupt istesin.
    NVIC_InitStructure.NVIC_IRQChannel = TIM7_IRQn;
    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
    NVIC_Init(&NVIC_InitStructure);


    TIM_Cmd(TIM7, ENABLE);// Timeri başlat
}



void TIM7_IRQHandler(void)
{
TIM7->SR=0;
timer_update=1;
}


void init_gpio(void){
  RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOD,ENABLE);

  GPIO_Init_Struct.GPIO_Pin = GPIO_Pin_12 | GPIO_Pin_13 | GPIO_Pin_14 | GPIO_Pin_15;
  GPIO_Init_Struct.GPIO_Mode = GPIO_Mode_OUT;
  GPIO_Init_Struct.GPIO_OType= GPIO_OType_PP;
  GPIO_Init_Struct.GPIO_Speed= GPIO_Speed_100MHz;
  GPIO_Init_Struct.GPIO_PuPd=GPIO_PuPd_NOPULL;
  GPIO_Init(GPIOD,&GPIO_Init_Struct);
}

int main(void)
{

  SystemInit();
  init_gpio();
  init_tim7();

	while(1)
    {
       if(timer_update){
            timer_update=0;

            if(++ledtime > 5000){
      			ledtime =0;
                GPIO_ToggleBits(GPIOD,GPIO_Pin_12);
                GPIOD->ODR ^= 0x0000008000;
            }
        }

    }
}


Kod açıklamaları:

TIM_TimeBaseInitTypeDef TIM_TBInitStruct;
NVIC_InitTypeDef NVIC_InitStructure;

Artık biliyoruz ki, hangi donanımı init edeceksek edelim, hepsi için tanımlanmış bir tip var.
Bu tip, genellikle donanımın adının kısaltması ile başlayıp, InitTypeDef ile sonlanıyor. NVIC_InitTypeDef  tipinde olduğu gibi.
Timer init tipinde ise Timeri hangi modda kullanacağımıza göre tipin tanımı değişiyor. Biz bu timeri zamanlayıcı olarak kullanacağımız için, TIM_TimeBaseInitTypeDef  tipini kullanıyoruz.

RCC_APB1PeriphClockCmd(RCC_APB1ENR_TIM7EN,ENABLE); // Timer saat kaynağını aç
Zaten biliyoruz. Donanımın registerlerine yazmaya başlamadan önce, saat kaynağını açıyoruz.

TIM_TBInitStruct.TIM_Prescaler = 4199; // ÖnBölücü (PSC) değeri 4199
TIM_TBInitStruct.TIM_Period =1; // Otomatik geri yükleme (ARR) eşiği 1
Prescaler ve Auto reload değerlerini ayrlıyoruz. (PSC, ARR) Bu registerler daha önce bolca konuşulduğu için burada anlatmıyorum. Hatırlamayanlar daha önceki CM4 başlıklarında daha detaylı bilgi bulabilir.

TIM_TimeBaseInit(TIM7,&TIM_TBInitStruct); // Timeri init et
Timer 7 yi init ediyoruz.
Kütüphanelerde bütün donanımların init yöntemi aynı. Önce bir "XXX_InitTypedef" tipinden bir değişken tanımlıyoruz. Bu değişken struct tipi bir değişken. Daha sonra bu değişkenin alanlarını dolduruyoruz, en son olarak da "Xxx_YyyInit()" fonksiyonunu çağırarak, donanımımızı init ediyoruz.

TIM_ITConfig(TIM7, TIM_IT_Update, ENABLE); // Timer Update olayında interrupt istesin.
Timer her taştığında (Update) Interrupt üretsin istiyoruz.

    NVIC_InitStructure.NVIC_IRQChannel = TIM7_IRQn;
    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
    NVIC_Init(&NVIC_InitStructure);
Burada TIM7 nin NVIC'deki tanımlarını yapıp, NVIC'yi init ediyoruz.
   
    TIM_Cmd(TIM7, ENABLE);// Timeri başlat
Son olarak da  sayıcıyı başlatıyoruz.


Klein

Konu ingilizce bilmeyenlr için muhittin. Orada yazılanları anlayanlar kapsama alanımızın dışında.

caglar

Kodu kopyaladım ve yapıştırdım fakat aşağıdaki kütüphanelerde hata verdi.
Neden öyledir acaba yeni başlayan birisi olarak yardımlarınızı bekliyorum.

#include "stm32f4xx_gpio.h"
#include "stm32f4xx_rcc.h"
#include "stm32f4xx_usart.h"
#include "stm32f4xx_tim.h"
#include "misc.h"

Klein

Verdiği hatalar nelerdir?  Başka bir mesaja yazdığından da anladığım kadarıya , bu dosyalar sende yok ya da derleyici kütüphanenin yolunu bilmiyor. 

caglar

ben hepsini yükledim ama sorun ne anlayamadım. Şu kütüphaneleri eklemeyi yolu belirtmeyi kontrol etmem açısından paylaşabilir misiniz rica etsem?

Klein

Keil kullananlar için , kütüphane yolu tanıtma  aşağıdaki linkte anlatılıyor.
https://www.picproje.org/index.php/topic,43088.0.html
3. Adımda

Kaanx

uint_8 uint_16 tanımlamalar ne anlama gelmekte ?

Klein

uint8_t 8 bit unsigned,
uint16_t 16bit unsigned.
uint32_t 32 bit unsigned
uint64_t 64 bit unsigned

int8_t 8bit signed
int16_t 16 bit signed
int32_t 32 bit signed
int64_t 64 bit signed

int , long, double gibi veri tiplerinin bit uzunlukları sabit değildir. İşlemcinin veri yoluna bağlı olarak değişir.
int tipi 8 ve 16 bit işlemcilerde 16 bit iken, 32 bit işlemcilerde 32 , 64 bit işlemcilerde ise 64 bittir.

değişkenin boyutu mimariye bağlı olark değişmesin diye bu standart tip tanımları kullanılır.

Kaanx

Hocam sagolun Uint = unsigned int oldugunu anlamıs oldum fakat bu 16 8 ve 32 olarak farklı farklı yerler kullanılıyor. Suan timer1 & tim 8 modulunu incelerken features bölumunde
16-bit up, down, up/down auto-reload counter.
● 16-bit programmable prescaler allowing dividing (also "on the fly") the counter clock
frequency either by any factor between 1 and 65535


böyle bir bölüm okudum mesela timerlarda kullanıcagım integer degerler için uint16_t mi kullanacagım ?

Klein

Registerlerin veri uzunluğunu öğrenmek için , STM32F10x.h veya STM32F4xx.h gibi dosyalara ,
veya datasheet'e bakmak gerek.  Timerlerde tüm registerler 16 bit. ancak başka donanımların registerleri 32 bit olabilir.

Örneğin
STM32F10x.h dosyasında Timer tipinin tanımlandığı bölüm.
typedef struct
{
  __IO uint16_t CR1;
  uint16_t  RESERVED0;
  __IO uint16_t CR2;
  uint16_t  RESERVED1;
  __IO uint16_t SMCR;
  uint16_t  RESERVED2;
  __IO uint16_t DIER;
  uint16_t  RESERVED3;
  __IO uint16_t SR;
  uint16_t  RESERVED4;
  __IO uint16_t EGR;
  uint16_t  RESERVED5;
  __IO uint16_t CCMR1;
  uint16_t  RESERVED6;
  __IO uint16_t CCMR2;
  uint16_t  RESERVED7;
  __IO uint16_t CCER;
  uint16_t  RESERVED8;
  __IO uint16_t CNT;
  uint16_t  RESERVED9;
  __IO uint16_t PSC;
  uint16_t  RESERVED10;
  __IO uint16_t ARR;
  uint16_t  RESERVED11;
  __IO uint16_t RCR;
  uint16_t  RESERVED12;
  __IO uint16_t CCR1;
  uint16_t  RESERVED13;
  __IO uint16_t CCR2;
  uint16_t  RESERVED14;
  __IO uint16_t CCR3;
  uint16_t  RESERVED15;
  __IO uint16_t CCR4;
  uint16_t  RESERVED16;
  __IO uint16_t BDTR;
  uint16_t  RESERVED17;
  __IO uint16_t DCR;
  uint16_t  RESERVED18;
  __IO uint16_t DMAR;
  uint16_t  RESERVED19;
} TIM_TypeDef;


typedef struct
{
  __IO uint32_t CR;
  __IO uint32_t CFGR;
  __IO uint32_t CIR;
  __IO uint32_t APB2RSTR;
  __IO uint32_t APB1RSTR;
  __IO uint32_t AHBENR;
  __IO uint32_t APB2ENR;
  __IO uint32_t APB1ENR;
  __IO uint32_t BDCR;
  __IO uint32_t CSR;

#ifdef STM32F10X_CL  
  __IO uint32_t AHBRSTR;
  __IO uint32_t CFGR2;
#endif /* STM32F10X_CL */ 

#if defined (STM32F10X_LD_VL) || defined (STM32F10X_MD_VL) || defined (STM32F10X_HD_VL)   
  uint32_t RESERVED0;
  __IO uint32_t CFGR2;
#endif /* STM32F10X_LD_VL || STM32F10X_MD_VL || STM32F10X_HD_VL */ 
} RCC_TypeDef;

Buradan da görüleceği üzere, Timer registerlerinin tamamının 16 bit olmasına karşın, RCC registerleri 32 bit.

Kaanx

Anladım hocam bir sorum daha olucak izninizle __IO olarak tanımlamak bize ne saglıyor gecen ki kodumda delay fonksıyonunu (__IO uint16_t nCount ) neden __IO olarak tanımladıgımı sormustunuz ama ben o knuyla ilgili hala bir acıklama bulamadım.

Klein

#12
https://www.picproje.org/index.php/topic,37346.msg271342.html#msg271342
standar bir değişken tanımlarken _IO tanımlayıcısını kullanma. 

cm3 kütüphanesinde __IO tanımı bir bellek bölgesi için kullanmamış. 

/**
* IO definitions
*
* define access restrictions to peripheral registers
*/

#ifdef __cplusplus
  #define     __I     volatile                /*!< defines 'read only' permissions      */
#else
  #define     __I     volatile const          /*!< defines 'read only' permissions      */
#endif
#define     __O     volatile                  /*!< defines 'write only' permissions     */
#define     __IO    volatile                  /*!< defines 'read / write' permissions   */

değişkeni volatile yapmak için kullanmış.
Ama sen yüne de __IO şeklinde kullanma.
değişkeni volatile yapmak istiyorsan volatile tanımlayıcısını kullan.
__IO tanımlayıcısını sadece çevre birimlerle ilgili bir register tanımlarken kullan.
Muhtemelen ihtiyacın olmayacak.

volatile nedir?
değişkeni volatile yaparak, derleyiciye
kod optimizasyonu yaparken  bu değişkeni optimize etme,  değişken ile yaptığım şey sana anlamsız da görünse ne görüyorsan onu uygula diyoruz.

Kaanx

#13
Hocam cok tesekkur ederim acıklamalarınız cok aydınlattı beni timer bölumuyle ilgili bir uygulama yapıp tekrar sizleri rahatsiz edicem :)

mesaj birleştirme:: 15 Mart 2013, 23:01:37

Hocam ben kodlarımı atollicte derlıyorum bu yuzden systemınıt kodlarım system_stm32f4xx.c de tanımlı gelıyor otomatikman bu zmana kadar library uygulamalarını yaparken bu system init kodunu hiç degıstırmedım ben degiştirmem gerekiyor mu ?

Kaanx

Stm32f4 discovery std lib timer kullanımı ile ilgili örnekler.Umarım yararlı olur herkese iyi çalısmalar kolay gelsin.

http://kaankandemir.wordpress.com/category/stm32f4-discovery/