Keilde F11 ile adım adım koşturularak çalıştırılacak yanıp sönen led programı (OSC vs ayarlaması yok)
Bu başlık altındaki örnekleri kolay anlamak için HARD dokumanın 49..53 sayfalarını print edin.
#include "STM32F4xx.h"
void SystemInit()
{
(*((int*)0xE000ED88))|=0x0F00000; // Floating Point donanımını aktifleştir. !!! Başımızın derdi !!!
RCC->AHB1ENR|=0x00000008; // GPIOD donanımının clock sinyalini uygulayalım
GPIOD->MODER=0x55000000; // GPIOD nin 15, 14, 13, 12 pinleri cikis tanimlandi (Ledler bu pinlerde)
GPIOD->OSPEEDR= 0xFFFFFFFF; // GPIOD nin tum cikislari en yuksek hizda kullanacagiz
}
int main()
{
while(1)
{
GPIOD->ODR= 0x0000F000; // Ledler yansin
GPIOD->ODR= 0x00000000; // Ledler sonsun
}
}
// Programın sonudur.
User butonuna basıldığında ledleri yakan basılmadığında ledleri söndüren program
CPU 8 Mhz Xtal OSC ile 168Mhz de koşuyor.
AHB frekansı 168 Mhz
APB1 frekansı 42 Mhz
APB2 frekansı 84 Mhz
#include "STM32F4xx.h"
void SystemInit()
{
unsigned int i;
(*((int*)0xE000ED88))|=0x0F00000;
for (i=0;i<0x00100000;i++); // OSC oturtma ve kurtarma rutini
RCC->CFGR |= 0x00009400; // AHB ve APB hizlarini max degerlere set edelim
RCC->CR |= 0x00010000; // HSE Xtal osc calismaya baslasin
while (!(RCC->CR & 0x00020000));// Xtal osc stabil hale gelsin
RCC->PLLCFGR = 0x07405408; // PLL katsayilarini M=8, N=336, P=2 ve Q=7 yapalim
// RCC->PLLCFGR = 0x07402A04; // PLL katsayilarini M=4, N=168, P=2 ve Q=7 yapalim
RCC->CR |= 0x01000000; // PLL calismaya baslasin (Rehber Sayfa 95)
while(!(RCC->CR & 0x02000000)); // Pll hazir oluncaya kadar bekle
// FLASH->ACR = 0x00000705; // Flash ROM icin 5 Wait state secelim ve ART yi aktif edelim (Rehber Sayfa 55)
FLASH->ACR = 0x00000605; // Flash ROM icin 5 Wait state secelim ve ART yi aktif edelim (Rehber Sayfa 55)
RCC->CFGR |= 0x00000002; // Sistem Clk u PLL uzerinden besleyelim
while ((RCC->CFGR & 0x0000000F) != 0x0000000A); // Besleninceye kadar bekle
RCC->AHB1ENR |= 0x0000000F; // GPIO A,B,C,D clock'u aktif edelim
GPIOD->MODER = 0x55000000; // GPIOD nin 15, 14, 13, 12 pinleri cikis tanimlandi (LEDler icin)
GPIOD->OSPEEDR= 0xFFFFFFFF; // GPIOD nin tum cikislari en yuksek hizda kullanacagiz
}
int main()
{
while(1)
{
if (GPIOA->IDR & 0x000000001) GPIOD->ODR= 0x0000F000; // Ledler yansin
else GPIOD->ODR= 0x00000000; // Ledler sonsun
}
}
// Programın sonu.
Ledleri flash eden program
CPU 8 Mhz Xtal OSC ile 168Mhz de koşuyor.
AHB frekansı 168 Mhz
APB1 frekansı 42 Mhz
APB2 frekansı 84 Mhz
#include "STM32F4xx.h"
void SystemInit()
{
// Yukarıdaki örnek programdaki kodların aynısı
}
void Delay()
{
unsigned int i;
for(i=0;i<0x800000;i++);
}
int main()
{
while(1)
{
GPIOD->ODR= 0x0000F000; // Ledler yansin
Delay();
GPIOD->ODR= 0x00000000; // Ledler sonsun
Delay();
}
}
// Programın sonu.
Timer 7 kullanarak Ledleri flash eden program (Interrupt kullanılmıyor)
CPU 8 Mhz Xtal OSC ile 168Mhz de koşuyor.
AHB frekansı 168 Mhz
APB1 frekansı 42 Mhz
APB2 frekansı 84 Mhz
Timer7 içeriği gözlenerek ledler yakılıp söndürülüyor
#include "STM32F4xx.h"
void SystemInit()
{
// Yukarıdaki örnek programdaki kodların aynısı
}
int main()
{
RCC->APB1ENR|=0x00000020; // Timer7 CLK'u aktif edelim (42 Mhz)
TIM7->CR1=0x0080; // Otomatik Reload
TIM7->PSC =42000-1; // Prescaler değerimiz 42000, Count frekansimiz = fCK_PSC / (Yuklenen Deger + 1) 42E6 / (42000) = 1000 Hz
TIM7->ARR =1000; // Counter, Decimal 1000 olunca basa donsun 1 sn demek
TIM7->CR1|=0x0001; // Counter Enable
while(1)
{
if (TIM7->CNT > 500) GPIOD->ODR= 0x0000F000; // Ledler yansin
else GPIOD->ODR= 0x00000000; // Ledler sonsun
}
}
// Programin sonu
Not: Programda kurulan mantığa göre ledlerin saniyede 1 kez yanıp sönmesi gerekiyor.
Fakat saniyede 2 kez yanıp sönüyor. Hatanın sebebi henüz belli değil.
CPU, AHB ve APB Bus frekanslarını yeni baştan gözden geçirmek gerekecek.
GPIO pinlerinde alternatif fonksiyonları kullanmak
Bir önceki Timer7 programında ledlerin yanıp sönme hızının beklenenden 2 kat fazla olduğu gözlenince akla gelen sorulardan birisi acaba
PLL ayarlarını yanlış yaptık da çevrebirimleri olması gerekenden 2 kat hızlı mı koşuyor oldu.
Bu programda MCO2 pininden SYSCLK sinyalini çıkartıp osiloskop ile frekansını ölçeceğiz.
Rehber Sayfa 85 de SYSCLK ve MCO2 yi inceleyin.
CPU 8 Mhz Xtal OSC ile 168Mhz de koşuyor. (Acaba)
AHB frekansı 168 Mhz (Acaba)
APB1 frekansı 42 Mhz (Acaba)
APB2 frekansı 84 Mhz (Acaba)
// Programın başı
#include "STM32F4xx.h"
void SystemInit()
{
// Yukarıdaki örnek programdaki kodların aynısı
}
int main()
{
// MOC2 pininden SYSCLK cikacagiz
RCC->CFGR &= 0x07FFFFFF; // 31,30,29,28,27 nolu bitleri silelim (Aslinda zaten 0) (Prescaler degerinide silelim)
RCC->CFGR |= 0x30000000; // MCO2 prescaler /4 secildi
// Hard sayfa 46 dan MCO2 nin GPIO C9 pini oldugu tespit edildi
// http://img263.imageshack.us/img263/4633/pinlistesi.jpg (http://img263.imageshack.us/img263/4633/pinlistesi.jpg) dan PC9 un bos pin oldugu teyid edildi
// PC9 a hangi alternatif fonksiyon atanacağını bulalım (Hard Sayfa 50 den MCO2 nin AF0 oldugu goruldu)
GPIOC->AFR[1] &= ~0x000000F0; // 7,6,5,4 nolu bitler silindi
// Keil yada ST yukarıdaki registeri neden structure içinde array tanımlamış anlamadım,
// Halbuki diğer regler gibi yapabilirdi (header dosyayı değiştirmek istemiyorum ama istersek yapabiliriz)
GPIOC->OSPEEDR = 0xFFFFFFFF; // GPIOC nin tum cikislarinı en yuksek hizda kullanacagiz
// GPIOC de 9 nolu pine ait cikisi alternatif fonksiyon secelim
GPIOC->MODER = 0x00080000; // Bit 19=1 ve Bit 18=0 yaparak pinin alternatif fonksiyon olmasini sagladik
while(1)
{
}
}
// Programın sonu
MCO2 pini (PC9) scopla gözlendi ve 42Mhz ölçüldü. MCO2 prescaler 4'e set edildiğindenö SYSCLK frekansımızın 4x42=168Mhz oldugu anlaşıldı.
Burda hata olsaydı yanlışlıkla overclock yapmış ve bir ihtimal sistemi 336Mhz ile besleyebilirdik.
Neden prescalerı 1 yapmadıkda 4 yaptık? Dokümanlarda, GPIO lardan 100Mhz den yüksek frekansda sinyal çıkamazsınız deniyor.
SYSCLK 168Mhz buna rağmen Timer7 örneğindeki ledler 1 sn yerine 0.5 sn de yanıp sönüyorsa, olası durumlar;
1. APB1 BUS'ı 42 yerine 84Mhz ile besledik.
2. Timer Clk kaynağı APB1 BUS clk dan beslenmiyor.
3. Timer programında mantık hatası yapıyorum.
Sonuç: Timer7 programındaki hatayı hala bulamadık. Fakat bu program sayesinde alternatif fonksiyon kullanımını görmüş olduk.
Timer 7 Programındaki hatanın sebebi
Bir önceki Timer7 programında ledlerin yanıp sönme hızının beklenenden 2 kat fazla olduğunu gözleyince Timer7 nin CLK frekansını 2 kat yüksek olmasına neden olacak BUS frekans hatta CPU CLK (SYSCLK) ayarlamalarını yanlıs yaptığımdan şüphelenmiştim. Ancak MCO2 pininden SYSCLK sinyalini gözetledik ve frekansının doğru şekilde 168Mhz olduğunu ispatladık. Geriye http://www.cncdesigner.com/STM/Chip.JPG (http://www.cncdesigner.com/STM/Chip.JPG) den TIMER7 nin bağlı olduğu APB1 BUS'ının iki kat yüksek frekansla beslendiği ihtimali kaldı. Fakat SystemInit kodlarında prescaler değerlerinin de doğru olduğu anlaşıldı. Bunun üzerine Rehber dokumanı karıştırırken Sayfa 86 daki şu açıklama dikkatimi çekti.
The timer clock frequencies are automatically set by hardware. There are two cases:
1. 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.
2. Otherwise, they are set to twice (×2) the frequency of the APB domain to which the
timers are connected.
Neticede diyorki;
Eğer APB prescaler 1 değilse Timerlar bağlı oluğu APB BUS frekansından 2 kat yüksek frekansla saydırılır.
(APB1 için prescaler değerimiz 4 dü. O halde Timer7 ye 42 değil 84Mhz giriyor.)
Bu durumda ledlerimiz neden 1 sn yerine 0.5 saniyede yanıp sönüyor anlaşılmış oldu. Sözkonusu durumu artık aşağıdaki gibi çözeceğiz.
Timer 7 kullanarak Ledleri flash eden program (Interrupt kullanılmıyor)
CPU 8 Mhz Xtal OSC ile 168Mhz de koşuyor.
AHB frekansı 168 Mhz
APB1 frekansı 42 Mhz
APB2 frekansı 84 Mhz
Timer7 içeriği gözlenerek ledler yakılıp söndürülüyor
// Programın başı
#include "STM32F4xx.h"
void SystemInit()
{
// Yukarıdaki örnek programdaki kodların aynısı
}
int main()
{
RCC->APB1ENR|=0x00000020; // Timer7 CLK'u aktif edelim (84 Mhz)
TIM7->CR1=0x0080; // Otomatik Reload
TIM7->PSC =42000; // Prescaler değerimiz 42000, Count frekansimiz = fCK_PSC / (Yuklenen Deger + 1) 84E6 / (42000) = 2000 Hz
TIM7->ARR =2000; // Counter, Decimal 2000 olunca basa donsun 1 sn demek
TIM7->CR1|=0x0001; // Counter Enable
while(1)
{
if (TIM7->CNT > 1000) GPIOD->ODR= 0x0000F000; // Ledler yansin
else GPIOD->ODR= 0x00000000; // Ledler sonsun
}
}
// Programin sonu
Timer 7 ve interrupt kullanarak yanıp sönen led programı
// Programın başı
#include "STM32F4xx.h"
void SystemInit()
{
// Yukarıdaki örnek programdaki kodların aynısı
}
void TIM7_IRQHandler()
{
volatile short i;
static char LedFlag=0;
TIM7->SR=0; // Timer Int Flagý silelim
LedFlag=(LedFlag+1)&1;
if (LedFlag) GPIOD->ODR= 0x0000F000; // Ledler yansin
else GPIOD->ODR= 0x00000000; // Ledler sonsun
}
int main()
{
RCC->APB1ENR|=0x00000020; // Timer7 CLK'u aktif edelim (84 Mhz)
TIM7->CR1=0x0080; // Otomatik Reload
TIM7->PSC =42000-1; // Prescaler deðerimiz 42000, Count frekansimiz = fCK_PSC / (Yuklenen Deger + 1) 84E6 / (42000) = 2000 Hz
TIM7->ARR =1000; // Counter, Decimal 1000 olunca basa donsun 0.5 sn demek
TIM7->DIER=0x0001; // Update Int enable
NVIC->ISER[1] = 0X00800000; // NVIC de Timer 7 interrupta izin verelim
TIM7->CR1|=0x0001; // Counter Enable
while(1)
{
}
}
// Programin sonu
PC monitötünü STM32F Discovery kitimize bağlamak Şu ana kadar öğrendiğimiz bilgileri özetlersek;
Çipin CLK üretim ünitesini istediğimiz gibi programlayabiliyoruz.
GPIO ları I/O Port olarak tanımlayabiliyoruz.
Timerları programlayabiliyor ve int ürettirebiliyoruz.
NVIC interrupt kontrol ünitesini programlayabiliyoruz.
Bu tecrübeler PC monitörünü ARM kitimize bağlamak için yeterli.
(http://www.cncdesigner.com/STM/CRT0.JPG)
(http://www.cncdesigner.com/STM/CRT1.JPG)
(http://www.cncdesigner.com/STM/CRT2.JPG)
Programa karakterlere ait pixel bilgilerinden olusturulmus tabloyu eklemedim. Tablo olusturmak isterseniz karakter desenleri http://bytecollector.com/archive/mark_8/My_Mark-8_Info/DigitalGroupPacket/M6570.pdf (http://bytecollector.com/archive/mark_8/My_Mark-8_Info/DigitalGroupPacket/M6570.pdf) dokümanının 7 sayfasından mevcut.
Bu tablo olusturulur ve verdigim ornek kodlar modifiye edilirse program ise yarayabilir.
Monitörün STM32F - Discovery kitimize bağlantısı için 15 pin VGA dişi konnektöre ihtiyacımız var. Ben eski bir VGA kartından söktüm. Bağlantı için sadece 4 kablo yeterli.
Konnektörün 1 numarası seri 100 Ohm üzerinden kitimizin D12 pinine,
Konnektörün 5 numarası kitimizin Gnd pinine,
Konnektörün 13 numarası kitimizin D13 pinine,
Konnektörün 14 numarası kitimizin D14 pinine.
Kodlari indirmek icin: http://www.cncdesigner.com/STM/VIDEO.rar (http://www.cncdesigner.com/STM/VIDEO.rar)
Kitimizde ARM çipimizin GPIOD pinlerine kart üzerindeki ledler baglı. Monitor için sinyaller, ledlere giden pinlerden alındı. Haliyle bu sinyallerin çıktığı pinlere çok yüklenilmiş durumda. Buna rağmen elde edilen görüntü idare eder. Görüntü elde edince de monitor sinyallerini boştaki pinlerden alma yoluna gitmedim.
--------------------------------------------------------------------------------
Programı yeni baştan yazdım ve bunun sonucu öncekinden daha iyi. Ayrıca karakter jenaratörü de eklendi.
Programın kaynak kodu için: www.cncdesigner.com/STM/CRT.rar (http://www.cncdesigner.com/STM/CRT.rar)
Monitör bağlantıları GPIOD 8-9-10 dan alındı. (8 Video), (9 HS), (10 VS)
System Tick Counter kullanarak 1ms lik int uretmek Alıntı Yap
#include "STM32F4xx.h"
#define STK_CTRL (*((volatile unsigned int*) 0xE000E010))
#define STK_LOAD (*((volatile unsigned int*) 0xE000E014))
#define STK_VAL (*((volatile unsigned int*) 0xE000E018))
/*****************************************************************************************************
CPU PLL ile 168Mhz de kosturulur
AHB frekansý 168 Mhz
APB1 frekansý 42 Mhz
APB2 frekansý 84 Mhz
*****************************************************************************************************/
void SystemInit()
{
unsigned int i;
(*((int*)0xE000ED88))|=0x0F00000;
for (i=0;i<0x00100000;i++); // OSC oturtma ve kurtarma rutini
RCC->CFGR |= 0x00009400; // AHB ve APB hizlarini max degerlere set edelim
RCC->CR |= 0x00010000; // HSE Xtal osc calismaya baslasin
while (!(RCC->CR & 0x00020000));// Xtal osc stabil hale gelsin
// RCC->PLLCFGR = 0x07405408; // PLL katsayilarini M=8, N=336, P=2 ve Q=7 yapalim
RCC->PLLCFGR = 0x07402A04; // PLL katsayilarini M=4, N=168, P=2 ve Q=7 yapalim
RCC->CR |= 0x01000000; // PLL calismaya baslasin (Rehber Sayfa 95)
while(!(RCC->CR & 0x02000000)); // Pll hazir oluncaya kadar bekle
// FLASH->ACR = 0x00000705; // Flash ROM icin 5 Wait state secelim ve ART yi aktif edelim (Rehber Sayfa 55)
FLASH->ACR = 0x00000605; // Flash ROM icin 5 Wait state secelim ve ART yi aktif edelim (Rehber Sayfa 55)
RCC->CFGR |= 0x00000002; // Sistem Clk u PLL uzerinden besleyelim
while ((RCC->CFGR & 0x0000000F) != 0x0000000A); // Besleninceye kadar bekle
RCC->AHB1ENR |= 0x0000000F; // GPIO A,B,C,D clock'u aktif edelim
GPIOD->MODER = 0x55000000; // GPIOD nin 15, 14, 13, 12 pinleri cikis tanimlandi (LEDler icin)
GPIOD->OSPEEDR= 0xFFFFFFFF; // GPIOD nin tum cikislari en yuksek hizda kullanacagiz
}
/*****************************************************************************************************
STS TICK COUNTER AHB FREKANSINDA (168 MHZ) KOSACAK
*****************************************************************************************************/
void SysTickInit()
{
STK_LOAD= 0X00029040>>1; // 168E6/1000/2=168000 TICK TIME 1MS
STK_CTRL&=~0x00010000; // Count Flagi silelim,
STK_CTRL|= 0x00000007; // int enb ve count enb yapalim, clk kaynagini AHB yapalim
}
void SysTick_Handler()
{
volatile static int flag=0;
STK_CTRL&= ~0x00010000; // Count Flagi silelim
flag^=0xF000;
GPIOD->ODR= flag; // LEDLER yansin
}
int main()
{
SysTickInit();
while(1)
{
}
}
Multi tasking https://www.picproje.org/index.php?topic=35654.msg259298#msg259298 (https://www.picproje.org/index.php?topic=35654.msg259298#msg259298) Bug olan versiyon
https://www.picproje.org/index.php?topic=35654.msg2599719#msg259719 (https://www.picproje.org/index.php?topic=35654.msg2599719#msg259719) Son versiyon
Konuyu bölmek gibi olmasın ama PC monitötünü STM32F Discovery kitimize bağlamak isimli uygulamada STM32F407VG ARM yerine STM32VL DISCOVERY kit kullansak olur mu?
Sözkonusu programda video sinyali hiç bir donanım kullanılmadan tamamen yazılımla üretiliyor. Bu ise ancak yüksek işlemci hızıyla mümkün.
Bu nedenle 268Mhz de koşan işlemcilerde programı işletmek zorundasınız.
Daha düşük hızlı işlemcilerle deneme yapmak isterseniz yazılımı değiştirerek 1 satırdaki karakter sayısını azaltmanız gerekir. Ancak karakterleriniz anormal şekilde şişman görüleceklerdir.
STM32F Discovery kitimizle bir başka video uygulamasının anlatım ve kaynak kodlarına http://www.mcu-turkey.com/?p=20659&preview=true&preview_id=20659&preview_nonce=9be3fc4e75 (http://www.mcu-turkey.com/?p=20659&preview=true&preview_id=20659&preview_nonce=9be3fc4e75) linkinden ulaşabilirsiniz.
Bu yazıda, monitörlerin çalışma prensibi, farklı bir yaklaşımla ele alınmış, video sinyali, senkron palsları gibi kavramlar üzerinde de durulmuştur.
Ayrıca monitörü, 720x400 70Hz modunda kullanmak için hangi hesaplamaların yapıldığına değinilmiştir.
Bu monitör uygulaması, daha öncekilerden farklı olarak, gif animasyonlardaki gibi animasyon yapmakta ilave olarak animasyonu döndürebilmektedir.
http://www.mcu-turkey.com/wp-content/uploads/2011/11/Video.wmv (http://www.mcu-turkey.com/wp-content/uploads/2011/11/Video.wmv)
"Memory"den "Memory"e DMA kullanarak veri transferi yapmak
Örnek programda Source[1024] array içine veri doldurulmakta daha sonra bu veriler DMA marifetiyle Target[1024] array içine taşınmaktadır. (Interrupt kullanılmamıştır.)
#include "STM32F4xx.h"
char Source[1024];
char Target[1024];
void SystemInit()
{
unsigned int i;
(*((int*)0xE000ED88))|=0x0F00000;
for (i=0;i<0x00100000;i++); // OSC oturtma ve kurtarma rutini
RCC->CFGR |= 0x00009400; // AHB ve APB hizlarini max degerlere set edelim
RCC->CR |= 0x00010000; // HSE Xtal osc calismaya baslasin
while (!(RCC->CR & 0x00020000)); // Xtal osc stabil hale gelsin
RCC->PLLCFGR = 0x07402584; // PLL katsayilarini M=4, N=150, P=2 ve Q=7 yapalim 150 Mhz
RCC->CR |= 0x01000000; // PLL calismaya baslasin (Rehber Sayfa 95)
while(!(RCC->CR & 0x02000000)); // Pll hazir oluncaya kadar bekle
FLASH->ACR = 0x00000605; // Flash ROM icin 5 Wait state secelim ve ART yi aktif edelim (Rehber Sayfa 55)
RCC->CFGR |= 0x00000002; // Sistem Clk u PLL uzerinden besleyelim
while ((RCC->CFGR & 0x0000000F) != 0x0000000A); // Besleninceye kadar bekle
RCC->AHB1ENR |= 0x0000000F; // GPIO A,B,C,D clock'u aktif edelim
GPIOD->MODER = 0x55550000; // GPIOD nin 15, 14, 13, 12, 11, 10, 9, 8 pinleri cikis tanimlandi (LEDler icin)
GPIOD->OSPEEDR= 0xFFFFFFFF; // GPIOD nin tum cikislari en yuksek hizda kullanacagiz
}
int main()
{
volatile int i;
RCC->AHB1ENR |= 0x00400000; // DMA2 clock'u aktif edelim
while(DMA2_Stream0->CR&1); // DMA 0 kanalinin isi varsa bitmesini bekleyelim
DMA2_Stream0->PAR=(int)&Source[0]; // Source array dan datalari alacagiz
DMA2_Stream0->M0AR=(int)&Target[0]; // Target array a datalari tasiyacagiz
DMA2_Stream0->NDTR=1024; // 1024 adet veri tasiyacagiz
DMA2_Stream0->CR=0x00A00680;
for(i=0;i<1024;i++) Source[i]=i; // Source alanina datalarimizi koyalim
DMA2_Stream0->CR|=1; // Transferi baslat
// Artik biz kendi yolumuza DMA kendi yoluna
for(i=0;i<0x100000;i++);
while(DMA2_Stream0->CR&1); // DMA2 0 kanalinin isini bitirmediyse bekleyelim
{
}
}
STM32F407 RNG modülü ile random sayı üretmek
RNG modülü ile random sayı üretmek oldukça basit bir işlem. Donanım, analog olarak üretilen seed değerlerini LFSR registerine yüklenmekte ve random sayı üretmektedir. Üretilen sayı bazı kriterleri sağlıyorsa, sayı hazır flağını set etmekte ve bize sadece bu değeri okumak kalmaktadır.
#include "STM32F4xx.h"
int Random[256];
void SystemInit()
{
unsigned int i;
(*((int*)0xE000ED88))|=0x0F00000;
for (i=0;i<0x00100000;i++); // OSC oturtma ve kurtarma rutini
RCC->CFGR |= 0x00009400; // AHB ve APB hizlarini max degerlere set edelim
RCC->CR |= 0x00010000; // HSE Xtal osc calismaya baslasin
while (!(RCC->CR & 0x00020000)); // Xtal osc stabil hale gelsin
RCC->PLLCFGR = 0x07402A04; // PLL katsayilarini M=4, N=168, P=2 ve Q=7 yapalim 168 Mhz
RCC->CR |= 0x01000000; // PLL calismaya baslasin (Rehber Sayfa 95)
while(!(RCC->CR & 0x02000000)); // Pll hazir oluncaya kadar bekle
FLASH->ACR = 0x00000605; // Flash ROM icin 5 Wait state secelim ve ART yi aktif edelim (Rehber Sayfa 55)
RCC->CFGR |= 0x00000002; // Sistem Clk u PLL uzerinden besleyelim
while ((RCC->CFGR & 0x0000000F) != 0x0000000A); // Besleninceye kadar bekle
RCC->AHB1ENR |= 0x0000000F; // GPIO A,B,C,D clock'u aktif edelim
GPIOD->MODER = 0x55550000; // GPIOD nin 15, 14, 13, 12, 11, 10, 9, 8 pinleri cikis tanimlandi (LEDler icin)
GPIOD->OSPEEDR= 0xFFFFFFFF; // GPIOD nin tum cikislari en yuksek hizda kullanacagiz
}
int main()
{
volatile int i,r;
RCC->AHB2ENR |= 0x40; // RNG modulunun clock'unu aktif edelim
RNG->CR=0x04; // RNG modulu calismaya basladin
for(i=0;i<256;i++) // 256 adet random sayi uretilsin
{
while (!(RNG->SR&1)); // kullanilabilir sayi olusumunu bekle
Random [ i ] = RNG->DR;
}
while(1);
}
Kit üzerindeki LIS302DL çipini (3 axis accelerometer) SPI modülü üzerinden kullanmak
Bu çalışmada interruptlar kullanılmamıştır.
#include "STM32F4xx.h"
char x,y,z;
void SystemInit()
{
unsigned int i;
(*((int*)0xE000ED88))|=0x0F00000;
for (i=0;i<0x00100000;i++); // OSC oturtma ve kurtarma rutini
RCC->CFGR |= 0x00009400; // AHB ve APB hizlarini max degerlere set edelim
RCC->CR |= 0x00010000; // HSE Xtal osc calismaya baslasin
while (!(RCC->CR & 0x00020000)); // Xtal osc stabil hale gelsin
RCC->PLLCFGR = 0x07402A04; // PLL katsayilarini M=4, N=168, P=2 ve Q=7 yapalim 168 Mhz
RCC->CR |= 0x01000000; // PLL calismaya baslasin (Rehber Sayfa 95)
while(!(RCC->CR & 0x02000000)); // Pll hazir oluncaya kadar bekle
FLASH->ACR = 0x00000605; // Flash ROM icin 5 Wait state secelim ve ART yi aktif edelim (Rehber Sayfa 55)
RCC->CFGR |= 0x00000002; // Sistem Clk u PLL uzerinden besleyelim
while ((RCC->CFGR & 0x0000000F) != 0x0000000A); // Besleninceye kadar bekle
RCC->AHB1ENR |= 0x0000001F; // GPIO A,B,C,D,E clock'u aktif edelim
GPIOD->MODER = 0x55550000; // GPIOD nin 15, 14, 13, 12, 11, 10, 9, 8 pinleri cikis tanimlandi (LEDler icin)
GPIOD->OSPEEDR= 0xFFFFFFFF; // GPIOD nin tum cikislari en yuksek hizda kullanacagiz
// GPIOA da A7, A6, A5 pinleri, LIS302DL cipiyle haberlesmek icin SPI moduna alinacak
GPIOA->AFR[0]=0x55500000; // SPI1 secelim (Rehber Sayfa 141), Hard Sayfa 49
GPIOA->MODER|=0x0000A800; // A7,A6,A5 Alternatif fonksiyon
RCC->APB2ENR|=0x00001000; // SPI1 clk enable // GPIOE3 pinini output tanimlayalim (LIS302DL SPI/I2C secimi)
GPIOE->MODER = 0x00000040; // GPIOE nin 3 nolu pini cikis tanimlandi
GPIOE->OSPEEDR= 0xFFFFFFFF; // GPIOE nin tum cikislari en yuksek hizda kullanacagiz
GPIOE->BSRRL=0x0008; // GPIOE3=1; LIS302DL CS=1
SPI1->CR1=0x00000B7F; // SPI1 16 bit, master , fulldublex vs
SPI1->CR2=0X0000;
}
void Write(char Adr,unsigned char Data)
{
GPIOE->BSRRH=0x0008; // LIS302DL CS=0
SPI1->DR=((Adr&0x3F)<<8)|Data;
while(!(SPI1->SR&2));
GPIOE->BSRRL=0x0008; // LIS302DL CS=1
}
char Read(char Adr)
{
GPIOE->BSRRH=0x0008; // LIS302DL CS=0
SPI1->DR=((Adr&0x3F)|0x80)<<8;
while(!(SPI1->SR&1));
GPIOE->BSRRL=0x0008; // LIS302DL CS=1
return(SPI1->DR);
}
int main()
{
char who;
if(Read(0x0F)==0x3B) // Who are you ?
{
Write(0x20,0x47); // Data Rate=100Hz, Full Scale=2g, Activate, x,y,z enable
while(1)
{
who=Read(0x27); // Statusu ogrenelim. Kim hazir kim değil?
if (who&1) x=Read(0x29);
if (who&2) y=Read(0x2B);
if (who&4) z=Read(0x2D);
}
}
while(1);
}
Programda onemli bir hata var. Bunun icin asagidaki linki muhakkak okuyun.
Programdaki hatayi, linki ziyaret ettikten sonra kendiniz duzeltirsiniz.
https://www.picproje.org/index.php/topic,35794.msg269243.html#msg269243 (https://www.picproje.org/index.php/topic,35794.msg269243.html#msg269243)
USART3 modulunu kullanarak 1 Start Bit, 8 Data Bit, 1 Stop bit, No Parity, 9600 Baud Asenkron haberlesme calismasi yapmak.
#include "STM32F4xx.h"
/*********************************************************************************
CPU frekansi 168Mhz
AHB frekansi 84 Mhz
APB frekansi 42 Mhz
*********************************************************************************/
void SystemInit()
{
unsigned int i;
(*((int*)0xE000ED88))|=0x0F00000;
for (i=0;i<0x00100000;i++); // OSC oturtma ve kurtarma rutini
RCC->CFGR |= 0x00009400; // AHB ve APB hizlarini max degerlere set edelim
RCC->CR |= 0x00010000; // HSE Xtal osc calismaya baslasin
while (!(RCC->CR & 0x00020000));// Xtal osc stabil hale gelsin
RCC->PLLCFGR = 0x07402A04; // PLL katsayilarini M=4, N=168, P=2 ve Q=7 yapalim 168 Mhz
RCC->CR |= 0x01000000; // PLL calismaya baslasin (Rehber Sayfa 95)
while(!(RCC->CR & 0x02000000)); // Pll hazir oluncaya kadar bekle
FLASH->ACR = 0x00000605; // Flash ROM icin 5 Wait state secelim ve ART yi aktif edelim (Rehber Sayfa 55)
RCC->CFGR |= 0x00000002; // Sistem Clk u PLL uzerinden besleyelim
while ((RCC->CFGR & 0x0000000F) != 0x0000000A); // Besleninceye kadar bekle
RCC->AHB1ENR |= 0x0000001F; // GPIO A,B,C,D,E clock'u aktif edelim
GPIOD->MODER = 0x55550000; // GPIOD nin 15, 14, 13, 12, 11, 10, 9, 8 pinleri cikis tanimlandi (LEDler icin)
GPIOD->OSPEEDR= 0xFFFFFFFF; // GPIOD nin tum cikislari en yuksek hizda kullanacagiz
}
/*********************************************************************************
USART3 modulunu kullanarak asenkron haberlesme
Interrupt kullanilmamistir
*********************************************************************************/
void UsartInit()
{
// USART3 MODULUNU AKTIF HALE GETIRELIM
RCC->APB1ENR|=0x00040000; // USART3 Clk Enable (Rehber Sayfa 113)
RCC->APB1RSTR|=0x00040000; // USART3 Resetlendi
GPIOB->AFR[1]=0x07777700; // PB10..PB14 pinleri USART3 ile alakalandirildi (Hard Sayfa 49)
GPIOB->MODER|=0x2AA00000; // GPIOB 10..14 icin alternatif fonksiyon tanimi (Rehber Sayfa 148)
// USART3 MODULUNU AYARLAYALIM // 1 Start, 8 Data, 1 Stop, No parity (Default degerler)
RCC->APB1RSTR&=~0x00040000; // USART3 Reseti kaldiralim
USART3->SR&=~0X03FF; // Status registeri silelim
USART3->BRR=0X1112; // 9600 Baud
USART3->CR1|=0x0000200C; // USART3 enable
}
void SendChar(char Tx)
{
while(!(USART3->SR&0x80)); // TX Buffer dolu ise bekle (Rehber Sayfa 646)
USART3->DR=Tx;
}
char WaitChar()
{
while(!(USART3->SR&0x20)); // RX Buffer bos ise bekle (Rehber Sayfa 646)
return(USART3->DR);
}
int main()
{
UsartInit();
SendChar(0x1B);
WaitChar();
while(1);
}
Bundan sonraki asamada ornek programlarda interrupt kullanimina agirlik verecegiz. Register atamalarinda okunurlugu artirmak adina C yi daha etkin kullanacagiz.
USART3 modülünü kullanan (9600, 8, N, 1Stp) alım işlemini interrupt rutini üzerinden gerçekleştiren program örneği
#include "STM32F4xx.h"
unsigned char WAdr,RAdr;
char RxBuf[128];
/*********************************************************************************
CPU frekansi 168Mhz
AHB frekansi 84 Mhz
APB frekansi 42 Mhz
*********************************************************************************/
void SystemInit()
{
unsigned int i;
(*((int*)0xE000ED88))|=0x0F00000;
for (i=0;i<0x00100000;i++); // OSC oturtma ve kurtarma rutini
RCC->CFGR |= 0x00009400; // AHB ve APB hizlarini max degerlere set edelim
RCC->CR |= 0x00010000; // HSE Xtal osc calismaya baslasin
while (!(RCC->CR & 0x00020000));// Xtal osc stabil hale gelsin
RCC->PLLCFGR = 0x07402A04; // PLL katsayilarini M=4, N=168, P=2 ve Q=7 yapalim 168 Mhz
RCC->CR |= 0x01000000; // PLL calismaya baslasin (Rehber Sayfa 95)
while(!(RCC->CR & 0x02000000)); // Pll hazir oluncaya kadar bekle
FLASH->ACR = 0x00000605; // Flash ROM icin 5 Wait state secelim ve ART yi aktif edelim (Rehber Sayfa 55)
RCC->CFGR |= 0x00000002; // Sistem Clk u PLL uzerinden besleyelim
while ((RCC->CFGR & 0x0000000F) != 0x0000000A); // Besleninceye kadar bekle
RCC->AHB1ENR |= 0x0000001F; // GPIO A,B,C,D,E clock'u aktif edelim
GPIOD->MODER = 0x55550000; // GPIOD nin 15, 14, 13, 12, 11, 10, 9, 8 pinleri cikis tanimlandi (LEDler icin)
GPIOD->OSPEEDR= 0xFFFFFFFF; // GPIOD nin tum cikislari en yuksek hizda kullanacagiz
}
/*********************************************************************************
USART3 modulunu kullanarak asenkron haberlesme (Hata kontrolu yapilmiyor)
*********************************************************************************/
void USART3_IRQHandler()
{
volatile int Sts;
Sts=USART3->SR;
RxBuf[WAdr]=USART3->DR;
WAdr=(WAdr+1)&0x7F;
}
void UsartInit()
{
WAdr=0;RAdr=0;
// USART3 MODULUNU AKTIF HALE GETIRELIM
RCC->APB1ENR|=0x00040000; // USART3 Clk Enable (Rehber Sayfa 113)
RCC->APB1RSTR|=0x00040000; // USART3 Resetlendi
GPIOB->AFR[1]=0x07777700; // PB10..PB14 pinleri USART3 ile alakalandirildi (Hard Sayfa 49)
GPIOB->MODER|=0x2AA00000; // GPIOB 10..14 icin alternatif fonksiyon tanimi (Rehber Sayfa 148)
// USART3 MODULUNU AYARLAYALIM // 1 Start, 8 Data, 1 Stop, No parity (Default degerler)
RCC->APB1RSTR&=~0x00040000; // USART3 Reseti kaldiralim
// USART3->SR&=~0X03FF; // Status registeri silelim
USART3->BRR=0X1112; // 9600 Baud
USART3->CR1|=0x0000202C; // USART3 enable
NVIC->ISER[1]|=0x80; // NVIC da USART3 interrupta izin verelim
}
void SendChar(char Tx)
{
while(!(USART3->SR&0x80)); // TX Buffer dolu ise bekle (Rehber Sayfa 646)
USART3->DR=Tx;
}
void SendTxt(char *Adr)
{
while(*Adr)
{
SendChar(*Adr);
Adr++;
}
}
char DataReady()
{
return(WAdr-RAdr);
}
char ReadChar()
{
char Dat;
Dat=RxBuf[RAdr];
RAdr=(RAdr+1)&0x7F;
return(Dat);
}
// Rx ve TX pinlerini (GPIOB10 ve GPIOB11) birbirine baglarsaniz gonderdiginiz datalar geri gelecektir
int main()
{
int i;
UsartInit();
SendTxt("PicProje");
SendChar(' ');
SendTxt("Bunalmis");
for(i=0;i<0x1000000;i++); // Laf olsun diye bekledik
while(DataReady()) ReadChar();
while(1);
}
DMA ile Ramdaki verileri USART3 den yollayan, USART3 den gelen verileri ise INT ile yakalayan program örneği
#include "STM32F4xx.h"
char RxBuf[128];
char TxBuf[128];
int cntr=0;
unsigned char WAdr,RAdr;
/*********************************************************************************
CPU frekansi 168Mhz
AHB frekansi 84 Mhz
APB frekansi 42 Mhz
*********************************************************************************/
void SystemInit()
{
unsigned int i;
(*((int*)0xE000ED88))|=0x0F00000;
for (i=0;i<0x00100000;i++); // OSC oturtma ve kurtarma rutini
RCC->CFGR |= 0x00009400; // AHB ve APB hizlarini max degerlere set edelim
RCC->CR |= 0x00010000; // HSE Xtal osc calismaya baslasin
while (!(RCC->CR & 0x00020000)); // Xtal osc stabil hale gelsin
RCC->PLLCFGR = 0x07402A04; // PLL katsayilarini M=4, N=168, P=2 ve Q=7 yapalim 168 Mhz
RCC->CR |= 0x01000000; // PLL calismaya baslasin (Rehber Sayfa 95)
while(!(RCC->CR & 0x02000000)); // Pll hazir oluncaya kadar bekle
FLASH->ACR = 0x00000605; // Flash ROM icin 5 Wait state secelim ve ART yi aktif edelim (Rehber Sayfa 55)
RCC->CFGR |= 0x00000002; // Sistem Clk u PLL uzerinden besleyelim
while ((RCC->CFGR & 0x0000000F) != 0x0000000A); // Besleninceye kadar bekle
RCC->AHB1ENR |= 0x0000001F; // GPIO A,B,C,D,E clock'u aktif edelim
GPIOD->MODER = 0x55550000; // GPIOD nin 15, 14, 13, 12, 11, 10, 9, 8 pinleri cikis tanimlandi (LEDler icin)
GPIOD->OSPEEDR= 0xFFFFFFFF; // GPIOD nin tum cikislari en yuksek hizda kullanacagiz
}
/*********************************************************************************
USART3 modulunu kullanarak asenkron haberlesme (Hata kontrolu yapilmiyor)
*********************************************************************************/
void USART3_IRQHandler()
{
volatile int Sts;
Sts=USART3->SR;
RxBuf[WAdr]=USART3->DR;
WAdr=(WAdr+1)&0x7F;
cntr++;
}
void UsartInit()
{
WAdr=0;RAdr=0;
// USART3 MODULUNU AKTIF HALE GETIRELIM
RCC->APB1ENR|=0x00040000; // USART3 Clk Enable (Rehber Sayfa 113)
RCC->APB1RSTR|=0x00040000; // USART3 Resetlendi
GPIOB->AFR[1]=0x07777700; // PB10..PB14 pinleri USART3 ile alakalandirildi (Hard Sayfa 49)
GPIOB->MODER|=0x2AA00000; // GPIOB 10..14 icin alternatif fonksiyon tanimi (Rehber Sayfa 148)
// USART3 MODULUNU AYARLAYALIM 1 Start, 8 Data, 1 Stop, No parity (Default degerler)
RCC->APB1RSTR&=~0x00040000; // USART3 Reseti kaldiralim
USART3->BRR=0X1112; // 9600 Baud
USART3->CR1|=0x0000202C; // USART3 enable
USART3->CR3|=0x80; // DMA Transfer Enable (Transmit)
NVIC->ISER[1]|=0x80; // NVIC da USART3 interrupta izin verelim
}
// Rx ve TX pinlerini (GPIOB10 ve GPIOB11) birbirine baglarsaniz gonderdiginiz datalar geri gelecektir
int main()
{
volatile int i;
UsartInit();
RCC->AHB1ENR |= 0x00200000; // DMA1 clock'u aktif edelim
RCC->AHB1RSTR|= 0x00200000; // DMA1 resetleyelim
for(i=0;i<0x1FF;i++);
RCC->AHB1RSTR&=~0x00200000; // DMA1 reseti kaldiralim
DMA1_Stream4->M0AR=(int)&TxBuf[0]; // Nereden okuyacagiz
DMA1_Stream4->PAR=(int)&USART3->DR;// Nereye yazacagiz
DMA1_Stream4->FCR&=~0xFFFFFF40;
DMA1_Stream4->CR=(DMA1_Stream4->CR & 0xF0100000)| 0x0E000440; // CH7 vs
for(i=0;i<128;i++) TxBuf=i+1; // Laf olsun diye tasinacak verileri olusturalim
DMA1_Stream4->NDTR=50; // 50 adet veri tasiyacagiz
USART3->SR&=~0x40; // Rehberde boyle yapin deniyor fakat yapmasak da oluyor !!!!
DMA1_Stream4->CR|=1; // Transferi baslat
// Asagidaki while dongusune girdigimizde DMA, Ramdaki verileri USART'dan yollarken
// CPU da int Data received anlamina gelen interrupt ile Usartdan verileri okur
// ve circular buffera yazar.
// Transferin bittigini interrupt ile ya da dogrudan
// DMA1_Stream4->CR yada DMA_HISR registerinden ogrenebilirsiniz.
while(1);
}
Interrupt kullanarak yazılımsal PWM sinyalleri üretmek
Aşağıda 8 kanallı yazılımsal olarak PWM sinyal üreten örnek yazılım görülmektedir. RC Servo çalışması yapmak isteyenler için PWM peryodu 20 mili saniye seçilmiş olup her bir PWM 0..1000 aralığında değer alabilir. Programda değişiklik yapıp, PWM kanallarının sayısını dilediğiniz kadar artırabilirsiniz.
#include "STM32F4xx.h"
unsigned short PWM[8]; // PWM registerler
unsigned short SRG[8]; // Shadow Registerler
unsigned short CNTR; // PWM Counter
/*****************************************************************************************************
CPU PLL ile 168Mhz de kosturulur
AHB frekansy 168 Mhz
APB1 frekansy 42 Mhz
APB2 frekansy 84 Mhz
*****************************************************************************************************/
void SystemInit()
{
unsigned int i;
(*((int*)0xE000ED88))|=0x0F00000;
for (i=0;i<0x00100000;i++); // OSC oturtma ve kurtarma rutini
RCC->CFGR |= 0x00009400; // AHB ve APB hizlarini max degerlere set edelim
RCC->CR |= 0x00010000; // HSE Xtal osc calismaya baslasin
while (!(RCC->CR & 0x00020000));// Xtal osc stabil hale gelsin
RCC->PLLCFGR = 0x07402A04; // PLL katsayilarini M=4, N=168, P=2 ve Q=7 yapalim
RCC->CR |= 0x01000000; // PLL calismaya baslasin (Rehber Sayfa 95)
while(!(RCC->CR & 0x02000000)); // Pll hazir oluncaya kadar bekle
FLASH->ACR = 0x00000605; // Flash ROM icin 5 Wait state secelim ve ART yi aktif edelim (Rehber Sayfa 55)
RCC->CFGR |= 0x00000002; // Sistem Clk u PLL uzerinden besleyelim
while ((RCC->CFGR & 0x0000000F) != 0x0000000A); // Besleninceye kadar bekle
RCC->AHB1ENR |= 0x0000000F; // GPIO A,B,C,D clock'u aktif edelim
GPIOD->MODER = 0x55550000; // GPIOD nin 15, 14, 13, 12, 11, 10, 9, 8 pinleri cikis tanimlandi (LEDler icin)
GPIOD->OSPEEDR= 0xFFFFFFFF; // GPIOD nin tum cikislari en yuksek hizda kullanacagiz
RCC->APB1ENR|=0x00000020; // Timer7 CLK'u aktif edelim (84 Mhz)
TIM7->CR1=0x0080; // Otomatik Reload
TIM7->PSC =839; // Prescaler degerimiz 839, Count frekansimiz = fCK_PSC / (Yuklenen Deger + 1) 84E6 / (840) = 100 KHz
TIM7->ARR =1; // Counter, Decimal 1 olunca basa donsun. Her 20 mikrosaniye de bir timer int olusacak.
TIM7->DIER=0x0001; // Update Int enable
NVIC->ISER[1] = 0X00800000; // NVIC de Timer 7 interrupta izin verelim
TIM7->CR1|=0x0001; // Counter Enable
}
void TIM7_IRQHandler()
{
unsigned short d,i,j;
TIM7->SR=0; // Timer Int Flagini silelim
d=GPIOD->ODR & 0x00FF;
CNTR++;
if(CNTR>=1000)
{
CNTR=0;
for(i=0;i<8;i++)
{
if(PWM[i]>1000) PWM[i]=1000;
SRG[i]=PWM[i];
}
}
j=0x8000;
for(i=0;i<8;i++)
{
if (CNTR>=SRG[i]) d|=j;
j=j>>1;
}
GPIOD->ODR=d;
}
int main()
{
PWM[0]=100;
PWM[1]=200;
PWM[2]=300;
PWM[3]=400;
PWM[4]=500;
PWM[5]=600;
PWM[6]=700;
PWM[7]=800;
while(1);
}
DAC kullanımı
STMF4 kartımızda 2 adet DAC bulunmaktadır. Bunlardan birincisini kullanmak için basit bir kod örneğimiz aşağıda. DAC için DMA ve interrupt kullanılmamıştır. Timer7 her 20 mikrosaniyede bir int çakarak işlemciyi döngüden çıkartıp CNTR değişkenini 1 artırmakta ve eğer 1024 olduysa sıfırlamaktadır. Daha sonrada CNTR değerini DAC a yüklemektedir.
#include "STM32F4xx.h"
int CNTR;
/*****************************************************************************************************
CPU PLL ile 168Mhz de kosturulur
AHB frekansy 168 Mhz
APB1 frekansy 42 Mhz
APB2 frekansy 84 Mhz
*****************************************************************************************************/
void SystemInit()
{
unsigned int i;
(*((int*)0xE000ED88))|=0x0F00000;
for (i=0;i<0x00100000;i++); // OSC oturtma ve kurtarma rutini
RCC->CFGR |= 0x00009400; // AHB ve APB hizlarini max degerlere set edelim
RCC->CR |= 0x00010000; // HSE Xtal osc calismaya baslasin
while (!(RCC->CR & 0x00020000));// Xtal osc stabil hale gelsin
RCC->PLLCFGR = 0x07402A04; // PLL katsayilarini M=4, N=168, P=2 ve Q=7 yapalim
RCC->CR |= 0x01000000; // PLL calismaya baslasin (Rehber Sayfa 95)
while(!(RCC->CR & 0x02000000)); // Pll hazir oluncaya kadar bekle
FLASH->ACR = 0x00000605; // Flash ROM icin 5 Wait state secelim ve ART yi aktif edelim (Rehber Sayfa 55)
RCC->CFGR |= 0x00000002; // Sistem Clk u PLL uzerinden besleyelim
while ((RCC->CFGR & 0x0000000F) != 0x0000000A); // Besleninceye kadar bekle
RCC->AHB1ENR |= 0x0000000F; // GPIO A,B,C,D clock'u aktif edelim
GPIOD->MODER = 0x55550000; // GPIOD nin 15, 14, 13, 12, 11, 10, 9, 8 pinleri cikis tanimlandi (LEDler icin)
GPIOD->OSPEEDR= 0xFFFFFFFF; // GPIOD nin tum cikislari en yuksek hizda kullanacagiz
// DAC1 kullanacagiz
GPIOA->MODER=0xA8000200; // GPIOA4 Analog inp yapildi
RCC->APB1ENR|=1<<29; // Artislik olsun (0x20000000 ile OR yap demek)
DAC->CR=0x00000003; // DAC1 ve Bufferi aktif edelim
// Timer 7 ile calisalim
RCC->APB1ENR|=0x00000020; // Timer7 CLK'u aktif edelim (84 Mhz)
TIM7->CR1=0x0080; // Otomatik Reload
TIM7->PSC =839; // Prescaler degerimiz 839, Count frekansimiz = fCK_PSC / (Yuklenen Deger + 1) 84E6 / (840) = 100 KHz
TIM7->ARR =1; // Counter, Decimal 1 olunca basa donsun. Her 20 mikrosaniye de bir timer int olusacak.
TIM7->DIER=0x0001; // Update Int enable
NVIC->ISER[1] = 0X00800000; // NVIC de Timer 7 interrupta izin verelim
TIM7->CR1|=0x0001; // Counter Enable
}
void TIM7_IRQHandler()
{
TIM7->SR=0; // Timer Int Flagini silelim
CNTR++;
CNTR&=0x3FF;
DAC->DHR12R1=CNTR;
}
int main()
{
while(1);
}
Program, GPIOA4 den analog sinyal çıkartmaktadır. Ancak bu pin aynı zamanda kart üzerindeki digital çiplerden birisine daha gidiyor. Açıkcası digital bir pine analog sinyal girmek hiç hoş bir şey değil ama kısa süreli denemeler için başka çaremiz yok. Çünkü her iki DAC çıkışı da mevcut kart üzerinde alıkonulmuş durumda.
Bir sonraki programımızda şenlik var. Amplifikatörlerinizi hazır edin.
GPIO Pinlerini INT pini olarak kullanmak
Ayni programi bir baska baslikta vermistik.
Program kart uzerindeki butona (GPIOA0 ile baglantili) basildiginda int uretmekte ve yesil ledi toggle etmektedir.
#include "STM32F4xx.h"
// FCPU =168Mhz
// FAHB =FCPU
// FAPB2=FCPU/2
// FAPB1=FCPU/4
void SystemInit()
{
unsigned int i;
(*((int*)0xE000ED88))|=0x0F00000;
for (i=0;i<0x00100000;i++); // OSC oturtma ve kurtarma rutini
RCC->CFGR |= 0x00009400; // AHB ve APB hizlarini max degerlere set edelim
RCC->CR |= 0x00010000; // HSE Xtal osc calismaya baslasin
while (!(RCC->CR & 0x00020000));// Xtal osc stabil hale gelsin
RCC->PLLCFGR = 0x07402A04; // PLL katsayilarini M=4, N=168, P=2 ve Q=7 yapalim
RCC->CR |= 0x01000000; // PLL calismaya baslasin (Rehber Sayfa 95)
while(!(RCC->CR & 0x02000000)); // Pll hazir oluncaya kadar bekle
FLASH->ACR = 0x00000605; // Flash ROM icin 5 Wait state secelim ve ART yi aktif edelim (Rehber Sayfa 55)
RCC->CFGR |= 0x00000002; // Sistem Clk u PLL uzerinden besleyelim
while ((RCC->CFGR & 0x0000000F) != 0x0000000A); // Besleninceye kadar bekle
RCC->AHB1ENR |= 0x0000000F; // GPIO A,B,C,D clock'u aktif edelim
GPIOD->MODER = 0x55000000; // GPIOD nin 15, 14, 13, 12 pinleri cikis tanimlandi (LEDler icin)
GPIOD->OSPEEDR= 0xFFFFFFFF; // GPIOD nin tum cikislari en yuksek hizda kullanacagiz
RCC->APB2ENR|=0x4000; // SYSCFG Enable
}
void EXTI0_IRQHandler ()
{
EXTI->PR|=0x00000001; // EXTIO INT flagimizi silelim
GPIOD->ODR^=0x00001000;
}
int main()
{
// Butona basinca pinimiz H oluyor
GPIOA->MODER&=~0x00000003; // GPIO pin ancak inp modunda interrupt uretebilir (Rehber 143)
SYSCFG->EXTICR[0]&=~0x0000000F; // GPIO A0 interrupt uretecek
EXTI->RTSR=1; // Yukselen kenar tetiklemesi yapacagiz. (EXTI0)
EXTI->FTSR=0; // Dusen kenar tetiklemesi istemiyoruz. (EXTI0)
EXTI->IMR=1; // EXTI0 Int enable (Rehber 202-203)
EXTI->EMR=0; // Event istemiyoruz
NVIC->ISER[0] = 0x00000040; // NVIC EXTI0_IRQ interrupti acalim
while(1);
}
WAV Dosyasi dinlemek
STM32F4 Discovery kitindeki işlemcimizde iki tane DAC bulunmaktadır. DAC sayesinde sayısal verileri kolayca analog sinyallere dönüştürebiliyoruz. Bu yazımda wav uzantılı dosyaları seslendirmek için örnek program vereceğim. Bu program aynı zamanda DAC kullanımı için de bir örnek teşkil edecektir.
Bilgisayarınızdaki wav uzantılı dosya içeriğini doğrudan kaynak kodlar arasına ekleyeceğiz. Bunun için PC üzerinde koşturulan wav.exe adını verdiğim programdan yararlanacağız. Wav.exe programını çalıştırıp Load butonuna basarak wav dosyasını yükleyin ve ardından Save tuşuna basın. Wav.c adıyla oluşan dosya doğrudan C program içinden kullanılabilecek formattadır. Bu dosyayı (wav.c) aşağıdaki programın bulunduğu proje klasörünüze kopyalayın ve projeyi derleyin.
Kit üzerinde koşacak program derlenirken, wav.exe programının ürettiği wav.c dosyası da derlenmektedir. Kitimizin PA4 pinindeki ses sinyalini, bu pine bağlayacağınız 1uf kapasitör üzerinden alıp doğrudan bilgisayarın ses kartının girişine yada bir amplifikatöre bağlayabilirsiniz.
wav.exe programi icin http://www.cncdesigner.com/STM/wav.rar (http://www.cncdesigner.com/STM/wav.rar)
#include "STM32F4xx.h"
#include "wav.c"
/*****************************************************************************************************
CPU PLL ile 168Mhz de kosturulur
AHB frekansy 168 Mhz
APB1 frekansy 42 Mhz
APB2 frekansy 84 Mhz
*****************************************************************************************************/
void SystemInit()
{
unsigned int i;
(*((int*)0xE000ED88))|=0x0F00000;
for (i=0;i<0x00100000;i++); // OSC oturtma ve kurtarma rutini
RCC->CFGR |= 0x00009400; // AHB ve APB hizlarini max degerlere set edelim
RCC->CR |= 0x00010000; // HSE Xtal osc calismaya baslasin
while (!(RCC->CR & 0x00020000));// Xtal osc stabil hale gelsin
RCC->PLLCFGR = 0x07402A04; // PLL katsayilarini M=4, N=168, P=2 ve Q=7 yapalim
RCC->CR |= 0x01000000; // PLL calismaya baslasin (Rehber Sayfa 95)
while(!(RCC->CR & 0x02000000)); // Pll hazir oluncaya kadar bekle
FLASH->ACR = 0x00000605; // Flash ROM icin 5 Wait state secelim ve ART yi aktif edelim (Rehber Sayfa 55)
RCC->CFGR |= 0x00000002; // Sistem Clk u PLL uzerinden besleyelim
while ((RCC->CFGR & 0x0000000F) != 0x0000000A); // Besleninceye kadar bekle
RCC->AHB1ENR |= 0x0000000F; // GPIO A,B,C,D clock'u aktif edelim
GPIOD->MODER = 0x55550000; // GPIOD nin 15, 14, 13, 12, 11, 10, 9, 8 pinleri cikis tanimlandi (LEDler icin)
GPIOD->OSPEEDR= 0xFFFFFFFF; // GPIOD nin tum cikislari en yuksek hizda kullanacagiz
// DAC1 kullanacagiz
GPIOA->MODER=0xA8000200; // GPIOA4 Analog inp yapildi
RCC->APB1ENR|=1<<29; // Artislik olsun (0x20000000 ile OR yap demek)
DAC->CR=0x00000003; // DAC1 ve Bufferi aktif edelim
// Timer 7 ile calisalim
RCC->APB1ENR|=0x00000020; // Timer7 CLK'u aktif edelim (84 Mhz)
TIM7->CR1=0x0080; // Otomatik Reload
TIM7->PSC =0; // Prescaler cikis frekansimiz 84Mhz
TIM7->ARR =84000000/SampleRate; // Counter, Decimal 1 olunca basa donsun.
TIM7->DIER=0x0001; // Update Int enable
NVIC->ISER[1] = 0X00800000; // NVIC de Timer 7 interrupta izin verelim
TIM7->CR1|=0x0001; // Counter Enable
}
void TIM7_IRQHandler()
{
static int Indx=0;
TIM7->SR=0; // Timer Int Flagini silelim
if (Indx<NumOfData)
{
DAC->DHR12R1=Wav[Indx]<<4;
Indx++;
}
GPIOD->ODR^=0xF000;
}
int main()
{
while(1);
}
Speech Synthesizer
0...999999 aralığındaki sayıları konuşan program. Ses verileri de içerdiğinden dolayı çok uzun olduğundan rar dosyası olarak veriyorum.
http://www.cncdesigner.com/STM/Ses_Sentez.rar (http://www.cncdesigner.com/STM/Ses_Sentez.rar)
Konuşan Tavla Zarları
Program donanımsal Random Jenoratörü ile zar atmakta ve sonuçları konuşarak söylemektedir.Zar atmak için mavi butona basın.
#include "STM32F4xx.h"
char Soyle;
int Sayi, EndAdr, Bekle, Indx;
char Wav[]={ // Bir üstteki Speech Synthesizer programindaki char Wav kısmın aynısıdır.
}
/*****************************************************************************************************
CPU PLL ile 168Mhz de kosturulur
AHB frekansy 168 Mhz
APB1 frekansy 42 Mhz
APB2 frekansy 84 Mhz
*****************************************************************************************************/
void SystemInit()
{
unsigned int i;
(*((int*)0xE000ED88))|=0x0F00000;
for (i=0;i<0x00100000;i++); // OSC oturtma ve kurtarma rutini
RCC->CFGR |= 0x00009400; // AHB ve APB hizlarini max degerlere set edelim
RCC->CR |= 0x00010000; // HSE Xtal osc calismaya baslasin
while (!(RCC->CR & 0x00020000));// Xtal osc stabil hale gelsin
RCC->PLLCFGR = 0x07402A04; // PLL katsayilarini M=4, N=168, P=2 ve Q=7 yapalim
RCC->CR |= 0x01000000; // PLL calismaya baslasin (Rehber Sayfa 95)
while(!(RCC->CR & 0x02000000)); // Pll hazir oluncaya kadar bekle
FLASH->ACR = 0x00000605; // Flash ROM icin 5 Wait state secelim ve ART yi aktif edelim (Rehber Sayfa 55)
RCC->CFGR |= 0x00000002; // Sistem Clk u PLL uzerinden besleyelim
while ((RCC->CFGR & 0x0000000F) != 0x0000000A); // Besleninceye kadar bekle
RCC->AHB1ENR |= 0x0000000F; // GPIO A,B,C,D clock'u aktif edelim
GPIOD->MODER = 0x55550000; // GPIOD nin 15, 14, 13, 12, 11, 10, 9, 8 pinleri cikis tanimlandi (LEDler icin)
GPIOD->OSPEEDR= 0xFFFFFFFF; // GPIOD nin tum cikislari en yuksek hizda kullanacagiz
// DAC1 kullanacagiz
GPIOA->MODER=0xA8000200; // GPIOA4 Analog inp yapildi
RCC->APB1ENR|=1<<29; // Artislik olsun (0x20000000 ile OR yap demek)
DAC->CR=0x00000003; // DAC1 ve Bufferi aktif edelim
// Timer 7 ile calisalim
RCC->APB1ENR|=0x00000020; // Timer7 CLK'u aktif edelim (84 Mhz)
TIM7->CR1=0x0080; // Otomatik Reload
TIM7->PSC =0; // Prescaler cikis frekansimiz 84Mhz
TIM7->ARR =84000000/8000; // Counter, Decimal 1 olunca basa donsun. 8Khz
TIM7->DIER=0x0001; // Update Int enable
NVIC->ISER[1] = 0X00800000; // NVIC de Timer 7 interrupta izin verelim
}
void TIM7_IRQHandler()
{
TIM7->SR=0; // Timer Int Flagini silelim
if (Soyle)
{
DAC->DHR12R1=Wav[Indx]<<4;
Indx++;
if(Indx>EndAdr) Soyle=0;
}
else if(Bekle) Bekle--;
GPIOD->ODR^=0xF000;
}
void NefesAl()
{
Bekle=6000;
}
char ZarAt()
{
int Zar;
Zar=0;
while((!Zar) || (Zar>6))
{
while (!(RNG->SR&1)); // kullanilabilir sayi olusumunu bekle
Zar = RNG->DR &0x0F;
}
return(Zar);
}
void Sound(short N)
{
while(Soyle|Bekle);
switch(N)
{
case 1:{ Indx=4620 ; EndAdr=7279; break;}
case 2:{ Indx=7280 ; EndAdr=10599; break;}
case 3:{ Indx=11120; EndAdr=14999; break;}
case 4:{ Indx=15000; EndAdr=18119; break;}
case 5:{ Indx=18120; EndAdr=24419; break;}
case 6:{ Indx=24420; EndAdr=28399; break;}
}
Soyle=1;
}
int main()
{
int Z1,Z2;
Soyle=0;
Indx=0;
EndAdr=0;
Bekle=0;
TIM7->CR1|=0x0001; // Timer Enable
RCC->AHB2ENR |= 0x40; // RNG modulunun clock'unu aktif edelim
RNG->CR=0x04; // RNG modulu calismaya basladin
while(1)
{
Z1=ZarAt();
Z2=ZarAt();
while(!(GPIOA->IDR&1));
Sound(Z1);
Sound(Z2);
while(GPIOA->IDR&1);
}
}
Kartın eğimiyle orantılı olarak ledleri yakmak
Aşağıdaki programda, kartı elinizle tutup eğdikçe ledler eğilen yonde ışıldıyo.
#include "STM32F4xx.h"
unsigned char PWM[8]; // PWM registerler
unsigned char SRG[8]; // Shadow Registerler
unsigned char CNTR; // PWM Counter
/*****************************************************************************************************
CPU PLL ile 168Mhz de kosturulur
AHB frekansy 168 Mhz
APB1 frekansy 42 Mhz
APB2 frekansy 84 Mhz
*****************************************************************************************************/
void SystemInit()
{
volatile unsigned int i;
(*((int*)0xE000ED88))|=0x0F00000;
for (i=0;i<0x00100000;i++); // OSC oturtma ve kurtarma rutini
RCC->CFGR |= 0x00009400; // AHB ve APB hizlarini max degerlere set edelim
RCC->CR |= 0x00010000; // HSE Xtal osc calismaya baslasin
while (!(RCC->CR & 0x00020000));// Xtal osc stabil hale gelsin
RCC->PLLCFGR = 0x07402A04; // PLL katsayilarini M=4, N=168, P=2 ve Q=7 yapalim
RCC->CR |= 0x01000000; // PLL calismaya baslasin (Rehber Sayfa 95)
while(!(RCC->CR & 0x02000000)); // Pll hazir oluncaya kadar bekle
FLASH->ACR = 0x00000605; // Flash ROM icin 5 Wait state secelim ve ART yi aktif edelim (Rehber Sayfa 55)
RCC->CFGR |= 0x00000002; // Sistem Clk u PLL uzerinden besleyelim
while ((RCC->CFGR & 0x0000000F) != 0x0000000A); // Besleninceye kadar bekle
RCC->AHB1ENR |= 0x0000001F; // GPIO A,B,C,D,E clock'u aktif edelim
GPIOD->MODER = 0x55550000; // GPIOD nin 15, 14, 13, 12, 11, 10, 9, 8 pinleri cikis tanimlandi (LEDler icin)
GPIOD->OSPEEDR= 0xFFFFFFFF; // GPIOD nin tum cikislari en yuksek hizda kullanacagiz
// GPIOA da A7, A6, A5 pinleri, LIS302DL cipiyle haberlesmek icin SPI moduna alinacak
GPIOA->AFR[0]=0x55500000; // SPI1 secelim (Rehber Sayfa 141), Hard Sayfa 49
GPIOA->MODER|=0x0000A800; // A7,A6,A5 Alternatif fonksiyon
RCC->APB2ENR|=0x00001000; // SPI1 clk enable // GPIOE3 pinini output tanimlayalim (LIS302DL SPI/I2C secimi)
GPIOE->MODER = 0x00000040; // GPIOE nin 3 nolu pini cikis tanimlandi
GPIOE->OSPEEDR= 0xFFFFFFFF; // GPIOE nin tum cikislari en yuksek hizda kullanacagiz
GPIOE->BSRRL=0x0008; // GPIOE3=1; LIS302DL CS=1
SPI1->CR1=0x00000B7F; // SPI1 16 bit, master , fulldublex vs
SPI1->CR2=0X0000;
RCC->APB1ENR|=0x00000020; // Timer7 CLK'u aktif edelim (84 Mhz)
TIM7->CR1=0x0080; // Otomatik Reload
TIM7->PSC =839; // Prescaler degerimiz 839, Count frekansimiz = fCK_PSC / (Yuklenen Deger + 1) 84E6 / (840) = 100 KHz
TIM7->ARR =1; // Counter, Decimal 1 olunca basa donsun. Her 20 mikrosaniye de bir timer int olusacak.
TIM7->DIER=0x0001; // Update Int enable
NVIC->ISER[1] = 0X00800000; // NVIC de Timer 7 interrupta izin verelim
TIM7->CR1|=0x0001; // Counter Enable
}
void TIM7_IRQHandler()
{
unsigned short d,i,j;
TIM7->SR=0; // Timer Int Flagini silelim
d=GPIOD->ODR | 0xFF00;
CNTR++;
if(!CNTR)
{
for(i=0;i<8;i++) SRG[i]=PWM[i];
}
j=0x8000;
for(i=0;i<8;i++)
{
if (CNTR>=SRG[i]) d&=~j;
j=j>>1;
}
GPIOD->ODR=d;
}
signed char SPI_CMD(short DAT)
{
signed char RxDat;
GPIOE->BSRRH=0x0008; // LIS302DL CS=0
RxDat=SPI1->SR; // AMAC DELAY (kalmasinda fayda var)
SPI1->DR=DAT; // Komutu yukle
while(!(SPI1->SR&0x01)); // RX BUF bos ise beklemede kal
while(SPI1->SR&0x80); // BSY durumu varsa kalkmasini bekleyelim
RxDat=SPI1->DR; // Cipten gelen veriyi oku
while(SPI1->SR!=0x02); // CS=1 yapmadan once cipin orjinal duruma donmeyi bekleyelim
GPIOE->BSRRL=0x0008; // LIS302DL CS=1
return(RxDat);
}
signed char Write(char Adr,unsigned char Data)
{
return(SPI_CMD(((Adr&0x3F)<<8 )|Data));
}
signed char Read(char Adr)
{
return(SPI_CMD(((Adr&0x3F)|0x80)<<8 ));
}
int main()
{
int i;
signed char x[16]; // PWM registerler
signed char y[16]; // PWM registerler
signed char who,xo,yo, b;
signed short a;
if(Read(0x0F)==0x3B) // Who are you ?
{
Write(0x20,0x47); // Data Rate=100Hz, Full Scale=2g, Activate, x,y,z enable
while(!(Read(0x27)&1)); xo=Read(0x29);
while(!(Read(0x27)&2)); yo=Read(0x2B);
while(1)
{
who=Read(0x27); // Statusu ogrenelim. Kim hazir kim değil?
if (who&1)
{
a=x[0];
b=Read(0x29)-xo;
for(i=15;i>0;i--){ x[i]=x[i-1]; a+=(signed short)x[i];}
x[0]=b; a=a>>2;
if (a>=0) { PWM[0]=a; PWM[2]=0; }
else { PWM[0]=0; PWM[2]=-a;}
}
if (who&2)
{
a=y[0];
b=Read(0x2B)-yo;
for(i=15;i>0;i--){ y[i]=y[i-1]; a+=(signed short)y[i];}
y[0]=b; a=a>>2;
if (a>=0) { PWM[1]=a; PWM[3]=0; }
else { PWM[1]=0; PWM[3]=-a;}
}
}
}
TIM7->DIER=0x0000; // Update Int disable
while(1)
{
for(i=0;i<0x1000000;i++);
GPIOD->ODR^=0x0000F000;
}
}
Programda onemli bir hata vardi (duzeltildi). Bunun icin asagidaki linki muhakkak okuyun.
https://www.picproje.org/index.php/topic,35794.msg269243.html#msg269243 (https://www.picproje.org/index.php/topic,35794.msg269243.html#msg269243)
PA0 ve PB2 pinlerini ext int pini olarak kullanmak
#include "STM32F4xx.h"
// FCPU =168Mhz
// FAHB =FCPU
// FAPB2=FCPU/2
// FAPB1=FCPU/4
void SystemInit()
{
unsigned int i;
(*((int*)0xE000ED88))|=0x0F00000;
for (i=0;i<0x00100000;i++); // OSC oturtma ve kurtarma rutini
RCC->CFGR |= 0x00009400; // AHB ve APB hizlarini max degerlere set edelim
RCC->CR |= 0x00010000; // HSE Xtal osc calismaya baslasin
while (!(RCC->CR & 0x00020000));// Xtal osc stabil hale gelsin
RCC->PLLCFGR = 0x07402A04; // PLL katsayilarini M=4, N=168, P=2 ve Q=7 yapalim
RCC->CR |= 0x01000000; // PLL calismaya baslasin (Rehber Sayfa 95)
while(!(RCC->CR & 0x02000000)); // Pll hazir oluncaya kadar bekle
FLASH->ACR = 0x00000605; // Flash ROM icin 5 Wait state secelim ve ART yi aktif edelim (Rehber Sayfa 55)
RCC->CFGR |= 0x00000002; // Sistem Clk u PLL uzerinden besleyelim
while ((RCC->CFGR & 0x0000000F) != 0x0000000A); // Besleninceye kadar bekle
RCC->AHB1ENR |= 0x0000000F; // GPIO A,B,C,D clock'u aktif edelim
GPIOD->MODER = 0x55000000; // GPIOD nin 15, 14, 13, 12 pinleri cikis tanimlandi (LEDler icin)
GPIOD->OSPEEDR= 0xFFFFFFFF; // GPIOD nin tum cikislari en yuksek hizda kullanacagiz
RCC->APB2ENR|=0x4000; // SYSCFG Enable
}
void EXTI0_IRQHandler () // A0 int
{
EXTI->PR|=1; // INT flagimizi silelim
GPIOD->ODR^=0x00001000;
}
void EXTI2_IRQHandler () // B2 int
{
EXTI->PR|=4; // INT flagimizi silelim
GPIOD->ODR^=0x00002000;
}
int main()
{
GPIOA->MODER&=~0x00000003; // GPIO A0 pin Inp modunda
GPIOB->MODER&=~0x0000003A; // GPIO B2 pin Inp modunda
SYSCFG->EXTICR[0]=0x00000100; // A0 ve B2 intlar acildi
EXTI->RTSR=0x05; // Yukselen kenar tetiklemesi yapacagiz. (EXTI0)
EXTI->FTSR=0; // Dusen kenar tetiklemesi istemiyoruz. (EXTI0)
EXTI->IMR=0x05; // EXTI0 Int enable (Rehber 202-203)
EXTI->EMR=0; // Event istemiyoruz
NVIC->ISER[0] = 0x140; // NVIC EXTI0_IRQ ve EXTI2_IRQ interrupti acalim
while(1);
}