Reputation: 117
I've tried doing my own millisecond timer on stm32f103r6t, I've used timer 2 with interrupt on period elapsed, then I increase the counter by one step. The clock frequency is 64mhz, (APB1&2 are 64Mhz as well), prescaller is at 127 and the period value is set to 500. I tested by toggling a pin on interrupt and I got a 1ms half-period on the oscilloscope (which is expected). The other test that I did was to compare it with __Hal_get_ticks() and send it to uart. It seems that __Hal_get_ticks() is faster, and their difference keeps increasing with time. I've posted the code bellow, although I do initialize more peripherals, I haven't used them yet.
long milliseconds=0; void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef* htim) { HAL_GPIO_TogglePin(GPIOC, GPIO_PIN_9); milliseconds++; }
int main(void)
{
/* MCU Configuration--------------------------------------------------------*/
/* Reset of all peripherals, Initializes the Flash interface and the Systick. */
HAL_Init();
/* Configure the system clock */
SystemClock_Config();
/* Initialize all configured peripherals */
MX_GPIO_Init();
MX_ADC1_Init();
MX_CAN_Init();
MX_SPI1_Init();
MX_TIM2_Init();
MX_TIM3_Init();
stm32_uart2_set_state(1);
HAL_TIM_Base_Start_IT(&htim2);
// MX_WWDG_Init();
/* USER CODE BEGIN 2 */
char string[100]={0};
int index=0;
/* Infinite loop */
while (1)
{
uint32_t hall_tick=HAL_GetTick();
sprintf(string,"It:%lu\tHt:%lu\n\r",milliseconds,hall_tick);
stm32_uart2_send_string(string, strlen(string));
}
}
/**
* @brief System Clock Configuration
* @retval None
*/
void SystemClock_Config(void)
{
RCC_OscInitTypeDef RCC_OscInitStruct = {0};
RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};
RCC_PeriphCLKInitTypeDef PeriphClkInit = {0};
/** Initializes the RCC Oscillators according to the specified parameters
* in the RCC_OscInitTypeDef structure.
*/
RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI;
RCC_OscInitStruct.HSIState = RCC_HSI_ON;
RCC_OscInitStruct.HSICalibrationValue = RCC_HSICALIBRATION_DEFAULT;
RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSI_DIV2;
RCC_OscInitStruct.PLL.PLLMUL = RCC_PLL_MUL16;
if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
{
Error_Handler();
}
/** Initializes the CPU, AHB and APB buses clocks
*/
RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
|RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;
RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV2;
RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;
if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_2) != HAL_OK)
{
Error_Handler();
}
PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_ADC;
PeriphClkInit.AdcClockSelection = RCC_ADCPCLK2_DIV8;
if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInit) != HAL_OK)
{
Error_Handler();
}
}
static void MX_TIM2_Init(void)
{
TIM_ClockConfigTypeDef sClockSourceConfig = {0};
TIM_MasterConfigTypeDef sMasterConfig = {0};
htim2.Instance = TIM2;
htim2.Init.Prescaler = 127; //prescaller is zero-based (0 means clk/1)
htim2.Init.CounterMode = TIM_COUNTERMODE_UP;
htim2.Init.Period = 500;
htim2.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
htim2.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_ENABLE;
if (HAL_TIM_Base_Init(&htim2) != HAL_OK)
{
Error_Handler();
}
sClockSourceConfig.ClockSource = TIM_CLOCKSOURCE_INTERNAL;
if (HAL_TIM_ConfigClockSource(&htim2, &sClockSourceConfig) != HAL_OK)
{
Error_Handler();
}
sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET;
sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;
if (HAL_TIMEx_MasterConfigSynchronization(&htim2, &sMasterConfig) != HAL_OK)
{
Error_Handler();
}
}
EDIT: This is the default init function for the hal counter, interrupt priority by default is 15, I've tried setting it to 0 but the results are the same. I've measured the perio of HAL_get_tick() and its 998us instead of 1ms
_weak HAL_StatusTypeDef HAL_InitTick(uint32_t TickPriority)
{
/* Configure the SysTick to have interrupt in 1ms time basis*/
if (HAL_SYSTICK_Config(SystemCoreClock / (1000U / uwTickFreq)) > 0U)
{
return HAL_ERROR;
}
/* Configure the SysTick IRQ priority */
if (TickPriority < (1UL << __NVIC_PRIO_BITS))
{
HAL_NVIC_SetPriority(SysTick_IRQn, TickPriority, 0U);
uwTickPrio = TickPriority;
}
else
{
return HAL_ERROR;
}
/* Return function status */
return HAL_OK;
}
Upvotes: 1
Views: 701
Reputation: 4297
I think you probably want to set your TIM2 period to 499. It is zero-based just like the pre-scaler. From the manual:
In upcounting mode, the counter counts from 0 to the auto-reload value(content of the TIMx_ARR register), then restarts from 0 and generates a counter overflow event.
You want to count from 0 to 499, then reset to zero.
This would explain why you are out by 2us per ms.
Upvotes: 1