AnsweredAssumed Answered

STM32F446 inverse PWM duty cycle?!?

Question asked by Blessinger.Matthew on Mar 17, 2017
Latest reply on Apr 7, 2017 by Kim.Bum_Sik

I have an embedded STM32F446VE with which I am outputting 6 PWM signals with advanced timers 1 & 8 (channels 2,3,4 from each timer). I have initialized the timers to output compare mode 1 with counting up. The first time I load the program with a ST-Link v2 debugger (on a Nucleo STM32F446ZE), the duty cycle is the correct value I set it to via the pulse value.

 

Now the issue is that if I simply reprogram the MCU (stop the debugger and restart it), while changing nothing in the program, the duty becomes inverse! It appears to be operating in down counting mode, i.e. pulse=0 is 100% duty cycle. The debugger says the timer is still in counting mode 0 with up counting. The only way it works correctly again is if I remove the power from the MCU or debugger and apply it again. The number of times I reprogram before it stops working varies.

 

I should also mention it is only channels 2 & 3 from each timer that has the inverse duty cycle. Channel 4 does not appear to be affected by whatever is going on.

 

Has anyone seen this behavior before? I have this setup code on the Nucleo board without any problems. Please provide any suggestions you can think of! Thank you.

 

Main code. MX_TIM1_Init and MXTIM8_Init setup the timers. PWM_Init starts the PWM channels and set the pulse value for the duty cycle. Those 3 functions are in the other code block below.

 

#include "main.h"

#include "stm32f4xx_hal.h"

#include "diag/Trace.h"

 

/* Private variables ---------------------------------------------------------*/

CRC_HandleTypeDef hcrc;

SPI_HandleTypeDef hspi3;

TIM_HandleTypeDef htim1;

TIM_HandleTypeDef htim8;

UART_HandleTypeDef huart4;

 

 

/* Private function prototypes -----------------------------------------------*/

void Error_Handler(void);

void SystemClock_Config(void);

void MX_CRC_Init(CRC_HandleTypeDef);

void GPIO_CLK_Init(void);

TIM_HandleTypeDef MX_TIM1_Init(TIM_HandleTypeDef);

TIM_HandleTypeDef MX_TIM8_Init(TIM_HandleTypeDef);

void PWM_Init(TIM_HandleTypeDef, TIM_HandleTypeDef);

SPI_HandleTypeDef MX_SPI3_Init(SPI_HandleTypeDef);

UART_HandleTypeDef MX_UART4_Init(UART_HandleTypeDef);

void Encoder_Init(void);

void HallSensor_Init(void);

void TFTpins_Init(void);

void LEDs_Init(void);

void DRV8301pins_Init(void);

void DRV8301_Init(SPI_HandleTypeDef);

 

 

int main(void)

{

 

  HAL_Init();

 

  /* Configure the system clock */

  SystemClock_Config();

  MX_CRC_Init(hcrc);

 

  /* Initialize all configured peripherals */

  GPIO_CLK_Init();                // enable GPIO port clocks

  htim1 = MX_TIM1_Init(htim1);    // setup Timer1

  htim8 = MX_TIM8_Init(htim8);    // setup Timer8

  PWM_Init(htim1, htim8);         // start PWM channel counters

  hspi3 = MX_SPI3_Init(hspi3);    // setup SPI for DRV8301

  huart4 = MX_UART4_Init(huart4); // setup UART for FTDI

  Encoder_Init();                 // setup encoder and switch interrupts

  HallSensor_Init();              // setup hall effect sensor interrupts

  LEDs_Init();                    // setup LEDs and check functionality

  DRV8301pins_Init();             // setup pins for DRV8301 (interrupts, current sense, etc.)

  TFTpins_Init();                 // setup pins for TFT screen

//  DRV8301_Init(hspi3);            // initialize DRV8301 settings via SPI

 

  trace_printf("System clock: %u Hz\n", SystemCoreClock);

 

  while (1)

  {

      HAL_GPIO_TogglePin(LED_OV24V_GPIO_Port, LED_OV24V_Pin);

      HAL_Delay(1000);

  }

}

 

Code where timers are setup and started.

#include "stm32f4xx_hal.h"

 

extern void Error_Handler(void);

 

void PWM_Init(TIM_HandleTypeDef htim1, TIM_HandleTypeDef htim8)

{

  // !!! add synchronization !!!

  // Start counter

  HAL_TIM_PWM_Start(&htim1, TIM_CHANNEL_2);

  HAL_TIM_PWM_Start(&htim1, TIM_CHANNEL_3);

  HAL_TIM_PWM_Start(&htim1, TIM_CHANNEL_4);

  HAL_TIM_PWM_Start(&htim8, TIM_CHANNEL_2);

  HAL_TIM_PWM_Start(&htim8, TIM_CHANNEL_3);

  HAL_TIM_PWM_Start(&htim8, TIM_CHANNEL_4);

 

//  // Set output compare > 0 to check signals

  __HAL_TIM_SET_COMPARE(&htim1, TIM_CHANNEL_2, 3);

  __HAL_TIM_SET_COMPARE(&htim1, TIM_CHANNEL_3, 4);

  __HAL_TIM_SET_COMPARE(&htim1, TIM_CHANNEL_4, 499);

  __HAL_TIM_SET_COMPARE(&htim8, TIM_CHANNEL_2, 0);

  __HAL_TIM_SET_COMPARE(&htim8, TIM_CHANNEL_3, 1);

  __HAL_TIM_SET_COMPARE(&htim8, TIM_CHANNEL_4, 2);

}

 

/* TIM1 init function */

TIM_HandleTypeDef MX_TIM1_Init(TIM_HandleTypeDef htim)

