AnsweredAssumed Answered

STM32 Delay timer issues

Question asked by Alexander Hoffman on Jan 19, 2018

Hi all,

 

I am trying to implement a milli and microsecond delay, most importantly a micro delay as milli is obviously provided by the HAL libraries. My knowledge of timers is quite limited so I might be missing some key concept here.

 

I have been having some success with getting a milli second timer going but a couple of things that seem to work have left me with some questions. I added a timer to my project through CubeMX.

 

 

My through process was to be able to change the clock prescalar to switch between micro and milli and then simply do a count compare in a while loop to perform the delay.

 

My default generated timer config code is as follows 

 

static void MX_TIM2_Init(void)
{

TIM_ClockConfigTypeDef sClockSourceConfig;
TIM_MasterConfigTypeDef sMasterConfig;
TIM_OC_InitTypeDef sConfigOC;

htim2.Instance = TIM2;
htim2.Init.Prescaler = ((SystemCoreClock/TIMER_PRESCALAR_US) / (SystemCoreClock/PCLK2_FREQ))-1;
htim2.Init.CounterMode = TIM_COUNTERMODE_UP;
htim2.Init.Period = 0xFFFFFFFF;
htim2.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
if (HAL_TIM_Base_Init(&htim2) != HAL_OK)
{
_Error_Handler(__FILE__, __LINE__);
}

sClockSourceConfig.ClockSource = TIM_CLOCKSOURCE_INTERNAL;
if (HAL_TIM_ConfigClockSource(&htim2, &sClockSourceConfig) != HAL_OK)
{
_Error_Handler(__FILE__, __LINE__);
}

if (HAL_TIM_OC_Init(&htim2) != HAL_OK)
{
_Error_Handler(__FILE__, __LINE__);
}

sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET;
sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;
if (HAL_TIMEx_MasterConfigSynchronization(&htim2, &sMasterConfig) != HAL_OK)
{
_Error_Handler(__FILE__, __LINE__);
}

sConfigOC.OCMode = TIM_OCMODE_TIMING;
sConfigOC.Pulse = 0;
sConfigOC.OCPolarity = TIM_OCPOLARITY_HIGH;
sConfigOC.OCFastMode = TIM_OCFAST_DISABLE;
if (HAL_TIM_OC_ConfigChannel(&htim2, &sConfigOC, TIM_CHANNEL_1) != HAL_OK)
{
_Error_Handler(__FILE__, __LINE__);
}

}

 

I then have two functions to set up the timer again into the milli and micro configs, as follows 

#define PCLK2_FREQ 90000000

void my_timer_config_us(void)
{
htim2.Instance = TIM2;
htim2.Init.Prescaler =
((SystemCoreClock/TIMER_PRESCALAR_US) / (SystemCoreClock/PCLK2_FREQ))-1;
htim2.Init.Period = UINT32_MAX;
htim2.Init.CounterMode = TIM_COUNTERMODE_UP;
htim2.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;

if (HAL_TIM_Base_Init(&htim2) != HAL_OK)
{
_Error_Handler(__FILE__, __LINE__);
}
HAL_TIM_Base_Start(&htim2);
}

void my_timer_config_ms(void)
{
TIM_ClockConfigTypeDef sClockSourceConfig;
sClockSourceConfig.ClockSource = TIM_CLOCKSOURCE_INTERNAL;


htim2.Instance = TIM2;
htim2.Init.Prescaler =
((SystemCoreClock/TIMER_PRESCALAR_MS) / (SystemCoreClock/PCLK2_FREQ))-1;
htim2.Init.Period = UINT32_MAX;
htim2.Init.CounterMode = TIM_COUNTERMODE_UP;
htim2.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;

if (HAL_TIM_Base_Init(&htim2) != HAL_OK)
{
_Error_Handler(__FILE__, __LINE__);
}


HAL_TIM_Base_Start(&htim2);
}

I then use these config functions with the following functions to stop, modify and restart the timer.

void stahp_timerz(void)
{
HAL_TIM_Base_Stop(&htim2);
HAL_TIM_Base_DeInit(&htim2);
}

void Delay_ms(uint32_t mS)
{
my_timer_config_ms();

volatile uint32_t start_count = TIM2->CNT;
while(TIM2->CNT-start_count <= mS);

stahp_timerz();
}

void Delay_us(uint32_t uS)
{
my_timer_config_us();

volatile uint32_t start_count = TIM2->CNT;
while(TIM2->CNT-start_count <= uS);

stahp_timerz();
}

The micro second delay seems to work well but the micro does not work as expected. I also was getting weird results until I added the PCLK2_FREQ bit, but I was unable to get it from the system so I used a define. Any tips on how to get that from the system would be appreciated. 

 

By my reasoning the milli second delay should work with my 180Mhz sysclock if I set a prescalar of 180000 but it does weird things.

 

Any help would be very much appreciated.

Alex

Outcomes