Report
4 months, 1 week ago.

How to choose PWN output pins?

I need to output four PWM signals on four different pins. How does one choose the pins?

Running on the Nucleo F401RE

My software is running and I look using a logic analyzer and I see only three of the four output pins with signals on them.

I found Peripheral Pins.c and the data structure const PinMap PinMap_PWM[] I'm guessing it is bad to choose pins that use the same timer. So I selected these four. PA_7 PA_0 PA_6 PB_6 Three of these are OK. PA_7 just has some millivolts of noise on it.

Here is test code

test code

#include "mbed.h"

PwmOut testPin1(PA_7);
PwmOut testPin2(PA_0);
PwmOut testPin3(PA_6);
PwmOut testPin4(PB_6);

int main() {
   
   testPin1.period( 1.0 / 1000.0);  // 1KHz
   testPin2.period( 1.0 / 1000.0);  // 1KHz
   testPin3.period( 1.0 / 1000.0);  // 1KHz
   testPin4.period( 1.0 / 1000.0);  // 1KHz
   
   testPin1 = 0.1;
   testPin2 = 0.2;
   testPin3 = 0.3;
   testPin4 = 0.4; 
}
Comment on this question

2 Answers

4 months, 1 week ago.

Which pin did not produce the PWM output on the 401? There are times where it makes sense to separate the PWMs by timer and other times it does not. In your example above the timebase timer should be capable of running all 4 PWMs off the same internal clock. You should be able to move the outputs around and see that you still get the PWM out.

I'm now thinking this was an electrical problem, not software. Just recently I have a 5V power supply in the same breadboard as the F401RE. Could have had an accident. I move swap hardware and the problem goes away.

But STILL. I need to understand . So you are saying I can use ANY combination of pins from PinMap_PWM[] . Even all of them at once?

When should I separate them by timer?

What should I be reading? The API reference does not go into this level of detail.

posted by Chris Albertson 15 May 2017

I would start at the STM 401 datasheet level off of the ST website. There is a good block diagram of the timers in there. You'll notice that the part is split into two "Advanced Peripheral Busses" (APBs) which have different internal clocks. That may not matter for your application now but it might have importance later on. From there, go get the "Reference Guide" pdf off the ST website. That'll provide more insight into how the timers are programmed and what you can do with them. If you're doing simplistic timing then it really doesn't matter which timer you use. If you need to do *relational* timing (PWM phasing for example) then you need to worry about the timer - but the mbed API is not set up to do that type of timer programming. You'd have to import one of the many user libraries that do. If you're sticking to ST parts (for now) you can directly program the timers using ST's "HAL" interface which is a bit archaic but can set up any timer any way for your mbed code. There are a lot of good examples on here on how to use those calls in your mbed code. All that said, I would start by just assigning pins at a high level based on a pin map shown here (https://developer.mbed.org/platforms/ST-Nucleo-F401RE/) and not worry too much about the C code implementation at the lower level. Once you find you can't accomplish the timing characteristics then I would dig down a bit further. Also be sure to look at FastPWM as a better library for PWM if you're trying to do any dynamic PWM timing changes while running.

posted by Bill Bellis 17 May 2017
4 months ago.

Chris -

On your original question:

Your code may be executing properly but you may be incorrectly interpretting the signal outputs. The three outputs that appear to be operating correctly are all non-inverting outputs from their respective timers. The rising edges of the pulses from these three outputs should occur at essentially at the same time (there will be some small timing differences, since their timers are independent) with a common pulse period of 1 ms and pulse widths of 200, 300 and 400 us.

The output that does not appear to be operating correctly (PA_7) is an inverted output - the inverted output of Channel 1 of Timer1. Your code sets its duty cycle to 10%. What you should see at PA_7 is a logic level 0 for 900 us followed by a logic level 1 for 100 us, so this output should be at logic level 0 during the entire time that the other three pulses are at logic level 1. You could be missing this pulse if your logic analyzer is triggering off of one of the non-inverted outputs and you are not looking over multiple 1 ms periods.

Try using PA_8 instead of PA_7 for Channel 1 of Timer1. It is a non-inverted output and should act like the other three PWM signals.

On your follow-up questions:

1) You should be able to use any combination of pin names in the PWM list in Peripheral Pins.c without a hardware conflict - except the ones that are commented out. The PWM pin names that are commented out have conflicts with other mbed functions (e.g.. us_ticker and UART_2, the default uart) or conflicts with other timers.

2) Your Nucleo-F401RE board has four independent timers available for PWM output using the mbed API. These four timers include three different timer types, but the mbed API does not appear to take advantage of the features that differentiate them (aside from supporting the inverted Timer1 outputs). All four of these timers have four channels whose duty cycle can be independently programmed with a common period.

You definitely need to use different timers if you want to simultaneously generate different periods (eg. to vary the output frequency while keeping a fixed duty cycle). You will also need to use independent timers if you want to control the phase offset between outputs (e.g.. to commutate a motor), but I think you would be much better off doing that using some of the STM timer advanced features that are not supported by the mbed API.

3) By design, the mbed API does not really get into hardware specific issues. It also tends to be NXP-centric, so hardware aspects specific to STM MCUs may not get a lot of coverage. STM has some excellent documentation, but it can be a bit difficult to determine where to find information on a specific topic. AN4013 "STM32 cross-series timer overview" is a good place to start for a general explanation of the various timer features. AN4776 "General-purpose timer cookbook" is another good STM timer reference. As suggested in Bill Bellis’ response, the reference manuals for the specific MCUs on your boards (RM0368 for the MCU on the Nucleo-F401RE board and RM0390 for the MCU on the Nucelo-F446RE Board) have detailed descriptions of each timer and how to configure their registers. Finally, look at the examples in the STM32CubeF4 firmware package and its user manual UM1725. The examples for the STM32 446E_EVAL board include "TIM_Encoder" for processing quadrature encoder outputs and "TIM_PWMOutput" for generating four PWM waveforms, along with a number of additional timer examples.


To post an answer, please log in.