STM32F407 Cortex M4 şamataları

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

ergen

#1050
Alıntı yapılan: muuzoo - 05 Eylül 2012, 23:22:15
İlk atamada sadece ilgili saklayıcıdaki istediğiniz biti değiştirmiş oluyorsunuz. Diyelim ki CR saklayıcısının içeriği : 0x00000011 olsun. Siz ilk kullanımdaki gibi veya operatörü ile atama yaparsanız saklayıcının içeriği : 0x01000011 olacaktır. Fakat ikinci kullanımdaki gibi atama yaparsanız önceki değerler değişecek ve son atadığınız değer olacaktır. Peki neden böyle kullanıyoruz? Eğer ilgili saklayıcının içeriğinin tamamını değil de sadece belli bir kısmını değiştirmek istiyorsak bu şekilde çeşitli operatörler kullanrak atama yaparız. Yok değeri olduğu gibi yazacaksak ikinci şekli kullanırız.
Çok teşekkür ederim oldukça açıklayıcı oldu bunu ben nasıl düşünemedim o ayrı bir konu neyse anlaşılan daha çok çalısmamız lazim :-[

mesaj birleştirme:: 06 Eylül 2012, 15:26:51

#include "STM32F4xx.h"

// FCPU =168Mhz
// FAHB =FCPU
// FAPB2=FCPU/2
// FAPB1=FCPU/4

void SystemInit()
{
unsigned int i;

    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 
    GPIOB->MODER = 0x00000015;      // GPIOB nin 0,1,2 pinleri cikis tanimlandi (LEDler icin)
    GPIOB->OSPEEDR= 0xFFFFFFFF;     // GPIOD nin tum cikislari en yuksek hizda kullanacagiz 
	  RCC->APB2ENR|=0x4000;           // SYSCFG Enable
	  
} 

void EXTI1_IRQHandler ()
{
    EXTI->PR|=0x00000002;           // EXTIO INT flagimizi silelim
	  GPIOB->ODR^=0x00000007; 	
} 


int main()
{
//  Butona basinca pinimiz H oluyor
    GPIOA->MODER &=~0x0000000C;      // GPIO pin ancak inp modunda interrupt uretebilir (Rehber 143)
    //GPIOA->PUPDR &= 0x00000004;
    SYSCFG->EXTICR[0]&=~0x000000F0; // GPIO A1 interrupt uretecek
    EXTI->RTSR=0x00000002;                   // Yukselen kenar tetiklemesi yapacagiz. (EXTI1)
    EXTI->FTSR=0;                   // Dusen kenar tetiklemesi istemiyoruz.  (EXTI1)
    EXTI->IMR=0x00000002;                    // EXTI1 Int enable (Rehber 202-203)
    EXTI->EMR=0;                    // Event istemiyoruz
    NVIC->ISER[0] = 0x00000080;     // NVIC EXTI1_IRQ interrupti acalim
    while(1);      
}


Bülent hocamızın yapmış olduğu kodlardan yararlanarak toggle işlemini kart üzerinden degilde harici olarak bi buton bagladım ve yine harici bagladıgım üç ledi yakıyorum.Fakat bazı problemler var mesela butona ardarda basınca ledler çok kararlı ve hızlı bir şekilde yanıp sönme işlemi yapmıyo bazen bassamda sönmüyo ve yanmıyo parazitle ilgili olabilir ama yükselen kenardan sonra gecikme eklemek istiyorm bunu hangi satıra eklicem onu kestiremedim.yada bunun başka bir çözümü varmı.birde ekledigim butonun girişini dahili direnç ile pull-down yapmak istiyorum            GPIOA->PUPDR &= 0x00000004;  bu satırı ekledim ama olmadı yine kendim direnç baglamak zorunda kaldım.yardımcı olurmusunuz çok ihtiyacım var.

fatih6761

Boştayken 2.5 volt görmeniz normal. Dijital mantıkta bildiğin gibi iki değer var : High ve Low. Giriş olarak belirlenen pinler ise bu iki duruma da eşit uzaklıkta yani (5 - 0) / 2 den 2.5 volt olur. Bu değere lojik Float durumu da denir. 0.4 volt gördüğünüz bacaklarda muhtemelen ya çip içinde özel bir donanıma bağlı, ya da kart üzerinde bir elemana bağlıdır...

ergen

Yukarda yazdığım mesaja cevap veren yokmu arkadaşlar bilen varsa rica ediyorum.

fatih6761

Gecikmenizi EXTI1_IRQHandler metoduna yazacaksınız.
void EXTI1_IRQHandler ()
{
    volatile int i;
    EXTI->PR|=0x00000002;           // EXTIO INT flagimizi silelim
    GPIOB->ODR^=0x00000007; 	
    for(i = 0; i < 0x7FFFF; i++)
        ;
}

muhittin_kaplan

Alıntı Yapprensip olarak
ama neden ?

fatih6761

@gerbay hocam haklısınız interrupt rutinlerini küçük tutmakta fayda var ama bu arkadaşın birşeyleri deneyerke öğrenmesi için faydası olacağını düşündüm. Ona kalırsa while döngüsüyle gecikme yapmakda kötü. SysTick kullanmak ta mümkün. ancak bu iyileştirmelerin hepsi programı daha da karmaşıklaştır. Bırakın da arkadaş bazı şeyleri deneyerek öğrensin :)

muhittin_kaplan

@gerbay
Hocam Aslında cevabını Bildiğim Bir Soruyu Açmanızı İstedim. İnterrupt çok kısa tutulmalı çünki başka bir interrupt gelebilir vs. değilmi ama.

fatih6761

