İletişim Formu Sorunu (Düzeltildi)

Ne zamandır aklımdaydı. Uzun zamandır iletişim formundan bir mesaj gelmediğini fark ettim. Ayarlarımı kontrol ederken hizmet aldığım yer sağlayıcı firması bilgilendirme yapmadan bazı değişiklikler yapmış ve benim mail ayarlarımı geçersiz kılmış. O yüzden bana gönderilecek mesajlar gönderilememiş.

Bu süre zarfında benimle iletişime geçmeye çalışıp da cevap alamayan arkadaşlardan özür dilerim. Gönderdiğiniz mesajların hiç biri bana ulaşmadığı için cevap veremedim.

How to Install Cuda 6.0 on Ubuntu 14.04

Update(22.08.2014)

CUDA 6.5 has been released by NVIDIA. It has native Ubuntu 14.04 support. You can download from here.

https://developer.nvidia.com/cuda-downloads

What do we need ?

  1. Latest GPU driver from NVIDIA for your GPU  and please install it. You can find many tutorial for this. Instead of using the restricted driver, I chose to use the new version from NVIDIA. In this guide I use NVIDIA 334.21 drivers for my GTX 750 Ti and GTX 650 Ti Boost.
  2. Latest CUDA installation file (.run file, not .deb). You can download from HERE .
  3. Required libraries: freeglut3-dev, libglu1-mesa-dev, libxmu-dev, libxi-dev, build-essential.
sudo apt-get install build-essential freeglut3-dev libglu1-mesa-dev libxmu-dev libxi-dev

CUDA 6.0 Installation Step

Extract installation file from CUDA .run file:

./cuda_6.0.37_linux_64.run -extract=/your_path

 

Now we have three file :

  • cuda-linux64-rel-6.0.37-18176142.run
  • cuda-samples-linux-6.0.37-18176142.run
  • NVIDIA-Linux-x86_64-331.62.run (Ignore it)

Now we can install cuda.

sudo ./cuda-linux64-rel-6.0.37-18176142.run

Then we can install cuda-samples:

sudo ./cuda-samples-linux-6.0.37-18176142.run

If you want you can compile the samples after installation. But this process may take some time.

cd /your/nvidia_sample_path
make

Congratulations 🙂

Some proof:

 

STM32F4 Discovery Maceraları – 8 : TIM10 İle PWM ve Pin Yönlendirme

Bir önceki yazımda timer kullanımını göstermiştik. Bu yazımızda bir adım daha ileri gidelim ve TIM10 kullanarak PWM üretelim. Ayrıca bu işlemi gerçekleştirirken yine güzel bir özellik olan pin yönlendirme işlemini de yapalım. O halde elimize bir kağıt kalem önce hesap yapıyoruz.

1 – Hesap Kitap

PWM işleminden önce elimizde olanlara bakıyoruz. Buna göre isteklerimizi gözden geçirip en uygun çözümü bulacağız. Çünkü aynı işi yapmanın birden fazla yolu var. Öncelikle elimizdekiler:

  • Çalışma Frekansımız : 168 MHz.
  • APB2 Frekansımız : 168 Mhz (Nedeni Açıklanacak)
  • Hedef PWM Frekansı : 32KHz (Tamamen kendi seçimim. Özel bir nedeni yok)
  • PWM Doluluğu : %50 (Kendi seçimim)

Şimdi APB2 neden önemli? DM00037051 rehberinin 18. sayfasını incelerseniz TIM10 doğrudan APB2 veri yoluna bağlı. Bir önceki yazıyı okumuşsanız eğer , ön bölücü değerlerinin 1 değerinden farklı olması sebebiyle TIM bileşenleri bağlı oldukları veri yolunun 2 katı bir hızla tetikleniyor. APB2 normalde 84MHz’de çalışmaktadır. Fakat bu püf noktası sebebi ile buna baplı olan TIM10 168MHz’lik bir kaynakla beslenmektedir.

Sıra geldi 168MHz’de çalışan bir kaynaktan %50 doluluk oranına sahip 32KHz’lik bir PWM işareti üretmeye. İlk yapmamız gerekn biraz yavaşlamak. Bunu sağlayan ise TIM10’a ait “prescaler” değeri. Bu değer sayesinde TIM10’u besleyen frekansı bölmüş olacağız.

