STM32F407 Cortex M4 şamataları

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

pcb

arkadaşlar benim anlamadığım en başta mesela
GPIOD->MODER = 0x55000000;     // GPIOD nin 15, 14, 13, 12 pinleri cikis tanimlandi

0x55000000 bu hex i anlamadım , nasıl oluşturuluyor ? nasıl ayarlanıyor ? kısaca açıklarmısınız ?

-Hasan-

#781


Rehber Sayfa 148

GPIOD->MODER = 0x55000000;

Dediğimiz zaman bu registerin en yüskek değerlikli byte 01010101 olur. Bu durumda GPIOD ' nin son 4 pini için General Purpouse Output Mode seçilmiş olur. Yani bir pini yönlendirmek için 2 bit kullanılıyor:

01010101

GPIOD 15. Pin
GPIOD 14. Pin
GPIOD 13. Pin
GPIOD 12. Pin

pcb

#782
rehber i indirdim , anladım teşekkür ederim

z

Alıntı yapılan: -Hasan- - 18 Ocak 2012, 08:50:56
Yani hocam Timer2 ' nin Autoreload yapması için ilk başta bir kere taşana kadar sayması mı gerekiyor?

Görünen durum bu. Daha önceki örneklerde timerlar 16 bit oldukları için taşması kısa zaman alıyordu.
Ancak örnek olarak verdiğim programlar fazla düşünülmeden yazılmış programlar. Dokumanlara tekrardan gözatıp reload şartlarına bir daha bakmak lazım.

Şu anki çözümüm iş görse de açıkcası hiç beğenmedim.
Bana e^st de diyebilirsiniz.   www.cncdesigner.com

-Hasan-

Alıntı yapılan: JKramer - 18 Ocak 2012, 09:04:36
TIMx->CR1 deki ARPE bit'ini 0 yaparsanız, yüklediğiniz değer bir sonraki update'i beklemeden doğrudan shadow register'a yüklenir.

Hocam bu şekilde yapınca oluyor. Siz o biti hep 1 yapmışsınız. O bitin görevi nedir tam anlayamadım?

Bit 7 ARPE: Auto-reload preload enable
0: TIMx_ARR register is not buffered
1: TIMx_ARR register is buffered


NVIC->ISER[1]=0x00800000;


Bir de hocam Rehber ' de bu registeri bulamadım. Ben mi göremiyorum acaba?

Alıntı yapılan: bunalmisŞu anki çözümüm iş görse de açıkcası hiç beğenmedim.

Estağfurullah hocam. Buradaki çoğu kişi (ben de dahil) sizin sayenizde ARM ' a başlangıç yaptı. Size ne kadar teşekkür etsek azdır. O incelikleri de yaptıkça görüyoruz işte.

z

Denemedim ama evet mantıklı. Gölge register deselerdi anlamak daha kolay olurdu.
Bana e^st de diyebilirsiniz.   www.cncdesigner.com

JKramer

Auto Reload Register iki parçadan oluşuyor; biri bizim okuyup yazdığımız Preload (önyükleme) register, diğeri Shadow (gölge) register. Timer taştığı zaman önceden yüklenmiş değeri almak için Auto Reload Register'ın Shadow kısmına bakıyor.

ARPE bit'i 0 olduğunda preload register'ına yüklediğimiz değer doğrudan shadow register'a kopyalanıyor.
ARPE bit'i 1 olduğunda ise preload register'ına yüklenmiş değer, sadece bir "update event" (UEV) oluştuğunda shadow register'a kopyalanıyor.

UEV, üç farklı şekilde oluşabilir:

1- Sayaçların taşma durumunda
2- Yazılımsal olarak (TIMx->EGR'deki Update Generation _UG_ bit'i set edildiğinde)
3- Diğer timer'lardan ya da harici (?) kaynaklardan tetiklenme durumunda

ARPE bit'inin 1 olduğu durumda Auto Reload Register içindeki shadow register'ı güncellemek için UG bit'ini set etmeniz yeterli.

CLR

#787
Alıntı yapılan: -Hasan- - 18 Ocak 2012, 12:40:35
Hocam bu şekilde yapınca oluyor. Siz o biti hep 1 yapmışsınız. O bitin görevi nedir tam anlayamadım?

Bit 7 ARPE: Auto-reload preload enable
0: TIMx_ARR register is not buffered
1: TIMx_ARR register is buffered


