AnsweredAssumed Answered

Problems with input capture on Nucleo152RE

Question asked by grossi.marco on Dec 4, 2015
Latest reply on Dec 5, 2015 by Clive One
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;
    }
  }
}

Outcomes