2022-03-08 12:29 PM
I am using the STM32L4S9AII6 clocked at 120MHz.
I am trying to configure a simple (to me it should be simple) retriggerable one pulse mode timer. I was able to configure TIM6 in one-shot mode, but I had the following issues:
I am now trying to use general purpose timer TIM15 because the reference manual is inferring that this is the only timer that is capable of retriggerable one pulse mode. However, I am not even able to get this timer to trip an interrupt. My frustration is that I have now come across 3 different ST documents that explain how to configure the timer in this mode, but all of them reference hardware registers which means little to me because MxCube does not indicate what registers are being changed with the avalable settings.
Can someone please help me know how to set up a retriggerable one pulse timer using MxCube? Specifically, I want this to be completely software driven where a single pulse of fixed duration occurs at the moment I call:
HAL_TIM_Base_Start_IT(&htim15);
I do have the TIM15 interrupt enabled in MxCube. Here are the remaining pieces of configuration details, however, I have tried many different combinations of things. My expectation is that the clock ticks every micro-second (120MHz/120) and the interrupt callback gets called after about 45us (45-1).
Solved! Go to Solution.
2022-03-10 12:32 PM
Okay, It seems I have it now (Knock on Wood).
It seems that all I was missing was that I needed to clear the INT flag before enabling the interrupt at startup and again within the callback function. Again, I thought that this would be something MxCube would take care of for me, but I guess not.
htim15.Instance->SR &= ~TIM_SR_UIF; // Clear pending flag
2022-03-09 11:19 AM
For TIM1 on a L432, but should work similar:
Internal Clock will work well as clock source.
Timer needs an external trigger source like ETR1. ETR pin is then the input.
Depending on your setup, activate internal pull-up for ETR pin.
Timer must be configured in slave mode: combined reset trigger mode.
Set CH1 to PWM Generation CH1. CH1 pin is the output.
Set Prescaler, Period, and CH1 Pulse to the values needed.
Activate One Pulse Mode
Set CH1 mode to PWM mode 2.
Start timer in code with HAL_TIM_PWM_Start(&htim1, TIM_CHANNEL_1);
Maybe _IT if you like.
Output stays normally (ETR open) low.
If ETR goes low, timer is reset, any pending pulse at the output is finished.
As long as ETR remains low, output stays low.
When ETR goes high, counter counts, and, after Pulse time, output goes high until Period time or ETR low again.
hth
KnarfB
2022-03-09 01:48 PM
Let me be more clear as to what it is I'm trying to do. I want to be able to trigger a timer with a function call, delay 45us, and then run some more code. I don't want to interface to any external input or output pins.
Here is a block diagram of what I'm trying to accomplish.
2022-03-10 01:14 AM
For this, you don't need to use the slave-mode controller at all. What you call "trigger" here, is simply just enabling the timer's counter.
JW
2022-03-10 09:35 AM
First of all, thank you very much for both of your timely responses. I have been fighting this for longer than I want to admit. waclawek.jan, your response took me 95% of the way to a working solution, so thank you very much for that.
I want to document here how I configured this for others and probably my future self.
Everything waclawek.jan said is true, but from what I can tell this can NOT be fully implemented using the MxCube tool. If I am wrong, please post here how to do so. Here is how I did it. Note again that I have my system clock set to 120MHz.
However, we are not done. MxCube does not seem to have a way to set "Update Interrupt Enable", so I had to do that manually within the MX_TIM15_Init() function within main.c.
static void MX_TIM15_Init(void)
{
........
........
........
/* USER CODE BEGIN TIM15_Init 2 */
htim15.Instance->DIER |= TIM_DIER_UIE; // Update interrupt enable
/* USER CODE END TIM15_Init 2 */
}
Also, the provided APIs listed here did not work for me to trigger the timer, so I made my own function to do this manually.
Does NOT Work:
This DOES Work:
void TriggerOneShotTimer(void) {
htim15.Instance->CR1 |= TIM_CR1_CEN; // Enable Counter
}
Doing this allows the following ISR callback function to get executed about 45us later.
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
..........
..........
if (htim->Instance == TIM15) {
MyCode();
}
}
Everything now works. Again, thanks for the help!!!
2022-03-10 10:36 AM
Never mind. The solution I just posted has a serious drawback. By calling
htim15.Instance->DIER |= TIM_DIER_UIE; // Update interrupt enable
within MX_TIM15_Init() I now notice that none of my SPI ISRs are working.
How do I flip this bit without damaging other aspects of the system?
2022-03-10 11:35 AM
No, the peripherals are highly independent. And you are just flipping a bit.
There are HAL wrapper (stm32l4xx_hal_tim.h) for that like
__HAL_TIM_ENABLE_IT(&htim15, TIM_IT_UPDATE) and
__HAL_TIM_ENABLE(&htim15);
and those do just what you did.
You can also flip or watch the changes in the SFR (special function registers) view of CubeIDE while debug-stepping through the code.
Check how NVIC is setup. In the generated code this might be in a *_msp.c file.
Check the IRQ priorities, maybe a higher prio IRQ is blocking others.
Check that the peripherals get their clocks.
hth
KnarfB
2022-03-10 12:32 PM
Okay, It seems I have it now (Knock on Wood).
It seems that all I was missing was that I needed to clear the INT flag before enabling the interrupt at startup and again within the callback function. Again, I thought that this would be something MxCube would take care of for me, but I guess not.
htim15.Instance->SR &= ~TIM_SR_UIF; // Clear pending flag