Aslında PWM hızımızı belirleyen iki bileşen mevcut. Biri daha önce bahsettiğim “prescaler” -ön bölücü- değeri. Diğeri ise TIM10 ARR saklayıcısına yüklediğimiz hedef değer. Bu iki bileşenin değeri ile oynayarak istediğimiz hızı elde edebiliyoruz. TIM10’a ait genel şema şu şekilde :

Ben TIM10 çalışma hızı olarak 320KHz beliriyorum kendime. Bunu sağlamak için gerekli ön bölücü değerimizi ise şu şekilde hesaplıyoruz:

PSC_Değeri = (SystemCoreClock / 320000) – 1

Bu hesabın sonucunda ön bölücü değerimiz 524 oluyor. TIM10 bu durumda 320KHz hızda çalışmaya başladı. Biz ise 32KHz elde etmek istiyoruz. Yani 10’da birini. O halde her 10 sayımda bir çıkış üretirsek isteğimiz elde etmiş oluruz. Bu yüzden ARR saklayıcısına yüklememiz gerekn değeri şu şekilde buluyoruz:

ARR_Değeri = (320KHz / 32KHz) – 1

Bu işlemin sonucunda ARR için geçerli olan değer 9 değeri elde ediliyor. Nihayet 32KHz’lik bir işaret elde edebildik. Sıra geldi işaretin doluluk oranına. Bunun içinse TIM10_CCR1 saklayıcısına vereceğimiz değer önem kazanıyor. Düşünce basit. Sayıcı CCR1 içinde belirlenen değere ulaştığında çıkış terslenecek, sayıcı sıfırlandığında tekrar terslenecek. Sayma işlemi 0 dan 9’a kadar gerçekleşiyor. Biz CCR1 değeri olarak 5 değerini verirsek tam ortası olacağı için %50 oranını yakalamış oluruz. Bu değerin üst limiti ARR_Değeri olan 9 dur. Eğer 9 verirseniz %100 doluluk oranına ulaşırsınız.

Şu anda bize lazım olan tüm değerlere sahibiz. Fakat incelemeye devam edelim. Şimdi aynı hesaplamaları bu sefer TIM10’un 1.6MHz‘de çalıştığı duruma göre hesaplayalım. Ön bölücü PSC_Değeri = 104 olur. ARR_Değeri = 49 ve son olarak %50 doluluk oranı için CCR1 = 25 olarak bulunur.

TIM10’u 8MHz‘de çalıştığını varsayarsak değerler ne olur? PSC_Değeri = 20, ARR_Değeri = 249, CCR1 = 125 olur. Bunları aşağıdali gibi özetleyelim:

  1. F_TIM10 = 320KHz, PSC_Değeri = 524, ARR_Değeri = 9, CCR1 = 5
  2. F_TIM10 = 1.6MHz, PSC_Değeri = 104, ARR_Değeri = 49, CCR1 = 25
  3. F_TIM10 = 8.0MHz, PSC_Değeri = 20, ARR_Değeri = 249, CCR1 = 125

Bu konunun üzerinde durmamın sebebi şu. eğer dikkat ettiyseniz TIM10’un çalışma frekansı düştükçe PWM doluluk oranı ayarlama hassasiyetimiz giderek azalıyor.

1. durumda kabaca 10 basamak halinde (%10’luk hassasiyetle) ayarlayabiliyoruz. Yuvarlarsak yaklaşık 4 bit (aslında 3.5 🙂 diyelim azami değer 9 çünkü).

2. durumda 50 basamak halinde (%2’lik hassasiyetle) ayarlayabiliyoruz. Yuvarlarsak yaklaşık 6 bit hassasiyet.

3. durumda 250 basamak halinde (%0,4 hassasiyet). Yaklaşık 8 bit çözünürlük.

Bu örnekleri ilerletmek mümkün. Bu durumda önemli olan ne kadarlık bir hassasiyet istediğiniz. Ona göre gerekli gerekli değerli verilen formüllerle hesaplayabilirsiniz.

2 – Yazılım Zamanı

