2015-12-04 07:46 AM
I am working on a Nucleo152RE using EmBitz. The code generates a PWM signal (200Hz 50% duty-cycle) on PB8 (TIM4 channel 3) (It works, I tested with an oscilloscope), then gives this signal as input to PC6 (TIM3 channel 1) and uses TIM3 in input capture mode to measure the frequency of the signal. The frequency is then displayed on a LCD (the code for the LCD works).
The code for input capture is copied from an ST example. However, the value displayed on the LCD is not correct.Following is the code (the LCD code is omitted).#include ''stm32l1xx_conf.h''#include ''lcd_hd4478.h''volatile uint8_t phase;volatile uint16_t Capture1, Capture2;volatile uint32_t Capture, freq_int, freq_int2;uint8_t digit0,digit1,digit2,digit3;char freq_str[4];static void my_delay(__IO uint32_t nCount2);void GPIO_initialization(void);void Initialize_Timer_PWM_out(void);void Initialize_Timer_IC(void);int main(void){ my_delay(5250); LCD_Initialize(); LCD_Clear_Screen(); LCD_Write_String('' FREQUENCY (HZ) '', 0, 0); phase=0; GPIO_initialization(); Initialize_Timer_PWM_out(); Initialize_Timer_IC(); while(1) { my_delay(5250); freq_int = freq_int2; digit3 = (uint8_t)(freq_int/1000); if (digit3 == 0) freq_str[0]=' '; else freq_str[0]=digit3+48; digit2 = (uint8_t)(freq_int - 1000*digit3)/100; freq_str[1]=digit2+48; digit1 = (uint8_t)(freq_int - 1000*digit3 - 100*digit2)/10; freq_str[2]=digit1+48; freq_str[3]='.'; digit0 = (uint8_t)(freq_int - 1000*digit3 - 100*digit2 - 10*digit1); freq_str[4]=digit0+48; LCD_Write_String(freq_str, 1, 5); }}static void my_delay(__IO uint32_t nCount2){ __IO uint32_t index_new = 0; for(index_new = (0xFF * nCount2); index_new != 0; index_new--) { }}void GPIO_initialization(void){ RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOB | RCC_AHBPeriph_GPIOC, ENABLE); GPIO_InitTypeDef gpioStructure; gpioStructure.GPIO_Pin = GPIO_Pin_8; gpioStructure.GPIO_Mode = GPIO_Mode_AF; gpioStructure.GPIO_PuPd = GPIO_PuPd_NOPULL; gpioStructure.GPIO_Speed = GPIO_Speed_2MHz; GPIO_Init(GPIOB, &gpioStructure); gpioStructure.GPIO_Pin = GPIO_Pin_6; gpioStructure.GPIO_Mode = GPIO_Mode_AF; gpioStructure.GPIO_PuPd = GPIO_PuPd_NOPULL; gpioStructure.GPIO_Speed = GPIO_Speed_2MHz; GPIO_Init(GPIOC, &gpioStructure); GPIO_PinAFConfig(GPIOB, GPIO_PinSource8, GPIO_AF_TIM4); GPIO_PinAFConfig(GPIOC, GPIO_PinSource6, GPIO_AF_TIM3);}void Initialize_Timer_PWM_out(void){ RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM4, ENABLE); TIM_TimeBaseInitTypeDef timerInitStructure; TIM_OCInitTypeDef timer_OCInitStructure; timerInitStructure.TIM_Prescaler = 1600-1; // 32MHz / 1600 = 20kHz timerInitStructure.TIM_CounterMode = TIM_CounterMode_Up; timerInitStructure.TIM_Period = 100-1; timerInitStructure.TIM_ClockDivision = TIM_CKD_DIV1; TIM_TimeBaseInit(TIM4, &timerInitStructure); timer_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1; timer_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; timer_OCInitStructure.TIM_Pulse = 50; // TIM_OCPolarity_High -> Output High if TIM2 value < TIM_Pulse // TIM_OCPolarity_Low -> Output High if TIM2 value > TIM_Pulse timer_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High; TIM_OC3Init(TIM4, &timer_OCInitStructure); TIM_OC3PreloadConfig(TIM4, TIM_OCPreload_Enable); TIM_Cmd(TIM4, ENABLE);}void Initialize_Timer_IC(void){ RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE); TIM_TimeBaseInitTypeDef timerInitStructure; TIM_ICInitTypeDef timer_ICInitStructure; NVIC_InitTypeDef NVIC_InitStructure; timerInitStructure.TIM_Prescaler = 32-1; // 32MHz / 32 = 1MHz Tclk,timer = 1us timerInitStructure.TIM_CounterMode = TIM_CounterMode_Up; timerInitStructure.TIM_ClockDivision = TIM_CKD_DIV1; TIM_TimeBaseInit(TIM3, &timerInitStructure); timer_ICInitStructure.TIM_Channel=TIM_Channel_1; timer_ICInitStructure.TIM_ICPolarity=TIM_ICPolarity_Rising; timer_ICInitStructure.TIM_ICSelection = TIM_ICSelection_DirectTI; timer_ICInitStructure.TIM_ICPrescaler = TIM_ICPSC_DIV1; timer_ICInitStructure.TIM_ICFilter = 0x0; TIM_ICInit(TIM3, &timer_ICInitStructure); TIM_Cmd(TIM3, ENABLE); TIM_ITConfig(TIM3, TIM_IT_CC1, ENABLE); NVIC_InitStructure.NVIC_IRQChannel = TIM3_IRQn; NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0; NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; NVIC_Init(&NVIC_InitStructure);}void TIM3_IRQHandler(void){ if (TIM_GetITStatus(TIM3, TIM_IT_CC1) != RESET) { TIM_ClearITPendingBit(TIM3, TIM_IT_CC1); if(phase == 0) { Capture1 = TIM_GetCapture1(TIM3); phase = 1; } else if(phase == 1) { Capture2 = TIM_GetCapture1(TIM3); if (Capture2 > Capture1) { Capture = (Capture2 - Capture1) - 1; } else if (Capture2 < Capture1) { Capture = ((0xFFFF - Capture1) + Capture2) - 1; } else { Capture = 0; } freq_int2=(uint32_t)(100000/Capture); phase = 0; } }}2015-12-04 02:09 PM
So what happens when Capture is zero? The math in your measurement is horribly broken.
else if(phase == 1)
{
Capture2 = TIM_GetCapture1(TIM3);
Capture = (Capture2 - Capture1) ;
if (Capture)
freq_int2= 1000000 / (uint32_t)Capture; // It's 1 MHz, right?
else
freq_int2=0
phase = 0;
}
2015-12-05 02:18 AM
Corrected the code for the case Capture=0.
In the case Capture!=0 however the code isfreq_int2= 100000 / (uint32_t)Capture;
freq_int2 is ten times the real frequency since I want to measure also the 0.1HzHowever it still does not work. The measured frequency is always 0Hz and sometimes 0.1Hz.2015-12-05 04:30 AM
Make sure to properly initialize the timebase, currently random stack junk
timerInitStructure.TIM_Period = 0xFFFF; // 16-bit maximal2015-12-05 06:31 AM
freq_int2 is ten times the real frequency since I want to measure also the 0.1Hz
Then surely you'd need to divide INTO 10 Million, not 100 Thousand?