cancel
Showing results for 
Search instead for 
Did you mean: 

HAL_TIM_ReadCapturedValue returning zero even if interrupt is called

DMårt
Lead

Hi!

I have enabled encoder and input capture and only encoder works.

The reason is that CCR3 and CCR4 is zero.

HAL_TIM_ReadCapturedValue

Why does this happen? I have enabled NVIC for TIM4 and TIM19 and HAL_TIM_IC_CaptureCallback is called when the Input Capture get a rising edge, but still, CCR3 and CCR4 is zero. Why?

0693W00000BbbpEQAR.png0693W00000BbbpnQAB.png 

Here is when I am in the debug mode.

0693W00000BbbpdQAB.pngHere is my complete and very simple C-code.

/*
 * Counter.c
 *
 *  Created on: Jun 13, 2021
 *      Author: 
 */
 
#include "Functions.h"
 
static uint16_t encoder[2];
volatile static uint16_t input_capture[3];
 
void STM32_PLC_Start_Counters(TIM_HandleTypeDef* htim4, TIM_HandleTypeDef* htim19) {
	/* Encoder */
	HAL_TIM_Encoder_Start_IT(htim4, TIM_CHANNEL_ALL);
	HAL_TIM_Encoder_Start_IT(htim19, TIM_CHANNEL_ALL);
	encoder[0] = 0x8000; /* Initial settings */
	encoder[1] = 0x8000;
 
	/* Input Capture */
	HAL_TIM_IC_Start_IT(htim4, TIM_CHANNEL_3);
	HAL_TIM_IC_Start_IT(htim4, TIM_CHANNEL_4);
	HAL_TIM_IC_Start_IT(htim19, TIM_CHANNEL_3);
	input_capture[0] = 0; /* Initial settings */
	input_capture[1] = 0;
	input_capture[2] = 0;
}
 
void STM32_PLC_Encoder0(TIM_HandleTypeDef* htim) {
	bool encoder0_direction = !(__HAL_TIM_IS_TIM_COUNTING_DOWN(htim));
 
	/* Values between 0 and 0xFFFF */
	if(encoder0_direction)
		encoder[0] = 0x8000 + __HAL_TIM_GetCounter(htim); /* Positive rotation: 0x8000 - 0xFFFF */
	else
		encoder[0] = __HAL_TIM_GetCounter(htim) - 0x8000; /* Negative rotation: 0 - 0x7FFF */
}
 
void STM32_PLC_Encoder1(TIM_HandleTypeDef* htim) {
	bool encoder1_direction = !(__HAL_TIM_IS_TIM_COUNTING_DOWN(htim));
 
	/* Values between 0 and 0xFFFF */
	if(encoder1_direction)
		encoder[1] = 0x8000 + __HAL_TIM_GetCounter(htim); /* Positive rotation: 0x8000 - 0xFFFF */
	else
		encoder[1] = __HAL_TIM_GetCounter(htim) - 0x8000; /* Negative rotation: 0 - 0x7FFF */
}
 
uint16_t STM32_PLC_Encoder_Get(uint8_t i) {
	return encoder[i];
}
 
void STM32_PLC_Input_Capture0(TIM_HandleTypeDef* htim) {
	input_capture[0] = HAL_TIM_ReadCapturedValue(htim, TIM_CHANNEL_4);
}
 
void STM32_PLC_Input_Capture1(TIM_HandleTypeDef* htim) {
	input_capture[1] = HAL_TIM_ReadCapturedValue(htim, TIM_CHANNEL_3);
}
 
void STM32_PLC_Input_Capture2(TIM_HandleTypeDef* htim) {
	input_capture[2] = HAL_TIM_ReadCapturedValue(htim, TIM_CHANNEL_3);
}
 
uint16_t STM32_PLC_Input_Capture_Get(uint8_t i) {
	return input_capture[i];
}
 
/* Callbacks for Encoder and Input Capture */
void HAL_TIM_IC_CaptureCallback(TIM_HandleTypeDef* htim){
	if (htim->Instance == TIM4) {
		if(htim->Channel == HAL_TIM_ACTIVE_CHANNEL_3)
			STM32_PLC_Input_Capture1(htim);
		else if(htim->Channel == HAL_TIM_ACTIVE_CHANNEL_4)
			STM32_PLC_Input_Capture0(htim);
		else if(htim->Channel == HAL_TIM_ACTIVE_CHANNEL_1 || htim->Channel == HAL_TIM_ACTIVE_CHANNEL_2)
			STM32_PLC_Encoder0(htim);
	} else if (htim->Instance == TIM19) {
		if(htim->Channel == HAL_TIM_ACTIVE_CHANNEL_3)
			STM32_PLC_Input_Capture2(htim);
		else if(htim->Channel == HAL_TIM_ACTIVE_CHANNEL_1 || htim->Channel == HAL_TIM_ACTIVE_CHANNEL_2)
			STM32_PLC_Encoder1(htim);
	}
}

STM32MP151AAC3 custom board with STM32-OS as operating system: https://github.com/DanielMartensson/STM32-Computer
1 ACCEPTED SOLUTION

Accepted Solutions

That is one of the ways how to do it.

JW

View solution in original post

8 REPLIES 8
TDK
Guru

CNT is also zero. Seems reasonable that the input capture was triggered when CNT=0, which would lead to CCR3=0 as well. What value are you expecting it to be?

Not sure if encoder and IC can be used simultaneously, but if they can, they share the same counter.

If you feel a post has answered your question, please click "Accept as Solution".

> Not sure if encoder and IC can be used simultaneously

Yes it can, and, as you've said, it captures the value counted for the encoder. For time measurement, another timer has to be used.

Also, nonzero prescaler in encoder mode leads to nonsensical readings.

JW

Thank you.

I have set the prescaler to 0.

So I need to have a counter that measure the time between two interrupts?

STM32MP151AAC3 custom board with STM32-OS as operating system: https://github.com/DanielMartensson/STM32-Computer

I'm expecting that CNT would remember its past value.

How can I set up another timer for measuring speed for Input capture?

STM32MP151AAC3 custom board with STM32-OS as operating system: https://github.com/DanielMartensson/STM32-Computer

There is only one counting element in one timer. You either use it for the encoder, or for measuring time, can't do both in the same timer.

JW

So the reason why I'm getting CCR3 = 0 all the time, is because I'm using the Encoder at the same timer.

So if I want to measure the difference between two interrupts, I can just use HAL_SysTick() to get a value and the next interrupt, I compare the old SysTick value with next SysTick value?

STM32MP151AAC3 custom board with STM32-OS as operating system: https://github.com/DanielMartensson/STM32-Computer

That is one of the ways how to do it.

JW

Thank you!

STM32MP151AAC3 custom board with STM32-OS as operating system: https://github.com/DanielMartensson/STM32-Computer