cancel
Showing results for 
Search instead for 
Did you mean: 

STM32F4 Timer Input capture problem

RN
Senior
Posted on May 19, 2018 at 12:48

Hello , 

I am using stm32f446re nucleo board . and i face some issue in timer input capture . 

here i am using 2 timers TIM6 ( for time base generation ) and TIM2 (free running input capture purpose)

actually my code is working fine when i run the first timer(TIM6) at 10 micro or 100 micro second time base generation . I actually toggle the gpio in IRQ handler of TIM6 and that is input to the TIM2 input channel where i detect the gap between rising and falling edge of a gpio . TIM2 actually DMA the content of CCR1 to memory . 

as i said this works  fine when i use the TIM6 for 10 micro and 100 micro time base generation 

but when i use the TIM6 for 1 mirco second time base generation , the TIM2 is not giving correct values for the gpio toggling . Can you please help me to understand what is going wrong ?

i am using AHB = 84Mhz, timer clock = 48Mhz. 

Here is a code 

int main(void)

{

/* USER CODE BEGIN 1 */

uint32_t diffCapture=0;

double frequency=0;

char msg[30];

/* USER CODE END 1 */

/* MCU Configuration----------------------------------------------------------*/

/* Reset of all peripherals, Initializes the Flash interface and the Systick. */

HAL_Init();

/* USER CODE BEGIN Init */

/* USER CODE END Init */

/* Configure the system clock */

SystemClock_Config();

/* USER CODE BEGIN SysInit */

/* USER CODE END SysInit */

/* Initialize all configured peripherals */

MX_GPIO_Init();

MX_DMA_Init();

MX_USART2_UART_Init();

MX_TIM6_Init();

MX_TIM2_Init();

/* USER CODE BEGIN 2 */

HAL_TIM_IC_Start_DMA(&htim2, TIM_CHANNEL_1, (uint32_t*) captures, 2);

HAL_TIM_Base_Start_IT(&htim6);

/* USER CODE END 2 */

/* Infinite loop */

/* USER CODE BEGIN WHILE */

while (1)

{

   if (captureDone != 0) {

   if (captures[1] >= captures[0])

   diffCapture = captures[1] - captures[0];

   else

   diffCapture = (htim2.Instance->ARR - captures[0]) + captures[1];

   frequency = HAL_RCC_GetPCLK1Freq() / (htim2.Instance->PSC + 1);

   frequency = (float) frequency / diffCapture;

   sprintf(msg, 'Input frequency: %.3f\r\n', frequency);

   //HAL_UART_Transmit(&huart2, (uint8_t*) msg, strlen(msg), HAL_MAX_DELAY);

   //while (1);

}

}

}

/* TIM2 init function */

static void MX_TIM2_Init(void)

{

TIM_MasterConfigTypeDef sMasterConfig;

TIM_IC_InitTypeDef sConfigIC;

htim2.Instance = TIM2;

htim2.Init.Prescaler = 0;

htim2.Init.CounterMode = TIM_COUNTERMODE_UP;

htim2.Init.Period = 65535;

htim2.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;

if (HAL_TIM_IC_Init(&htim2) != HAL_OK)

{

_Error_Handler(__FILE__, __LINE__);

}

sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET;

sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;

if (HAL_TIMEx_MasterConfigSynchronization(&htim2, &sMasterConfig) != HAL_OK)

{

_Error_Handler(__FILE__, __LINE__);

}

sConfigIC.ICPolarity = TIM_INPUTCHANNELPOLARITY_RISING;

sConfigIC.ICSelection = TIM_ICSELECTION_DIRECTTI;

sConfigIC.ICPrescaler = TIM_ICPSC_DIV1;

sConfigIC.ICFilter = 0;

if (HAL_TIM_IC_ConfigChannel(&htim2, &sConfigIC, TIM_CHANNEL_1) != HAL_OK)

{

_Error_Handler(__FILE__, __LINE__);

}

}

/* TIM6 init function */

static void MX_TIM6_Init(void)

