cancel
Showing results for 
Search instead for 
Did you mean: 

Timer

stephen5489
Associate II
Posted on October 18, 2013 at 04:13

Hi, I am makin a encoder interface on the et-arm stamp stm32, my problem is that maximun frequency I can get from the encoder is 30Hz and I just can measure at less 1190Hz (based in PWM_IN example) I am measuring the time betwen falling and rising voltage and this is my code. The code doesn't work could anyone please help me?

void RCC_ExIT_Configuration(void){

/* TIM2 clock enable */

 RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);

}

void GPIO_ExIT_Configuration(void){

//GPIO_InitTypeDef GPIO_InitStructure;

/* TIM2 channel 2 pin (PA.01) configuration */

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);

}

void EXTI_Exp(void)

{

    // System Clocks Configuration

    //

RCC_ExIT_Configuration();

    //

    // Configure the GPIO ports

    //

    GPIO_ExIT_Configuration();

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

    ------------------------------------------------------------ */

    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(TIM2, &TIM_ICInitStructure);

    /* Select the TIM2 Input Trigger: TI2FP2 */

    TIM_SelectInputTrigger(TIM2, TIM_TS_TI2FP2);

    /* Select the slave Mode: Reset Mode */

    TIM_SelectSlaveMode(TIM2, TIM_SlaveMode_Reset);

    TIM_SelectSlaveMode(TIM4, TIM_SlaveMode_Reset);

    /* Enable the Master/Slave Mode */

    TIM_SelectMasterSlaveMode(TIM2, TIM_MasterSlaveMode_Enable);

    /* TIM enable counter */

    TIM_Cmd(TIM2, ENABLE);

    /* Enable the CC2 Interrupt Request */

    //TIM_ITConfig(TIM2, TIM_IT_CC2 | TIM_IT_Trigger, ENABLE);

}

void TIM2_IRQHandler(void){

int IC2Value=0;

// Clear TIM2 Capture compare interrupt pending bit

//TIM_ClearITPendingBit(TIM2, TIM_IT_CC2);

if (TIM_GetITStatus(TIM2, TIM_IT_CC2)== SET){

if(count!=0){

// Get the Input Capture value

IC2Value = TIM_GetCapture2(TIM2);

if ((IC2Value != 0))

{

// Frequency computation

Frequency = SystemCoreClock / IC2Value;

count+=(1/Frequency);

//Frequency2 = SystemCoreClock / IC2Value2;

}

else

{

//DutyCycle = 0;

Frequency = 0;

//Frequency2 = 0;

}

TIM_ClearITPendingBit(TIM2, TIM_IT_CC2);

count=0;

}

}

else if(TIM_GetITStatus(TIM2, TIM_IT_Trigger)== SET){

count+=1/1190;

}

}

14 REPLIES 14
Posted on October 25, 2013 at 17:16

Ok, that's pretty hopeless, try this, it's a complete worked example, adapt to the specifics of your board.