Hesabı kitabı yaptık sıra geldi yazılıma. Kod yazmadan önce bir noktaya dikkat çekmek istiyorum. PWM çıkışımızı hangi pinden alacağız? Bu noktada devreye DM00037051 rehberinin 58. sayfasında bulunan tablo giriyor. Hatırlarsanız pinlerimizi ayarlarken giriş, çıkış, analog ve ek özellikler şeklinde yapılandırabiliyoruz. Fakat her pine her özelliği atayabiliriz gibi bir serbestliğimiz de yok. O yüzden ilgili belgenin 58. sayfasındaki tabloda TIM10’un AF3 kanalına bağlı olduğunu ve TIM10 için PORTB de bulunan 8. pini kullanabileceğimiz yazıyor. O halde TIM10 çıkışını PB8’e yönlendireceğiz. Bunu iki şekilde yapabiliriz, ilk olarak StdPeriph kütüphanesi yardımıyla :

GPIO_PinAFConfig(GPIOB,GPIO_PinSource8,GPIO_AF_TIM10);

Ya da ilgili saklayıcıları el ile değiştirerek :

GPIOB->AFR[1] |= 0x00000003;

Hangi saklayıcının bizim işimize yaradığını ise DM00031020 belgesinin 6.4.9 ve 6.4.10 başlıklarını inceleyerek görebilirsiniz. Bu ayrıntıya dikkat ettikten sonra kodumuzu yazabiliriz. İlk olarak StdPeriph kullanarak yazılan kodu paylaşıyorum:

/* TIM10_PWM
 * main.c
 *
 *  Created on: 12 Agu 2012
 *      Author: m2k
 */
#include "stm32f4xx.h"
 
GPIO_InitTypeDef  GPIO_InitStructure;
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
TIM_OCInitTypeDef	TIM_OCInitStructure;
uint16_t PrescalerValue = 0;
 
void GPIO_Conf(void) {
 
	/* GPIOB ve TIM10 CLK Kaynağı etkinleştiriliyor */
	RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB,ENABLE);
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM10,ENABLE);
 
	/* PB8 Ek özellikler için ayarlanıyor */
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
	GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;
	GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;
	GPIO_Init(GPIOB, &GPIO_InitStructure);
 
	/*Pin Yönlendirme İşlemi*/
	GPIO_PinAFConfig(GPIOB,GPIO_PinSource8,GPIO_AF_TIM10);
}
 
void TIM_Conf(void) {
 
	PrescalerValue = (uint16_t)(SystemCoreClock / 8000000) - 1;
 
	/* TIM10 Ayarları Yapılıyor */
	TIM_TimeBaseStructure.TIM_ClockDivision = 0;
	/* TIM10 İçin CounterMode_UP Gereksizdir. Fakat Kodu değiştirip
	 * diğer sayıcılar için kullanma ihtimaline karşı silmiyorum */
	TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
	TIM_TimeBaseStructure.TIM_Period = 249;
	TIM_TimeBaseStructure.TIM_Prescaler = PrescalerValue;
	TIM_TimeBaseInit(TIM10, &TIM_TimeBaseStructure);
 
	/* PWM Ayarları yapılıyor. 32KHz @ %50 */
	TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;
	TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;
	TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
	TIM_OCInitStructure.TIM_Pulse = 125;
	TIM_OC1Init(TIM10, &TIM_OCInitStructure);
	TIM_OC1PreloadConfig(TIM10, TIM_OCPreload_Enable);
	TIM_ARRPreloadConfig(TIM10, ENABLE);
 
}
int main(void) {
	GPIO_Conf();
	TIM_Conf();
	/* TIM10 Başlatılıyor */
	TIM_Cmd(TIM10, ENABLE);
 
  while (1) {}
}

Bu kodun çalışması için ilgili stm32f4xx_tim.h dosyasını projeye dahil etmeyi unutmuyoruz. Aynı kodu bir de alt seviye de yazdık. Kullandığım kütüphane fonksiyonlarını silmedim. Onların yerine yazdığım kodları da görebilmeniz için bıraktım. Her satıra karşılık kullandığım kod için açıklama yazdım. Hangi biçimde kod yazmak isterseniz:

/* TIM10_PWM
 * main.c
 *
 *  Created on: 12 Agu 2012
 *      Author: m2k
 */
