Set up (for example) timer 1 and load the pulse width you want.
TIM1->ARR = PulseWidth; but don't enable the timer yet. Set up another timer for a 20ms periodic interrupt. In that interrupt, start your pulse and enable timer 1. GPIO_WriteBit(GPIOA, GPIO_Pin_0, Bit_SET); //pulse output high TIM_Cmd(TIM1, ENABLE); //start timer 1 The timer 1 interrupt will interrupt after PulseWidth period. In the timer 1 interrupt, disable and reload the timer and clear the pulse output low. void TIM1_UP_IRQHandler(void) { //Clear TIM1 update interrupt TIM_ClearITPendingBit(TIM1, TIM_IT_Update); //handle the pulse using timer 1 TIM1->CR1 &= ((uint16_t)0x03FE); //disable the TIM Counter TIM1->CNT = (uint16_t) 0; //clear the counter TIM1->ARR = PulseWidth; GPIO_WriteBit(GPIOA, GPIO_Pin_0, Bit_RESET); //pulse output low } You can change the PulseWidth on the fly if you want for different widths every 20ms.
If you understood my suggestion, you should find it works well for you for one servo. (I wrote it to drive a servo with software controlled pulse width.)
If you mean to drive
multiple servos with different pulse widths
then you may have to do more processing in a faster interrupt.
Sorry I should have specified that - the application is to drive numerous RC Servos without much CPU overhead or wait loops. Therefore I would like to vary the Pulse signal from approximately 1ms to 2ms.
An example would be greatly appreciated. I am new to STM32 and so far this community has been great!
There is an example in ST library for one pulse mode which helped me to understand the one pulse mode for timers Let's we use TIM2 and TIM4 timers: TIM2 will trigger TIM4 every 20 ms. TIM2 must be configured in such way to generate update event every 20 ms (APB frequency/ARR register = 50 Hz, I think you must use timer prescaler) and select update event of TIM2 to trigger TIM4 using TIM_SelectOutputTrigger(TIM2, TIM_TRGOSource_Update) Now TIM4 must be configured in one pulse mode then select the input trigger from TIM2 using TIM_SelectInputTrigger() (you must refer to your product reference manual to know if you should select ITR0 , ITR1 or ITR2...) Finally, select slave mode with trigger for TIM4 using TIM_SelectSlaveMode() Now enable both timers TIM_Cmd(TIMx, ENABLE) In this configuration, you don't need processing interrupts. Do not hesitate if that stills not clear otherwise tell me how I can send you my source. Herzlich, MCU Lüfter
I think this would probably work, thanks for your example. I will try it. I know I didn't specify the pulse should change in my original post, but in order to maximize resolution for adjusting the pulse width I believe I should adjust the scale so that period is close to 65536. Please confirm my calculations here:
SYSClock = 72Mhz
AHB prescalar = 1
APB1 prescalar = 2
PCLK1 = 36 Mhz
Scale = (36000000*.02)/65536 = 11 (3.272 Mhz)
Period = (36000000/11)*.02 = 65455
Width(1ms) = 3272
Width(2ms) = 6546
This effectively gives me a resolution of about 3273 between 1ms and 2ms, correct?
Look at the clock tree again, I'm pretty sure that the timer clock will still be 72 MHz I picked values to get the 20 ms exact. But yes you just reduce the scale to give you finer granularity in the width control, while keeping the numbers below 65536. You should be able to get the counter to generate an interrupt, and modulate the width there. Fix to my code printf(''TIM4 rate %d Hz, width %d us\n'',TIM4_Frequency, TIM4_Width); You could use floats to provide decimals places.
Tips, Buy me a coffee, or three.. PayPal VenmoUp vote any posts that you find helpful, it shows what's working..