STM32F4 Discovery ile rotary encoder pulse sayma | YARDIM

Başlatan OrkUn®, 08 Temmuz 2012, 14:52:40

OrkUn®

Herkese kolay gelsin. STM32F4 kartı ile encoder uygulaması yapmak istedim fakat Sayıcıda taşma oldugunda interrupt oluşmuyor daha doğrusu interrupt ayarlarını yapabildiğimi sanmıyorum program; (Encoder'i bağladığım pinler PE0 ve PD2)

#include <stdio.h>
#include <stm32f4xx.h>

//void NVIC_EnableIRQ (IRQ29_TIM3 IRQ29);

void SystemInit ()         //Port yönleri ve Tim3/4 ayarlari (sayici) olarak kullanilacak
{
   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 |= 0x07405408;         // PLL katsayilarini M=8, N=336, P=2 ve Q=7 yapalim
    //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 = 0x00000705;          // Flash ROM icin 5 Wait state secelim ve ART yi aktif edelim (Rehber Sayfa 55)
    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 |= 0x00000018;      // GPIO D GPIO E clock'ları aktif edelim
    RCC->APB1ENR |= 0X00000006;   // Timer 3 ve 4 aktif
    GPIOE->AFR[0] |= 0x00000002;   // Port A'nın 6 nolu (7.) bitini Alternate Function TIM3_ETR olarak ayarladık
    GPIOD->AFR[1] |= 0x00000200;     // Port D'nin 12 nolu (13.) bitini Alternate Function TIM4_ETR olarak ayarladık
    GPIOD->MODER = 0x56000000;         // GPIOD nin 15, 14, 13, pinleri cikis tanimlandi (LEDler icin) 12 pini Alternate Funcion olarak tanımladnı TIM4_CH1
    GPIOE->MODER |= 0x00000002;   // GPIOA nın 6. pini Alternate Function olarak tanımlandı TIM3_CH1
    GPIOD->OSPEEDR = 0xFFFFFFFF;       // GPIOD nin tum cikislari en yuksek hizda kullanacagiz 
    GPIOD->OSPEEDR = 0xFFFFFFFF;       // GPIOE nin tum cikislari en yuksek hizda kullanacagiz
}

void bekle ()
{
   unsigned int i;
   GPIOD->ODR &= 0xFFFF1FFF;
   for (i=0;i<=200000;i++)
   {
   ;   
   }
   GPIOD->ODR |= 0x0000E000;
}

void delay (int x)
{
   unsigned long int j;

   for (j=0;j<=x;j++);
}

void TimerKurulumu ()
{
   
   TIM3->CR1 |= 0x0085;             // Timer 3 ve Timer 4 Kontrol saklayıcısına gereken değerler
               TIM4->CR1 |= 0x0085;             // CEN=enable | URS=only counter overflow | Auto-Reload ON |   Upcounter (DIR=0) |
   TIM3->SMCR |= 0x0071;             // Timer 3 --> Ext_Trigger input | Encoder mode 1
   TIM4->SMCR |= 0x0071;              // Timer 4 --> Ext_Trigger input | Encoder mode 1
   TIM3->DIER |= 0x0001;         //TIM3 Update Interrupt Enable
   TIM4->DIER |= 0x0001;         //TIM4   "   "         "
   TIM3->CCER &= 0x4444;
   TIM4->CCER &= 0x4444;
   TIM3->EGR |= 0x0001;             // UG biti 1 --> Sayıcının tekrar ayarlanması (Tim3)
   TIM4->EGR |= 0x0001;             // UG biti 1 --> Sayıcının tekrar ayarlanması (Tim4)
   TIM3->PSC = 0x0000;
   TIM3->ARR = 0xFFF6;         //Timer 3/4 otomatik yükleme degeri
   TIM3->CNT = 0xFFF6;         //Timer 3/4 10 pulse saydiktan sonra kesme üretmesi için
   TIM4->PSC = 0x0000;
   TIM4->ARR = 0xFFF6;
   TIM4->CNT = 0xFFF6;
}

void TIM3_IRQHandler ()
{                                   
   bekle();
}

void TIM4_IRQHandler ()
{
   bekle();
}

int main ()
{
   GPIOD->ODR |= 0x00004000;   
   TimerKurulumu();

   while(1)
   {
      
      
      while ((TIM3->CNT) != (TIM4->CNT))
      {   
         GPIOD->ODR |= 0x0000E000;   
         delay(15000000);
         TIM4->CR1 |= 0x0001;
         TIM3->CR1 |= 0x0001;
      
         if((TIM3->CNT) > (TIM4->CNT))
         {
            TIM4->CR1 &= 0xFFFE;
            GPIOD->ODR |= 0x0000C000;
         }
         else if ((TIM3->CNT) < (TIM4->CNT))
         {
            TIM3->CR1 &= 0xFFFE;
            GPIOD->ODR &= 0xFFFF6FFF;
            delay(15000000);
         }
       }
      
       GPIOD->ODR |= 0x00004000;
       delay(15000000);
       GPIOD->ODR &= 0xFFFF1FFF;
       delay(15000000);
   }
}


Ana fonksiyonda D portuna yüklediğim değerler denemek için. TIM4->CNT değerini arttırınca şart yapısının içerisine giriyor fakat palsleri saymıyor. Şimdiden Teşekkürler.

pisayisi

Hedefe ulaşma şeklin yanlış, en gelişmiş işlemcilerden biranesi ile uğraşıp insan kulağını tersten göstermeye çalışırsa bu hiç yerinde olmaz. Bu işlemcilerin stm32f1 serilerinden itibaren encoder modülü mevcut, ref manual yeterince incelememişsin. Bu encoder modülünün motor control kütüpanesinde kullanan alt c modülünü tam olarak aşağıda yayınlıyorum. Normalde confidential versiyondur yayınlanması yasal değildir sen ilgili kısımlarını stm32f4 register ları nı da gözönüne alıp düzenlersen sonuca ilerlersin...

/******************** (C) COPYRIGHT 2008 STMicroelectronics ********************
* File Name          : stm32f10x_encoder.c 
* Author             : IMS Systems Lab  
* Date First Issued  : 21/11/07
* Description        : This file contains the software implementation for the
*                      encoder unit
********************************************************************************
* History:
* 21/11/07 v1.0
* 29/05/08 v2.0
********************************************************************************
* THE PRESENT SOFTWARE 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 SOFTWARE AND/OR THE USE MADE BY CUSTOMERS OF THE CODING
* INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS.
*
* THIS SOURCE CODE IS PROTECTED BY A LICENSE.
* FOR MORE INFORMATION PLEASE CAREFULLY READ THE LICENSE AGREEMENT FILE LOCATED
* IN THE ROOT DIRECTORY OF THIS FIRMWARE PACKAGE.
*******************************************************************************/
/* Includes ------------------------------------------------------------------*/
#include "stm32f10x_lib.h"
#include "stm32f10x_encoder.h"
#include "stm32f10x_it.h"
#include "MC_Globals.h"
#include "stm32f10x_MClib.h"

/* Private typedef -----------------------------------------------------------*/
/* Private define ------------------------------------------------------------*/
#define COUNTER_RESET       (u16) ((((s32)(ALIGNMENT_ANGLE)*4*ENCODER_PPR/360)\
                                                              -1)/POLE_PAIR_NUM)
