Haberler:

Foruma Resim Yükleme ve Boyut Sınırlaması ( ! )  https://bit.ly/2GMFb8H

Ana Menü

input capture

Başlatan muhittin_kaplan, 16 Eylül 2013, 18:26:23

mistek

Alıntı yapılan: muhittin_kaplan - 17 Eylül 2013, 14:12:33
akşam usarttan basacağım değerleri. bakalım ne olacak.
(debug modda timer lar duruyor mu breakpoint koyunca ?)

Hocam debug modda Run yapınca Timerlar çalışıyor kesme gelince breakpoint noktasına geliyor. Eğer adım adım işletirseniz timerlar duruyor.
boş işlerin adamı ---- OHM Kanunu: I = V/R ---- Güç Formülü: P = V*I = I^2*R = V^2/R

muhittin_kaplan

Adım Adım Çalıştığında timer da değerine göre artış oluyor yani.

muhittin_kaplan

#17
GPIOC 8  ile toogle yapıyorum. Bu çıkışı kullanıp GPIOA 1 e giriyorum.

ve sadece düşen kenarda void TIM2_IRQHandler(void) fonksiyonuna giriyor.

#include "stm32f10x.h"

 TIM_ICInitTypeDef  TIM_ICInitStructure;

/* Private function prototypes -----------------------------------------------*/
void RCC_Configuration(void);
void GPIO_Configuration(void);
void SetupNVIC(void);
void SetupPWM_Input(void);
/* Private functions ---------------------------------------------------------*/


int IC2Value = 0;
int IC1Value = 0;
int DutyCycle = 0;
int Frequency = 0;




void TIM2_IRQHandler(void)
{

  TIM_ClearITPendingBit(TIM2, TIM_IT_CC2);


  IC2Value = TIM_GetCapture2(TIM2); //CCR2

  if (IC2Value != 0)
  {
    /* Duty cycle computation */
	  IC1Value=TIM_GetCapture1(TIM2);
    DutyCycle = (IC1Value * 100) / IC2Value;

    /* Frequency computation */
    Frequency = SystemCoreClock / IC2Value;
  }
  else
  {
    DutyCycle = 0;
    Frequency = 0;
  }
}

void SetupPWM_Input(void)
{
  /* TIM2 configuration: PWM Input mode ------------------------
     The external signal is connected to TIM2 CH2 pin (PA.01),
     The Rising edge is used as active edge,
     The TIM2 CCR2 is used to compute the frequency value
     The TIM2 CCR1 is used to compute the duty cycle value
  ------------------------------------------------------------ */

 //he TIMxCLK frequency is set to 3.6 MHz, the Prescaler is 20 so the TIM2 counter
 //clock is 3.6 MHz.  3600M/65535=55Hz The minmum value can be measured is 55Hz,the max is
   TIM_PrescalerConfig(TIM2, 9, TIM_PSCReloadMode_Immediate);   //TIM2CLK/£¨20£©=3.6MHz


  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 = 0x03;

  TIM_PWMIConfig(TIM2, &TIM_ICInitStructure);

  TIM_PrescalerConfig(TIM2, 19, TIM_PSCReloadMode_Immediate);   //TIM2CLK/£¨20£©=3.6MHz

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

  /* Select the slave Mode: Reset Mode */
  TIM_SelectSlaveMode(TIM2, TIM_SlaveMode_Reset);

  /* Enable the Master/Slave Mode */
  TIM_SelectMasterSlaveMode(TIM2, TIM_MasterSlaveMode_Enable);



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

    /* TIM enable counter */
   TIM_Cmd(TIM2, ENABLE);
}


int main(void)
{

  SystemInit();
  RCC_Configuration();
  SetupPWM_Input();
  SetupNVIC();
  GPIO_Configuration();


  while (1){
	  int z;
	  GPIO_SetBits(GPIOC,GPIO_Pin_8);

	  GPIO_ResetBits(GPIOC,GPIO_Pin_8);
  }
}


void RCC_Configuration(void)
{
  /* TIM3 clock enable */
  RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);

  /* GPIOA clock enable */
  RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
  RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC, ENABLE);
}


void GPIO_Configuration(void)
{
  GPIO_InitTypeDef GPIO_InitStructure;

  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;

  GPIO_Init(GPIOA, &GPIO_InitStructure);

  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;

    GPIO_Init(GPIOC, &GPIO_InitStructure);



}


