2022-09-26 04:35 AM
Hello guys,
I have just started working with stm32 controllers. I am trying to capture the frequency of signal using timer 2 input capture mode.
I am getting absolutely correct frequency if i use ARR = 65535 but when i use ARR = 0xffffffff (As timer 2 is 32bit) i am getting wrong result.
I am using this reference equation
Frequency = TIM_CLOCK / ((C2-C1)*(prescaler+1))
Where C2 = capture value 2 // Both Rising edge
C1 = capture value 1
TIM_CLOCK = 1Mhz
TIMER_PSC = 16-1
SYSTEM_CLOCK = 16Mhz
Please help if i am missing something.
Solved! Go to Solution.
2022-09-27 10:00 PM
@Community member Yes i have read that.
Please note that i am not changing ARR after timer started.
#include "stm32f401xc.h"
void Gpio_Init(void);
void Timer_Init(void);
//-----------------------Main start----------------------------
int main()
{
volatile uint32_t C1, C2;
Gpio_Init();
Timer_Init();
while(1)
{
TIM1->CNT = 0;
//Polling method
while((TIM1->SR & (1 << 1)) == 0);
C1 = TIM1->CCR1; //Capture 1
while((TIM1->SR & (1 << 1)) == 0);
C2 = TIM1->CCR1; //Capture 2
}
}//----------------------Main end------------------------------
//F01-GPIO Init
void Gpio_Init(void)
{
//1 Enable clock to gpio
RCC->AHB1ENR |= (1 << 0); //Port A
//2 Gpio mode
GPIOA->MODER &= ~(1U << 16);
GPIOA->MODER |= (1 << 17); //PA8 alternate func mode
//3 Alter function define
GPIOA->AFR[1] |= (1 << 0); //AF == TIM1_CH1
}
//F02-Timer Init
void Timer_Init(void)
{
//1 Timer clock enable
RCC->APB2ENR |= (1 << 0);
//2 Stop timer
TIM1->CR1 &= ~(1U << 0);
//3 Set timer prescaler
TIM1->PSC = 16-1;
//4 Set autoreload value
TIM1->ARR = 65535;
//5 Select timer configurations
TIM1->CR1 &= ~(1U << 7); //Autoreoad disable
TIM1->CR1 &= ~(1U << 4); //Upcount
//6 Input channel select
TIM1->CR2 &= ~(1U << 7); //TIM1_CH1 as TI1
TIM1->CCMR1 &= ~(3U << 0); //Clear CC1S bits
TIM1->CCMR1 |= (1 << 0); //IC1 is mapped on TI1
//7 Select filter value
TIM1->CR1 &= ~(3U << 8); //tDTS == tCK_CNT(prescaler)
TIM1->CCMR1 &= ~(0xfU << 4); //No filter
//8 Select edge
TIM1->CCER &= ~((1U << 1)|(1U << 3));
//9 Select prescalers for capture
TIM1->CCMR1 &= ~(3U << 2);
//10 Capture enable
TIM1->CCER |= (1 << 0);
//11 Timer run
TIM1->CR1 |= (1U << 0);
}
Thank you
2022-09-28 07:33 AM
After you've set TIM1->PSC, do
TIM1->EGR = TIM_EGR_UG;
JW
2022-09-28 02:03 PM
Use uint16_t/uint32_t for 16/32-bit timers respectively. And, to deal with overflow properly, the result of the subtraction must also be of the same type.
2022-09-28 02:06 PM
Better set TIM_EGR_UG after both the PSC and ARR registers are set.
> TIM1->ARR = 65535;
No need to explicitly set the maximum value as that is the default value after reset.
2022-09-28 10:57 PM
@Community member @Piranha Tried both the things but still result is same.
2022-09-28 11:18 PM
Post code and concrete numbers.
JW
2022-09-29 01:14 AM
Output 1: ARR 65535
Output 2: ARR 0xFFFFFFFF
2022-09-29 01:16 AM
Please note that I have not changed ARR once the timer start.
2022-09-29 02:26 AM
And the code?
JW
2022-09-29 02:41 AM
#include "stm32f429xx.h"
//Function Prototypes
void Gpio_Init(void);
void Timer_Init(void);
//-------------------------Main start-------------------------
int main()
{
volatile uint32_t time1, time2, time3;
volatile float fre, per, Toff, Duty;
Gpio_Init();
Timer_Init();
while(1)
{
TIM2->CNT = 0;
while((TIM2->SR & (1 << 1)) == 0);
time1 = TIM2->CCR1;
while((TIM2->SR & (1 << 1)) == 0);
time2 = TIM2->CCR1;
while((TIM2->SR & (1 << 1)) == 0);
time3 = TIM2->CCR1;
//Frequency calculations 1Mhz Timer clock so 1us per clock pulse
per = (float)(time3 - time1); //To convert in ms divide it by 1000
fre = (float)1 / per;
fre *= 1000000;
//Duty cycle calculations
Toff = (float)(time3 - time2);
Duty = (float)(((per-Toff)*100)/per);
time1 = 0; time2 = 0; time3 = 0;
}
}//-----------------------Main end---------------------------
//F01-GPIO config
void Gpio_Init(void)
{
//1 Enable clock
RCC->AHB1ENR |= (1 << 0); //Port A
//2 Pin mode
GPIOA->MODER &= ~(1U << 10);
GPIOA->MODER |= (1 << 11); //PA5 as alterenate function
//3 Alternate function decide
GPIOA->AFR[0] |= (1 << 20);
}
//F02-Timer config
void Timer_Init(void)
{
//1 Enable clock
RCC->APB1ENR |= (1 << 0); //Timer 2
//2 Stop timer
TIM2->CR1 &= ~(1U << 0);
//3 Prescaler for timer
TIM2->PSC = 16 - 1;
//4 Select autoreload value
TIM2->ARR = 65535; //Not working for 0xffffffff? Ask
//5 Timer config
TIM2->CR1 &= ~(1U << 7); //Autoreload disable
TIM2->CR1 &= ~(1U << 4); //Upcounter
//6 Timer channel config
TIM2->CCMR1 |= (1 << 0); //Tim1_CH1 as TI1
//7 Edge select
TIM2->CCER |= (1U << 1)|(1U << 3); //Both edges for PWM input
//TIM2->CCER &= ~((1U << 1)|(1U << 3)); //Rising edge
//8 Input capture enable
TIM2->CCER |= (1 << 0);
//9 Timer run
TIM2->CNT = 0;
TIM2->CR1 |= (1 << 0);
}