STM32F407 Cortex M4 şamataları

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

Pir-O

Ben ADC için bir örnek yaptım. Biraz da alıntı yaptım bunalmıs hocanın kodlarından. Program ADC'yi interrupt ile okuyor okuduğu bilgiyi usart3 modülünden gönderiyor. Program denendi çalışıyor.  PA0 pininden okuma yapılıyor.

#include <stm32f4xx.h>

unsigned int i,x,en,an;


void SystemInit(void)
{
        // Burası alıntıdır.
	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   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 
	

}

void USART3_IRQHandler()
{
        //Burası Alıntıdır.
	volatile int Sts;
	Sts=USART3->SR;
	//RxBuf[WAdr]=USART3->DR;
	x=USART3->DR;
	
}

void ADC_IRQHandler (void)
{
	volatile int Sts;
	Sts=ADC2->SR;
	an=ADC2->DR;
	en=1;
} 

void UsartInit()
{
    
// Burası alıntıdır.
// 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) 
{
      // Burası alıntıdır.
      while(!(USART3->SR&0x80));  // TX Buffer dolu ise bekle (Rehber Sayfa 646)
      USART3->DR=Tx;
}
 
void SendTxt(char *Adr)
{
     //Burası alıntıdır.
      while(*Adr) 
        {
          SendChar(*Adr);
          Adr++;
        }  
}
  

void AdcInit(void)
{
	unsigned long i;
	RCC->APB2ENR |= 0x00000700;		// ADC Clock aktif.
	RCC->APB2RSTR |=0x00000100;		// ADC Resetlendi.
	GPIOA->MODER |=0x00000003;		// PA0 Analog olarak ayarlandı.
	RCC->APB2RSTR &=~0x00000100;
	ADC2->CR2 |=0x00000003; 			// ADC Aktif edildi, Continuous mod seçildi.
	for(i=0;i<0x1000000;i++);                      // Biraz Beklemek Gerekiyor.
	ADC2->CR1 |= 0X00000020;			// 12 Bitlik çevirim yapılacak ve interrupt aktif.
	NVIC->ISER[0]|=0x00040000;			// ADC interrupt aktif ediliyor.
	ADC2->CR2 |= 0x40000000;			// ADC Çevirimi başlatıldı.
	
	
	
}

void SendInt (unsigned long sayi)
{
	unsigned char dizi[10];
	unsigned char i,durum=0;
	for(i=0;i<=9;i++)dizi[i]=0;
	if(sayi==0){
		SendChar('0');	
		
	}
	else{
		
		dizi[0]=sayi/1000000000;
			sayi-=dizi[0]*1000000000;
	   	dizi[1]=sayi/100000000;
			sayi-=dizi[1]*100000000;
		dizi[2]=sayi/10000000;
			sayi-=dizi[2]*10000000;
		dizi[3]=sayi/1000000;
			sayi-=dizi[3]*1000000;
		dizi[4]=sayi/100000;
			sayi-=dizi[4]*100000;
		dizi[5]=sayi/10000;
			sayi-=dizi[5]*10000;
		dizi[6]=sayi/1000;
			sayi-=dizi[6]*1000;
		dizi[7]=sayi/100;
			sayi-=dizi[7]*100;
		dizi[8]=sayi/10;
			sayi-=dizi[8]*10;
		dizi[9]=sayi%10;
		for(i=0;i<=9;i++)
		{
		
			if(dizi[i]!=0)
			{
				durum=1;	
			}
			if(durum==1){
				switch (dizi[i]){
					case 0:
						SendChar(48);
						break;
					case 1:
						SendChar(49);
						break;
					case 2:
						SendChar(50);
						break;
					case 3:
						SendChar(51);
						break;
					case 4:
						SendChar(52);
						break;
					case 5:
						SendChar(53);
						break;
					case 6:
						SendChar(53);
						break;
					case 7:
						SendChar(55);
						break;
					case 8:
						SendChar(56);
						break;
					case 9:
						SendChar(57);
						break;
					default:
						break;
		
					}
			 }
		}
		
	}
}

int main(void)
{
	
	UsartInit(); 
	AdcInit();
	SendTxt("Deneme");
	SendChar(' ');  
	
	         
	
	while(1){
	
		
		if(en==1){
			SendInt(an);
			SendChar(' ');
			SendChar(' ');
			SendChar(' ');
			SendChar(' ');
			en=0;
		}
	
	} 



}

pcb

ekrana yazdırma dışında bana yetebilecek örnekler oluştu neredeyse
peki arkadaşlar kendi kartımızı hazırladığımızda bu programları nasıl gönderebiliriz işlemciye ?
Mikroişlemci gibi bir yükleyici yok bildiğim kadarı ile , karta yükleme devresini de ilave etmemiz mi gerekiyor ?

-Hasan-

Dahili bootloaderleri kullanılarak LPC ' lerdeki gibi seri porttan yüklenebilir.

z

Alıntı yapılan: pcb - 20 Ocak 2012, 13:57:24
ekrana yazdırma dışında bana yetebilecek örnekler oluştu neredeyse
peki arkadaşlar kendi kartımızı hazırladığımızda bu programları nasıl gönderebiliriz işlemciye ?
Mikroişlemci gibi bir yükleyici yok bildiğim kadarı ile , karta yükleme devresini de ilave etmemiz mi gerekiyor ?

Discovery kartımız üzerinde programlama ünitesi mevcut. Kendi yaptığın kartın SWD pinlerine bağlayacağın kabloları Discovery kartının SWD pinlerine bağladığında program atarsın. Yapacağın tek şey Discovery kartında jumper pozisyonlarını değiştirmek.

Bu jumperlar SWD ünitesini ya senin kartdaki CPUya yada Discovery üzerindeki CPUya ilişkilendiriyor.


Bana e^st de diyebilirsiniz.   www.cncdesigner.com

muhittin_kaplan

örnek olması açısından
Nvic de
OTG_HS int açmak için komutun ne olması gerekir ?
NVIC->????????=?????

NaMcHo

Alıntı yapılan: muhittin_kaplan - 21 Ocak 2012, 15:39:58
örnek olması açısından
Nvic de
OTG_HS int açmak için komutun ne olması gerekir ?
NVIC->????????=?????
NVIC->ISER[2]=(1<<13)

muhittin_kaplan

Alıntı Yap
// Bu kısım Timer 7 den çekilen kopya.
     RCC->APB1ENR|=0x00000001;       // Timer2 CLK'u aktif edelim (84 Mhz)
     TIM2->PSC = 4199;
     TIM2->ARR = 2000;
     TIM2->DIER = 0x0001;
bu değerlere göre timer 2 kesme zamanı nedir ?

EMG81

Cortex M4 için NVIC dökümanına ihtiyacım var. Elinde olan, gören , duyan paylaşabilirmi ?

Klein


EMG81

#819
Tamam. Buraya bende baktım, baktım ama döküman içerisinde "NVIC->ISER[1]|= 0x80; // NVIC da USART3 interrupta izin verelim" bunun açıklamasını bulamadım. Veya NVIC->ISER[1] = 0X00800000; // NVIC de Timer 7 interrupta izin verelim bunun. Yada NVIC->ISER[0] = 0x00000040; // NVIC EXTI0_IRQ interrupti acalim bunun




z

Herhangi bir ARM CM3 cipin NVIC dokumanina bakin.
Bana e^st de diyebilirsiniz.   www.cncdesigner.com

muhittin_kaplan


Klein

"core_cm4.h" dosyasını incelemekte fayda var. 
Interrupt Enable bitleri ISER registerlerinde bulunuyor. Bunlardaki her bit bir tane kesmeyi açıyor ya da kapatıyor.
ISER registerleri 32 bitlik 8 elemandan oluşan bir array. 8x32 =256 toplamda 256 tane interrupt kontrol edilebilir.
"core_cm4.h" içerisinde tanımlılar. typedef struct
{
  __IO uint32_t ISER[8];                 /*!< Offset: 0x000 (R/W)  Interrupt Set Enable Register           */
...
}

NVIC->ISER[0] |=0x00000001 dediğimizde  İlk interrupt'a izin vermiş oluyoruz.

Peki bu ilk interrupt hangisi. Bu sanıyorum çipin üreticisine göre değişiyor. Bu yüzden Cortex-M dokümanlarında bulunmuyor. Belki üreticiler arasında bir standartlaşma vardır. Onu bilmiyorum.
Bizim çipimiz STM32F4XX olduğu için  kaçıncı kesmenin ne olduğunu bulmak için  Rehber:196'ya bakıyoruz.

Tablonun en solundaki sayı bizim kesmemizin bu array içindeki yerini gösteriyor.
ISER[0]'ın 0. biti WWDG (Window Watch Dog) kesmesiymiş.

Diyelim ki TIMER7 kesmesini arıyoruz. Rehber:196.. dan bakıyoruz.  Pozisyonumuz 55. yani 55. bitteyiz. Gerisi bit hesabı.

Bit hesabını bilmeyenler , elinde bit sayan hesap makinası yoksa basitçe yeri şöyle bulabilir.
55. bit  ISER'in neresinde? ISER registerlerimiz 32 bit.  55/32 = 1.71...  tam kısım 1 yani ISER[1] deymişiz.

Ama ben bit hesabı yapmak istemiyorum derseniz ,  "core_cm4.h" size kolaylıklar sunmuş.

NVIC_EnableIRQ(TIM7_IRQn);
NVIC_DisableIRQ(TIM7_IRQn);

muhittin_kaplan

#823
hocam yukarda bir XLS dosya yaptım NVIC için. Hata yoktur diye umut ediyorum
Ve soruma geçiyorum

RCC->APB1ENR|=0x00000002;       // Timer3 CLK'u aktif edelim (84 Mhz)
    TIM3->PSC = 4199;
    TIM3->ARR = 2000;
    TIM3->DIER = 0x0001;

// Bu kısım Rehberde verilen talimatlar
     TIM3->CCMR1 |= 0x0002; //CCR 1 için Giriş kaynağı TI2 seçildi
     TIM3->CCER &= ~0x000A;	 // TI1FP1 için polarite seçimi. evirilmemiş / yükselen kenar
     TIM3->CCMR1 |= 0x0200; //CCR 2 için Giriş kaynağı TI1 seçildi
     TIM3->CCER |= 0x0020;	 // TI1FP2 için polarite seçimi. evirilmiş / düşen kenar
     TIM3->SMCR |= 0x0050; // geçerli tetikleme kaynağı TI1FP1
     TIM3->SMCR |= 0x0004; // Slave mode = reset Yükselen kenarda sayıcıyı sıfırla ve değeri güncelle.
     TIM3->CCER |= 0x0011; // CC1 ve CC2 aaktif.

// Bu kısım PA 15 portunu TIM5 ile ilişkilendiren Alternatif fonksiyon tanımlama
     GPIOC->MODER  &=0xFFFF2FFF;//	 
     GPIOC->PUPDR |=0x00001000; // Port PULL_UP direncini aç	  
         GPIOC->AFR[0]|=0x02000000; // PC6 Portu TIM3 ile ilişkilendir.

// Bu kısım interrupt aktif etme ve sayıcıyı başlatma
     NVIC->ISER[0]|=0x20000000; //Timer 0 interrupt aktif et;NVIC->ISER[0]|=0x10000000
     TIM3->CR1 |= 0x0001; // sayıcıyı başlat. 

}