void SetupNVIC(void)
 {
  NVIC_InitTypeDef NVIC_InitStructure;

#ifdef  VECT_TAB_RAM
  /* Set the Vector Table base location at 0x20000000 */
  NVIC_SetVectorTable(NVIC_VectTab_RAM, 0x0);
#else  /* VECT_TAB_FLASH  */
  /* Set the Vector Table base location at 0x08000000 */
  NVIC_SetVectorTable(NVIC_VectTab_FLASH, 0x0);
#endif

  /* Enable the TIM2 global Interrupt */
  NVIC_InitStructure.NVIC_IRQChannel = TIM2_IRQn;
  NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
  NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
  NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
  NVIC_Init(&NVIC_InitStructure);


 }


mesaj birleştirme:: 18 Eylül 2013, 00:26:53

buda kendi örneği, yine PC8 de toggle yaptım sadece yükselen kenarda giriyor. Bir Deneyip Sonucu Bana Bildiren olursa sevineceğim.

#include "stm32f10x.h"

/** @addtogroup STM32F10x_StdPeriph_Examples
  * @{
  */

/** @addtogroup TIM_PWM_Input
  * @{
  */

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

/* Private function prototypes -----------------------------------------------*/
void RCC_Configuration(void);
void GPIO_Configuration(void);
void NVIC_Configuration(void);

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

__IO uint16_t IC2Value = 0;
__IO uint16_t DutyCycle = 0;
__IO uint32_t Frequency = 0;


void TIM3_IRQHandler(void)
{
  /* Clear TIM3 Capture compare interrupt pending bit */
  TIM_ClearITPendingBit(TIM3, TIM_IT_CC2);

  /* Get the Input Capture value */
  IC2Value = TIM_GetCapture2(TIM3);

  if (IC2Value != 0)
  {
    /* Duty cycle computation */
    DutyCycle = (TIM_GetCapture1(TIM3) * 100) / IC2Value;

    /* Frequency computation */
    Frequency = SystemCoreClock / IC2Value;
  }
  else
  {
    DutyCycle = 0;
    Frequency = 0;
  }
}





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_stm32f10x_xx.s) before to branch to application main.
       To reconfigure the default setting of SystemInit() function, refer to
       system_stm32f10x.c file
     */
	SystemInit();
  /* System Clocks Configuration */
  RCC_Configuration();

  /* NVIC configuration */
  NVIC_Configuration();

  /* Configure the GPIO ports */
  GPIO_Configuration();

  /* TIM3 configuration: PWM Input mode ------------------------
     The external signal is connected to TIM3 CH2 pin (PA.01),
     The Rising edge is used as active edge,
     The TIM3 CCR2 is used to compute the frequency value
     The TIM3 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(TIM3, &TIM_ICInitStructure);

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

  /* Select the slave Mode: Reset Mode */
  TIM_SelectSlaveMode(TIM3, TIM_SlaveMode_Reset);

  /* Enable the Master/Slave Mode */
  TIM_SelectMasterSlaveMode(TIM3, TIM_MasterSlaveMode_Enable);

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

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

  while (1){
	  GPIO_ResetBits(GPIOC,GPIO_Pin_8);
	  GPIO_SetBits(GPIOC,GPIO_Pin_8);
  }
}

/**
  * @brief  Configures the different system clocks.
  * @param  None
  * @retval None
  */
void RCC_Configuration(void)
{
  /* TIM3 clock enable */
  RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE);

  /* GPIOA clock enable */
  RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
  RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC, ENABLE);

}

/**
  * @brief  Configure the GPIO Pins.
  * @param  None
  * @retval None
  */
void GPIO_Configuration(void)
{
  GPIO_InitTypeDef GPIO_InitStructure;

  /* TIM3 channel 2 pin (PA.07) configuration */
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_7;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;

  GPIO_Init(GPIOA, &GPIO_InitStructure);

  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;

    GPIO_Init(GPIOC, &GPIO_InitStructure);
}

/**
  * @brief  Configure the nested vectored interrupt controller.
  * @param  None
  * @retval None
  */
