cancel
Showing results for 
Search instead for 
Did you mean: 

How to generate and control a PWM with registers (NO HAL) in STM32F446RE?

Mbp.1
Associate

I am working on controlling of a stepper motor with STM32F446 and want to generate a PWM with variable frequency (trapezoidal) and stop it after some specified (n) pulses. I want to do this with register programming not HAL functions. So I want to know three steps bellow:

  1. How can I generate a PWM pulse with registers?
  2. How I can change its frequency?
  3. How I can count generated pulses and stop generating after som pulses?

could someone help me in register programming?

1 ACCEPTED SOLUTION

Accepted Solutions

Start by reading the TIM chapter in RM. It won't be clear at the first reading, so repeat until it starts to be a bit clearer.

  1. Set up the required pin - enable GPIO clock in RCC, then in given GPIO set respective bits in GPIOx_MODER so that pin is set to AF, and set in AFR[] the proper AF according to the table in Datasheet. Set up timer to run, i.e. enable its clock in RCC, set TIMx_ARR to the period you want and enable the timer to run by setting TIMx_CR1.CEN=1. For given channel, set one of the PWM modes in TIMx_CCMRx.OCxM, set duty cycle by setting respective TIMx_CCRx to a value between 0 and ARR, and enable given channel in TIMx_CCER. If it's TIM1 or TIM8, set TIMx_BDTR.MOE.
  2. By changing TIMx_ARR. If you want to do it on the fly, you should enable ARR preload by setting TIMx_CR1.ARPE.
  3. There are several ways to do it, but it's a bit tricky and you should leave it until you manage basic PWM operation.

JW

View solution in original post

4 REPLIES 4

Start by reading the TIM chapter in RM. It won't be clear at the first reading, so repeat until it starts to be a bit clearer.

  1. Set up the required pin - enable GPIO clock in RCC, then in given GPIO set respective bits in GPIOx_MODER so that pin is set to AF, and set in AFR[] the proper AF according to the table in Datasheet. Set up timer to run, i.e. enable its clock in RCC, set TIMx_ARR to the period you want and enable the timer to run by setting TIMx_CR1.CEN=1. For given channel, set one of the PWM modes in TIMx_CCMRx.OCxM, set duty cycle by setting respective TIMx_CCRx to a value between 0 and ARR, and enable given channel in TIMx_CCER. If it's TIM1 or TIM8, set TIMx_BDTR.MOE.
  2. By changing TIMx_ARR. If you want to do it on the fly, you should enable ARR preload by setting TIMx_CR1.ARPE.
  3. There are several ways to do it, but it's a bit tricky and you should leave it until you manage basic PWM operation.

JW

Hi, I was curious, is there an official documentation that gives the steps listed by you? I went through reference manual and datasheet, but still, without this comment of yours, I would have missed some of the steps since I couldn't find any other clear step by step list.

I know most of this should be intuitive, but it wont be for beginners, that's why I'm asking.

> is there an official documentation that gives the steps listed by you?

I don't know, but given that "officially" you are supposed to click in CubeMX, I don't think so.

Maybe if you click in CubeMX and then let it generate Cube/LL code, you'll see the individual steps, if you don't mind the "name mangling" of LL. I don't use Cube so don't know.

You can also look at AN4776 and AN4013. Not exactly what you're looking for, but maybe englightening. Maybe not.

> I know most of this should be intuitive

I wouldn't call it intuitive. What I did is exactly wrote above: I read the TIM chapter (plus the relevant portions of rest of RM and DS) multiple times, while experimenting. After you set up the timers a dozen of times and make a dozen of errors, it then starts to be sort of "intuitive" ("familiar", rather).

JW