NVIC->ISER[1]=0x00800000;


Bir de hocam Rehber ' de bu registeri bulamadım. Ben mi göremiyorum acaba?

Estağfurullah hocam. Buradaki çoğu kişi (ben de dahil) sizin sayenizde ARM ' a başlangıç yaptı. Size ne kadar teşekkür etsek azdır. O incelikleri de yaptıkça görüyoruz işte.

UG'yi timer'ı ayarladıktan sonra set etmezseniz, ilk timer süreniz değişir.
Ve eğer timer interrupt kullanacaksanız, doğrudan timer interrupta gidersiniz.

ISER registeri için diyorsan, o register arm cortex m3 programming manual içinde. Systemtick, interrupt registerleri daha doğrusu core ile ilgili registerler.

STM'de yukarıda karşılaştığınız durama benzer şeyler var, bitanesini söylüyeyim mesela i2c modülünü registerleri ayarladıktan sonra enable yaparsanız(modul enable, clk enable değil) i2c modulünü çalıştıramıya bilirsiniz veya dengesiz çalışır.


Knowledge and Experience are Power

mcan

Tanımlayabileceğimiz maximum char dizisi kaç elemanlı olabilir? Ben kullandığım işlemcinin ram kapasitesinden daha büyük diziler tanımladığımda bana herhangi bir hata vermiyor  ve programı çalıştırdığımda çakılıyor. Sanırım exeption olayından biri gerçekleşiyor .Debuggerım yok. Hafıza sınırlamalarını hangi kaynakdan okurum? Birde keilin kullandığım mcu nun ram*rom sınırlarını aştığımda bana uyarı vermesini nasıl sağlarım.

muhittin_kaplan

/**
  ******************************************************************************
  * @file    TIM_PWM_Input/main.c 
  * @author  MCD Application Team
  * @version V1.0.0
  * @date    19-September-2011
  * @brief   Main program body
  ******************************************************************************
  * @attention
  *
  * THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS
  * WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE
  * TIME. AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY
  * DIRECT, INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING
  * FROM THE CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE
  * CODING INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS.
  *
  * <h2><center>&copy; COPYRIGHT 2011 STMicroelectronics</center></h2>
  ******************************************************************************
  */ 

/* Includes ------------------------------------------------------------------*/
#include "stm32f4_discovery.h"

/** @addtogroup STM32F4_Discovery_Peripheral_Examples
  * @{
  */

/** @addtogroup TIM_PWM_Input
  * @{
  */ 

/* Private typedef -----------------------------------------------------------*/
/* Private define ------------------------------------------------------------*/
/* Private macro -------------------------------------------------------------*/
/* Private variables ---------------------------------------------------------*/
TIM_ICInitTypeDef  TIM_ICInitStructure;

/* Private function prototypes -----------------------------------------------*/
void TIM_Config(void);

/* Private functions ---------------------------------------------------------*/

/**
  * @brief  Main program
  * @param  None
  * @retval None
  */
int main(void)
{
  /*!< At this stage the microcontroller clock setting is already configured, 
       this is done through SystemInit() function which is called from startup
       file (startup_stm32f4xx.s) before to branch to application main.
       To reconfigure the default setting of SystemInit() function, refer to
       system_stm32f4xx.c file
     */
       
  /* TIM Configuration */
  TIM_Config();

  /* TIM4 configuration: PWM Input mode ------------------------
     The external signal is connected to TIM4 CH2 pin (PB.07), 
     The Rising edge is used as active edge,
     The TIM4 CCR2 is used to compute the frequency value 
     The TIM4 CCR1 is used to compute the duty cycle value
  ------------------------------------------------------------ */

  TIM_ICInitStructure.TIM_Channel = TIM_Channel_2;
  TIM_ICInitStructure.TIM_ICPolarity = TIM_ICPolarity_Rising;
  TIM_ICInitStructure.TIM_ICSelection = TIM_ICSelection_DirectTI;
  TIM_ICInitStructure.TIM_ICPrescaler = TIM_ICPSC_DIV1;
  TIM_ICInitStructure.TIM_ICFilter = 0x0;

  TIM_PWMIConfig(TIM4, &TIM_ICInitStructure);

  /* Select the TIM4 Input Trigger: TI2FP2 */
  TIM_SelectInputTrigger(TIM4, TIM_TS_TI2FP2);

  /* Select the slave Mode: Reset Mode */
  TIM_SelectSlaveMode(TIM4, TIM_SlaveMode_Reset);
  TIM_SelectMasterSlaveMode(TIM4,TIM_MasterSlaveMode_Enable);

  /* TIM enable counter */
  TIM_Cmd(TIM4, ENABLE);

  /* Enable the CC2 Interrupt Request */
  TIM_ITConfig(TIM4, TIM_IT_CC2, ENABLE);

  while (1);
 
}