void NVIC_Configuration(void)
{
  NVIC_InitTypeDef NVIC_InitStructure;

  /* Enable the TIM3 global Interrupt */
  NVIC_InitStructure.NVIC_IRQChannel = TIM3_IRQn;
  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****/

muhittin_kaplan

#18
Acaba hala hata mı  yapıyorum dedim. ve int rutinin içerisine PC 9 u togge yapacak bir satır ekledim. yani her int girdiğinde PC 9 durum değiştirecekti. PC 8 dende toggle eden basit iki satr yazdım. aşağıdaki şeklde kanal 1 PC8, kanal 2 PC 9 yani int rutini içerisinde durum değiştiren pin.



mesaj birleştirme:: 18 Eylül 2013, 00:59:06

Hep Yükselen Kenarda Durum değiştiriyor.
Peki Bu Adamlar Nasıl Ölçüm Yapmış PWM in Duty i ile Frekansını ?

(Hala Acaba Ben mi hata Yapıyorum Bir Yerde Atladığım bir yermi var diyorum.)

mesaj birleştirme:: 18 Eylül 2013, 01:09:03

şu fonksiyon ilginç

void TIM_PWMIConfig(TIM_TypeDef* TIMx, TIM_ICInitTypeDef* TIM_ICInitStruct)
{
  uint16_t icoppositepolarity = TIM_ICPolarity_Rising;
  uint16_t icoppositeselection = TIM_ICSelection_DirectTI;
  /* Check the parameters */
  assert_param(IS_TIM_LIST6_PERIPH(TIMx));
  /* Select the Opposite Input Polarity */
  if (TIM_ICInitStruct->TIM_ICPolarity == TIM_ICPolarity_Rising)
  {
    icoppositepolarity = TIM_ICPolarity_Falling;
  }
  else
  {
    icoppositepolarity = TIM_ICPolarity_Rising;
  }
  /* Select the Opposite Input */
  if (TIM_ICInitStruct->TIM_ICSelection == TIM_ICSelection_DirectTI)
  {
    icoppositeselection = TIM_ICSelection_IndirectTI;
  }
  else
  {
    icoppositeselection = TIM_ICSelection_DirectTI;
  }
  if (TIM_ICInitStruct->TIM_Channel == TIM_Channel_1)
  {
    /* TI1 Configuration */
    TI1_Config(TIMx, TIM_ICInitStruct->TIM_ICPolarity, TIM_ICInitStruct->TIM_ICSelection,
               TIM_ICInitStruct->TIM_ICFilter);
    /* Set the Input Capture Prescaler value */
    TIM_SetIC1Prescaler(TIMx, TIM_ICInitStruct->TIM_ICPrescaler);
    /* TI2 Configuration */
    TI2_Config(TIMx, icoppositepolarity, icoppositeselection, TIM_ICInitStruct->TIM_ICFilter);
    /* Set the Input Capture Prescaler value */
    TIM_SetIC2Prescaler(TIMx, TIM_ICInitStruct->TIM_ICPrescaler);
  }
  else
  { 
    /* TI2 Configuration */
    TI2_Config(TIMx, TIM_ICInitStruct->TIM_ICPolarity, TIM_ICInitStruct->TIM_ICSelection,
               TIM_ICInitStruct->TIM_ICFilter);
    /* Set the Input Capture Prescaler value */
    TIM_SetIC2Prescaler(TIMx, TIM_ICInitStruct->TIM_ICPrescaler);
    /* TI1 Configuration */
    TI1_Config(TIMx, icoppositepolarity, icoppositeselection, TIM_ICInitStruct->TIM_ICFilter);
    /* Set the Input Capture Prescaler value */
    TIM_SetIC1Prescaler(TIMx, TIM_ICInitStruct->TIM_ICPrescaler);
  }
}

parametrelerin opositini alıyor ve TI2_Config e gönderiyor.

muhittin_kaplan

herhangi bir sinyalin 1 de kalma süresini ölçmek istiyorum, çok mu :'(
bunun için hem1 hem 0 a giden kenarların yakalanması gerekmez mi.

neden sadece
TIM_ITConfig(TIM2, TIM_IT_CC2, ENABLE);
yapmışta
TIM_ITConfig(TIM2, TIM_IT_CC1, ENABLE);
i eklememiş.
(biri yükselen diğeri düşen kenar için)

JKramer

Belirlediğiniz kenarda capture olduğunda, ilgili register sayıcı değerini donanımsal olarak alıyor; kesmede yazılımsal yapılan bir şey yok. Biz, giriş sinyalinin bir periyodu tamamlandığında register'larda yakalanan capture değerlerini kullanıp frekans ve duty değerini hesaplamak için kesmeye gidiyoruz.

muhittin_kaplan


JKramer

Düşen kenarda kesmeye girmesinin bir anlamı yok, daha periyot tamamlanmadı.

muhittin_kaplan

ama duty tamamlandı. Duty yi nereden anlıyorsunuz ?

JKramer

Düşen kenarda register, sayıcıdan o anki değeri alıyor çünkü CCR1'e bağlı IC1 düşen kenar tetiklemeli. Birkaç mesaj yukarıda "parametrelerin opositini alıyor ve TI2_Config e gönderiyor." demişsiniz ama aslında T1'e gönderiyor çünkü InitStructure'da ayarları yaparken şöyle yazmışsınız: "TIM_ICInitStructure.TIM_Channel = TIM_Channel_2;"

yldzelektronik

Belki ihtiyaç vardır.Microchipin app notu.Güzel döküman;

http://s3.dosya.tc/server10/IkUyHY/41214a.pdf.html
Kişinin başına gelen hayır Allah'tandır. Kişinin başına gelen şer nefsindendir. Nefislerimizle kendimize zulüm ediyoruz.

muhittin_kaplan


yldzelektronik

Alıntı yapılan: muhittin_kaplan - 18 Eylül 2013, 13:17:46
Hocam Ürün STM

Abi farkındayım da duty ölçümünde frekans ölçümünde metodda yardımı olur diye düşündüm.
Kişinin başına gelen hayır Allah'tandır. Kişinin başına gelen şer nefsindendir. Nefislerimizle kendimize zulüm ediyoruz.

muhittin_kaplan

@yldzelektronik
Sağol Hocam.

@jkramer
Hocam Konuyu , eğer siizn için problem olmayacaksa örnekle açıklayabilirmisiniz

JKramer

[IMG]http://i.imgur.com/7RkRjeQ.png[/img]

Bu resimde TI1, sinyali bağladığınız pin'dir. IC1'den sonrası CCR1 register'ına gidiyor.

Dikkat ederseniz IC1 yazan bölüm, yapacağımız seçime göre TI1FP1'e, TI2FP1'e ya da TRC'ye bağlanabiliyor. (IC1 CCR1'e bağlı) Yani CCR1 register'ının sayaçtan hangi girişle (TI1FP1, TI2FP1, TRC)  hangi olayla (düşen kenar, yükselen kenar) mevcut değeri alacağını (capture edeceğini) seçebiliyoruz. Aynı şey IC2'nin bağlı olduğu CCR2 register'ı için de geçerli.