void TIM3_IRQHandler()
{
    ccp_update=1;
    ccr3_1=TIM3->CCR1;
	
    ccr3_2=TIM3->CCR2;
	SendChar(ccr3_2+0x2D); //deger A dan başlaması için bu işlem yapıldı
	
TIM3->SR=0;    
}


PWM girişi olarak PC6 da hatam nerede ki çalışmıyor (CCR2 de hiç değer yok)


--      GPIOC->AFR[0]|=0x02000000; // PC6 Portu TIM3 ile ilişkilendir.-- Olarak değiştirilde Hala Çalışmıyor

EMG81

Alıntı yapılan: Klein - 22 Ocak 2012, 21:26:04
"core_cm4.h" dosyasını incelemekte fayda var. 
Interrupt Enable bitleri ISER registerlerinde bulunuyor. Bunlardaki her bit bir tane kesmeyi açıyor ya da kapatıyor.
ISER registerleri 32 bitlik 8 elemandan oluşan bir array. 8x32 =256 toplamda 256 tane interrupt kontrol edilebilir.
"core_cm4.h" içerisinde tanımlılar. typedef struct
{
  __IO uint32_t ISER[8];                 /*!< Offset: 0x000 (R/W)  Interrupt Set Enable Register           */
...
}

NVIC->ISER[0] |=0x00000001 dediğimizde  İlk interrupt'a izin vermiş oluyoruz.