#define ICx_FILTER          (u8) 8 // 8<-> 670nsec

#define SPEED_SAMPLING_FREQ (u16)(2000/(SPEED_SAMPLING_TIME+1))

#define TIMx_PRE_EMPTION_PRIORITY 2
#define TIMx_SUB_PRIORITY 0

#define SPEED_SAMPLING_TIME   PID_SPEED_SAMPLING_TIME

/* Private macro -------------------------------------------------------------*/
// To avoid obvious initialization errors...
#if  ( (defined(TIMER2_HANDLES_ENCODER) && defined(TIMER3_HANDLES_ENCODER)) \
    || (defined(TIMER2_HANDLES_ENCODER) && defined(TIMER4_HANDLES_ENCODER)) \
    || (defined(TIMER3_HANDLES_ENCODER) && defined(TIMER4_HANDLES_ENCODER)))
  #error "Invalid encoder setup: 2 timers selected"
#endif

#ifdef ENCODER

// Warning message if encoder unit not connected
#ifndef TIMER2_HANDLES_ENCODER
#ifndef TIMER3_HANDLES_ENCODER
#ifndef TIMER4_HANDLES_ENCODER
#warning "Encoder not selected"
#endif
#endif
#endif
#endif  // ENCODER

/* Private functions ---------------------------------------------------------*/
s16 ENC_Calc_Rot_Speed(void);

