4
\$\begingroup\$

Using a STM32F407 board. I want to generate a PWM signal. I have the following function:

/**
 * \brief Sets the CCR timer register. The register determines the duty cyle.
 * \param ChannelNumber: channel index from channels configuration array.
 * \param DutyCycle: value that represents the duty cycle of PWM signal. Can take values between 0x00 and 0x8000.
 * \return -
 */
void Pwm_SetDutyCycle(Pwm_ChannelType ChannelNumber, uint16 DutyCycle)
{
 uint32 ul_ARR = Pwm_pt_GroupsConfig[ChannelNumber].pt_Register->ARR;
 DutyCycle = ((DutyCycle * ul_ARR) >> 15U) ;
 *Pwm_pt_GroupsConfig[ChannelNumber].pt_DutyCycleRegister = DutyCycle;
}

When I call the function with a value between 0x0000 and 0x8000, for example 0x4000, I have 50 % duty cycle: enter image description here

For 0x8000 I get 100 % duty cycle. All good.

enter image description here

If I want 0 % duty cycle : 0x0000

enter image description here

When DutyCycleRegister is set to 0x00 seems that the PWM pin is floating or compare unit is inactive, not pulled to ground. Does anyone know what is going on ?

If I modify the PWM function like this and not allow the DutyCycle to take 0 value.

DutyCycle = ((DutyCycle * ul_ARR) >> 15U) +1;

At 0x0000: enter image description here The configuration array:

 /** \brief Register configuration array */
static const RegInit_Masked32BitsSingleType Pwm_kat_Registers[PWM_NUMBER_OF_REGISTERS] =
{
/* TIMER 2 CONFIGURATION */
 /**
 * Configuration of TIM2_CR1 register
 * - Set the counting direction as 'upcounter'
 * 0: Upcounter
 * 1: Downcounter
 *
 */
 {
 (volatile uint32*) &TIM2->CR1,
 (uint32) ~(TIM_CR1_DIR),
 (uint32) (0x00)
 },
 /**
 * Configuration of TIM2_EGR register
 * - Set update generation to restart the counter after it has reached its peak value.
 * 0: No action
 * 1: Re-initialize the counter
 *
 *
 */
 {
 (volatile uint32*) &TIM2->EGR,
 (uint32) ~(TIM_EGR_UG),
 (uint32) (TIM_EGR_UG)
 },
 /**
 * Configuration of TIM2_PSC register
 * - Set prescaler value to 0.
 * Range: 0 to 0xFFFF
 * Divided clock frequency: fCK_PSC / (PSC[15:0] + 1).
 *
 *
 */
 {
 (volatile uint32*) &TIM2->PSC,
 (uint32) ~(TIM_PSC_PSC),
 (uint32) (0x00)
 },
 /**
 * Configuration of TIM2_ARR register
 * - Set auto-reload value to 0xFA0.
 *
 *
 */
 {
 (volatile uint32*) &TIM2->ARR,
 (uint32) ~(TIM_ARR_PRELOAD),
 (uint32) (TIM_ARR_FREQUENCY)
 },
 /**
 * Configuration of TIM2_CR1 register
 * - Set the counter enable register to 1
 * 0: Counter disabled
 * 1: Counter enabled
 *
 */
 {
 (volatile uint32*) &TIM2->CR1,
 (uint32) ~(TIM_CR1_CEN),
 (uint32) (TIM_CR1_CEN)
 },
 /**
 * Configuration of TIM2_CCMR1 register
 * - Set the PWM mode 1
 * 110: PWM mode 1 - In upcounting, channel 1 is active as long as TIMx_CNT<TIMx_CCR1
 * else inactive. In downcounting, channel 1 is inactive (OC1REF=‘0’) as long as
 * TIMx_CNT>TIMx_CCR1 else active (OC1REF=’1’).
 * 111: PWM mode 2 - In upcounting, channel 1 is inactive as long as TIMx_CNT<TIMx_CCR1
 * else active. In downcounting, channel 1 is active as long as TIMx_CNT>TIMx_CCR1 else
 * inactive.
 *
 */
 {
 (volatile uint32*) &TIM2->CCMR1,
 (uint32) ~(
 TIM_CCMR1_OC2PE |
 TIM_CCMR1_OC2M_2 |
 TIM_CCMR1_OC2M_1),
 (uint32) (
 TIM_CCMR1_OC2PE |
 TIM_CCMR1_OC2M_2 |
 TIM_CCMR1_OC2M_1)
 },
 /**
 * Configuration of TIM2_CCER register
 * - Set capture/compare enable register. Enable CC2E: Capture/Compare 2 output enable.
 *
 */
 {
 (volatile uint32*) &TIM2->CCER,
 (uint32) ~(TIM_CCER_CC2E),
 (uint32) (TIM_CCER_CC2E)
 },
 /**
 * Configuration of TIM2_CCR2 register. While initialization the duty cycle is set to 0.
 *
 */
 {
 (volatile uint32*) &TIM2->CCR2,
 (uint32) ~(TIM_CCR2_CCR2),
 (uint32) (0x00)
 },
}