#include "stm32f4xx.h"
 
GPIO_InitTypeDef  GPIO_InitStructure;
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
TIM_OCInitTypeDef	TIM_OCInitStructure;
uint16_t PrescalerValue = 0;
 
void GPIO_Conf(void) {
	/* GPIOB ve TIM10 CLK Kaynağı etkinleştiriliyor */
//	RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB,ENABLE);
//	RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM10,ENABLE);
	RCC->AHB1ENR |= 0x00000002;
	RCC->APB2ENR |= 0x00020000;
 
	/* PB8 Ayarları Yapılıyor. */
//	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8;
//	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
//	GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
//	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;
//	GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;
//	GPIO_Init(GPIOB, &GPIO_InitStructure);
 
	GPIOB->MODER   |= 0x00020000;
	GPIOB->OTYPER  |= 0x00000000;
	GPIOB->OSPEEDR |= 0x00030000;
	GPIOB->PUPDR   |= 0x00010000;
 
	/*Pin Yönlendirme İşlemi*/
//	GPIO_PinAFConfig(GPIOB,GPIO_PinSource8,GPIO_AF_TIM10);
	GPIOB->AFR[1] |= 0x00000003;
}
 
void TIM_Conf(void) {
	PrescalerValue = (uint16_t)(SystemCoreClock / 8000000) - 1;
 
	/* TIM10 Ayarları Yapılıyor */
//	TIM_TimeBaseStructure.TIM_ClockDivision = 0;
	/* TIM10 İçin CounterMode_UP Gereksizdir. Fakat Kodu değiştirip
	 * diğer sayıcılar için kullanma ihtimaline karşı silmiyorum */
//	TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
//	TIM_TimeBaseStructure.TIM_Period = 249;
//	TIM_TimeBaseStructure.TIM_Prescaler = PrescalerValue;
//	TIM_TimeBaseInit(TIM10, &TIM_TimeBaseStructure);
 
	TIM10->CR1 |= 0x0000;	//ClockDivision
	TIM10->ARR  = 0x00F9;	//Period = 249
	TIM10->PSC  = PrescalerValue;
	TIM10->EGR  = 0x0001;
 
	/* PWM Ayarları yapılıyor. 32KHz @ %50 */
//	TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;
//	TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;
//	TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
//	TIM_OCInitStructure.TIM_Pulse = 125;
//	TIM_OC1Init(TIM10, &TIM_OCInitStructure);
//	TIM_OC1PreloadConfig(TIM10, TIM_OCPreload_Enable);
//	TIM_ARRPreloadConfig(TIM10, ENABLE);
 
	TIM10->CCMR1 |= 0x0060;	//PWM1_MODE
	TIM10->CCER  |= 0x0000;	//OCPolarity_High
	TIM10->CCER  |= 0x0001; //OutputState_Enable
	TIM10->CCR1   = 0x007D;	//Pulse = 125
	TIM10->CCMR1 |= 0x0008; //Preload_Enable
	TIM10->CR1   |= 0x0080; //ARRPreload Enable
 
}
int main(void) {
	GPIO_Conf();
	TIM_Conf();
	/* TIM10 Başlatılıyor */
	TIM10->CR1 |= 0x0001;
 
  while (1) {
 
  }
}

Son olarak yazdığımız kod neticesinde elde ettiğimiz çıkışa ait görselleri paylaşalım. İlk olarak 320KHz @32KHz @ %50

32 KHz ve %50 doluluk oranı.

Diğer resim ise 8MHz @ 32KHz @ %25 lik işarete ait.

32KHz ve %25 doluluk oranı.

Bir yazımızın daha sonuna geldik. Herkese iyi çalışmalar.

STM32F4 Discovery Maceraları – 7 : Buton Okuma ve Timer Kullanımı

Buton Okuma

Şimdiye kadar bol bol led yakıp söndürdük fakat baktım ki hiç butonu kullanmamışız. Hemen basit bir kod yazıp hem buton okuyalım hem de GPIO için tanımlanmış fonksiyonlardan kullanmadığımız iki komutu kullanalım istedim. Senaryomuz basit; butona bastıkça ledleri yakıp söndürecek bir uygulama. Her yazımda tekrar ediyorum olacak ama bu kodları yazarken de iki temel kaynağı kullanıyoruz. Biri DM00031020 ve stm32f4xx_dsp_stdperiph_lib_um. Hemen kaynak kodumuzu verelim:

