cancel
Showing results for 
Search instead for 
Did you mean: 

STM32L4: How to setup CC1IE for TIM2

KBrad.2
Associate II

I copied the code for my timer setup, and the plan was every time the capture compare was equal the CC1IF would set and I toggle the LED in the IRQHandler; however, upon loading in the code it seems the IRQHandler only gets called once to turn the LED on, and then never again. The clock is set to the default of 4MHz

void timer_config(){

RCC->APB1ENR1 |= RCC_APB1ENR1_TIM2EN; // Enable TIMER 2 clock

TIM2->CR1 &= ~TIM_CR1_DIR;      // Counting direction: 0 = up-counting, 1 = down-counting

TIM2->PSC = 3;    // Prescaler = 3 // 4MHz/(1+PSC) = 4MHz/4 = 1MHz //Target PWM frequency = 100Hz // ARR=1MHz /100 Hz-1=9999

TIM2->ARR = 9999;          // Auto-reload: Upcouting (0..ARR),Downcouting (ARR..0)

TIM2->CCMR1 &= ~TIM_CCMR1_OC1M;    // Clear ouput compare mode bits for channel 1

TIM2->CCMR1 |= TIM_CCMR1_OC1M_1 | TIM_CCMR1_OC1M_2; // OC1M = 110 for PWM Mode 1 output on ch1

TIM2->CCMR1 |= TIM_CCMR1_OC1PE;    // Output 1 preload enable

TIM2->CCER &= ~TIM_CCER_CC1NP;    // Select output polarity: 0 = active high, 1 = active low // select active high

TIM2->CCER |= TIM_CCER_CC1NE;     // Enable output for ch1N: 0 = Disable, 1 = Enable

TIM2->BDTR |= TIM_BDTR_MOE;      // Main output enable (MOE): 0 = Disable, 1 = Enable

TIM2->DIER |= TIM_DIER_UDE;      // Enable DMA request on channel 1

TIM2->CCR1 = TIM2->ARR/2;       // Init duty cycle to 50% ARR/2

TIM2->SR &= ~TIM_SR_UIF;

TIM2->CCMR1 &= ~TIM_CCMR1_IC1F;

NVIC_SetPriority(TIM2_IRQn,2);

TIM2->DIER |= 0x02;          // Enable Timer Interrupts

NVIC_EnableIRQ(TIM2_IRQn);

TIM2->CR1 |= TIM_CR1_CEN;       // Enable Counter

}

void TIM2_IRQHandler(void){

if(TIM2->SR & TIM_SR_UIF){

overflowCount++;

TIM2->SR &= ~TIM_SR_UIF; // Disable the CC1 Interrupt Flag

//GPIOA->ODR ^= (1 << 5);   // Toggle PA5

}

if(TIM2->SR & TIM_SR_CC1IF){

TIM2->SR &= ~TIM_SR_CC1IF; // Disable the CC1 Interrupt Flag

TIM2->SR &= ~TIM_SR_CC1OF; // Disable the CC1 Interrupt Flag

GPIOA->ODR ^= (1 << 5);   // Toggle PA5

}

//GPIOA->ODR ^= (1 << 5);   // Toggle PA5

}

1 ACCEPTED SOLUTION

Accepted Solutions
KBrad.2
Associate II

I believe my problem with this was I only toggled LED when I was getting interrupts from the capture/compare on channel 1 but I also did not account for the LED toggle I would have to do at an overflow/underflow.

So changing the duty cycle was not actually doing anything and the LED just appeared to always be on even though it was blinking quite fast.

KB

View solution in original post

3 REPLIES 3

How do you observe this? 50Hz is too fast to be seen by naked eye. Use oscilloscope/LA, or increase TIM2_ARR significantly.

If still problems, read out TIM and relevant GPIO registers content using debugger and check/post.

Also, probably not the problem here, but don't use RMW to clear TIM_SR flags.

JW

The idea was to set CCR1 to different values to change the duty cycle. For instance, CCR1 = 9998 I would expect the LED to be off for a considerable amount of time but it is still just always on and the light never gets dimmer.

KB

KBrad.2
Associate II

I believe my problem with this was I only toggled LED when I was getting interrupts from the capture/compare on channel 1 but I also did not account for the LED toggle I would have to do at an overflow/underflow.

So changing the duty cycle was not actually doing anything and the LED just appeared to always be on even though it was blinking quite fast.

KB