cancel
Showing results for 
Search instead for 
Did you mean: 

STM32F302 using TIM in output compare

Aljaz Prislan
Associate
Posted on November 20, 2017 at 13:41

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;

}

#output-compare #opm #one-pulse-mode #tim #config
1 REPLY 1
Posted on November 20, 2017 at 14:01

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

That means you won't see much after init. Try without OPM first.

      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)

Make sure CCR1 < ARR.

      TIM1->CCMR1 |= TIM_CCMR1_OC1FE | TIM_CCMR1_OC2FE;     // Fast enable:

                                                                                                                     // reduces delay clock cycles to min of 3

This should be quite irrelevant to PWM as such. Try without.

If still no work, read out and post timer and relevant GPIO registers' content.

JW