cancel
Showing results for 
Search instead for 
Did you mean: 

Timer 2 Nucleo L476RG

SWenn.1
Senior III

I am using the above Timer as both a debounce of 50ms and as a PWM for the on board LED. Basically I hit the user button, debounce for 50ms. While button held PWM to the LED of 1/2 sec on, 1/2 sec off.....Release button and PWM stops.

The timer is running at 4MHz with a prescaler of 4000 and a period of 1000. The pulse is set to 500.

When I push the button the first time all seems to work, I release and all is good. When I push the button the second time and set a breakpoint at the following line I notice two things....

(htim2.Instance->CNT) += 500;

1st the counter doesn't seem to update by 500 when I step over this line....

2nd the count value is upwards of 80000 sometimes.....Why is this when the period is 1000.

void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
{
	(htim2.Instance->CNT) += 500;
	HAL_TIM_Base_Start_IT(&htim2);
	htim2.Instance->SR &= ~TIM_SR_UIF; //Start creates a flag glitch!  This is needed.
 
	if (GPIO_Pin == BUTTON_Pin)
		EXTI->PR1 |= 1 << BUTTON_Pin;
}
 
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
	if (htim == &htim2)
	{
		HAL_TIM_Base_Stop_IT(&htim2);
		htim2.Instance->SR &= ~TIM_SR_UIF;
		if (HAL_GPIO_ReadPin(BUTTON_GPIO_Port, BUTTON_Pin) == GPIO_PIN_RESET)
			HAL_TIM_PWM_Start(&htim2, TIM_CHANNEL_1);
		else
			HAL_TIM_PWM_Stop(&htim2, TIM_CHANNEL_1);
	}
}

7 REPLIES 7
TDK
Guru

> (htim2.Instance->CNT) |= 500;

> 1st the counter doesn't seem to update by 500 when I step over this line....

You're doing a bitwise or operation, unlikely to be what you intended. If you want to set the counter to 500:

htim2.Instance->CNT = 500;

> 2nd the count value is upwards of 80000 sometimes.....Why is this when the period is 1000.

Most likely, as a result of your operation above, the CNT value jumps from below ARR to above ARR so it doesn't reset.

If you feel a post has answered your question, please click "Accept as Solution".
SWenn.1
Senior III

I adjusted the line, my apologies.....

(htim2.Instance->CCR2) = (htim2.Instance->CNT + 500);

I don't want to reset the counter to 500 each time, I want it to continually roll and I add 500 (50ms ) when a button is pushed??.....It still is not working..

For instance in MSP430 land I can

TB1CCR0 = TB1R + 500;

...and it will update the CCR register even when the counter rolls over....So for instance an 10 bit counter rolls at 1024....If the counter was at 900 when this statement gets called it will make CCR0 = 376 and as the counter wraps it will generate an IRQ at 376....

The STM32 seems to add 500 to the counter and go out of range rather than wrapping.....it takes 900 + 500 and loads the CCR reg with 1400....Unfortunately the counter is configured to a max count of 1000 so the CCR NEVER gets reached

TDK
Guru

> I adjusted the line

But you still have the same error. You're jumping over ARR.

You really should be able to devise a debounce scheme without changing the timer's counter.

Edit: If you really want to add 500:

htim2.Instance->CNT = (htim2.Instance->CNT + 500) % (htim2.Instance->ARR + 1);

No guarantees that will make your program work, but it will advance the counter by 500.

If you feel a post has answered your question, please click "Accept as Solution".
SWenn.1
Senior III

I'm sorry I don't understand.....

I want TIM2 to count at 1ms for 1000 counts using a 4MHz clock. I want this to be a free-running counter. If a button is hit I would like the GPIO ISR to load one of the CCR registers with the counter + 500 and clear the GPIO flag. After the timer reaches the CCR register I want to go into the TIM2 ISR clear a flag if necessary and then based on the GPIO pin value either enable or disable a PWM (TIM2_CH1) that is ALSO running from TIM2. First question:

  1. Is this even do-able?
  2. in the .ioc file I have enable T2_Global_Interrupt, channel 1 is set to PWM generation Ch1. Do I need to do anything else here?
  3. does HAL_TIM_Base_Stop_IT(&htim2) the following call cause the timer to stop counting? What call do I want to use?

My code:

void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
{
	htim2.Instance->CCR2 = (htim2.Instance->CNT + 500);
	HAL_TIM_Base_Start_IT(&htim2);
	if (GPIO_Pin == BUTTON_Pin)
		EXTI->PR1 |= 1 << BUTTON_Pin;
}

At startup a breakpoint at line 4 reveals:

(see file) ....You can see CNT and CCR2. Please tell me how to get CCR2 to add 500 to the current CNT value and wrap around SUCH that it is not larger than CNT??? Are these MCUs really not capable of detecting that and I have to check for greater than ARR and if so subtract ARR value to create my own 'wrap around'?

Thank you

Steve

S.Ma
Principal

Key debounce doesn't need time accuracy, you could for example use a timer overflow to generate a set flag every say 10ms, the main loop or task poll for the flag set, then clear and check the key level from last key level 10ms before and incrementba confirmcounter, when reach 5, action....

TDK
Guru

> Please tell me how to get CCR2 to add 500 to the current CNT value and wrap around SUCH that it is not larger than CNT??? Are these MCUs really not capable of detecting that and I have to check for greater than ARR and if so subtract ARR value to create my own 'wrap around'?

I did, above:

htim2.Instance->CCR2 = (htim2.Instance->CNT + 500) % (htim2.Instance->ARR + 1);

The MCU is not a mind reader. The timer is a state machine and behaves according to the description in the reference manual.

If you feel a post has answered your question, please click "Accept as Solution".
Piranha
Chief II

On MSP430 the timer B period can be configured to 8, 10, 12 or 16-bit counter and that way deal with the wraparound by just ignoring the higher bits. But that way one can have only 4 distinct period values, while on STM32 a period can be set to any value with ARR register.

One can emulate MSP430 by doing a single AND operation:

CCR2 = (CNT + 500) & (PERIOD - 1);

But, like MSP430 timer, that is limited to only periods of powers of two. For an arbitrary number do a % PERIOD, which is what TDK already showed.