/* Private variables ---------------------------------------------------------*/
static s16 hPrevious_angle, hSpeed_Buffer[SPEED_BUFFER_SIZE], hRot_Speed;
static u8 bSpeed_Buffer_Index = 0;
static volatile u16 hEncoder_Timer_Overflow; 
static bool bIs_First_Measurement = TRUE;
static bool bError_Speed_Measurement = FALSE;

/*******************************************************************************
* Function Name  : ENC_Init
* Description    : General Purpose Timer x set-up for encoder speed/position 
*                  sensors
* Input          : None
* Output         : None
* Return         : None
*******************************************************************************/

void ENC_Init(void)
{
  TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;
  TIM_ICInitTypeDef TIM_ICInitStructure;
  
#if defined(TIMER2_HANDLES_ENCODER)   // Encoder unit connected to TIM2, 4X mode
    
  GPIO_InitTypeDef GPIO_InitStructure;
  NVIC_InitTypeDef NVIC_InitStructure;
    
  /* TIM2 clock source enable */
  RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);
  /* Enable GPIOA, clock */
  RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
  
  GPIO_StructInit(&GPIO_InitStructure);
  /* Configure PA.00,01 as encoder input */
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
  GPIO_Init(GPIOA, &GPIO_InitStructure);
  
  /* Enable the TIM2 Update Interrupt */
  NVIC_InitStructure.NVIC_IRQChannel = TIM2_IRQChannel;
  NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = TIMx_PRE_EMPTION_PRIORITY;
  NVIC_InitStructure.NVIC_IRQChannelSubPriority = TIMx_SUB_PRIORITY;
  NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
  NVIC_Init(&NVIC_InitStructure);

#elif defined(TIMER3_HANDLES_ENCODER) // Encoder unit connected to TIM3, 4X mode
  GPIO_InitTypeDef GPIO_InitStructure;
  NVIC_InitTypeDef NVIC_InitStructure;
  
  /* TIM3 clock source enable */
  RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE);
  /* Enable GPIOA, clock */
  RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
  
  GPIO_StructInit(&GPIO_InitStructure);
  /* Configure PA.06,07 as encoder input */
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6 | GPIO_Pin_7;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
  GPIO_Init(GPIOA, &GPIO_InitStructure);
  
  /* Enable the TIM3 Update Interrupt */
  NVIC_InitStructure.NVIC_IRQChannel = TIM3_IRQChannel;
  NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = TIMx_PRE_EMPTION_PRIORITY;
  NVIC_InitStructure.NVIC_IRQChannelSubPriority = TIMx_SUB_PRIORITY;
  NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
  NVIC_Init(&NVIC_InitStructure);

#elif defined(TIMER4_HANDLES_ENCODER) // Encoder unit connected to TIM4, 4X mode
  GPIO_InitTypeDef GPIO_InitStructure;
  NVIC_InitTypeDef NVIC_InitStructure;
  
  /* TIM4 clock source enable */
  RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM4, ENABLE);
  /* Enable GPIOA, clock */
  RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
  
  GPIO_StructInit(&GPIO_InitStructure);
  /* Configure PB.06,07 as encoder input */
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6 | GPIO_Pin_7;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
  GPIO_Init(GPIOB, &GPIO_InitStructure);
  
  /* Enable the TIM4 Update Interrupt */
  NVIC_InitStructure.NVIC_IRQChannel = TIM4_IRQChannel;
  NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = TIMx_PRE_EMPTION_PRIORITY;
  NVIC_InitStructure.NVIC_IRQChannelSubPriority = TIMx_SUB_PRIORITY;
  NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
  NVIC_Init(&NVIC_InitStructure);