gerbay hocam bahsi geçen rtos larda nesne kilitleme ( lock ) mekanizması var mı? Yani paralel işlemle beraber paralel olay işleme?

ergen

gerbay hocam çok teşekkürler en kısa zamanda araştırma yapıp bu kodları eklicem..birde ekledigim butonun girişini dahili direnç ile pull-down yapmak istiyorum            GPIOA->PUPDR &= 0x00000004;  bu satırı ekledim debug yaparken bu satırda register a yazma yapmıyo neden böyle bişey olabilir.

fatih6761

Yazma yapmıyor değil. &= 4 sadece 3.bite AND işlemi uygular. Ayrıca buton girişi zaten donanımsal olarak PullDown'dır. Satır içi Bit-Set/Reset şöyle yapılır:
(REGISTER) |= (1 << BIT); // Set
(REGISTER) &= ~(1 << BIT); // Reset
// Örnek
GPIOA->PUPDR |= (1 << 1); // GPIOA.0 (Buton) Pull Down

fatih6761

Yok hocam Mutex'i kasdetmiyorum. Mesela anlattığınız gibi farklı metodlarda ortak kullanılan nesnelerin "gölge kopya mantığıyla" bir örneğinin iki farklı yerde bulundurulması ve değişme olduğunda nesnenin iki farklı örneğine yazılması. Veya aynı anda nesnelerin aynı anda hem okunup hem yazılması. Bu mekanizmayı bir işletim sistemi projesinde görmüştüm diye hatırlıyorum. Anlattığınız RTOS larda da benzeri mekanizma var mıdır?

fatih6761

Hmm anladım hocam. Şu an hatırlamadığım Unix türevi değişik bir sistemde görmüştüm. Demekki söylediğiniz gibi ekstradan yazılmış bir özellik.  Teşekkür ederim...

ergen

#include "STM32F4xx.h"

// FCPU =168Mhz
// FAHB =FCPU
// FAPB2=FCPU/2
// FAPB1=FCPU/4

void SystemInit()
{
unsigned int i;

    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 
    GPIOB->MODER = 0x00000015;      // GPIOB nin 0,1,2 pinleri cikis tanimlandi (LEDler icin)
    GPIOB->OSPEEDR= 0xFFFFFFFF;     // GPIOD nin tum cikislari en yuksek hizda kullanacagiz 
    RCC->APB2ENR|=0x4000;           // SYSCFG Enable
    GPIOA->PUPDR |= 0x00000008;
} 

static volatile int binarySemaphore1 = 0;
static volatile int countingSemaphore1 = 0;

interruptHandler1()
{
  binarySemaphore1 = 1;
}

interruptHandler2()
{
  countingSemaphore1++;
}

void EXTI1_IRQHandler ()
{
    EXTI->PR|=0x00000002;           // EXTI1 INT flagimizi silelim
    GPIOB->ODR^=0x00000007; 
} 

void Delay()
{
    unsigned int i;
    for(i=0;i<0x800000;i++);
}


int main()
{
	
	
	
//  Butona basinca pinimiz H oluyor
    GPIOA->MODER &=~0x0000000C;      // GPIO pin ancak inp modunda interrupt uretebilir (Rehber 143)
	  
    SYSCFG->EXTICR[0]&=~0x000000F0; // GPIO A1 interrupt uretecek
	  //Delay();  
    EXTI->RTSR=0x00000002;          // Yukselen kenar tetiklemesi yapacagiz. (EXTI1)
    EXTI->FTSR=0;                   // Dusen kenar tetiklemesi istemiyoruz.  (EXTI1)
    EXTI->IMR=0x00000002;           // EXTI1 Int enable (Rehber 202-203)
    EXTI->EMR=0;                    // Event istemiyoruz
    NVIC->ISER[0] = 0x00000080;     // NVIC EXTI1_IRQ interrupti acalim
	  
   while(1)
   {
    if (1 == binarySemaphore1)
    {
      binarySemaphore1 = 0;
      int1_DoWork();
    }
    if (countingSemaphore1 > 0)
    {
      countingSemaphore1--;
      int2_DoWork();
    }
   }
	  
    	
}

Gerbay hocam yukardaki gibi kodları ekledim ama (main.c(81): warning:  #223-D: function "int2_DoWork" declared implicitly) şeklinde bir hata veriyor.fonksiyonumu bulamıyo acaba.bu kodlar interrupt ile mi çalışıyor yani bunları interrupt rutini olarak mı eklicem.yazılım kısmını biraz daha açıklama imkanınız varmı.

fatih6761

Gerbay hocam, bu sıkıntılar arkadaşların C yi iyi bilmemesinden kaynaklanıyor. Projelere girişmeden önce en azından bir yere kadar C öğrenseler, bu sıkıntıları yaşamayacaklar. Yani Implicit Declaration'ın ne olduğunu bilmeden program yazmak yerine kitaplardan veya internetten biraz daha C öğrenrek, temel örnekleri uygulayarak kendilerini geliştirseler... Haksız mıyım hocam? Arkadaşlar bu arada yanlış anlamayın tavsiye amacıyla söylüyorum...

cooldoubtless

fatih hocam ben çok da iyi olmasa da c bildiğimi ZANNEDİYORDUM. ancak bu söylediğiniz implict declararation kalıbıyla nedemek istediğinizi anlamadım..eğer bahsettiğiniz şey daha önce tanımlanmamış fonksiyon ile program karşılaştığında verdiği hata iletisi ise biliyorum ancak ayrı bir anlamı ya da "declaration" ifadesi var ise bilmiyorum..eğer bundan bahseden bir c kaynağı var ise hemen okumak isterim mümkünse link paylaşır mısınız?