{

  TIM_OC_InitTypeDef sConfigOC;

 

  htim.Instance = TIM1;

  htim.Init.Prescaler = 5;

  htim.Init.CounterMode = TIM_COUNTERMODE_UP;

  htim.Init.Period = 499;

  htim.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;

  htim.Init.RepetitionCounter = 0;

  if (HAL_TIM_PWM_Init(&htim) != HAL_OK)

  {    Error_Handler();  }

 

  sConfigOC.OCMode = TIM_OCMODE_PWM1;

  sConfigOC.Pulse = 10;

  sConfigOC.OCPolarity = TIM_OCPOLARITY_HIGH;

  sConfigOC.OCFastMode = TIM_OCFAST_DISABLE;

  if (HAL_TIM_PWM_ConfigChannel(&htim, &sConfigOC, TIM_CHANNEL_2) != HAL_OK)

  {    Error_Handler();  }

 

  if (HAL_TIM_PWM_ConfigChannel(&htim, &sConfigOC, TIM_CHANNEL_3) != HAL_OK)

  {    Error_Handler();  }

 

  if (HAL_TIM_PWM_ConfigChannel(&htim, &sConfigOC, TIM_CHANNEL_4) != HAL_OK)

  {    Error_Handler();  }

  return htim;

}

 

/* TIM8 init function */

TIM_HandleTypeDef MX_TIM8_Init(TIM_HandleTypeDef htim)

{

  TIM_OC_InitTypeDef sConfigOC;

 

  htim.Instance = TIM8;

  htim.Init.Prescaler = 5;

  htim.Init.CounterMode = TIM_COUNTERMODE_UP;

  htim.Init.Period = 499;

  htim.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;

  htim.Init.RepetitionCounter = 0;

  if (HAL_TIM_PWM_Init(&htim) != HAL_OK)

  {    Error_Handler();  }

 

  sConfigOC.OCMode = TIM_OCMODE_PWM1;

  sConfigOC.Pulse = 0;

  sConfigOC.OCPolarity = TIM_OCPOLARITY_HIGH;

  sConfigOC.OCFastMode = TIM_OCFAST_DISABLE;

  if (HAL_TIM_PWM_ConfigChannel(&htim, &sConfigOC, TIM_CHANNEL_2) != HAL_OK)

  {    Error_Handler();  }

 

  if (HAL_TIM_PWM_ConfigChannel(&htim, &sConfigOC, TIM_CHANNEL_3) != HAL_OK)

  {    Error_Handler();  }

 

  if (HAL_TIM_PWM_ConfigChannel(&htim, &sConfigOC, TIM_CHANNEL_4) != HAL_OK)

  {    Error_Handler();  }

  return htim;

}

 

void HAL_TIM_PWM_MspInit(TIM_HandleTypeDef* htim_pwm)

{

 

  GPIO_InitTypeDef GPIO_InitStruct;

  if(htim_pwm->Instance==TIM1)

  {

    /* Peripheral clock enable */

    __HAL_RCC_TIM1_CLK_ENABLE();

 

    /**TIM1 GPIO Configuration

    PA8      ------> TIM1_CH1

    PA9      ------> TIM1_CH2

    PA10     ------> TIM1_CH3

    PA11     ------> TIM1_CH4

    */

    GPIO_InitStruct.Pin = GPIO_PIN_8|GB_H_Pin|GA_L_Pin|GA_H_Pin;

    GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;

    GPIO_InitStruct.Pull = GPIO_NOPULL;

    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;

    GPIO_InitStruct.Alternate = GPIO_AF1_TIM1;

    HAL_GPIO_Init(GA_H_GPIO_Port, &GPIO_InitStruct);

  }

  else if(htim_pwm->Instance==TIM8)

  {

    /* Peripheral clock enable */

    __HAL_RCC_TIM8_CLK_ENABLE();

 

    /**TIM8 GPIO Configuration

    PC6     ------> TIM8_CH1

    PC7     ------> TIM8_CH2

    PC8     ------> TIM8_CH3

    PC9     ------> TIM8_CH4

    */

    GPIO_InitStruct.Pin = GPIO_PIN_6|GC_L_Pin|GC_H_Pin|GB_L_Pin;

    GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;

    GPIO_InitStruct.Pull = GPIO_NOPULL;

    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;

    GPIO_InitStruct.Alternate = GPIO_AF3_TIM8;

    HAL_GPIO_Init(GC_L_GPIO_Port, &GPIO_InitStruct);

  }

}

 

void HAL_TIM_PWM_MspDeInit(TIM_HandleTypeDef* htim_pwm)

{

 

  if(htim_pwm->Instance==TIM1)

  {

 

    /* Peripheral clock disable */

    __HAL_RCC_TIM1_CLK_DISABLE();

 

    /**TIM1 GPIO Configuration

    PA8      ------> TIM1_CH1

    PA9      ------> TIM1_CH2

    PA10     ------> TIM1_CH3

    PA11     ------> TIM1_CH4

    */

    HAL_GPIO_DeInit(GA_H_GPIO_Port, GPIO_PIN_8|GB_H_Pin|GA_L_Pin|GA_H_Pin);

 

  }

  else if(htim_pwm->Instance==TIM8)

  {

 

    /* Peripheral clock disable */

    __HAL_RCC_TIM8_CLK_DISABLE();

 

    /**TIM8 GPIO Configuration

    PC6     ------> TIM8_CH1

    PC7     ------> TIM8_CH2

    PC8     ------> TIM8_CH3

    PC9     ------> TIM8_CH4

    */

    HAL_GPIO_DeInit(GC_L_GPIO_Port, GPIO_PIN_6|GC_L_Pin|GC_H_Pin|GB_L_Pin);

 

  }

 

}

Outcomes