/**
  * @brief  Configure the TIM4 Pins.
  * @param  None
  * @retval None
  */
void TIM_Config(void)
{
  GPIO_InitTypeDef GPIO_InitStructure;
  NVIC_InitTypeDef NVIC_InitStructure;

  /* TIM4 clock enable */
  RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM4, ENABLE); //RCC->APB1ENR|=0x00000004

  /* GPIOB clock enable */
  RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB, ENABLE);//RCC->AHB1ENR|=0x00000002
  
  /* TIM4 chennel2 configuration : PB.07 */
  GPIO_InitStructure.GPIO_Pin   = GPIO_Pin_7;
  GPIO_InitStructure.GPIO_Mode  = GPIO_Mode_AF;//GPIO->MODER&=0xFFFFBFFF
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;//GPIOB->OSPEEDR=0xFFFFFFFF
  GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;//
  GPIO_InitStructure.GPIO_PuPd  = GPIO_PuPd_UP ;//GPIO->OTYPER=0x00000000
  GPIO_Init(GPIOB, &GPIO_InitStructure);
  
  /* Connect TIM pin to AF2 */
  GPIO_PinAFConfig(GPIOB, GPIO_PinSource7, GPIO_AF_TIM4);

  /* Enable the TIM4 global Interrupt */
  NVIC_InitStructure.NVIC_IRQChannel = TIM4_IRQn;//NVIC->ISER[0] = 0X40000000;
  NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
  NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
  NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
  NVIC_Init(&NVIC_InitStructure);

}

#ifdef  USE_FULL_ASSERT

/**
  * @brief  Reports the name of the source file and the source line number
  *         where the assert_param error has occurred.
  * @param  file: pointer to the source file name
  * @param  line: assert_param error line source number
  * @retval None
  */
void assert_failed(uint8_t* file, uint32_t line)
{
  /* User can add his own implementation to report the file name and line number,
     ex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */

  while (1)
  {}
}
#endif

/**
  * @}
  */ 

/**
  * @}
  */ 

/******************* (C) COPYRIGHT 2011 STMicroelectronics *****END OF FILE****/


Hocam PWM input la ilgili bir Example varmış. Bir kütüphane kullanaak yapılmış. Tabiki anlamadım. Arayıp Bulduğum yerleri Açıklama şeklinde yazdım.  Ama Yardıma İhtiyacım Var. PWM INPUT örneğini Register kodlaması yaparak yazabilirmiyiz?

fatihinanc

Alıntı yapılan: mcan - 18 Ocak 2012, 21:14:10
Tanımlayabileceğimiz maximum char dizisi kaç elemanlı olabilir? Ben kullandığım işlemcinin ram kapasitesinden daha büyük diziler tanımladığımda bana herhangi bir hata vermiyor  ve programı çalıştırdığımda çakılıyor. Sanırım exeption olayından biri gerçekleşiyor .Debuggerım yok. Hafıza sınırlamalarını hangi kaynakdan okurum? Birde keilin kullandığım mcu nun ram*rom sınırlarını aştığımda bana uyarı vermesini nasıl sağlarım.

STM32F4 Discovery üzerindeki ST Link tarafından debug yapabilirsiniz.

Bu arada derleyici o tanımladığını dizi için ancak kullanıldığı zaman derlemede yer ayırıyor. Yoksa oraları zaten boş diye derlemeye almıyor.
Eğer kod içerisinde dinamik olarak kullanırsanız o zaman muhtemelen hata/uyarı mesajı alırsınız. Diğer türlü sabit olarak tanımlarsanız yani ana program içerisinde dizi değişkenlerine atama yapmazsanız o zaman da static olarak derleme esnasında flasha gömülüyor değerler. Ve bu sebepten dolayı da yine RAM de yer tutmuyor.
Kainat dediğimiz kitap, yazıldığı dil ve harfler öğrenilmedikçe anlaşılamaz.  (Galileo Galilei)

