STM32F407 Cortex M4 şamataları

Başlatan bunalmis, 16 Ekim 2011, 17:14:50

muhittin_kaplan

Alıntı yapılan: Enginar - 02 Ekim 2012, 02:10:07
Peki programda kodlarımızı yazarken bildiğim kadarıyla belli bi mantık sırasına veya düzene göre yazıyoruz . Bazı kodların yerini değiştirdiğimiz taktirde programımız çalışmıyo veya eksik çalışıyo :'( Kodlarımızı hangi mantığa veya düzene göre Nasıl yazmalıyız ?  Bu konuda bilgisi olan arkadaşların yardımlarını bekliyorum :)
Enginar bunu başka bir başlık açarak orada konuşsak daha iyi olacak. cortex m leride şişirmemiş oluruz.

MC_Skywalker

#1096
Alıntı yapılan: Enginar - 02 Ekim 2012, 12:05:27
Sanırım sorumu yanlış aktardım.

Şöyle sorayım Mesela SystemInt içindeki kodların yerlerini , sırasını değiştirdiğimizde kodlarımız neden çalışmıyo? Bunu neye göre tayin edeceğiz ?


SystemInt fonksiyonu MCU içindeki işlemcimizin ilk çalıştırma paremetrtelerini yüklemek için. Normal şartlarda biz kendi main.c içine SystemInt ile ilgili herhangi bir tanımlama yapmadığımızada bu tanımlamalar MCU ya özel proje anında eklenen startupxxxxx.s dosyasından gelir.

ARM CORTEX-M3 MCU lar ilk çalışmaya başladığında dahili içi RC osilatör ile çalışmaya başlar. Daha sonra ya startupxxxxx.s tanımlamalardan yada bizim main.c dosyamınız ilk kısmına yazdığımız kodlar vasıtası ile ve main fonksiyonu içinde bunu aktif ettiğimizde RC/Xtal/RTC ile çalışır ve iç PLL beslenip hangi frekansta koşacağı ayarlanır.

startupxxxxx.s dosyası genellikle mcu fizksel olark üreten firma tarafından hazırlanır ve OSC, NVIC vb. tanımlamalar bu dosyadadır. KEIL bunları uVison içine ekler.


Forumuzda ki örneklerde bulunan SystemInt kodlarına biraz daha yakından bakalım.

Bizim örneklerimizde sadece MCU çalışma frekansı ile ilgili tanımlamalar var. bunları belirli bir sırada işletilmesi gerekmektedir.

ilk adım PLL besleyecek saat darbesi üretcini seçmek RC/XTAL/RTC

RC = Chip üreticisi tarafından MCU içine kuonulan Direnç ve Kondasatörden oluşan saat darbesi üreteci
XTAL = XTAL pinlerine bağlanan harici XTAL tabanlı saat darbesi üreteci
RTC = MCU içindeki Gerçek zaman saati devresi besleyen RTCXTAL pinlerine bağlanan harici XTAL tabanlı saat darbesi üreteci

ikinci adım seçilen kaynağın PLL e bağlanması
üçüncü adım PLL çarpanının belirlenmesi
dördüncü adım PLL çıkışının Cortex-M çekirdeğine yönlendirilmesi.

Aşağıda NXP firmasının ürettiği LPC1768 işlemcisi için kullandığım OSC ayar rutinlerini içiren koda parçası bulunmakta. her satıra tek tek açıklama yazmaya çalıştım.