/* Buton Okuma
 * main.c
 *
 *  Created on: 13 May 2012
 *      Author: m2k
 */
#include "stm32f4xx.h"
 
GPIO_InitTypeDef  GPIOD_InitStructure,GPIOA_InitStructure;
 
void Delay(__IO uint32_t nCount) {
  while(nCount--) {
  }
}
 
int main(void) {
  /* GPIOD Periph clock enable */
  RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOD|RCC_AHB1Periph_GPIOA, ENABLE);
 
  /* Configure PD12, 13, 14 and PD15 in output pushpull mode */
  GPIOD_InitStructure.GPIO_Pin = GPIO_Pin_12 | GPIO_Pin_13 | GPIO_Pin_14 | GPIO_Pin_15;
  GPIOD_InitStructure.GPIO_Mode = GPIO_Mode_OUT;
  GPIOD_InitStructure.GPIO_OType = GPIO_OType_PP;
  GPIOD_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;
  GPIOD_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
 
  /* Configure PA0 input mode */
  GPIOA_InitStructure.GPIO_Pin = GPIO_Pin_0;
  GPIOA_InitStructure.GPIO_Mode = GPIO_Mode_IN;
  GPIOA_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
 
  GPIO_Init(GPIOD, &GPIOD_InitStructure);
  GPIO_Init(GPIOA, &GPIOA_InitStructure);
 
  GPIO_ResetBits(GPIOD,GPIO_Pin_12|GPIO_Pin_13|GPIO_Pin_14|GPIO_Pin_15);
 
  while (1) {
    if(GPIO_ReadInputDataBit(GPIOA,GPIO_Pin_0))	{
    	while(GPIO_ReadInputDataBit(GPIOA,GPIO_Pin_0));
    	Delay(1000000L);
    	GPIO_ToggleBits(GPIOD,GPIO_Pin_12|GPIO_Pin_13|GPIO_Pin_14|GPIO_Pin_15);
    }
  }
}

Bazı satırlara daha önceki çalışmalardan aşina olmuşsunuzdur. İlk önce ledlerin bağlı olduğu bacaklar için çıkış tanımlamalarımızı yapıyoruz. Daha sonra PA0 pini için giriş tanımlamalarını yapıyoruz. Çünkü STM32F4 kartımız üzerindeki “User Button” olarak geçen mavi düğme PA0 pinine bağlı. Okuma yaptığımız kısıma gelelim.

GPIO_ReadInputDataBit(GPIOA,GPIO_Pin_0) komutu ile GPIOA portunun 0. bitini okumuş olduk. Ondan sonraki gelen while döngüsü ise bir çeşit koruma. Amaç butonun pek çok kez art arda basılmış gibi algılanmasını engellemeye çalışmak. Ondan sonra gelen gecikme fonksiyonu da aynı amaca hizmet ediyor.

GPIO_ToggleBits(GPIOD,GPIO_Pin_12|GPIO_Pin_13|GPIO_Pin_14|GPIO_Pin_15); Komutu ile ledlerin bağlı olduğu pinlerin değerini 1 ve 0 olarak sırası ile değiştiriyoruz. Zaten komutun yaptığı iş isminden de belli.

Timer Kullanımı

Bir diğer çalışmamız da timer kullanımı ile alakalı. Bu çalışmada basit olduğu için Timer7 ile çalıştık. Kullandığımız mikrodenetleyici çok sayıda timer donanımına sahip. Bunları kısaca listelersek:

  • Gelişmiş Özellikleri Olan : TIM1 (16 bit) ve TIM8 (16bit)
  • Genel Amaçlı -1 : TIM2 (16bit), TIM3 (32bit), TIM4 (32bit) ve TIM5(16bit)
  • Genel Amaçlı -2: TIM9’dan TIM14’e kadar. Farklı ayarlanabilir özellikler mevcut.
  • Basit Özellikleri Olan: TIM6 (16bit) ve TIM7 (16bit)

