在网上看了一些参考,具体实现细节还是没搞懂,后来发现只有自己去尝试下才能明白
我这里使用了TIM14的捕捉功能,计算两次上升沿的时间去算频率
void MX_TIM14_Init(void)
{
__HAL_RCC_TIM14_CLK_ENABLE();
__HAL_RCC_GPIOA_CLK_ENABLE();
TIM_IC_InitTypeDef sConfigIC = {0};
htim14.Instance = TIM14;
htim14.Init.Prescaler = 4800-1; //预分频
htim14.Init.CounterMode = TIM_COUNTERMODE_UP;//向上计数
htim14.Init.Period = 20000; //计数值
htim14.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;//1分频
htim14.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_ENABLE;//自动重载
HAL_TIM_Base_Init(&htim14);
sConfigIC.ICPolarity = TIM_INPUTCHANNELPOLARITY_RISING; //上升沿触发
sConfigIC.ICSelection = TIM_ICSELECTION_DIRECTTI;
sConfigIC.ICPrescaler = TIM_ICPSC_DIV1; //1分频
sConfigIC.ICFilter = 0; //不过滤
HAL_TIM_IC_ConfigChannel(&htim14, &sConfigIC, TIM_CHANNEL_1); //捕捉通道选择
HAL_TIM_IC_Init(&htim14);
/*通道使用脚位初始化*/
GPIO_InitTypeDef GPIO_InitStruct = {0};
GPIO_InitStruct.Pin = GPIO_PIN_4;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_PULLDOWN;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
GPIO_InitStruct.Alternate = GPIO_AF4_TIM14;
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
/* TIM14 interrupt Init */
HAL_NVIC_SetPriority(TIM14_IRQn, 0, 0); //设置中断优先级
HAL_NVIC_EnableIRQ(TIM14_IRQn); //使能中断
__HAL_TIM_ENABLE_IT(&htim14, TIM_IT_UPDATE);
HAL_TIM_IC_Start_IT(&htim14, TIM_CHANNEL_1); //开启捕捉中断
HAL_TIM_Base_Start_IT(&htim14); //开启计数中断
}
static uint8_t flag_capture = 0;
void HAL_TIM_IC_CaptureCallback(TIM_HandleTypeDef *htim)
{ //当有上升沿的时候会进这里
static uint32_t capture_valuel =0;
if (htim->Instance == TIM14)
{//第二个上升沿计数,根据计算值capture_valuel可计算出频率
if(flag_capture==1)
{
flag_capture=0;
capture_valuel = __HAL_TIM_GET_COUNTER(&htim14);
}
else if(flag_capture==0)
{//第一个上升沿,计算清零
flag_capture=1;
__HAL_TIM_SET_COUNTER(&htim14, 0);
}
}
}
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim) //TIM back
{/*计算值满会进这里,初始化为第一个上升沿,当规定时间没有脉冲的时候,频率为零,这个时间可以直接设置*/
if (htim->Instance == TIM14)
{
capture_valuel =0;
flag_capture=0;
}
}
这边试了一下,频率在50khz以下的频率计数,精度很高