#endif

  /* Timer configuration in Encoder mode */
  TIM_DeInit(ENCODER_TIMER);
  TIM_TimeBaseStructInit(&TIM_TimeBaseStructure);
  
  TIM_TimeBaseStructure.TIM_Prescaler = 0x0;  // No prescaling 
  TIM_TimeBaseStructure.TIM_Period = (4*ENCODER_PPR)-1;  
  TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1;
  TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;   
  TIM_TimeBaseInit(ENCODER_TIMER, &TIM_TimeBaseStructure);
 
  TIM_EncoderInterfaceConfig(ENCODER_TIMER, TIM_EncoderMode_TI12, 
                             TIM_ICPolarity_Rising, TIM_ICPolarity_Rising);
  TIM_ICStructInit(&TIM_ICInitStructure);
  
  TIM_ICInitStructure.TIM_ICFilter = ICx_FILTER;
  TIM_ICInit(ENCODER_TIMER, &TIM_ICInitStructure);
  
  TIM_ICInitStructure.TIM_Channel = TIM_Channel_2;
  TIM_ICInit(ENCODER_TIMER, &TIM_ICInitStructure);
      
 // Clear all pending interrupts
  TIM_ClearFlag(ENCODER_TIMER, TIM_FLAG_Update);
  TIM_ITConfig(ENCODER_TIMER, TIM_IT_Update, ENABLE);
  //Reset counter
  TIM2->CNT = COUNTER_RESET;
  
  TIM_Cmd(ENCODER_TIMER, ENABLE);
}

/*******************************************************************************
* Function Name  : ENC_Get_Electrical_Angle
* Description    : Returns the absolute electrical Rotor angle 
* Input          : None
* Output         : None
* Return         : Rotor electrical angle: 0 -> 0 degrees, 
*                                          S16_MAX-> 180 degrees, 
*                                          S16_MIN-> -180 degrees
*                  Mechanical angle can be derived calling this function and 
*                  dividing by POLE_PAIR_NUM
*******************************************************************************/
s16 ENC_Get_Electrical_Angle(void)
{
  s32 temp;
  
  temp = (s32)(TIM_GetCounter(ENCODER_TIMER)) * (s32)(U32_MAX / (4*ENCODER_PPR));         
  temp *= POLE_PAIR_NUM;  
  return((s16)(temp/65536)); // s16 result
}

/*******************************************************************************
* Function Name  : ENC_Get_Mechanical_Angle
* Description    : Returns the absolute mechanical Rotor angle 
* Input          : None
* Output         : None
* Return         : Rotor mechanical angle: 0 -> 0 degrees, S16_MAX-> 180 degrees, 
                                            S16_MIN-> -180 degrees
*******************************************************************************/
s16 ENC_Get_Mechanical_Angle(void)
{
  s32 temp;
  
  temp = (s32)(TIM_GetCounter(ENCODER_TIMER)) * (s32)(U32_MAX / (4*ENCODER_PPR)) ;
  return((s16)(temp/65536)); // s16 result
}

/*******************************************************************************
* Function Name  : ENC_ResetEncoder
* Description    : Write the encoder counter with the value corresponding to
*                  ALIGNMENT_ANGLE
* Input          : None
* Output         : None
* Return         : None
*******************************************************************************/
void ENC_ResetEncoder(void)
{
  //Reset counter
  TIM2->CNT = COUNTER_RESET;
}

             
/*******************************************************************************
* Function Name  : ENC_Clear_Speed_Buffer
* Description    : Clear speed buffer used for average speed calculation  
* Input          : None
* Output         : None
* Return         : None
*******************************************************************************/
void ENC_Clear_Speed_Buffer(void)
{   
  u32 i;

  for (i=0;i<SPEED_BUFFER_SIZE;i++)
  {
    hSpeed_Buffer[i] = 0;
  }
  bIs_First_Measurement = TRUE;
}

