AnsweredAssumed Answered

STM32F302 using TIM in output compare

Question asked by Aljaz Prislan on Nov 20, 2017
Latest reply on Nov 20, 2017 by waclawek.jan

I'm using STM32F302 Nucleo board and I'm trying to configure TIM1 in such a way that it will output a 12 us long pulse on its output.

 

I've configured TIM1, GPIO port C with its appropriate alternate functions as well as enabling TIM1 and GPIOC in RCC registers. The problem is that I get nothing on the TIM1_CH1 output on the scope. Counter has been checked and is counting as I was able to notice an appropriate change in TIM1_CNT register. Outputs are also working on the board as I was able to toggle them if condigured in PP mode (once configured in AF they do not work).

 

I'm hoping someone can help me out. I've obviously missed or overlooked something but I can't figure out why. Here's my source code.

 

int main()
{
      // Initialization
      SystemCoreClockUpdate();
      TIM_init();
      GPIO_init();

      TIM_set_channel(TIM1, 1);
      TIM_start(TIM1);


      while(1)
      {
      }
}

 

void TIM_init(void)
{
      RCC->APB2ENR |= RCC_APB2ENR_TIM1EN; // TIM1 enable (f_TIM1 = 72 MHz)

      TIM1->CR1 |= TIM_CR1_OPM;       // stop counter after it reaches value in ARR (CEN bit is cleared)

      TIM1->ARR = PULSE_PERIOD;       // time after which counter stops (defined in TIM.h)
      TIM1->CCR1 = PULSE_12_US;       // config timer to generate 12 us long pulse (defined in TIM.h)

      TIM1->CCMR1 |= TIM_CCMR1_OC1M_2 | TIM_CCMR1_OC1M_1; // PWM mode 1
      TIM1->CCMR1 |= TIM_CCMR1_OC1FE | TIM_CCMR1_OC2FE;     // Fast enable:

                                                                                                                     // reduces delay clock cycles to min of 3

      TIM1->BDTR |= TIM_BDTR_MOE; // Master (output) enable
      TIM1->BDTR |= TIM_BDTR_OSSI; // TIM controls output even after output goes to inactive state and

                                                                  // later into idle state (outputs don't go to High Z)

 

      TIM1->EGR |= TIM_EGR_UG;
      TIM1->SR = 0;
}

 

void TIM_set_channel(TIM_TypeDef* TIMx, uint8_t channel)
{
      switch (channel)
      {
      case 1:
            TIMx->CCER &= ~(TIM_CCER_CC2E | TIM_CCER_CC3E | TIM_CCER_CC4E);
            TIMx->CCER |= TIM_CCER_CC1E;
            break;

      case 2:
            TIMx->CCER &= ~(TIM_CCER_CC1E | TIM_CCER_CC3E | TIM_CCER_CC4E);
            TIMx->CCER |= TIM_CCER_CC2E;
            break;

      case 3:
            TIMx->CCER &= ~(TIM_CCER_CC1E | TIM_CCER_CC2E | TIM_CCER_CC4E);
            TIMx->CCER |= TIM_CCER_CC3E;
            break;

 

      case 4:
            TIMx->CCER &= ~(TIM_CCER_CC1E | TIM_CCER_CC2E | TIM_CCER_CC3E);
            TIMx->CCER |= TIM_CCER_CC4E;
            break;

      default:
            TIMx->CCER &= ~(TIM_CCER_CC1E | TIM_CCER_CC2E | TIM_CCER_CC3E | TIM_CCER_CC4E);
            break;
      }
}

 

void TIM_start(TIM_TypeDef* TIMx)
{
      TIMx->CR1 |= TIM_CR1_CEN;       // Start counter
}

 

void GPIO_init()
{
      // === Clock enable ===
      RCC->AHBENR |= RCC_AHBENR_GPIOCEN;


      // === ANALOG INPUTS ===
      // reduce consumption
      // MODER[1:0] = 11
      GPIOC->MODER = 0xFFFFFFFF;


      // === TIM ===
      // PC0: TIM1_CH1 PC1: TIM1_CH2 PC2: TIM1_CH3 PC3: TIM1_CH4
      GPIOC->AFR[0] |= GPIOC_AF_TIM1_CH1;
      GPIOC->AFR[0] |= GPIOC_AF_TIM1_CH2;
      GPIOC->AFR[0] |= GPIOC_AF_TIM1_CH3;
      GPIOC->AFR[0] |= GPIOC_AF_TIM1_CH4;

      // High speed outputs
      GPIOC->OSPEEDR |= GPIO_OSPEEDER_OSPEEDR0 | GPIO_OSPEEDER_OSPEEDR1 |       GPIO_OSPEEDER_OSPEEDR2 | GPIO_OSPEEDER_OSPEEDR3;

      // Push pull outputs
      // leave reset state

      // Pull-up and pull-down resistors
      // disabled after reset state
      
      // Alternate function (pins configured as outputs in TIM registers where they are regarded as channels)
      GPIOC->MODER &= ~(GPIO_MODER_MODER0 | GPIO_MODER_MODER1 | GPIO_MODER_MODER2 |       GPIO_MODER_MODER3);
      GPIOC->MODER |= GPIO_MODER_MODER0_1 | GPIO_MODER_MODER1_1 |       GPIO_MODER_MODER2_1 | GPIO_MODER_MODER3_1;

}

Outcomes