cancel
Showing results for 
Search instead for 
Did you mean: 

stm32l476 nucleo board --- experimenting with output compare timer 3 channel 1??

SWenn.1
Senior III

Good afternoon everyone....

I am trying to learn more about the stm32 and am using a nucleo L476 and an oscilloscope. In particular I want to understand more about the output compares of the timers. I have read many an app-note , user guide and data sheet regarding these and am now at the stage of testing stuff out.....I am running into complete confusion with respect to this...

I have a 26MHz clock with a prescaler of 26 -1 (should be a 1MHz Cnt clock). I have the ARR register loaded with 100 - 1 (should create an UIF event every 100us). I am using CubeMX to set this up. There are a few questions:

  1. I had to code the macro (see below) bcz CubeMx doesn't seem to check the UIE bit when setting up as compare output.....Can anyone comment as to why?
__HAL_TIM_ENABLE_IT(&htim3, TIM_IT_UPDATE);

The following below is my ISR.....My attempt was to have UIF interrupt me every 10khz (see above comment on this), turn the output on and arm the CCR with counter + 10. My thought was that after this expires (CNTR clock is 1MHz so my expectation was 10us later) I would get a CC1R interrupt and then clear the output using FORCED_ACTIVE and INACTIVE statements. There are a few things here:

  1. I notice with breakpoints set neither the macro nor the call after it clear the UIF flag....Why is this??(I have attached pic below showing enables or IRQs set and flags set
  2. I never get into the CC1 portion of the interrupt...any thoughts as to why?? as the expression solves to a '1'
  3. Where do I find the various priorities of the flags that can cause an interrupt in TIMER3?? is the UIE higher priority than the CCxE?
void HAL_TIM_OC_DelayElapsedCallback(TIM_HandleTypeDef *htim)
{
	if (htim == &htim3)
	{
		if(htim->Channel == HAL_TIM_ACTIVE_CHANNEL_1)
		{
			if (__HAL_TIM_GET_FLAG(htim, TIM_FLAG_CC1))
			{
				__HAL_TIM_CLEAR_FLAG(htim, TIM_IT_CC1);
				htim->Instance->SR &= ~TIM_SR_CC1IF;
				htim->Instance->CCR1 = 0;
				htim->Instance->CCMR1 = 0; //clears mode output bits --- freezes output
				htim->Instance->CCMR1 |= TIM_OCMODE_FORCED_INACTIVE; //forces output to 0??
			}
 
			else if (__HAL_TIM_GET_FLAG(htim, TIM_FLAG_UPDATE))
			{
				__HAL_TIM_CLEAR_FLAG(htim, TIM_IT_UPDATE); //clear UIF Flag
				htim->Instance->SR &= ~TIM_SR_UIF;
				htim->Instance->CCR1 = htim->Instance->CNT + 10;
				htim->Instance->CCMR1 = 0; //clears mode output bits --- freezes output
				htim->Instance->CCMR1 |= TIM_OCMODE_FORCED_ACTIVE;  //set output to 1 immediately
			}
 
		}
	}
}

0693W00000Y7AAaQAN.png

20 REPLIES 20

Yes, you are missing a lot.

The statement:

TIM->SR &= ~TIM_SR_UIF;

is actually executed as:

(1) temp = TIM->SR;

(2) temp &= ~TIM_SR_UIF;

(3) TIM->SR = temp;

where temp is an ARM processor register.

Now think what will happen if another timer event flag, like CC1IF, is set by timer hardware after (1) and before (3) is executed. This flag will be cleared by (3) because it has a value of 0 in temp and your software will have no chance to notice it being set - you will loose the CC1IF event in your ISR..

An old beginner's problem with STM32 timer flags... ;)

My STM32 stuff on github - compact USB device stack and more: https://github.com/gbm-ii/gbmUSBdevice