{

TIM_MasterConfigTypeDef sMasterConfig;

htim6.Instance = TIM6;

htim6.Init.Prescaler = 0;

htim6.Init.CounterMode = TIM_COUNTERMODE_UP;

htim6.Init.Period = 47;

if (HAL_TIM_Base_Init(&htim6) != HAL_OK)

{

_Error_Handler(__FILE__, __LINE__);

}

sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET;

sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;

if (HAL_TIMEx_MasterConfigSynchronization(&htim6, &sMasterConfig) != HAL_OK)

{

_Error_Handler(__FILE__, __LINE__);

}

}

/* USER CODE BEGIN 4 */

void HAL_TIM_IC_CaptureCallback(TIM_HandleTypeDef *htim) {

if (htim->Channel == HAL_TIM_ACTIVE_CHANNEL_1) {

captureDone = 1;

}

}
10 REPLIES 10
Posted on May 19, 2018 at 13:28

actually toggle the gpio in IRQ handler of TIM6

when i use the TIM6 for 1 mirco second time base generation , the TIM2 is not giving correct values for the gpio toggling

Executing the IRQ handler probably takes more than 1 microsecond.

Observe the waveform with an oscilloscope or logic analyzer. Better yet, use a timer with output channel and generate the waveform purely in hardware (PWM).

JW

Posted on May 19, 2018 at 13:42

Thanks for the reply , 

Actually TIM2 runs till 65535( @48Mhz) that is  ~1.3ms , even if TIM6 IRQ handler takes more than 1mirco second , it shouldnt be problem for input compare isnt it ?

Posted on May 19, 2018 at 17:19

TIM2 should be 32-bit, you should use full range (0xFFFFFFFF)

 diffCapture = captures[1] - captures[0]; // should work with ALL values, wrapping will be managed/contained within the uint32_t math

The TIM Clock on APB1 (PCLK1) will typically be PCLK*2 for any divider other than 1

>>i am using AHB = 84Mhz, timer clock = 48Mhz. 

Half of 84 is 42, not 48, the TIMCLK in this context will almost certainly be 84 MHz

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
henry.dick
Senior II
Posted on May 19, 2018 at 17:27

'

when i use the TIM6 for 1 mirco second time base generation ,'

make sure the ISR can be executed within that time framework.

Posted on May 19, 2018 at 17:31

The 8-ball here says ''signs point to no''

0690X0000060KrgQAE.png
Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
Posted on May 19, 2018 at 17:47

Problem is not with the input capture of TIM2, but with the signal generation using interrupt of TIM6.

JW

Posted on May 20, 2018 at 08:22

Thanks . now i understood basically the gpio cannot able to toggle exactly at 1mirco second due to delay caused by IRQ processing . now suppose if i want to toggle the gpio at 1 micro second ,what is the alternate ? i tried output compare toggle mode and max i can achieve is 300KHz switching frequency . How can i increase this to 1Mhz ? There also IRQ processing is involved where i need to feed the output compare register like below code

 if i switch to DMA can i achieve 1 MHz toggling ?

void HAL_TIM_OC_DelayElapsedCallback(TIM_HandleTypeDef *tim)

{

uint32_t pulse;

/* TIM2_CH1 toggling with frequency = 50KHz */

if(tim->Channel == HAL_TIM_ACTIVE_CHANNEL_1)

{

pulse = HAL_TIM_ReadCapturedValue(tim, TIM_CHANNEL_1);

/* Set the Capture Compare Register value */

__HAL_TIM_SET_COMPARE(&htim3, TIM_CHANNEL_1, (pulse + ch1_pulse_value));

}

}
Posted on May 20, 2018 at 08:26

Thanks . i am sorry,  the config is AHB=84Mhz and timer clock = 84Mhz as you said. can i get 1Mhz of output toggling using timer 2 ? is there any register where i can configure the pulse value and it generates output waveform auto feeding the output compare register ? instead of feeding it through DMA or IRQ handler ?

Posted on May 20, 2018 at 23:30

Autonomously outputting pulses - this is what the PWM mode of timer is all about.

So, read about PWM.

JW