/*******************************************************************************
* Function Name  : ENC_Calc_Rot_Speed
* Description    : Compute return latest speed measurement 
* Input          : None
* Output         : s16
* Return         : Return motor speed in 0.1 Hz resolution. Since the encoder is
                   used as speed sensor, this routine will return the mechanical
                   speed of the motor (NOT the electrical frequency)
                   Mechanical frequency is equal to electrical frequency/(number 
                   of pair poles).
*******************************************************************************/
s16 ENC_Calc_Rot_Speed(void)
{   
  s32 wDelta_angle;
  u16 hEnc_Timer_Overflow_sample_one, hEnc_Timer_Overflow_sample_two;
  u16 hCurrent_angle_sample_one, hCurrent_angle_sample_two;
  signed long long temp;
  s16 haux;
  
  if (!bIs_First_Measurement)
  {
    // 1st reading of overflow counter    
    hEnc_Timer_Overflow_sample_one = hEncoder_Timer_Overflow; 
    // 1st reading of encoder timer counter
    hCurrent_angle_sample_one = ENCODER_TIMER->CNT;
    // 2nd reading of overflow counter
    hEnc_Timer_Overflow_sample_two = hEncoder_Timer_Overflow;  
    // 2nd reading of encoder timer counter
    hCurrent_angle_sample_two = ENCODER_TIMER->CNT;      

    // Reset hEncoder_Timer_Overflow and read the counter value for the next
    // measurement
    hEncoder_Timer_Overflow = 0;
    haux = ENCODER_TIMER->CNT;   
    
    if (hEncoder_Timer_Overflow != 0) 
    {
      haux = ENCODER_TIMER->CNT; 
      hEncoder_Timer_Overflow = 0;            
    }
     
    if (hEnc_Timer_Overflow_sample_one != hEnc_Timer_Overflow_sample_two)
    { //Compare sample 1 & 2 and check if an overflow has been generated right 
      //after the reading of encoder timer. If yes, copy sample 2 result in 
      //sample 1 for next process 
      hCurrent_angle_sample_one = hCurrent_angle_sample_two;
      hEnc_Timer_Overflow_sample_one = hEnc_Timer_Overflow_sample_two;
    }
    
    if ( (ENCODER_TIMER->CR1 & TIM_CounterMode_Down) == TIM_CounterMode_Down)  
    {// encoder timer down-counting
      wDelta_angle = (s32)(hCurrent_angle_sample_one - hPrevious_angle - 
                    (hEnc_Timer_Overflow_sample_one) * (4*ENCODER_PPR));
    }
    else  
    {//encoder timer up-counting
      wDelta_angle = (s32)(hCurrent_angle_sample_one - hPrevious_angle + 
                    (hEnc_Timer_Overflow_sample_one) * (4*ENCODER_PPR));
    }
    
    // speed computation as delta angle * 1/(speed sempling time)
    temp = (signed long long)(wDelta_angle * SPEED_SAMPLING_FREQ);                                                                
    temp *= 10;  // 0.1 Hz resolution
    temp /= (4*ENCODER_PPR);
        
  } //is first measurement, discard it
  else
  {
    bIs_First_Measurement = FALSE;
    temp = 0;
    hEncoder_Timer_Overflow = 0;
    haux = ENCODER_TIMER->CNT;       
    // Check if Encoder_Timer_Overflow is still zero. In case an overflow IT 
    // occured it resets overflow counter and wPWM_Counter_Angular_Velocity
    if (hEncoder_Timer_Overflow != 0) 
    {
      haux = ENCODER_TIMER->CNT; 
      hEncoder_Timer_Overflow = 0;            
    }
  }
  
  hPrevious_angle = haux;  
 
  return((s16) temp);
}

/*******************************************************************************
* Function Name  : ENC_Get_Mechanical_Speed
* Description    : Export the value of the smoothed motor speed computed in 
*                  ENC_Calc_Average_Speed function  
* Input          : None
* Output         : s16
* Return         : Return motor speed in 0.1 Hz resolution. This routine 
                   will return the average mechanical speed of the motor.
*******************************************************************************/
s16 ENC_Get_Mechanical_Speed(void)
{
  return(hRot_Speed);
}