// STM32 VLDiscovery TIM2 Frequency Measurement 18-30 Hz - sourcer32@gmail.com
#include <
stdio.h
>
#include ''stm32F10x.h''
/**************************************************************************************/
void USART_Configuration(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
USART_InitTypeDef USART_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
/* Configure USART Tx as alternate function push-pull */
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9; // PA.09 USART1.TX
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure);
/* Configure USART Rx as input floating */
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10; // PA.10 USART1.RX
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
GPIO_Init(GPIOA, &GPIO_InitStructure);
/* USART resources configuration (Clock, GPIO pins and USART registers) ----*/
/* USART configured as follow:
- BaudRate = 115200 baud
- Word Length = 8 Bits
- One Stop Bit
- No parity
- Hardware flow control disabled (RTS and CTS signals)
- Receive and transmit enabled
*/
USART_InitStructure.USART_BaudRate = 115200;
USART_InitStructure.USART_WordLength = USART_WordLength_8b;
USART_InitStructure.USART_StopBits = USART_StopBits_1;
USART_InitStructure.USART_Parity = USART_Parity_No;
USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
/* Enable UART clock */
RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE);
/* USART configuration */
USART_Init(USART1, &USART_InitStructure);
/* Enable the USART1 */
USART_Cmd(USART1, ENABLE);
}
/**************************************************************************************/
void USART_PutString(char *s)
{
while(*s)
{
while(USART_GetFlagStatus(USART1, USART_FLAG_TXE) == RESET);
USART_SendData(USART1, *s++);
}
while((USART_GetFlagStatus(USART1, USART_FLAG_TC) != SET));
}
/**************************************************************************************/
void NVIC_Configuration(void)
{
NVIC_InitTypeDef NVIC_InitStructure;
NVIC_InitStructure.NVIC_IRQChannel = TIM2_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
}
/**************************************************************************************/
void TIM2_Configuration(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
TIM_ICInitTypeDef TIM_ICInitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1; // PA1 TIM2_CH2
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
GPIO_Init(GPIOA, &GPIO_InitStructure);
TIM_TimeBaseStructure.TIM_Prescaler = (uint16_t)(SystemCoreClock / 500000) - 1; // 500 KHz Time Base
TIM_TimeBaseStructure.TIM_Period = 65535; // Maximal
TIM_TimeBaseStructure.TIM_ClockDivision = 0;
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure);
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_ICInit(TIM2, &TIM_ICInitStructure);
TIM_Cmd(TIM2, ENABLE);
/* Enable the CC2 Interrupt Request */
TIM_ITConfig(TIM2, TIM_IT_CC2, ENABLE);
}
/**************************************************************************************/
volatile uint16_t TIM2CH2Measurement = 0;
void TIM2_IRQHandler(void)
{
if (TIM_GetITStatus(TIM2, TIM_IT_CC2) == SET)
{
static uint16_t ICValue1 = 0, ICValue2 = 0;
static int CaptureNumber = 0;
TIM_ClearITPendingBit(TIM2, TIM_IT_CC2);
if (CaptureNumber == 0)
{
ICValue1 = TIM_GetCapture2(TIM2);
CaptureNumber = 1;
}
else
{
ICValue2 = TIM_GetCapture2(TIM2);
TIM2CH2Measurement = ICValue2 - ICValue1; // Delta Ticks @ 500 KHz
ICValue1 = ICValue2;
}
}
}
/**************************************************************************************/
void TIM3_Configuration(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
TIM_OCInitTypeDef TIM_OCInitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC | RCC_APB2Periph_AFIO, ENABLE); // AFIO required for remapping
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6; // PC6 TIM3_CH1
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz;
GPIO_Init(GPIOC, &GPIO_InitStructure);
GPIO_PinRemapConfig(GPIO_FullRemap_TIM3, ENABLE);
TIM_TimeBaseStructure.TIM_Prescaler = (uint16_t)(SystemCoreClock / 1000000) - 1; // 1 MHz Time Base
TIM_TimeBaseStructure.TIM_Period = (uint16_t)(1000000 / 20) - 1; // 20 Hz
TIM_TimeBaseStructure.TIM_ClockDivision = 0;
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure);
// channel 1 configuration (PC.06) Remapped
TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;
TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
TIM_OCInitStructure.TIM_Pulse = (TIM_TimeBaseStructure.TIM_Period + 1) / 2; // 50% Duty
TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;
TIM_OC1Init(TIM3, &TIM_OCInitStructure);
TIM_Cmd(TIM3, ENABLE);
}
/**************************************************************************************/
void GPIO_Configuration(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC, ENABLE);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8; // PC.08 BLUE LED
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOC, &GPIO_InitStructure);
}
/**************************************************************************************/
int main(void)
{
USART_Configuration(); // For DEBUG
NVIC_Configuration();
TIM2_Configuration(); // Measurement Channel
TIM3_Configuration(); // Test Source
GPIO_Configuration(); // LED
while(1) // Infinite Loop
{
char String[30];
while(TIM2CH2Measurement == 0); // Wait for measurement
sprintf(String, ''%7.4lf Hz
'', 500000.0 / (double)TIM2CH2Measurement); // 500 KHz Ticks
GPIO_SetBits(GPIOC, GPIO_Pin_8); // BLUE LED
USART_PutString(String);
GPIO_ResetBits(GPIOC, GPIO_Pin_8);
TIM2CH2Measurement = 0; // Clear measurement
}
}

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
stephen5489
Associate II
Posted on October 26, 2013 at 02:50

Hi Clive.

thanks so much, It works perfect and in fact I can measure frequences till 8 Hz, by other hand you were totaly right about using funtion (sprintf();) to send data by serial channel I'm gonna use union type and get var char by char and send it. Again thanks so much.

stephen5489
Associate II
Posted on November 28, 2013 at 16:10

Hi Clive, me again

I've been playing with the code and looking for new ways the program works, this time I configure Channel 1 and 2 from timer 2 trying to count how much tics comes to the port and calculated with it the speed on two wheels, I just change the timer from 500kHz to 250kHz and create new variables to save the count, here are the changes.