Peki bu ilk interrupt hangisi. Bu sanıyorum çipin üreticisine göre değişiyor. Bu yüzden Cortex-M dokümanlarında bulunmuyor. Belki üreticiler arasında bir standartlaşma vardır. Onu bilmiyorum.
Bizim çipimiz STM32F4XX olduğu için  kaçıncı kesmenin ne olduğunu bulmak için  Rehber:196'ya bakıyoruz.

Tablonun en solundaki sayı bizim kesmemizin bu array içindeki yerini gösteriyor.
ISER[0]'ın 0. biti WWDG (Window Watch Dog) kesmesiymiş.

Diyelim ki TIMER7 kesmesini arıyoruz. Rehber:196.. dan bakıyoruz.  Pozisyonumuz 55. yani 55. bitteyiz. Gerisi bit hesabı.

Bit hesabını bilmeyenler , elinde bit sayan hesap makinası yoksa basitçe yeri şöyle bulabilir.
55. bit  ISER'in neresinde? ISER registerlerimiz 32 bit.  55/32 = 1.71...  tam kısım 1 yani ISER[1] deymişiz.

Ama ben bit hesabı yapmak istemiyorum derseniz ,  "core_cm4.h" size kolaylıklar sunmuş.

NVIC_EnableIRQ(TIM7_IRQn);
NVIC_DisableIRQ(TIM7_IRQn);

Dökümandan bile iyi bir anlatım olmuş. Kafamdaki tüm soru işaretleri kalktı. Teşekkür ederim.  ::)