Tüm bu zamanlıyıcılar ile alakalı en geniş bilgiyi DM00031020 belgesinin 13, 14, 15 ve 16. bölümlerinde bulabilirsiniz. Basit olduğu için TIM7’yi kullandık. Aynı kodları TIM6 için de kullanabilirsiniz. Genel olarak bu zamanlıyıcı donanımlarında kullanılabilecek komutların açıklamalarına ve listesine stm32f4xx_dsp_stdperiph_lib_um belgesinden ulaşabilirsiniz. Burda listeyi vermek isterdim fakat gerçekten uzun bir fonksiyon listesi. Sırasıyla neler yaptığımızı açıklayalım.

  1. İlk olarak kullanacağımız zamanlıyıcı için clk kaynağını etkinleştirmemiz lazım. Bunun için RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM7,ENABLE); komutunu kullanıyoruz.
  2. Daha sonra her ihtimale karşı zamanlıyıcıyı başlangıç ayarlarına döndürüyorum. Bunun için TIM_DeInit(TIM7); komutunu kullanıyorum.
  3. Sıra geldi ön bölücü (prescaler) ayarlarını yapmaya. Bunun için biraz kalem ve kağıda ihtiyacımız olacak. Şimdi göreceğiniz üzere TIM7 APB1’e bağlı gözüküyor. APB1’in çalışma hızı 42 MHz. fakat bu demek değildir ki bu zamanlayıcının saat kaynağı 42Mhz. Burda bir püf noktası var. DM00037051 belgesinin 18. sayfasında bulunan şemanın altında yazan iki önemli bilgi var; “The timers connected to APB2 are clocked from TIMxCLK up to 168 MHz, while the timers connected to APB1 are clocked from TIMxCLK up to 84 MHz.” Yani diyor ki, APB2’ye bağlı olan zamanlayıcılar için saat işareti 168Mhz’e kadar olabilir, APB1 içinse 84Mhz olabilir. Burada kafamızda bir “hmmm” baloncuğu ve yüzümüzde şüpheci bir ifade oluşuyor. Ve soruyoruz neye göre kime göre? Aynı zamanda yine aynı belgenin 29 sayfasında bulunan tablo 3’te  tüm timer donanımları için yapılmış olan karşılaştırma tablosunda diyor ki “Max Interface Clock : 42 MHz” ve “Max Timer Clock : 84 MHz” . Araştırmaya devam ediyoruz DM00031020 belgesinin 85. sayfasında bulunan 9 numaralı şemada tüm clk kaynaklarının bağlantıları gösteriliyor ve orada bizi ilgilendiren bir çizim var:

    Ve bu çizimin hemen ardından gelen 86. sayfada şu ifadeler geçiyor :”If the APB prescaler is 1, the timer clock frequencies are set to the same frequency as that of the APB domain to which the timers are connected. Otherwise, they are set to twice (×2) the frequency of the APB domain to which the timers are connected.” Yani diyor ki — bu arada bir imam tadı yakalamadım değil, onlar da önce arapçasını söyleyip sonra tercümesini veriyorlar 🙂 — APB ön bölücü değerinin1 ise sorun yok zamanlayıcılar da aynı frekansta çalışır diyor. Yok eğer ön bölücü değerin 1 değilse zamanlayıcılar APB’nin 2 katı hızda çalışır. Vay arkadaş dediğinizi duyar gibiyim. Çalıştıracağımız bir zamanlayıcı çektiğimiz çileye bak diyorsunuz az daha sabır, yüzdük yüzdük kuyruğuna geldik. APB ön bölücü ayarlarını daha ilk yazımda proje oluştururken kullandığımız “system_stm32f4xx.c” dosyasında belirtmiştik. Ne alaka diyenler için ilgili dosyanın 387. satırına bakabilirler. O dosyaya göre APB1 ön bölücü değerimiz 4 (168MHz/4 = 42MHz).

    İşte tüm bu nedenlerden dolayı TIM7’nin çalışma frekansı 84MHz. Şimdi buna göre hesap yapmamız gerekiyor. Hedeflediğimiz süre 0.5sn. Ön bölücü değerini öyle bir ayarlayacağız ve sayılan değer olarak öyle bir değer seçeceğiz ki bize 0.5sn lik aralıkları ölçebilelim. DM00031020 belgesinin 465. sayfasında bulunan ön bölücü ayarlarına göre : fCK_PSC / (PSC[15:0] + 1). olarak belirleniyor. Biz PSC değeri olarak 41999 dersek, +1 de hesaplamadan eklenip 84MH’i 42.000 değerine bölmüş olacağız bu durumda elde edeceğimiz değer 2000Hz oluyor. Artık çalışma frekansımız 2000Hz dir. Bu durumda biz sayılacak değer olarak 2000’i seçersek zamanlayıcımızda 1sn’lik bir değer elde etmiş olacağız. Bu nereden geldi derseniz ben de şu bağıntıyı veririm t=1/f . Timer içeriğini okuyarak kolayca 0.5sn’lik zamanlamaları elde edebiliriz.

    Yukarıda yazılan tüm bilgiler ışığında TIM_PrescalerConfig(TIM7,41999,TIM_PSCReloadMode_Update); komutu ile ön bölücü değerine 41999 değerini atıyoruz. Bu kadar açıkladık sonra bana gelip neden 41999 seçtik demeyin 🙂

  4. Sıra geldi tekrar yükleme değerine. Bu ayarı yaptığımızda zamanlayıcı içinde bulunan sayıcı belirtilen değere kadar saydığında tekrar baştan, sıfır değerinden saymaya başlar. O yüzden değer olarak 1999 değerini hedef değer olarak belirliyorum. TIM_SetAutoreload(TIM7,1999);
  5. Bu kadar işte. Temel seviyede Tim7 için gerekli ayarları tamamladık.

