2017-06-29 09:22 AM
I'm using stm32f767NI.
I need to use a timer in input capture mode, but I would like to adapt the prescaler to the input frequency.
So I set the same channel of the timer in TimeBase mode to catch overflows and in Input Capture mode to have frequency estimation. If I have more than two overflows, I calcule the prescaler on the numbers of overflows.
I fix the input frequency on 15kHz and I have 14400 counts between two rising edges of the signal, but sometimes I have 28800 counts. Sometimes one capture interrupt is ignored.
These are the two interrupt routines:
Overflows interrupt routine:
__HAL_TIM_CLEAR_IT(&(timDrvInst[TIM8_INST].timInst), TIM_IT_UPDATE);
timDrvInst[TIM8_INST].ICOverflows++;Input Capture interrupt routine:
__HAL_TIM_CLEAR_IT(&(timDrvInst[TIM8_INST].timInst), TIM_IT_CC3);
timDrvInst[TIM8_INST].timInst.Channel = HAL_TIM_ACTIVE_CHANNEL_3; HAL_TIM_IC_CaptureCallback(&(timDrvInst[TIM8_INST].timInst)); timDrvInst[TIM8_INST].timInst.Channel = HAL_TIM_ACTIVE_CHANNEL_CLEARED;Initialization of the timer:
TIM_IC_InitTypeDef sICConfig;
/* Set TIMx instance */ timDrvInst[*instInd].timInst.Instance = tim;/* Initialize TIMx peripheral as follows:
+ Period = 0xFFFF + Prescaler = 0 + ClockDivision = 0 + Counter direction = Up */ timDrvInst[*instInd].timInst.Init.Period = 0xFFFF; timDrvInst[*instInd].timInst.Init.Prescaler = 0; timDrvInst[*instInd].timInst.Init.ClockDivision = 0; timDrvInst[*instInd].timInst.Init.CounterMode = TIM_COUNTERMODE_UP; timDrvInst[*instInd].timInst.Init.RepetitionCounter = 0; if (HAL_TIM_Base_Init(&(timDrvInst[*instInd].timInst)) != HAL_OK) { /* Initialization Error */ return RET_TIM_INIT_ERROR; }/*##-2- Start the TIM Base generation in interrupt mode ####################*/
/* Start Channel1 */ if (HAL_TIM_Base_Start_IT(&(timDrvInst[*instInd].timInst)) != HAL_OK) { /* Starting Error */ return RET_TIM_INIT_ERROR; } HAL_TIM_IC_MspInit(&(timDrvInst[*instInd].timInst));sICConfig.ICPolarity = TIM_ICPOLARITY_RISING;
sICConfig.ICSelection = TIM_ICSELECTION_DIRECTTI; sICConfig.ICPrescaler = TIM_ICPSC_DIV1; sICConfig.ICFilter = 0; //Inizializzo meanDiv, cioè il il numero di ingressi per calcolare un perdiodo medio timDrvInst[*instInd].meanDiv = 1; if(HAL_TIM_IC_ConfigChannel(&(timDrvInst[*instInd].timInst), &sICConfig, chan) != HAL_OK) { /* Configuration Error */ return RET_TIM_INIT_ERROR; } /*##-3- Start the Input Capture in interrupt mode ##########################*/ if(HAL_TIM_IC_Start_IT(&(timDrvInst[*instInd].timInst), chan) != HAL_OK) { /* Starting Error */ return RET_TIM_INIT_ERROR; }void HAL_TIM_IC_MspInit(TIM_HandleTypeDef *htim)
{
GPIO_InitTypeDef GPIO_InitStruct;
/* Configure (TIMx_Channel) in Alternate function, push-pull and high speed */ GPIO_InitStruct.Pin = GPIO_PIN_7; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; GPIO_InitStruct.Pull = GPIO_PULLUP; GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH; GPIO_InitStruct.Alternate = GPIO_AF3_TIM8; HAL_GPIO_Init(GPIOI, &GPIO_InitStruct); /* Enable GPIO channels Clock */ __HAL_RCC_GPIOI_CLK_ENABLE();__HAL_RCC_TIM8_CLK_ENABLE();
HAL_NVIC_SetPriority(TIM8_CC_IRQn, 3, 0);/* Enable the TIMx global Interrupt */
HAL_NVIC_EnableIRQ(TIM8_CC_IRQn);}
void HAL_TIM_Base_MspInit(TIM_HandleTypeDef *htim)
{ __HAL_RCC_GPIOI_CLK_ENABLE();__HAL_RCC_TIM8_CLK_ENABLE();
HAL_NVIC_SetPriority(TIM8_UP_TIM13_IRQn, 4, 1);/* Enable the TIMx global Interrupt */
HAL_NVIC_EnableIRQ(TIM8_UP_TIM13_IRQn);}What is wrong?
2017-06-29 12:54 PM
Just an observation, but
__HAL_RCC_GPIOI_CLK_ENABLE(); // Do this BEFORE usingHAL_GPIO_Init()
2017-06-29 06:45 PM
I'm not familiar with F7, but firstly, as Clive One pointed out, you need to Enable clock before writing the registers.
Secondly, if you are using HAL library,
you have to check is it acceptable to start the handle twice in different modes.
(exam the library you will see lots of handle status check)
What is the frequency range of your signal? what resolution you need?
Do you just need to measure the frequency or even duty?
2017-06-30 12:16 AM
In the hal library there is a flag that avoid to configure IC mode and Time Base mode simultaneously:
if I used HAL_TIM_IC_Init instead of HAL_TIM_IC_MspInit, the state of the timer would be CONFIGURED, set by HAL_TIM_Base_Init.
I bypass this control calling HAL_TIM_IC_MspInit and the timer works well almost anytime but one in a dozen of capture event.
My signal frequency can be between 100mHz and 20Khz
I just need to measure frequency.
2017-07-01 04:54 AM
Don't have F7 at hands right now.
I found that F767 has 32 bit timer like TIM2 or you can chain two 16 bit timers to get a 32 bit timer to cover
timer counts from 10800(20KHz) to 2160000000(100mHz). Using the later model, you can actually count overflows in your scenario.
2017-07-03 03:26 AM
SOLVED:
Reading the compare register of the timer in the overflow routine cause an access problem with capture hardware.
The capture value is not saved, so when the overflow routine ends and the capture routine starts, the capture value is lost. I have the value of the last capture and not of the actual.
Could be the same problem if I loose an overflow: when I update the prescaler, I need to write update event, then I restart the compare. Could this cause some problems to the timer overflow interrupt? What is the right routine to update prescaler?