Electrical – Error using TIM1 for PWM on STM32F0

ceclipsestm32stm32f0

I'm trying to isolate this as much as possible (by commenting out the working TIM3 code for comparison). I've got PWM to work fine on TIM3, but have not seen anything on TIM1. Originally, the issue was pointed out in the comments that some of the TIM_OCInitStructure. calls were missing (OutputNState), but I have them all in there and am still not seeing any signal. Does anyone see anything else missing in the code?

void TIM_TIMER_Init(void)
{
    TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;

//  RCC_APB1PeriphClockCmd(RCC_APB1ENR_TIM3EN, ENABLE);   //timer 3
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM1, ENABLE);   //timer 1
    TIM_TimeBaseStructure.TIM_Prescaler = 0;
    TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;  
    TIM_TimeBaseStructure.TIM_Period = 4799;  // PER = F_timer / F_pwm - 1
    TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1;
    TIM_TimeBaseStructure.TIM_RepetitionCounter = 0;

    // Initialize TIMx
//  TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure);
    TIM_TimeBaseInit(TIM1, &TIM_TimeBaseStructure);

    // Start count on TIMx
//  TIM_Cmd(TIM3, ENABLE);
    TIM_Cmd(TIM1, ENABLE);
}

void TIM_PWM_Init(void)
{
    TIM_OCInitTypeDef   TIM_OCInitStructure;

    TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM2;   // PWM1/PWM2 = set/clear on compare match
    TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
    TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_Low;
    TIM_OCInitStructure.TIM_OutputNState = TIM_OutputNState_Disable;
    TIM_OCInitStructure.TIM_OCNIdleState = TIM_OCNIdleState_Reset;
    TIM_OCInitStructure.TIM_OCNPolarity = TIM_OCNPolarity_Low;
    TIM_OCInitStructure.TIM_OCIdleState = TIM_OCIdleState_Reset;

    TIM_OCInitStructure.TIM_Pulse = 959;    // 20% Duty Cycle on ch. 1
//  TIM_OC1Init(TIM3, &TIM_OCInitStructure);
//  TIM_OC1PreloadConfig(TIM3, TIM_OCPreload_Enable);
    TIM_OC1Init(TIM1, &TIM_OCInitStructure);
    TIM_OC1PreloadConfig(TIM1, TIM_OCPreload_Enable);
/*
    TIM_OCInitStructure.TIM_Pulse = 1919;   // 40% Duty Cycle on ch. 2
//  TIM_OC2Init(TIM3, &TIM_OCInitStructure);
//  TIM_OC2PreloadConfig(TIM3, TIM_OCPreload_Enable);
    TIM_OC2Init(TIM1, &TIM_OCInitStructure);
    TIM_OC2PreloadConfig(TIM1, TIM_OCPreload_Enable);

    TIM_OCInitStructure.TIM_Pulse = 2879;   // 60% Duty Cycle on ch. 3
//  TIM_OC3Init(TIM3, &TIM_OCInitStructure);
//  TIM_OC3PreloadConfig(TIM3, TIM_OCPreload_Enable);
    TIM_OC3Init(TIM1, &TIM_OCInitStructure);
    TIM_OC3PreloadConfig(TIM1, TIM_OCPreload_Enable);

    TIM_OCInitStructure.TIM_Pulse = 3839;   // 80% Duty Cycle on ch. 4
//  TIM_OC4Init(TIM3, &TIM_OCInitStructure);
//  TIM_OC4PreloadConfig(TIM3, TIM_OCPreload_Enable);
    TIM_OC4Init(TIM1, &TIM_OCInitStructure);
    TIM_OC4PreloadConfig(TIM1, TIM_OCPreload_Enable);
*/}

//"using convenience methods instead of CMSIS"
void TIM_PINS_Init(void)
{
    GPIO_InitTypeDef    GPIO_InitStructure;

//  RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOC, ENABLE);  //enabling port C
    RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOA, ENABLE);  //enabling port A 

    // Alternative Functions for pins
//  GPIO_PinAFConfig(GPIOC, GPIO_PinSource6, GPIO_AF_0);  // PC6
//  GPIO_PinAFConfig(GPIOC, GPIO_PinSource7, GPIO_AF_0);  // PC7
//  GPIO_PinAFConfig(GPIOC, GPIO_PinSource8, GPIO_AF_0);  // PC8
//  GPIO_PinAFConfig(GPIOC, GPIO_PinSource9, GPIO_AF_0);  // PC9

    GPIO_PinAFConfig(GPIOA, GPIO_PinSource8, GPIO_AF_2);    // PA8
    GPIO_PinAFConfig(GPIOA, GPIO_PinSource9, GPIO_AF_2);    // PA9
    GPIO_PinAFConfig(GPIOA, GPIO_PinSource10, GPIO_AF_2);   // PA10
    GPIO_PinAFConfig(GPIOA, GPIO_PinSource11, GPIO_AF_2);   // PA11

    // Set pins
//  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6 | GPIO_Pin_7 | GPIO_Pin_8 | GPIO_Pin_9;
    GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
    GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;


GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;

//  GPIO_Init(GPIOC, &GPIO_InitStructure);  

    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8 | GPIO_Pin_9 | GPIO_Pin_10 | GPIO_Pin_11;
    GPIO_Init(GPIOA, &GPIO_InitStructure);
}

//////////////////
Original Question
//////////////////

Does anyone see a problem with this bit of code?

TIM_OCInitTypeDef   TIM_OCInitStructure;

    TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM2;
    TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
    TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_Low;

    TIM_OCInitStructure.TIM_Pulse = 959;    // 20% Duty Cycle on ch. 1
    TIM_OC1Init(TIM3, &TIM_OCInitStructure);
    TIM_OC1PreloadConfig(TIM3, TIM_OCPreload_Enable);
    TIM_OC1Init(TIM1, &TIM_OCInitStructure);
    TIM_OC1PreloadConfig(TIM1, TIM_OCPreload_Enable);

The problem is with

TIM_OC1Init(TIM1, &TIM_OCInitStructure);

The error is

assert_param() failed: file "../system/src/stm32f0-stdperiph/stm32f0xx_tim.c", line 811. Looking that up that line is:

  if((TIMx == TIM1) || (TIMx == TIM15) || (TIMx == TIM16) || (TIMx == TIM17))
  {
    assert_param(IS_TIM_OUTPUTN_STATE(TIM_OCInitStruct->TIM_OutputNState)); // <- line 811

The TIM_OC1Init() function seems to work for TIM3, but not TIM1. I've seen others in this forum use TIM_OC1Init() for TIM1, so I'm not sure what the issue is for me. Isn't this how I set ch.1?

Best Answer

Adding TIM_CtrlPWMOutputs(TIM1, ENABLE); to the end of TIM_TIMER_Init() got all the PWM's on TIM1 going.

Interestingly, only TIM_OutputNState matters (Enable/Disable doesn't matter). TIM_OCNIdleState, TIM_OCNPolarity, and TIM_OCIdleState can be removed and there is no effect. Not sure I understand that since they are right under the original assert_param() errors from the original post, but anyways...