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.
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****/
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..