void SyatemInt(void)
{
    LPC_SC->SCS=0x20;				                //System Control and Status R/W 0 0x400F C1A0 5. bit 1 yapılıp xtal osc (main) aktif ediliyor
						                                //OSCRANGE 4.bit  0 ise 1Mhz ile 2Mhz arası 1 ise 15Mhz ile 25Mhz arası    
						                                //OSCEN 5.bit	0 ise devredışı 1 ise xtal uçlarına bağlı kristali kullanır
							                        //OSCSTAT 6.bit	0 ise osilatör hazır değil 1 ise osilatör hazır (sadece okunur)
    LPC_SC->CLKSRCSEL=0x01;				//select main oscilator	CLKSRCSEL 2 bit uzunluğunda
							                        //00 iç RC kaynağı osilatör olarak seçilmiş
							                        //01 ana osilatörü PLL0 için kaynak seç							  
							                        //10 iç RTC (gerçek zaman saati) osilatör olarak seç
							                        //11 bu durum kullanımaz rezerve edilmiş bir değerdir.
    LPC_SC->CCLKCFG=0x03;				        //pllclk/4
    LPC_SC->PLL0CON=0x01;				        //pll activeted
    LPC_SC->PLL0CFG=0x20031; 			        //msel=49,nsel=2;
    LPC_SC->PLL0FEED=0xAA;				        //pll i beslemek için yazılmalı datasheet te belirtiyor
    LPC_SC->PLL0FEED=0x55;				        //önce 0xAA sonra 0x55 yüklenir
    while(!(LPC_SC->PLL0STAT&(1<<26)));
    LPC_SC->PLL0CON=0x07;
    LPC_SC->PLL0FEED=0xAA;			               //pll i beslemek için yazılmalı datasheet te belirtiyor
    LPC_SC->PLL0FEED=0x55;				      //önce 0xAA sonra 0x55 yüklenir
    LPC_SC->PCLKSEL0=0;
}

muhittin_kaplan

zaman gecikmesi rutinlerini nasıl yapıyorsunuz ?

for ile kurduğumuz bir rutin, her bir artım için 3asm komutu işletiyor.
(Yanlış hatırlıyor olabilirim ARM da her asm komutunun işlem saykılı aynı değildi sanırım)
zaman hesaplamasını nasıl yapıyorsunuz ? Yada Debug esnasında Keilde görebiliyormuyuz ?

Enginar

Arkadaşlar USART_BRR registerinde baud hızını nasıl ayarlıyoruz ? Dıv mantissa ve Dıv fraction gibi terimler var tam anlayamadım. Bilen arkadaşların yardımlarını bekliyorum :)

alisoy

STMF4 de FLASH erişme wait statini neden 5 waitstate seciyoruz. Bu işlemcinin komut işleme suresini  yavaslatıyor. Daha kucuk secersek ne olur ? 

Klein

Alıntı yapılan: Enginar - 12 Ekim 2012, 23:55:26
Arkadaşlar USART_BRR registerinde baud hızını nasıl ayarlıyoruz ? Dıv mantissa ve Dıv fraction gibi terimler var tam anlayamadım. Bilen arkadaşların yardımlarını bekliyorum :)

Genellikle baud registerleri tamsayı olduğu için ne yaparsak yapalım istediğimiz hızı tam tutturamayız. Bunun için bazen kristal değiştirmek bile gerekebilir.  İşte o zaman şu bölücü register tam sayı olmasaydı ondalık sayılar da kullanabilseydik deriz. İşte fraction tam bu işe yarıyor.

Örneğin:
Fck = 8MHz.
ihtiyacımız olan baud hızı 9600.

Baud hızı = fck/(16xbölücü değeri) (oversampling =0 iken)

bölücüyü 52 yaparsak  baud hızımız 9615 olur.
bölücüyü 53 yaparsak baud hızımız  9433 olur. 

Tam hızı yakalamak için bölücümüzün 52.083333 olması gerek. Bunu sağlamak için fraction registerinden yararlanıyoruz.

Peki 52.08333 değerini nasıl yakalayacağız?
fraction registeri 4 bit. yani noktadan sonraki hanemiz en fazla 16 değer alabilir.

şimdi hesaplayalım.
mantissa = 52

fraction = 0.0833333 * 16 = 1.33333  en yakın tam sayı değer 1.

mantissa 52 fraction 1 olduğuna göre  bölücü değerimiz 52.1

şimdi baud hızımızı tekrar hesaplayalım

baud = fck/(16*div) = 8000000/(16*52.1) = 9596.9

Görüldüğü gibi tam sayı register ile çalışırken  istediğimiz baud ile gerçek baud arasındaki fark 15 iken  fraction kullandığımızda fark 3.1 oldu.   





fatih6761

@alisoy, rehber dökümanı incelersen orada bir tablo var. 168 MHz de minimum WaitState 5 olabilir. Frekansı düşürürseniz bu değeri arttırmanız mümkün...

EMP_Otto