/*******************************************************************************
* Function Name  : ENC_Calc_Average_Speed
* Description    : Compute smoothed motor speed based on last SPEED_BUFFER_SIZE
                   informations and store it variable  
* Input          : None
* Output         : s16
* Return         : Return rotor speed in 0.1 Hz resolution. This routine 
                   will return the average mechanical speed of the motor.
*******************************************************************************/
void ENC_Calc_Average_Speed(void)
{   
  s32 wtemp;
  u16 hAbstemp;
  u32 i;
  u8 static bError_counter;
  
  wtemp = ENC_Calc_Rot_Speed();
  hAbstemp = ( wtemp < 0 ? - wtemp :  wtemp);

/* Checks for speed measurement errors when in RUN State and saturates if 
                                                                    necessary*/  
  if (State == RUN)
  {    
    if(hAbstemp < MINIMUM_MECHANICAL_SPEED)
    { 
      if (wtemp < 0)
      {
        wtemp = -(s32)(MINIMUM_MECHANICAL_SPEED);
      }
      else
      {
        wtemp = MINIMUM_MECHANICAL_SPEED;
      }
      bError_counter++;
    }
    else  if (hAbstemp > MAXIMUM_MECHANICAL_SPEED) 
          {
            if (wtemp < 0)
            {
              wtemp = -(s32)(MAXIMUM_MECHANICAL_SPEED);
            }
            else
            {
              wtemp = MAXIMUM_MECHANICAL_SPEED;
            }
            bError_counter++;
          }
          else
          { 
            bError_counter = 0;
          }
  
    if (bError_counter >= MAXIMUM_ERROR_NUMBER)
    {
     bError_Speed_Measurement = TRUE;
    }
    else
    {
     bError_Speed_Measurement = FALSE;
    }
  }
  else
  {
    bError_Speed_Measurement = FALSE;
    bError_counter = 0;
  }
  
/* Compute the average of the read speeds */
  
  hSpeed_Buffer[bSpeed_Buffer_Index] = (s16)wtemp;
  bSpeed_Buffer_Index++;
  
  if (bSpeed_Buffer_Index == SPEED_BUFFER_SIZE) 
  {
    bSpeed_Buffer_Index = 0;
  }

  wtemp=0;

  for (i=0;i<SPEED_BUFFER_SIZE;i++)
    {
    wtemp += hSpeed_Buffer[i];
    }
  wtemp /= SPEED_BUFFER_SIZE;
  
  hRot_Speed = ((s16)(wtemp));
}

/*******************************************************************************
* Function Name  : ENC_ErrorOnFeedback
* Description    : Check for possible errors on speed measurement when State is 
*                  RUN. After MAXIMUM_ERROR_NUMBER consecutive speed measurement
*                  errors, the function return TRUE, else FALSE.
*                  Function return 
* Input          : None
* Output         : s16
* Return         : boolean variable
*******************************************************************************/
bool ENC_ErrorOnFeedback(void)
{
 return(bError_Speed_Measurement); 
}