int
tics1=0;
int
tics2=0;
void
TIM2_Configuration(
void
)
{
NVIC_TimeConfiguration();
//RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1; 
// PA1 TIM2_CH2
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_0; 
// PA0 TIM2_CH1
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure);
TIM_TimeBaseStructure.TIM_Prescaler = (uint16_t)(SystemCoreClock / 250000) - 1; 
// 250 KHz Time Base
TIM_TimeBaseStructure.TIM_Period = 65535; 
// Maximal
TIM_TimeBaseStructure.TIM_ClockDivision = 0;
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure);
TIM_ICInitStructure.TIM_Channel = TIM_Channel_1 | 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_ICInit(TIM2, &TIM_ICInitStructure);
TIM_Cmd(TIM2, ENABLE);
/* Enable the CC2 Interrupt Request */
TIM_ITConfig(TIM2, TIM_IT_CC1 | TIM_IT_CC2 | TIM_IT_Update, ENABLE);
}
void
TIM2_IRQHandler(
void
){
if
(TIM_GetITStatus(TIM2, TIM_IT_CC2) == SET){
TIM_ClearITPendingBit(TIM2, TIM_IT_CC2);
tics1++;
}
else
if
(TIM_GetITStatus(TIM2, TIM_IT_CC1) == SET){
TIM_ClearITPendingBit(TIM2, TIM_IT_CC1);
tics2++;
}
else
if
(TIM_GetITStatus(TIM2, TIM_IT_Update) == SET){
TIM_ClearITPendingBit(TIM2, TIM_IT_Update);
speed_Measure();
speed_Measure2();
tics1=0;
tics2=0;
}
}
/************************************************************************************************************/
union{
double
speed1;
char
speedR[8];
}SpdR={0};
union{
double
speed2;
char
speedL[8];
}SpdL={0};
void
speed_Measure(
void
){
double
c=7.5;
if
(PWM==0){
SpdR.speed1=(
double
)((gettics()*-8*(c/100))/0.26214); 
//velocity m/s
}
else
{
SpdR.speed1=(
double
)((gettics()*8*(c/100))/0.26214);
}
}
void
speed_Measure2(
void
){
double
c=7.5;
if
(PWM3==0){
SpdL.speed2=(
double
)((gettics2()*-8*(c/100))/0.26214);
}
else
{
SpdL.speed2=(
double
)((gettics2()*8*(c/100))/0.26214);
}
}
int
gettics(
void
)
{
return
tics1;
}
int
gettics2(
void
)
{
return
tics2;
}
/***********************************************************************************************************/
void
Fill_Buff(
void
){
sprintf(Data_Tx, 
''%s%d%c%d%c''
, 
''kk''
,(
int
) getSpeed1(),
','
, (
int
) getSpeed2(), 
'#'
);
i=7;
}
double
getSpeed1(
void
)
{
return
SpdR.speed1;
}
double
getSpeed2(
void
)
{
return
SpdL.speed2;
}

I see that the values in speed1 are ok but speed2 always is 2 or -2. it depend of if variable PWM!=0 or not, but never change its value just keep in 2 and -2, could you please help me?
Posted on November 28, 2013 at 16:33

Not sure I fully understand the merits of counting vs measuring period, but

I don't think you can compound the channels like this, you will need to configure them separately.

TIM_ICInitStructure.TIM_Channel = TIM_Channel_1 | TIM_Channel_2;

You also might want to consider in the IRQHandler will enter with multiple sources indicating, and define variables which are altered under interrupt as volatile.
Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
stephen5489
Associate II
Posted on November 28, 2013 at 19:59

believe me, me neither, but when I was measuring speed getting frequency first I notice that speed values change too much meanwhile the other technic hold it more the measure.

I don't think you can compound the channels like this, you will need to configure them separately.You also might want to consider in the IRQHandler will enter with multiple sources indicating you mean config like this?:

TIM_ICInitStructure.TIM_Channel = TIM_Channel_1;
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_ICInit(TIM2, &TIM_ICInitStructure);
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_ICInit(TIM2, &TIM_ICInitStructure);
TIM_ITConfig(TIM2, TIM_IT_CC1, ENABLE);
TIM_ITConfig(TIM2, TIM_IT_CC2, ENABLE);
TIM_ITConfig(TIM2, TIM_IT_Update, ENABLE);

because I did it and doesn't works well, the speed measure in both wheels was completely wrong.