#1102
@ Klein
hocam çok sağolun ben elazığdayım.Sorunumu hallettim.Ama bu kezde  error:Flash download failed -'Cortex M4 ' hatası veriyo :(
Sorunumun çözümü burada   -------------    https://www.picproje.org/index.php/topic,42626.0.html ---------
startup_stm32f4xx.s dosyasını değiştirdim oldu :)
Tekrar başladım çalışmalara.Herşey için çok tesekkür ederim .Sagolunnn...

hocam tüm sorunlarımı hallettim.
error:Flash download failed -'Cortex M4 '   hatası için Utilities bölümünden Use Target Driver Flash programming ---settings den  Add deyip  STM32F4xx Flash    ekledim.Sorun düzeldi.


HErkese kolay gelsin :)
Bu işler zordur,özveri ister...

muhittin_kaplan


EMG81

Muthittin visual tft görsel olarak daha düzgün sonuçlar veriyor. Tek sorun keil, iar gibi derleyiciler için çıktı vermiyor. Mikroe compiler ı kullanman gerekir.

muhittin_kaplan

Hocam geçen ay lcd aldım basit uygulamalarla başlayacağım. sonrasında seçim aşamasında bunları öğrenmemiz gerekecek..

Enginar

Arkadaşlar SPI uygulamasında anlamadığım noktaları sizinle paylaşmak istiyorum ve yardımlarınızı bekliyorum :)

1-)GPIOE->BSRR registeri hangi amaç için kullanılıyo ?

2-) Readchar rutininde SPI1->DR=((Adr&0x3F)|0x80)<<8;    ve  Wrintechar rutininde SPI1->DR=((Adr&0x3F)<< 8) |Data; kodlarının görevleri nelerdir ?


Klein

#1107
BSRR registeri  bit set ve bit reset registeridir. Portlar üzerinde bit işlem yapmak için kullanılır.  Alt 16 bit set  üst 16 bit resettir.
BSSR nin 0. bitini set edersen ilgili portun 0. pini  set edilir.  Aynı şekilde 16. bitini set edersen porton 0. pini resetlenir.

SPI DR registeri hem spi aygıtına yazacağımız hem de oradan okuyacağımız bilginin bulunduğu register. Bu registere veri yazdığımız anda bilgi karşı taraftaki aygıta yazılmaya başlar.
Daha önce başka bir arkadaş sormuştu.
https://www.picproje.org/index.php/topic,35794.975.html

Aslında kod karışık değil. Ama bunu anlamak için biraz SPI haberleşme yapısını bilmen gerek.
Bu örnekte 16Bit haberleşme kullanılıyor.
üst 8 bit  hangi adresten okuma veya yazam yapacağımız bilgisini alt 8 bit de veriyi tutuyor.

SPI1->DR=((Adr&0x3F)|0x80)<<8; 
Burada olan şu   Okuma yapmak istediğimiz adresi 0x3F ile and  işlemine sokuyoruz ki son 2 bitte 1 değeri varsa bu değerleri 0 yapalım ve kalan 6 bitin değeri ile oynamayalım.  Sonra bunu 0x80 sayısı ile veyalıyoruz. Yani en son biti 1 yapıyoruz. Bu bit1 olunca karşı taraf okuma yapmak istediğimizi anlıyor.  Sonra  elde ettiğimiz bu sayıyı 8 bit sola kaydırıyoruz. Çünkü adres ve oku-yaz bitleri üst 8 bitlik kısımda olacak , karşı taraf da bu bilgiyi alınca alt 8 biti göndereceği sayı ile dolduracak.

SPI1->DR=((Adr&0x3F)<<8 |Data;
Burada da yine aynı şeyi yapıyoruz.   Yazmak istediğimiz adres ile 0x3F sayısını  ve yapıyoruz. Ancak burada 0x80 ile orlama yapmıyoruz. çünkü okuma değil yazma yapacağız. Bunları 8 bit  sola kaydırıyoruz.  Sonra da yazmak istediğimiz veri ile veyalayıp veriyialt 8 bite yerleştiriyoruz.

Enginar

#1108
Heh anladım şimdi hocam Teşekkür ederim :)

muhittin_kaplan

Herhangi bir STM32 serisi işlemcinin SystemInit Rutinini Nasıl Hazırlanır?