cancel
Showing results for 
Search instead for 
Did you mean: 

Trying to find best and most reliable way when using the STM32 timers to change the timebase 'on the fly'.

mistert
Associate II

Hi, I've recently retired from being an electronics design engineer for over 40 years. I wanted to have some fun playing around with micros to do some basic control. I have both the Nucleo-F030R8 and STM32F4 Discovery evaluation boards and have been teaching myself on STM32CubeIDE. I am at the stage of writing some basic code and running it on the F0 board, The ST videos have been very helpful. What I'm trying to do is to create a timebase to drive a unipolar stepper motor driver board clock (I have lots of hardware already). I am currently using one of the timers in PWM mode to do this with pulse set to zero (my clock to the driver board is edge triggered and the driver board takes care of the motor phase outputs). The reason for this request is I'm trying to create a simple acceleration profile. So far I have a clock output which I've been able to change period on a cycle by cycle basis within the main code using the period end interrupt to set a flag which is detected and the ARR register changed, which seemed to work well. I've now progressed to try to get this to work within the ISR (period end triggered) without much success. Can one actually change the Timer ARR register so that it sync's every cycle to get a different consecutive period lengths. I'm thinking if the ARR register is changed in the ISR will that 'miss' the next cycle. I've not found a way yet of finding an interrupt that is say a proportion into the period where I can change the ARR value to guarantee a change at the next cycle. I could use the pulse width within the timer when set to PWM mode but that means I will also have to change that every time as well. Also, I've not managed to find a way of setting a Timer in base interrupt mode to drive an output pin, which may be easier than using in PWM mode. All this done by a lot of experimentation, maybe I'm just getting too old for this 🙂 If anyone can give me some pointers I would be most grateful. In the meantime I'll keep trying and learning. Thanks

1 ACCEPTED SOLUTION

Accepted Solutions

I don't quite understand what is your problem, but if you set ARR preload (TIMx_CR1.ARPE=1), ARR set in one Update interrupt gets active at the next Update - probably that's what you want. Also if you use CCRx preload, in the same interrupt you change both ARR and CCRx, and both get active simultaneously at the next Update.

Don't try to push the frequency to high if you use interrupts, generally interrupts should be not more often than once in 1000 system clock cycles, one or two orders of magnitude more if you want to stay on the safe side.

Next step would be to use DMA.

Generally, try to avoid Cube, and read the TIM chapter in RM, mainly the registers description, repeatedly, until it starts to make sense.

JW

View solution in original post

4 REPLIES 4

I don't quite understand what is your problem, but if you set ARR preload (TIMx_CR1.ARPE=1), ARR set in one Update interrupt gets active at the next Update - probably that's what you want. Also if you use CCRx preload, in the same interrupt you change both ARR and CCRx, and both get active simultaneously at the next Update.

Don't try to push the frequency to high if you use interrupts, generally interrupts should be not more often than once in 1000 system clock cycles, one or two orders of magnitude more if you want to stay on the safe side.

Next step would be to use DMA.

Generally, try to avoid Cube, and read the TIM chapter in RM, mainly the registers description, repeatedly, until it starts to make sense.

JW

There is a shadow register option which allows a load to occur at the update event. You could also feed new values via DMA

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..

Hi JW

Firstly thanks for your reply.

Regarding your first point, yes that is what I'm trying to do, I have the ARR enabled for pre-load. I am changing the ARR value within the timer interrupt for every interrupt instance (for a small number of changes at least), looking again it seems the interrupt always occurs at the end period and thus any change to ARR (or CCR) in the ISR will happen at the next count expiry as the counter has already started its next cycle by then.

I'm only running the timer clock at a few kHz max so don't believe this should be an issue.

Yes, I did see one can do what I want using DMA and it would be a further step. I was planning on a manually controlled (likely via the ADC) speed stepper motor, so the sequence changes in the timer count value to accelerate from x to y speed would always be different, which would need some thinking about to do via DMA where you have fixed steps. It maybe that once the stepper motor has started I can just change speed without need to accelerate which would be much easier, then I could use the DMA option just to do the first acceleration from zero speed.

What do you propose using instead of Cube. I must admit all the HAL functions are confusing so think going back to 'what I know' programming will likely help my understanding at hardware level. I have read in more detail now about the timer and you're right reading it over a few times helps. I've now hooked up my scope to look at the outputted signals toggling the onboard LED within the ISR and seeing the relation to the timer output pin. At least this way I can do some experimentation.

Off to do some more coding and playing now.

Appreciate your guidance.

Paul

Many Thanks for the advice. I think I'm getting there 😀