2021-07-24 11:34 AM
Hi,
I am new with the STM32H7 timer/counter. I found the LPTIM_PulseCounter example which was good starting point. But I have a couple of questions:
Thanks for your help!
Louis
Solved! Go to Solution.
2021-07-27 10:07 AM
Hi TDK,
Thanks, its working now. But, the next problem is the 16-bit encoder counter overflows and I could not find a interrupt handler (callback!!!) which would handle the encoder over/underflow. I drive the encoder from 10kHz pulses for 10 seconds. Counting on CH1/CH2 rising edges are configured so the encoder would contain 200 000 pulses. But it contains 3392, which is right because it overflows 3 times (3 * 65536) + 3392 = 200 000. I could handle it except this stupid way:
uint32_t lastEncoderPulses = 0;
while (1)
{
HAL_Delay(50);
//+++++
// TFS20210727 Read counter of TIMER4
// Take care about overflow manually because no interrupt provided for counter overflow...
//-----
encoderPulses = __HAL_TIM_GetCounter(&htim4);
if (encoderPulses < lastEncoderPulses)
encoderPulsesOvf++;
lastEncoderPulses = encoderPulses;
}
I found the following callbacks for TIMER4 in the "Description of STM32G4 HAL and low-layer drivers" manual. Please note that this is for STM32G4 not STM32H7 device...
58.2.9 TIM Callbacks functions
This section provides TIM callback functions:
• TIM Period elapsed callback
• TIM Output Compare callback
• TIM Input capture callback
• TIM Trigger callback
• TIM Error callback
• TIM Index callback (Not found or not implemented)
• TIM Direction change callback (Not found or not implemented)
• TIM Index error callback (Not found or not implemented)
• TIM Transition error callback
This section contains the following APIs:
• HAL_TIM_PeriodElapsedCallback
• HAL_TIM_PeriodElapsedHalfCpltCallback
• HAL_TIM_OC_DelayElapsedCallback
• HAL_TIM_IC_CaptureCallback
• HAL_TIM_IC_CaptureHalfCpltCallback
• HAL_TIM_PWM_PulseFinishedCallback
• HAL_TIM_PWM_PulseFinishedHalfCpltCallback
• HAL_TIM_TriggerCallback
• HAL_TIM_TriggerHalfCpltCallback
• HAL_TIM_ErrorCallback
Which one is the counter over/underflow? None.
Yes, the reference manual contains the description of the registers and registers bit. But, what I am looking for is an Example APP or a document which describes what I need to do and why (initialization, start, stop, clear, overflow handling) in order to be able to use Encoder. I could not find such document. I do not think it even exists.
Thank you for your help. I appreciate it very much.
Louie
2021-07-27 10:34 AM
2021-07-28 05:01 AM
Thanks TDK for the explanations, but the HAL_TIM_PeriodElapsedCallback() is never called back (in my case). The TIMER4 encoder gets 200 000 pulses under 10 seconds. The TIMER4 counter should overflow 3 times. But, if I set a breakpoint into the HAL_TIM_PeriodElapsedCallback() - where I increment the ecnoderPulsefOvf (Overflow) variable - then then the breakpoint is never hit.
Maybe I am doing something wrong. In main.c: enable TIMER4 interrupt:
// Set the TIM4 priority
HAL_NVIC_SetPriority(TIM4_IRQn, 0, 1);
// Enable the TIM4 global Interrupt
HAL_NVIC_EnableIRQ(TIM4_IRQn);
In main.c: start encoder with interrupt:
if(HAL_OK != HAL_TIM_Encoder_Start_IT(&htim4, TIM_CHANNEL_ALL))
{
Error_Handler();
}
In main.c: Handling the callback event:
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
// Works?
encoderPulsesOvf++;
}
In stm32h7xx_it.c: defining TIMER4 interrupt handler:
void TIM4_IRQHandler(void)
{
HAL_TIM_IRQHandler(&htim4);
}
So what do you think? What am I doing wrong?
Thanks for your help!
Louis
2021-07-28 06:49 AM
It doesn't look like HAL_TIM_Encoder_Start_IT actually enable the update interrupt. You can do this manually after starting the encoder:
/* Enable the TIM Update interrupt */
__HAL_TIM_ENABLE_IT(&htim4, TIM_IT_UPDATE);
HAL_TIM_Encoder_Start_IT does enable the CC1 and CC2 interrupts, which are going to cause HAL_TIM_IC_CaptureCallback to get called. It looks like this is the way HAL intends you to use the encoder in timer mode. Set CCR1 to 0 and CCR2 to half-range to be able to detect overflows. Check for htim->Channel == HAL_TIM_ACTIVE_CHANNEL_1 or HAL_TIM_ACTIVE_CHANNEL_2 to see which is getting called.
2021-07-29 06:52 AM
Hi TDK,
Genius! That solved my interrupt problem. Many thanks for the suggestion.
However, as I mentioned it earlier, if I enable TIMER4 CH1 = PD12 and CH2 = PD13 then the touch screen initialization returns error. I checked it and I found this is because the I2C controller of the touch screen uses PD12/13 as data/clock line. That means TIMER4 can't be used with touch screen at the same time. Too bad!
I also found that TIMER8 can be used. The CH1 and CH2 of TIMER8 can be PC6/7 ports. PC6/7 are used in camera driver which is not needed. The problem is when I try to enable the over/underflow interrupts for TIMER8 I get an error : TIM8_IRQn is not defined:
// Set the TIM8 priority
HAL_NVIC_SetPriority(TIM8_IRQn, 0, 1);
/* TDK: Enable the TIM Update interrupt */
__HAL_TIM_ENABLE_IT(&htim8, TIM_IT_UPDATE);
// Enable the TIM4 global Interrupt
HAL_NVIC_EnableIRQ(TIM8_IRQn);
I checked it and it is true. I have the following IRQ definitions only:
TIM8_BRK_TIM12_IRQn = 43, /*!< TIM8 Break Interrupt and TIM12 global interrupt */
TIM8_UP_TIM13_IRQn = 44, /*!< TIM8 Update Interrupt and TIM13 global interrupt */
TIM8_TRG_COM_TIM14_IRQn = 45, /*!< TIM8 Trigger and Commutation Interrupt and TIM14 global interrupt */
TIM8_CC_IRQn = 46, /*!< TIM8 Capture Compare Interrupt */
My stupid question is which one I can use instead of TIM8_IRQn? Why does the HAL support different the TIMER8 and TIMER4?
Many thanks for your help.
Best regards,
Louis
2021-07-29 07:01 AM
2021-07-29 07:43 AM
Hi TDK,
Yes, I did that. The TIM8_UP_TIM13_IRQn was my first pick (before I asked you):
// Set the TIM8 priority
HAL_NVIC_SetPriority(TIM8_UP_TIM13_IRQn, 0, 1);
/* TDK: Enable the TIM Update interrupt */
__HAL_TIM_ENABLE_IT(&htim8, TIM_IT_UPDATE);
// Enable the TIM4 global Interrupt
HAL_NVIC_EnableIRQ(TIM8_UP_TIM13_IRQn);
The callback never hit:
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
// Other timers can use this callback
if (htim->Instance == TIM8)
encoderPulsesOvf++;
}
Even it falls into a infinitive loop:
If I comment out "__HAL_TIM_ENABLE_IT(&htim8, TIM_IT_UPDATE)" then there is no inf. loop, but the callback is never hit.
I guess because the used the TIMER8 update IRQ, we do not need to enable it again. This seems to me logical, but why not the callback is not hit?
Any idea?
Thanks,
Louis
2021-07-29 08:07 AM
It's in an interrupt handler that you didn't define so it defaults to Default_Handler.
Ensure TIM8_UP_TIM13_IRQHandler is defined appropriately.
2021-07-29 08:56 AM
Hi TDK!
Super, as always, you are right, I used void TIM8_IRQHandler(void) which does not exist. Defining void TIM8_UP_TIM13_IRQHandler(void) solved the problem. One note: I still have to call __HAL_TIM_ENABLE_IT(&hTimer8, TIM_IT_UPDATE). Without this the callback function is never hit.
Both the ENCODER (TIMER8) and the touch screen works. Many thanks for your help.
Now the only thing left: how to measure the frequency of signals counted by TIMER8? Can I attach another timer (in order to measure the frequency) to the same pins (PC6/PC7) which are already used by TIMER8? Or I have to wire the signal connected to PC6/PC7 to other pins?
Thanks,
Louis
2021-07-29 09:10 AM