cancel
Showing results for 
Search instead for 
Did you mean: 

Unable to toggle LED with respect to Timer Interrupts on STM32F411-re

Npiet.1
Associate II

I am new to this evaluation board, (Nucleo-64 STM32F411), I am working on timer , I need to Update event for every 1s and for every 1 s response from the Timer base I need to toggle the status of the LED.

In the following code I am not able to toggle the LED. I can't figure out what I am missing out with the code weather I need to update something on the code??

// ----------------------------------------------------------------------------
 
#include <stdio.h>
#include <stdlib.h>
#include "diag/Trace.h"
#include "stm32f4xx.h"
#include "stm32f4xx_hal_tim.h"
// ----------------------------------------------------------------------------
//
// Standalone STM32F4 empty sample (trace via DEBUG).
//
// Trace support is enabled by adding the TRACE macro definition.
// By default the trace messages are forwarded to the DEBUG output,
// but can be rerouted to any device or completely suppressed, by
// changing the definitions required in system/src/diag/trace_impl.c
// (currently OS_USE_TRACE_ITM, OS_USE_TRACE_SEMIHOSTING_DEBUG/_STDOUT).
//
 
// ----- main() ---------------------------------------------------------------
 
// Sample pragmas to cope with warnings. Please note the related line at
// the end of this function, used to pop the compiler diagnostics status.
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wunused-parameter"
#pragma GCC diagnostic ignored "-Wmissing-declarations"
#pragma GCC diagnostic ignored "-Wreturn-type"
 
void init_periperalclock()
{
	  /* Enable GPIO clock */
	  RCC->AHB1ENR |= RCC_AHB1ENR_GPIOAEN;   //Port A clock enable
 
	  /* Enable USART clock */
	  RCC->APB1ENR |= RCC_APB1ENR_TIM2EN;  //TIM2 Enable
}
 
void init_gpiopins()
{
 
	/* GPIO Configurations for TIMER1 */
	GPIOA ->MODER |= GPIO_MODER_MODER0_1;// PA0 Timer channel 1
	GPIOA ->OTYPER|= 0;
	GPIOA ->OSPEEDR |= GPIO_OSPEEDER_OSPEEDR0_0;
	GPIOA ->PUPDR |= GPIO_PUPDR_PUPDR0_0 ;
	GPIOA ->AFR[0] |= 0x0001; // PA0 AFR value is AF01 so AFR[0] = 0x0001
 
	uint32_t position = 5;
	uint32_t temp = 0x00U;
 
	/* Configure IO Direction mode (Input, Output, Alternate or Analog) */
	temp = GPIOA->MODER; //0xa8000000   -- 10101000000000000000000000000000
	temp &= ~(GPIO_MODER_MODER0 << (position * 2U)); // 001111111111   // temp res = 0000000000000000000000000000000
	temp |= ((1 & 3) << (position * 2U));  // 10000000000
	GPIOA->MODER = temp;  	// temp res = 000000000000000000010000000000   // act data sheet val 1024 // GP Output mode
 
 
	/* Configure the IO Speed */
	temp = GPIOA->OSPEEDR; //0x0C000000  -- 1100000000000000000000000000
	temp &= ~(GPIO_OSPEEDER_OSPEEDR0 << (position * 2U)); // temp res = 00000000000000000000000000000000
	temp |= (2 << (position * 2U));      //   100000000000 // temp res = 00000000000000000000100000000000
	GPIOA->OSPEEDR = temp;
 
 
	/* Configure the IO Output Type */
	temp = GPIOA->OTYPER;
	temp &= ~(GPIO_OTYPER_OT_0 << position) ;  // 01111 & 00000  --> 00000
	temp |= (((1 & 0x00000010U) >> 4U) << position); // ((0>>4)<<5)
	GPIOA->OTYPER = temp;
 
 
	/* Activate the Pull-up or Pull down resistor for the current IO */
	temp = GPIOA->PUPDR;  //0x64000000 - 1100100000000000000000000000000
	temp &= ~(GPIO_PUPDR_PUPDR0 << (position * 2U));  // temp res  = 00000000000000000000000000000000
	temp |= ((1) << (position * 2U));  //temp == 10000000000
	GPIOA->PUPDR = temp;
 
 
}
 
void init_timerConfiguration()
{
 
	TIM2 ->PSC =  (uint16_t) (SystemCoreClock / 8000000) - 1;	//Setting up the pre-scalar value  can be 1
 
	//Configure the Internal Clock source
	TIM2->SMCR &= ~TIM_SMCR_SMS;  // Internal clock source
	TIM2-> CR1 |= TIM_CR1_CEN;
 
	//Select the up counter mode
	TIM2->CR1 |= TIM_COUNTERMODE_UP;
	TIM2->CR1 &= ~TIM_CR1_CKD;
 
	// Set the clock division to 1
	TIM2->CR1 |= TIM_CLOCKDIVISION_DIV1;
 
	//Set the Autoreload value
	TIM2->ARR = 49999;//PERIOD 
 
	// Generate an update event to reload the Prescaler value immediately
	TIM2->EGR = TIM_EGR_UG;
	TIM2->CCMR1 &= ~TIM_CCMR1_CC2S;
 
	TIM2 ->RCR |= ~TIM_RCR_REP;
 
	TIM2 ->SR = 0;
 
}
 
 
int
main(int argc, char* argv[])
{
 
init_periperalclock();
init_gpiopins();
init_timerConfiguration();
 
  // Infinite loop
  while (1)
    {
	  while((TIM2->SR & TIM_DIER_UIE))
	  {
		  GPIOA->ODR ^= GPIO_PIN_5;
	  }
    }
}
 
#pragma GCC diagnostic pop
 

3 REPLIES 3

> while((TIM2->SR & TIM_DIER_UIE))

> {

> GPIOA->ODR ^= GPIO_PIN_5;

> }

Why are you masking TIMx_SR bits by a constant related to TIM_DIER ?

Nonetheless, when update happens, the LED starts to toggle and this loop loops forever, as there's nothing which would stop toggling it. Observe it by an oscilloscope, as it blinks too fast for you to see.

JW

berendi
Principal

To answer the actual question, what you are missing is the clearing of the status register bit after checking it.

if(TIM2->SR & TIM_SR_UIF) { // as suggested by JW above
  TIM2->SR &= ~TIM_SR_UIF); // clear update status
  GPIOA->ODR ^= GPIO_PIN_5;
}

See the description of the SR register in the reference manual for details.

Npiet.1
Associate II

Hi berendi,

I had tried clearing the SR register after posting this and It is working fine. Thanks waclawek

regards,

Naveen