Bundan sonrası ise bildiğimiz led yak söndür kısmı. Şimdi sayıcımız 1sn lik bir süreyi ölçüyor. Sayıcının değerini okuyarak istediğimiz süreyi kestirebiliriz.Tim7 de bulunan sayıcının değerini okumak içinse TIM_GetCounter(TIM7) komutunu kullanıyoruz bu sayede o an içindeki sayıcı değerini öğrenmiş oluyoruz. Dilerseniz aşağıdan tüm kodu inceleyebilirsiniz.

/*TIMER 7 Kullanılarak Yanıp Sönen Led. Yanıp sönme aralığı 0.5sn
 * main.c
 *
 *  Created on: 13 May 2012
 *      Author: m2k
 */
#include "stm32f4xx.h"
 
GPIO_InitTypeDef  GPIOD_InitStructure;
 
int main(void) {
  /* GPIOD Periph clock enable */
  RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOD, ENABLE);
  RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM7,ENABLE);
 
  /* Configure PD12, 13, 14 and PD15 in output pushpull mode */
  GPIOD_InitStructure.GPIO_Pin = GPIO_Pin_12 | GPIO_Pin_13 | GPIO_Pin_14 | GPIO_Pin_15;
  GPIOD_InitStructure.GPIO_Mode = GPIO_Mode_OUT;
  GPIOD_InitStructure.GPIO_OType = GPIO_OType_PP;
  GPIOD_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;
  GPIOD_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
 
  /*TIM7 Settings*/
  TIM_DeInit(TIM7);
  TIM_PrescalerConfig(TIM7,41999,TIM_PSCReloadMode_Update);
  TIM_SetAutoreload(TIM7,1999);
 
  GPIO_Init(GPIOD, &GPIOD_InitStructure);
  GPIO_ResetBits(GPIOD,GPIO_Pin_12|GPIO_Pin_13|GPIO_Pin_14|GPIO_Pin_15);
  TIM_Cmd(TIM7,ENABLE);
 
  while (1) {
	  if(TIM_GetCounter(TIM7)>999){
		  GPIO_SetBits(GPIOD,GPIO_Pin_12|GPIO_Pin_13|GPIO_Pin_14|GPIO_Pin_15);
	  }else
		  GPIO_ResetBits(GPIOD,GPIO_Pin_12|GPIO_Pin_13|GPIO_Pin_14|GPIO_Pin_15);
  }
}

 

Son olarak süremizi hemen ölçelim. Aşağıdaki ekran görüntüsünden de görüleceği üzere 0.5sn’lik zamanlamalarımız sağlanmış surumda.