2020-07-20 05:03 AM
I'm using STM32F108RG on 48MHz clock configuration.
I need to generate a 1 micrososeconds timer tick on it, for driving an output pin interfaced with a 3rd party device. Using PWM is not an option available.
I tried configuring TIM3 with following parameters:
Clock: Internal (48MHz)
Prescaler: 47 (48 - 1)
Counter Mode: Up
Counter Period (Auto-Reload Register -16 bit): 1
Internal Clock Division: No Division
Auto-reload preload: Disabled
With these settings, the closest I can reach is 6.8us.
I was able to generate 10us with the above settings with Counter Period set to 10,
but it doesn't seem to go below 6.8us.
I also tried TIM1 for the same purpose, but got the same observations.
Is that a limitation of the device, or do I need to perform any additional steps?
2020-07-20 05:10 AM
Don't interrupt at these speeds you will saturate the processor.
Have a TIM count at 1 MHz, and spin on TIM->CNT advancing a required amount.
Consider also DWT_CYCCNT
2020-07-20 06:12 AM
You could use SPI with a 1MHz clock to output an arbitrary signal. Calling an interrupt at 1MHz isn't going to pan out well. It'll take more than 48 ticks for the ISR to complete.
2020-07-20 08:08 AM
Thanks for the response, clive1
I'm a complete noob on STM32 platform (otherwise wouldn't have had posted such queries)
So what exactly do you mean by "spin on TIM->CNT"?
Also, what is 'DWT_CYCCNT'?
I gave it a search in the HAL library thinking that it's some sort of peripheral register,
but couldn't find it.
Apologies for asking for more help on this.
2020-07-20 08:09 AM
That would have been a great idea.
Thanks for the response, TDK; but I don't think I have enough SPI peripherals left on my application.
2020-07-20 08:47 AM
If terms are unfamiliar stick them into Google or the search here, should be preexisting examples and postings.
With TIM3, prescale 47, period 0xFFFF (maximal)
void delay_us(uint16_t us)
{
uint16_t start = TIM3->CNT;
while((TIM3->CNT - start) < us) {};
}
For finer granularity, let the TIM clock faster, use a 32-bit TIM where available
2020-07-20 08:54 AM
//****************************************************************************
volatile unsigned int *DWT_CYCCNT = (volatile unsigned int *)0xE0001004; //address of the register
volatile unsigned int *DWT_CONTROL = (volatile unsigned int *)0xE0001000; //address of the register
volatile unsigned int *DWT_LAR = (volatile unsigned int *)0xE0001FB0; //address of the register
volatile unsigned int *SCB_DEMCR = (volatile unsigned int *)0xE000EDFC; //address of the register
//****************************************************************************
void EnableTiming(void)
{
*SCB_DEMCR |= 0x01000000;
*DWT_LAR = 0xC5ACCE55; // enable access (required on Cortex-M7)
*DWT_CYCCNT = 0; // reset the counter
*DWT_CONTROL |= 1 ; // enable the counter
}
//****************************************************************************
void Delay(uint32_t cycles) // Based on SystemCoreClock, at 48 MHz, 48 cycles is 1us, 48000 cycles is 1ms
{
uint32_t start = *DWT_CYCCNT;
while((*DWT_CYCCNT - start) < cycles);
} // sourcer32@gmail.com
//****************************************************************************
2020-07-20 09:08 AM
interrupts at 10kHz or higher is the symptom of danger. use hw assist as much as possible. if you have a spare timer pin channel or spi mosi, short it with the one you want to send a pulse pattern by dma if needed. no spare pin? new board design?
2020-07-20 09:56 AM
Indeed modulating patterns with fixed timing requirements can be done with TIM+DMA+GPIO more effectively than using timing loops eating all processor resources.
Consider also logic or CPLDs for hardware orientated problems.
2020-07-20 09:57 AM
With hard software timing loops you're going to run out of bandwidth for your application pretty quickly