STM32 HAL Kütüphanesi ile Saat (Clock) Ayarı -2-
STM32 HAL kütüphanesi ile saat ayarı yapmayı anlatmaya devam ediyoruz. Önceki makaleyi buradan okuyabilirsiniz. Şimdi kaldığımız yerden devam edelim.
1 |
RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON; |
Burada dikkat ederseniz OscInitStruct yapısının bir değişkenine değil OscInitStruct yapısında tanımladığımız PLL yapısının PLLState değişkenine değer atadığımızı görebilirsiniz. PLL yapısını yapı değişkeni olarak aldığını kütüphane kılavuzunda görebiliriz.
Şimdi PLLState değişkeninin hangi değerleri alabildiğine bakalım. PLL yapısının PLL birimi ile ilgili parametreleri aldığını biliyoruz. PLLState de adından anlaşılacağı üzere PLL durumunu belirten değerleri almalıdır.
1 2 3 |
#define RCC_PLL_NONE ((uint32_t)0x00000000) #define RCC_PLL_OFF ((uint32_t)0x00000001) #define RCC_PLL_ON ((uint32_t)0x00000002) |
Görüldüğü gibi burada PLL birimini açıp kapamak için RCC_PLL_ON ya da OFF parametrelerini kullanırız. Biz PLL kullanacağımız için PLL yapısındaki PLLState değişkenine RCC_PLL_ON parametresini yüklüyoruz. Yani bu da on altılık tabanda 2 değeri ikilik tabanda ise 10 değeri oluyor. Bu değerleri kütüphane alıp yazmaçların gerekli bitlerine atamayı yapacaktır. Yazmaç seviyesinde çalışırken zaten kütüphane ile işimiz olmayacağı için biz yine aldığı parametrelerin sayısına, işlevine ve adına dikkat ediyoruz.
1 |
RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE; |
Burada PLL yapısının bir diğer değişkeni olan PLLSource değişkenine bir değer atandığını görmekteyiz. PLLSource adından anlaşılacağı üzere PLL biriminin kaynak olarak aldığı sinyali belirler. Bu parametrelerin ne olduğunu Ctrl + Sol Tık ile veya kütüphane kılavuzuna bakarak öğrenebiliriz. Biz yine aynı şekilde bakalım.
1 2 |
#define RCC_PLLSOURCE_HSI RCC_CFGR_PLLSRC_HSI_DIV2 #define RCC_PLLSOURCE_HSE RCC_CFGR_PLLSRC_HSE_PREDIV |
Görüldüğü gibi HSI ve HSE olmak üzere yani dahili ve harici yüksek hızlı osilatör olmak üzere iki ayrı parametremiz var. Biz harici osilatör kullanacağımız için RCC_PLLSOURCE_HSE parametresini kullanıyoruz. PLL biriminin iki farklı kaynağı aldığını CubeMX programının arayüzünden de teknik veri kitapçığındaki saat biriminin diyagramından da kolaylıkla anlayabiliriz.
Görüldüğü gibi programda da HSI ve HSE olarak iki ayrı seçeneğimiz var. Ayrıca bu bölme oranını yine önceki değerlerde 1 olarak belirlemiştik. Bu diyagrama baktığımızda PLL yapısı için bir başka parametrenin olması gerektiğini anlayabiliriz. O da PLL çarpanı olacaktır.
1 |
RCC_OscInitStruct.PLL.PLLMUL = RCC_PLL_MUL9; |
Burada PLL yapısının PLLMUL adında bir değişkeninin olduğunu görüyoruz. İngilizce bilenler MUL kısaltmasından söylenmek istenilenin çarpım olacağını anlayabilir. Burada RCC_PLL_MUL9 derken PLL çarpanının 9 olacağını anlayabiliriz. Bunun için kılavuza bakmaya gerek olmasa da kullanabileceğimiz çarpanları yine kaynak kodda bulabiliriz.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
#define RCC_PLL_MUL2 RCC_CFGR_PLLMUL2 #define RCC_PLL_MUL3 RCC_CFGR_PLLMUL3 #define RCC_PLL_MUL4 RCC_CFGR_PLLMUL4 #define RCC_PLL_MUL5 RCC_CFGR_PLLMUL5 #define RCC_PLL_MUL6 RCC_CFGR_PLLMUL6 #define RCC_PLL_MUL7 RCC_CFGR_PLLMUL7 #define RCC_PLL_MUL8 RCC_CFGR_PLLMUL8 #define RCC_PLL_MUL9 RCC_CFGR_PLLMUL9 #define RCC_PLL_MUL10 RCC_CFGR_PLLMUL10 #define RCC_PLL_MUL11 RCC_CFGR_PLLMUL11 #define RCC_PLL_MUL12 RCC_CFGR_PLLMUL12 #define RCC_PLL_MUL13 RCC_CFGR_PLLMUL13 #define RCC_PLL_MUL14 RCC_CFGR_PLLMUL14 #define RCC_PLL_MUL15 RCC_CFGR_PLLMUL15 #define RCC_PLL_MUL16 RCC_CFGR_PLLMUL16 |
Görüldüğü gibi PLL çarpanları aynı programda olduğu gibi 2 ve 16 arasındadır. Yalnız saat hesaplamasını burada oturup bizim yapmamız gereklidir. Bunun için sadece programın değil teknik veri kitapçığının da yardımına başvurmak gerekecektir. Saat diyagramını ve hangi birime hangi çarpan ya da bölenle kaç MHz sinyal gittiği ve birimin desteklediği frekans aralığını bilmeden işimiz çok zor olacaktır. CubeMX programı bu hesaplamaları bizim için yapmaktadır. O yüzden yeni başlayanlara büyük kolaylık sağlamaktadır. Fakat CubeMX programını kullanmaya uzun süre devam edecek olsak bile sırf öğrenmek için bunları incelememiz gereklidir. CubeMX programı bu işi yapıyor zaten öğrenmeye ne gerek var diyemeyiz.
1 2 3 4 |
if (HAL_RCC_OscConfig(&RCC_OscInitStruct)!= HAL_OK) { Error_Handler(); } |
Burada hazırlanan yapı değeri HAL_RCC_OscConfig fonksiyonuna gönderilir ve fonksiyonun geri dönüşü denetlenerek olumsuz geri dönüşte hata fonksiyonuna gidiş sağlanır. Bu kontrol yapısı güvenlik görevini üstlenmektedir. O yüzden doğrudan HAL_RCC_OscConfig fonksiyonu ile de bunu yapabiliriz.
1 |
RCC_ClkInitStruct.ClockType = (RCC_CLOCKTYPE_SYSCLK | RCC_CLOCKTYPE_HCLK | RCC_CLOCKTYPE_PCLK1 | RCC_CLOCKTYPE_PCLK2); |
Buraya kadar osilatör ön ayarı için gereken işleri yaptık. Şimdi ise diğer saat ayarlarına bakacağız. Bunun için öncelikle ClockType değişkenine ayar yapacağımız saatleri söylememiz gerekli. OR (ya da) operatörü ile bunu yapmaktayız. Bazı eğitim verenlerin bu operatöre “ve operatörü” dediğine şahit oldum. Burada dil açısından ve anlamı taşıyabilse de mantıksal uygulamalarda OR’un “ve” anlamına geldiğini bilmek bize sıkıntı yaşatacaktır. O yüzden OR operatörünü “ya da” olarak bilmek gereklidir. Burada öncelikle kullanılacak saat tiplerinin ne olduğuna bakalım.
1 2 3 4 |
#define RCC_CLOCKTYPE_SYSCLK ((uint32_t)0x00000001) #define RCC_CLOCKTYPE_HCLK ((uint32_t)0x00000002) #define RCC_CLOCKTYPE_PCLK1 ((uint32_t)0x00000004) #define RCC_CLOCKTYPE_PCLK2 ((uint32_t)0x00000008) |
Görüldüğü gibi programımız ayarlanacak dört saati de ClockType değişkeninin bünyesine almış durumda. Bu ClockType kısmından önceki yazıda da bahsetmiştik. Şimdi diyagram üzerinden bu saatlerin nerede olduğunu işaretleyelim. Böylelikle bu saatleri anlamanız daha kolaylaşacaktır.
Bizim sistemin çalışabilmesi için SYSCLK ile HCLK ve çevre birimlerini kullanabilmemiz için PCLK1 ve PCLK2 saatleri üzerinde ayar yapmamız lazım. O yüzden dört saati de beraber seçiyoruz.
1 |
RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK; |
Burada SYSCLKSource adlı yani sistem saat kaynağı değişkenine RCC_SYSCLKSOURCE_PLLCLK değerinin atandığını görüyoruz. Yukarıdaki şemada bu kaynakların HSI, HSE ya da PLLCLK yani PLL çıkışı olduğunu görmemiz mümkün. Şimdi kaynak kodu inceleyelim.
1 2 3 |
#define RCC_SYSCLKSOURCE_HSI RCC_CFGR_SW_HSI #define RCC_SYSCLKSOURCE_HSE RCC_CFGR_SW_HSE #define RCC_SYSCLKSOURCE_PLLCLK RCC_CFGR_SW_PLL |
Burada da aynı şekilde üç farklı değeri görmekteyiz. CubeMX programı kullanmak yerine teknik veri kitapçığındaki anlaşılması daha zor diyagram üzerinden bu fonksiyonları kullanarak yapmaya kalksaydık ilk programımızı çalıştırabilmemiz için uzunca bir süre geçmesi gerekecekti. Çünkü bu saat yapısı karmaşık olduğu için ve en basit programı çalıştırmak için de gerekli olduğu için her şeyden önce bu öğrenilmesi gerekliydi. Şimdi ise bu saat ayarlarını öğrenmeyi erteleme imkanı bulabiliyoruz.
1 |
RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1; |
Yukarıdaki şemada gördüğünüz AHB Prescaler ayarını bu komut ile yapmaktayız. AHBCLKDivider adından anlayacağımız üzere sistem saatini bölerek HCLK saatini elde ediyoruz. Buradaki bölücü değer 1 olduğu için SYSCLK ile HCLK saat değeri aynı kalmış oluyor. Programda olduğu gibi kütüphanede de 512’ye kadar bölme seçeneği vardır.
1 2 3 4 5 6 7 8 9 |
#define RCC_SYSCLK_DIV1 RCC_CFGR_HPRE_DIV1 #define RCC_SYSCLK_DIV2 RCC_CFGR_HPRE_DIV2 #define RCC_SYSCLK_DIV4 RCC_CFGR_HPRE_DIV4 #define RCC_SYSCLK_DIV8 RCC_CFGR_HPRE_DIV8 #define RCC_SYSCLK_DIV16 RCC_CFGR_HPRE_DIV16 #define RCC_SYSCLK_DIV64 RCC_CFGR_HPRE_DIV64 #define RCC_SYSCLK_DIV128 RCC_CFGR_HPRE_DIV128 #define RCC_SYSCLK_DIV256 RCC_CFGR_HPRE_DIV256 #define RCC_SYSCLK_DIV512 RCC_CFGR_HPRE_DIV512 |
Şimdi ise incelememiz gereken iki komut kalıyor ve bu komutlar APB1 ve APB2 saatlerinin bölme değerleridir.
1 2 |
RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV2; RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1; |
Programın kütüphane kullanmaya gerek olmadan hazır kod vermesinin yanında diyagramı ve uyarıları beraberinde vermesi daha büyük bir özelliktir. Örneğin hangi saatin nereden giriş aldığı ve nereye giriş verdiğini rahatça görebileceğimiz gibi bu değerleri aştığımızda önceden uyarı almaktayız. Ayrıca yeni fark ettiğimiz bir özelliği de bu saat yapısını kolaylıkla bu program üzerinden öğrenebildik. Eğer hazırcı bir bakış açısıyla değil de öğrenmeye hevesli bir bakış açısıyla bakarsak böyle programlar bile bizim için bir nimet olacaktır. Buraya kadar temel seviyede STM32 hakkında saat bilgilerini size verdik. Bununla yetinmemek gerektiğini ve kullanacağınız farklı birimler için ayrı saat ayarlarının olduğunu çoktan öğrenmiş olmanız gerekir. Biz burada STM32 hakkında saat ayarlarını bırakalım ve lazım olduğunda CubeMX üzerinden devam edelim.
Bizi Facebook grubumuzda takip etmeyi unutmayın. Bilgili ve öğrenmeye hevesli bir topluluk oluşturmak istiyoruz.
https://www.facebook.com/groups/1233336523490761/
UYARI!!
Bu sitede yayınlanan yazılar orjinal içerik olup faydalanılan kaynaklar belirtilmiştir. Yazarın izni olmaksızın tamamen alıntı yapılamaz, kopyalanamaz. Kaynak göstermek kaydıyla (Yazının adı, yazar adı ve link) kısmen alıntı yapılabilir.
Son Yorumlar