Klein

#791
Alıntı yapılan: muhittin_kaplan - 18 Ocak 2012, 23:17:40
Hocam PWM input la ilgili bir Example varmış. Bir kütüphane kullanaak yapılmış. Tabiki anlamadım. Arayıp Bulduğum yerleri Açıklama şeklinde yazdım.  Ama Yardıma İhtiyacım Var. PWM INPUT örneğini Register kodlaması yaparak yazabilirmiyiz?

Yapılabilir. Aslında biraz örnekleri incelesen sen de yapabilirsin.
Geçtiğimiz günlerde (sanırım sizin sorunuzdu) Rehber 378 sayfadaki PWM Inpud mode için verdiği direktifleri türkçe olarak anlatmıştım.

O direktiflerde yazanları uygulaman, timer frekans ayarları için @bunalmıs hocamın örneklerinden TIMER 7 yi incelemen ve Port alternatif fonksiyonların tanımı için yazddığım header dosyasını incelemen yeterli.

senin için bu söylediklerimi kullanarak bir örnek yazdım. PWM input mode için rehberde söylenenleri aynen yaptım. Şu registere şu değeri yaz, buna bu değeri yaz gibi doğrudan değerler vermiş. Timer  saat kaynağı ayarları için TIM7 örneğinden bir bölüm aldım. gerisini de header dosyadan

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

// Bu kısım PA 15 portunu TIM2 ile ilişkilendiren Alternatif fonksiyon tanımlama
	 PA->MODER.pin.p15 = PORT_ALTERNATE_FUNC; // Port alternatif fonksiyon
	 PA->PUPDR.pin.p15 = PORT_PULL_UP; // Port PULL_UP direncini aç
	 PA->AFR.pin.p15 = PORT_AF1_TIM2; // Portu TIM2 ile ilişkilendir.

// Bu kısım interrupt aktif etme ve sayıcıyı başlatma
	 NVIC_EnableIRQ(TIM2_IRQn); //Timer 2 interrupt aktif et;
	 TIM2->CR1 |= 0x0001; // sayıcıyı başlat. 

// Bu kısım TIM2 interrupt rutini
// unsigned short ccr1,ccr2;
void TIM2_IRQHandler(){
	ccp_update=1;
	ccr1=TIM2->CCR1;
	ccr2=TIM2->CCR2;
TIM2->SR=0;    
}

// bu kısım da ana döngü içinde çalışan, CCR registerlerinden aldığım değerleri seri porttan gönderdiğim bölüm. Seri port örneklerde var.
	  	if(ccp_update ){
			ccp_update=0;
			sprintf(TxBuf,"CC1= %u\rCC2= %u\r",ccr1,ccr2);
			SendTxt(TxBuf);
		}

// CC2 duty değerini gösteriyor.
// CC1 hep 0 alıyorum. öyle mi olmalı? yoksa bir hata mı var bilmiyorum. Yarın incelerim.


PA 15'e ~13.3Hz civarında %80 civarı duty değeri olan PWM veriyorum.
TIM2 ön bölücü olarak 4200 verdik. CLK frekansımız 84MHz. sayıcımız saniyede 20000 sayıyor.
Frekansımız 13.3 duty %80.  Yaklaşık duty süremiz 60mS.  Duty süresince sayıcımızın sayması gereken değer 20000*0.06 =1200;
CC2 değerim 1200. Yani doğru okuyor.

Test edebilmen için  aşağıda  timer ile yazılımsal PWM üretmek için yazdığım deneme kodlarını veriyorum
// Başlatma kodları. PWM çıkışımız PB_5
	 PB->MODER.pin.p5 = PORT_OUTPUT;
	 PB->OSPEEDR.pin.p5 = PORT_FAST_SPEED;
	 PB->OTYPER.pin.p5 = PORT_PUSH_PULL;
	 RCC->APB1ENR|=0x00000008;       // Timer5 CLK'u aktif edelim (84 Mhz)
	 TIM5->PSC = 4199;
	 TIM5->ARR = 2;
	 TIM5->DIER = 0x0001;
	 NVIC_EnableIRQ(TIM5_IRQn); //Timer 5 interrupt aktif et;
	 TIM5->CR1 |= 0x0001; // sayıcıyı başlat. 