EDIT: @Alex Lee came with a good observation and I think is right. The solution, in order to get rid of spikes, at 100 % is to give to dutyCycle this expression:

DutyCycle = ((DutyCycle * (ul_ARR + 1)) >> 15U) ;

(TIMx_ARR + 1) because: 110: PWM mode 1 - In upcounting, channel 1 is active as long as TIMx_CNT < TIMx_CCRx else inactive.

asked Feb 21, 2019 at 9:41
\$\endgroup\$
6
  • 2
    \$\begingroup\$ Have you got a pulldown on that output? \$\endgroup\$ Commented Feb 21, 2019 at 10:08
  • \$\begingroup\$ No, I don't have. Is it necessary ? \$\endgroup\$ Commented Feb 21, 2019 at 10:10
  • \$\begingroup\$ Only if you want to prevent a floating signal, which seems to me is what you want. AFAIK there's a way to configure an internal pulldown as well, I think? \$\endgroup\$ Commented Feb 21, 2019 at 10:14
  • 5
    \$\begingroup\$ @JohnGo-Soco If it's a proper PWM it should actively drive the pin low. There should never be a need for external pulldown. This is likely some quirk of the specific PWM peripherals. Nothing else to do but to read everything in the PWM chapter of the manual. \$\endgroup\$ Commented Feb 21, 2019 at 11:52
  • 1
    \$\begingroup\$ You already asked this, had the issue of ground differential explained, then deleted that and reposted. That is not how this site is supposed to work. Don't delete questions only to repost. \$\endgroup\$ Commented Feb 21, 2019 at 15:40

1 Answer 1

15
\$\begingroup\$

The vertical scale on your first two oscilloscope traces (50% and 100% duty cycle) is roughly 0-3 V

The vertical scale on your third oscilloscope trace (0% duty cycle) is around 0-30 mV

The amplitude of the noise is thus probably the same in all the traces, but it is only obvious when magnified in the third image which is "zoomed in" by a factor of 100!

answered Feb 21, 2019 at 9:56
\$\endgroup\$
8
  • \$\begingroup\$ Good observation. \$\endgroup\$ Commented Feb 21, 2019 at 10:07
  • 3
    \$\begingroup\$ @pantarhei What does your 3.3V supply plane look like, with the same scope settings? \$\endgroup\$ Commented Feb 21, 2019 at 11:54
  • 2
    \$\begingroup\$ Has the same amount of noise if I zoom in. \$\endgroup\$ Commented Feb 21, 2019 at 11:58
  • 4
    \$\begingroup\$ @pantarhei - well there you go - you're seeing the power supply noise that's everywhere in your circuit. It's not reasonable to expect your micro's PWM output to be somehow 'cleaner' than the supply you give it. \$\endgroup\$ Commented Feb 21, 2019 at 14:24
  • 1
    \$\begingroup\$ @pantarhei Set the right time scale on your scope and you'll see a "mysterious" 60Hz (or perhaps 50, depending on where you live) signal on everything. Zoom in enough and any apparently "clean" signal will have nano-micro-millivolts of noise. Noise is an unfortunate fact of life, though fortunately for us, digital signals mostly ignore it. Respect/pity the analog designers and their fight against physics though... \$\endgroup\$ Commented Feb 21, 2019 at 18:15

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.