cancel
Showing results for 
Search instead for 
Did you mean: 

TIMER 1 PWM Mode, What am I missing

glenn0010
Associate III

Hi All,

I want to use timer 1 for my double pulse test. To start with though I want to get it going in a simple PWM mode at first.

I have gone trhough the reference amnual several times and looked at the block diagrams. I have got the registers intialized and the counter, counting. Howver I am gettting nothing at the output when I am trying to toggle the LED. What am I missing?

int init_TIM1()
{
	RCC->APB2ENR |= RCC_APB2ENR_TIM1EN; // Enabling Timer clock
	RCC->AHBENR |= RCC_AHBENR_GPIOCEN; // Enabling Port C clock
	
	GPIOC->MODER |= (1<<1); // Setting PC0 as alternate function
	GPIOC->MODER |= (1<<3); //Setting PC1 as alternate function
	GPIOC->OSPEEDR |= (1<<0) |(1<<1) | (1<<2) |(1<<3) ; // PC0, PC1 = High Speed
	
	TIM1->CCMR1 |= (1<<5) | (1<<6); // Setting Channel 1 in PWM Compare mode 1
	TIM1->CCMR1 |= (1<<13) | (1<<14); // Setting Channel 2 as PWM Compare mode 1
	TIM1->CCMR1 |= (1<<3) | (1<<11); // Enabling OC1 and OC2 preload registers
	TIM1->CCMR1 |= (1<<7) |(1<<15) ; // OCxRef is cleared as soon as a high level is detected on ocref_clr_int signal
	
  TIM1->CR1 |= (1<<7); // Enabling the auto reload preload register for the timer (buffered)
 
	TIM1->PSC = 6499; // PSC = 6500 (6499+1) = 36 Mhz / 6500 = 5538
	TIM1->ARR = 5538; // approx 1 s delay
	TIM1-> CCR1 = 2769;
	TIM1->CCR2 = 5538;
	
	TIM1->EGR |= (1<<5); // Enabling capture compare update generation
	TIM1->CCER |= (1<<0) | (1<<4); // Enabling OC outputs for ch1 and ch2 which maps them to the pin
  TIM1->BDTR |= (1<<15); // Main output enable
	
	TIM1->EGR |= (1<<0); // Reintializing the counter and generates an update of the registers
	TIM1->CR1 |= (1<<0); //enable counter 
	
	return(0);
}

Cheers

1 ACCEPTED SOLUTION

Accepted Solutions

Which STM32?

In GPIOx_AFR, you need to select the proper AF number, see the pin assignment table in Datasheet.

You may want to swap the enables, first enable GPIO, so that there's time between enabling GPIO and writing into its registered, see the errata (maybe this does not apply to your MCU but certainly won't harm).

JW

PS. Using symbols defined in the CMSIS-mandated device header increases readability.

View solution in original post

5 REPLIES 5

Which STM32?

In GPIOx_AFR, you need to select the proper AF number, see the pin assignment table in Datasheet.

You may want to swap the enables, first enable GPIO, so that there's time between enabling GPIO and writing into its registered, see the errata (maybe this does not apply to your MCU but certainly won't harm).

JW

PS. Using symbols defined in the CMSIS-mandated device header increases readability.

TIM1->EGR |= (1<<5); // Enabling capture compare update generation

This is probably harmless, but does not do what the comment says. Writing 1 to EGR bits fire not enable anything, it generates an internal event (signal).

Also, you don't RMW (|=) into EGR as it's a write-only register, i.e. you only =. Again it's harmless error as EGR reads as constant zero, but wrong practice nonetheless.

Did you copy this code from some source?

JW

glenn0010
Associate III

Hi Jan!

Thanks for your help! It was the alternate functions I forgot to set, it is now working.

With regards to the Internal even you are right , I didn't comment it properly.

This code is all mine I just have been looking at the manual, I admit some bits of it I have not fully comented properly. Also I understand what you're saying about the symbols but sometimes I just find it quicker just to plugin the bit rather than having to look up the symbol in the header file. Then I am putting comments in for readability.

Thanks for your tips. I am a power electronics engineer by trade so I am not great at programming and the STM32 is new to me (I am using STM32F302R8) nucleo to develop my own automated double pulse tester.

Thanks again for the tips!

berendi
Principal

> I just find it quicker just to plugin the bit rather than having to look up the symbol in the header file.

You don't have to look it up, the bitfields are (most of the time) named in a consistent way. So e.g. when the reference manual tells you that you set the CEN bit in CR1 to start the timer, you can just write

TIM1->CR1 |= TIM_CR1_CEN;

It works with with numerical bitfields too, e.g. to set PB2 to AF mode 2, write

GPIOB->AFR[0] = (GPIOB->AFR[0] & ~GPIO_AFRL_AFSEL1) | (2u << GPIO_AFRL_AFSEL1_Pos); // PB1 AF2 = TIM3_CH4

except when the bitfield is non-consecutive, then you have to resort to individual bit macros

TIM1->SMCR = (TIM1->SMCR & ~TIM_SMCR_SMS) | TIM_SMCR_SMS_3;

> I am not great at programming and the STM32 is new to me

You've already achieved more than a lot of people here who don't have the slightest idea wham I'm talking about when I tell them to check bit X in register Y.

> This code is all mine I just have been looking at the manual,

Ah I see.

I asked because I see this style quite often here (within the minority of users who don't click in CubeMX), so I suspected there's some common source.

> Also I understand what you're saying about the symbols but sometimes I just find it quicker just to plugin the bit

> rather than having to look up the symbol in the header file.

YMMV

> Then I am putting comments in for readability.

Thumbs up.

JW