前言
stm32f407单片机定时器最多只有32位,为了实现64位的高精度时间基准,这里使用stm32的定时器同步功能实现。将TIM2和TIM5级联起来,TIM2作为us定时器,TIM5作为s定时器,实现64位的精确到us的时间基准。
STM32F4xx中文参考手册对定时器同步的描述如下:
代码实现
void TIM2_Configuration(void)
{
TIM_ClockConfigTypeDef sClockSourceConfig = {0};
TIM_MasterConfigTypeDef sMasterConfig = {0};
__TIM2_CLK_ENABLE(); // 使能TIM5时钟
htim2.Instance = TIM2; // 选择定时器:TIM2
htim2.Init.Prescaler = 84 - 1; // 分频系数:84,单个脉冲周期1us
htim2.Init.CounterMode = TIM_COUNTERMODE_UP; // 计数方式:向上计数
htim2.Init.Period = 1000000 - 1; // 计时周期:1s
htim2.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1; // 时钟分频:不分频
htim2.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE; // 自动重装载:失能
if (HAL_TIM_Base_Init(&htim2) != HAL_OK) // 初始化TIM2时基
{
// Error_Handler();
}
sClockSourceConfig.ClockSource = TIM_CLOCKSOURCE_INTERNAL; // 时钟源:内部
if (HAL_TIM_ConfigClockSource(&htim2, &sClockSourceConfig) != HAL_OK) // 配置TIM2的时钟源
{
// Error_Handler();
}
sMasterConfig.MasterOutputTrigger = TIM_TRGO_UPDATE; // 每次更新事件TRGO1输出一个上升沿
sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_ENABLE; // 使能TIM2主模式
if (HAL_TIMEx_MasterConfigSynchronization(&htim2, &sMasterConfig) != HAL_OK) // 配置TIM2的主模式
{
// Error_Handler();
}
HAL_TIM_Base_Start(&htim2); // 打开定时器2
}
void TIM5_Configuration(void)
{
TIM_SlaveConfigTypeDef sSlaveConfig = {0};
TIM_MasterConfigTypeDef sMasterConfig = {0};
__TIM5_CLK_ENABLE(); // 使能TIM5时钟
htim5.Instance = TIM5; // 选择定时器:TIM5
htim5.Init.Prescaler = 1 - 1; // 分频系数:1,单个脉冲周期1s
htim5.Init.CounterMode = TIM_COUNTERMODE_UP; // 计数方式:向上计数
htim5.Init.Period = 0XFFFFFFFF - 1; // 计时周期:0xFFFFFFFF s
htim5.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1; // 时钟分频:不分频
htim5.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE; // 自动重装载:失能
if (HAL_TIM_Base_Init(&htim5) != HAL_OK) // 初始化TIM5时基
{
// Error_Handler();
}
sSlaveConfig.SlaveMode = TIM_SLAVEMODE_EXTERNAL1; // 从模式:外部时钟模式1
sSlaveConfig.InputTrigger = TIM_TS_ITR0; // 触发源:ITR0
if (HAL_TIM_SlaveConfigSynchro(&htim5, &sSlaveConfig) != HAL_OK) // 配置TIM5的从模式
{
// Error_Handler();
}
sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET; // 每次更新事件TRGO1输出一个上升沿
sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE; // 失能TIM5主模式
if (HAL_TIMEx_MasterConfigSynchronization(&htim5, &sMasterConfig) != HAL_OK) // 配置TIM2的主模式
{
// Error_Handler();
}
HAL_TIM_Base_Start(&htim5); // 打开定时器5
}
uint32_t GetSec(void)
{
return TIM5->CNT;
}
uint32_t GetUSec(void)
{
return TIM2->CNT;
}
// 获取64位本地时间,us
u64 getsysTime(void)
{
uint32_t sec = GetSec();
uint32_t us = GetUSec();
if(sec != GetSec())//防止正在取在s的跳变沿
{
sec = GetSec();
us = GetUSec();
}
return (u64)sec * 1000000 + (u64)us;
}