2024-10-24 02:15 PM
NUCLEO-64 STM32L476RG
STM32CubeIDE 1.10.1
Trying to get a microsecond delay to work based on this post.
APB1 Timer = 80 MHz from HSI->PLLCLK.
TIM6 = 1 MHz (Prescaler = 79, ARR = 0xFFFF)
My main (after MX stuff) looks like this and sets delay to 5000 us (5 ms).
LL_TIM_EnableCounter(TIM6);
while (1)
{
LL_GPIO_TogglePin(LD2_GPIO_Port, LD2_Pin);
DelayUs(5000);
}
My delay function looks like this.
static inline void DelayUs(uint16_t us)
{
uint16_t start = TIM6->CNT;
while((TIM6->CNT - start) < us);
}
The scope on LD2 shows this.
So I'm getting 5 ms pulses but occasionally it doesn't switch and essentially doubles up. I'm very much still learning all this and dug into the datasheets as much as I could, but at this point I need help from people far smarter than me :) Any help is greatly appreciated!
2024-10-24 02:34 PM
I'd use 32-bit TIM, will give you more run-way.
Would also not divide down much, as that will give you much finer granularity. You could divide by 8 (PSC=7) and get 1/10 us resolution, 6.5536 ms like scope (at 16-bit)
It randomly doubling on/off doesn't look to be consistent with a wrapping issue.
Anything else going on in the system here? Interrupts, etc?
Look at the generated code.
Perhaps counter-point with another TIM with a physical pin in toggle mode and 5ms period.
2024-10-24 04:25 PM
while((uint16_t)(TIM6->CNT - start) < us);
2024-10-24 05:39 PM
Hi,
Unfortunately, C is not good at overflow arithmetic. You need to change your strategy -
Change the Timer mode to Single Pulse Mode, set the appropriate prescalers etc...
static inline void DelayUs(uint16_t us) {
TIMx->CR1 &= ~TIM_CR1_CEN; //stop counter, if it happens to be going...
TIMx->ARR = us - 1; //preset counter
TIMx->EGR |= TIM_EGR_UG; //reset counter
TIMx->CR1 |= TIM_CR1_CEN; //start counter
while (TIMx->CR1 & TIM_CR1_CEN) {}
}
I hope that helps.
Kind regards
Pedro
2024-10-24 05:58 PM
PS: my notes say that there are bugs in HAL with setting up Single Pulse Mode - I do it manually. If there are problems, I can edit and post some code...
Kind Regards
Pedro
2024-10-25 08:05 AM
Thanks everyone!
@Pavel A. I swear I tried this before and it had no effect. Now it is stable at 5 ms.
@PGump.1 This also made it stable at 5 ms.
@Tesla DeLorean I'll have to get up to speed on setting up a 32-bit timer (only really know about basic timers at the moment). Not dividing down so much didn't fix the issue, but with the above recommendations I was able to get closer to us values. Ya no interrupts or anything, its a new project with the only additions in the OP.
So with @Pavel A. and @PGump.1 recommendations I was able to get good pulses at 5 ms. I can get to about 10 us before the pulses start to skew more significantly. At a demand of 1 us I get 2 us delay with @Pavel A. and a 2.5 us delay with @PGump.1 (I'm assuming due to the extra overhead in the function). If at all possible, I'd like to be within 10% of the demand, so 1.1 us would be great. I'll see if I can't get a 32-bit timer from @Tesla DeLorean up and running and see if that helps.
2024-10-25 08:29 PM
Hi,
You should study the timer and how the prescalers operate, this will help you make good choices. I use this strategy to create X 100nS timing. Plus, it can be easily modified for non-blocking...
Kind regards
Pedro