[IMG]http://i.imgur.com/dGIzbftl.png[/img]

Yukarıdaki resimde yazanları sırayla inceleyelim. Dediği gibi örnek olarak TI1'e PWM uygulansın. Bu durumda CCR1'den periyotu, CCR2'de duty'i alalım.

Sinyali TI1'e uyguladığımız için periyot ve duty değerini alacağımız CCR1 ve CCR2'yi TI1'e bağlamamız lazım.

İlk resime bakarsak; CCR1, IC1'e bağlı. IC1'i TI1FP1'e bağlamak için CCMR1'deki CC1S'e  01 yazmamız gerekiyor (eğer sinyal TI2'den gelseydi, register'a 10 yazarak IC1'i TI2FP1'e bağlamamız gerekecekti). Resimde sola doğru gitmeye devam edelim, sırada polarite seçimi var. Timing diagram'da görüldüğü gibi bununla duty'nin polariteleri ters olmak zorunda. Bu yüzden eğer bunu yükselen kenar tetiklemeli seçersek diğerini düşen kenar tetiklemeli seçmek zorundayız. Diagram'da olduğu gibi yükselen kenar seçtikten sonra bununla işimiz bitti.

Duty'e geçelim. CCR2, IC2'ye bağlı. Bu arkadaşı TI1FP2'e bağlamak için CCMR1'deki CC2S'e 10 yazmamız gerekiyor. Polaritesi de düşen kenar olmalı. TI1FP1 ve TI1FP2 konusunu daha iyi anlayabilmek için STM8 ref. manual'dan aldığım resime bakabilirsiniz:

[IMG]http://i.imgur.com/CLvKXXfl.png[/img]

Sanırım yukarıdaki resim, TI1FP2'nin IC2'ye nasıl bağlandığı konusunda açıklayıcı olmuştur.

Tüm bu bağlantılarla birlikte CCER register'ından capture'ları enable ettikten sonra; sinyalin yükselen kenarı gelmişse CCR1 register'ı sayacın o andaki değerini alacak, düşen kenarı gelmişse CCR2 register'ı sayacın o andaki değerini alacaktır. Yani bu "capture" işlemlerinin, CC1 ya da CC2 kesmesinin açık-kapalı olmasıyla bir ilgisi yok. Zaten bir olay olduğunda (burada düşen kenar-yükselen kenar, USART'da rx kesmesi, vb.) ilgili kesme kapalı dahi olsa bayrağı set ediliyor, öyle değil mi? Burada periyot değerinin saklandığı register CCR1 olduğundan sadece buna bağlı CC1 kesmesini açıyoruz ki periyot ve duty değerlerinin hazır olduğunu bilelim.