// interrupt handler 
void TIM5_IRQHandler(){
	 if(++ pwm_counter > pwm_duty){
	 	pwm_counter=0;
		if(!pwm_out){
			pwm_duty=800;
		} else pwm_duty=200;
		pwm_out =!pwm_out;
	 }
	 
	PB->ODR.pin.p5 = pwm_out;	
TIM5->SR=0;    		
}



Ekleme:
Bu aletin capture modülünün hayranı oldum. İnanılmaz stabil okuyor. En küçük bir oynama yok. Bunda darbeyi de aynı işlemciden vermiş olmamın da etkisi olabilir tabi. Ama yine de beğendim.


mcan

Alıntı yapılan: fatihinanc - 18 Ocak 2012, 23:46:46
STM32F4 Discovery üzerindeki ST Link tarafından debug yapabilirsiniz.

Bu arada derleyici o tanımladığını dizi için ancak kullanıldığı zaman derlemede yer ayırıyor. Yoksa oraları zaten boş diye derlemeye almıyor.
Eğer kod içerisinde dinamik olarak kullanırsanız o zaman muhtemelen hata/uyarı mesajı alırsınız. Diğer türlü sabit olarak tanımlarsanız yani ana program içerisinde dizi değişkenlerine atama yapmazsanız o zaman da static olarak derleme esnasında flasha gömülüyor değerler. Ve bu sebepten dolayı da yine RAM de yer tutmuyor.
Ben kullanıyorum, kullandığım zaman da göçüyor o noktaya kadar program normal işliyor o noktadan sonra göçüyor.Bende şu anda c4 yok c3 ile çalışıyorum zorunlu olarak o sebeple debugger da yok sadece uart ıle programı atabiliyorum.

CLR

Alıntı yapılan: mcan - 18 Ocak 2012, 21:14:10
Tanımlayabileceğimiz maximum char dizisi kaç elemanlı olabilir? Ben kullandığım işlemcinin ram kapasitesinden daha büyük diziler tanımladığımda bana herhangi bir hata vermiyor  ve programı çalıştırdığımda çakılıyor. Sanırım exeption olayından biri gerçekleşiyor .Debuggerım yok. Hafıza sınırlamalarını hangi kaynakdan okurum? Birde keilin kullandığım mcu nun ram*rom sınırlarını aştığımda bana uyarı vermesini nasıl sağlarım.

Dizide index boyutunu yazıyor musun? Mesela aşağıdaki gibi. Kullandığın işlemcinin hafızası kadar sınırın varsa okadar denebilir veya tanımlayabilecek variable kadar. Fakat programın büyüktür ve global değişkenlerin çoktur bunları hafıza sayısından düşmen gerekir ve tabii ektradan derleyicininde yaz boz yapacağı ram kadar bırakman gerekir yoksa arm'ı pic gibi hafızadan hafızaya data taşımak zorunda bırakırsın.
(piclerde bank işlemi)

char MyArray[20000];

   
Knowledge and Experience are Power

NecroCapo

ADC registerlarının ayarlanması ile ilgili bir örnek var mı acaba ? Konfigrasyon aşamasında hangi sıra ile gitmeliyiz ? En basitinden, tek bir adc çevrimi için hangi registerlar set edilmeli ?

Tüm pinlerde analog giriş işlemi yapılabiliyor mu? Yoksa piclerde olduğu gibi sadece bazı pinler mi bu iş için tahsis edilmiş? MODER registerlarındaki ilgili pinler "11: Analog mode" değerine set edildiğinde ADC işlevini gerçekleştiriyorsa, bu tüm pinlerin ADC için kullanılabileceğini mi belirtiyor ?

Yazmaya başladığım kod şu şekilde, fakat son kısmında takıldım:

  GPIOC->MODER |= 0x03;                      // C0 pini Analog ("11") olarak ayarlandı
  RCC->APB2ENR |= (1<<8);                  // ADC1 için clock sinyali aktif

  ADC1->SQR1    = 0x00000000;           // 1 çevrim yapılacak
  ADC1->SQR2    = 0x00000000;              
  ADC1->SQR3    =   ???              ;          // Burada 1.sıradaki çevrim için 4 bitlik SQ1[4:0] alanına ne yazmam gerekiyor ? 1. çevrim için kullanacağımız pini mi yazacağız ? Eğer öyleyse C0 pinini nasıl yazacağım ?


Bir de adc konusundaki registerlarda , aynı registerların "injected" olanları var. Injected tam olarak ne anlama geliyor ?