/*******************************************************************************
* Function Name : ENC_Start_Up
* Description   : The purpose of this function is to perform the alignment of 
*                 PMSM torque and flux regulation during the alignment phase.
* Input : details the input parameters.
* Output : details the output parameters.
* Return : details the return value.
*******************************************************************************/
void ENC_Start_Up(void)
{
  static u32 wTimebase=0;
  
  if ( (wGlobal_Flags & FIRST_START) == FIRST_START)
    {
      // First Motor start-up, alignment must be performed
      wTimebase++;
      if(wTimebase <= T_ALIGNMENT_PWM_STEPS)
      {                  
        hFlux_Reference = I_ALIGNMENT * wTimebase / T_ALIGNMENT_PWM_STEPS;               
        hTorque_Reference = 0;
        
        Stat_Curr_a_b = GET_PHASE_CURRENTS(); 
        Stat_Curr_alfa_beta = Clarke(Stat_Curr_a_b); 
        Stat_Curr_q_d = Park(Stat_Curr_alfa_beta, ALIGNMENT_ANGLE_S16);  
        /*loads the Torque Regulator output reference voltage Vqs*/   
        Stat_Volt_q_d.qV_Component1 = PID_Regulator(hTorque_Reference, 
                        Stat_Curr_q_d.qI_Component1, &PID_Torque_InitStructure);   
        
        /*loads the Flux Regulator output reference voltage Vds*/
        Stat_Volt_q_d.qV_Component2 = PID_Regulator(hFlux_Reference, 
                          Stat_Curr_q_d.qI_Component2, &PID_Flux_InitStructure); 
  
        RevPark_Circle_Limitation();

        /*Performs the Reverse Park transformation,
        i.e transforms stator voltages Vqs and Vds into Valpha and Vbeta on a 
        stationary reference frame*/
  
        Stat_Volt_alfa_beta = Rev_Park(Stat_Volt_q_d);

        /*Valpha and Vbeta finally drive the power stage*/ 
        CALC_SVPWM(Stat_Volt_alfa_beta);
      }
      else
      {
        wTimebase = 0;              
        ENC_ResetEncoder();          
        Stat_Volt_q_d.qV_Component1 = Stat_Volt_q_d.qV_Component2 = 0;
        hTorque_Reference = PID_TORQUE_REFERENCE;
        hFlux_Reference = PID_FLUX_REFERENCE;
        wGlobal_Flags &= ~FIRST_START;   // alignment done only once 
        //Clear the speed acquisition of the alignment phase
        ENC_Clear_Speed_Buffer();
#ifdef ENCODER
        State = RUN;
#endif
      }
    }
  else
  {
#ifdef ENCODER
    State = RUN;
#endif
  }
} 

/*******************************************************************************
* Function Name  : TIMx_IRQHandler
* Description    : This function handles TIMx Update interrupt request.
                   Encoder unit connected to TIMx (x = 2,3 or 4)
* Input          : None
* Output         : None
* Return         : None
*******************************************************************************/
#if defined(TIMER2_HANDLES_ENCODER)
  void TIM2_IRQHandler(void)
  {  
    /* Clear the interrupt pending flag */
    TIM_ClearFlag(ENCODER_TIMER, TIM_FLAG_Update);
    
    if (hEncoder_Timer_Overflow != U16_MAX)  
    {
     hEncoder_Timer_Overflow++;
    }
  }
#elif defined(TIMER3_HANDLES_ENCODER)

  void TIM3_IRQHandler(void)
  {
    TIM_ClearFlag(ENCODER_TIMER, TIM_FLAG_Update);
    if (Encoder_Timer_Overflow != U16_MAX)  
    {
     Encoder_Timer_Overflow++;
    }
  
  }

#elif defined(TIMER4_HANDLES_ENCODER)
    
  void TIM4_IRQHandler(void)
  {
    TIM_ClearFlag(ENCODER_TIMER, TIM_FLAG_Update);
    if (Encoder_Timer_Overflow != U16_MAX)  
    {
     Encoder_Timer_Overflow++;
    }  	
  }

#endif // TIMER4_HANDLES_ENCODER

/******************* (C) COPYRIGHT 2008 STMicroelectronics *****END OF FILE****/
Murat

OrkUn®

Teşekkür ederim kodları inceleyeceğim daha ilk denemem ref manual'i 2 gün inceledim fakat kendim yazmak istedim. Anlayamadıgım yada ref manuel, technical manuel ve programming manuel'de tim3_irqhandler'ıkullanmak için NVIC_ISERx saklayıcısında hangi biti aktif etmem gerekiyor? dışarıdan pulse saymak istiyorum.

mesaj birleştirme:: 09 Temmuz 2012, 00:20:50

NVIC->ISER saklayıcısında ayarlayabileceğimiz 81 tane bit var fakat 82 tane interrupt var hangisi bu listede değil bunu anlamış değilim.. Yardım eden birisi olursa sevinirim..