因为之前就一直想做输入捕获,查阅了很多资料发现,说的都很复杂,让人摸不到头脑,研究后作为笔记。
先确定频率
定时器计数肯定是有一个频率,我们看时钟树,看到80mhz是连到定时器的。
想要计数频率为1Mhz,就需要把80Mhz频率分频。注意 79+1是80/(79+1),因为0开始计数,计数到溢出,也就是多数了一个,所以需要加1。0xffff是以1Mhz频率进行计数,也就是1us加一次,加到0xffff需要0xffff+1秒
代码
首先可以参考一下官方的例程
/* Timer handler declaration */
TIM_HandleTypeDef TimHandle;
/* Timer Input Capture Configuration Structure declaration */
TIM_IC_InitTypeDef sICConfig;
/* Captured Values */
uint32_t uwIC2Value1 = 0;
uint32_t uwIC2Value2 = 0;
uint32_t uwDiffCapture = 0;
/* Capture index */
uint16_t uhCaptureIndex = 0;
/* Frequency Value */
uint32_t uwFrequency = 0;
/*##-1- Configure the TIM peripheral #######################################*/
/* TIM1 configuration: Input Capture mode ---------------------
The external signal is connected to TIM1 CH2 pin (PA.09)
The Rising edge is used as active edge,
The TIM1 CCR2 is used to compute the frequency value
------------------------------------------------------------ */
/* Set TIMx instance */
TimHandle.Instance = TIMx;
/* Initialize TIMx peripheral as follows:
+ Period = 0xFFFF
+ Prescaler = 0
+ ClockDivision = 0
+ Counter direction = Up
*/
TimHandle.Init.Period = 0xFFFF;
TimHandle.Init.Prescaler = 0;
TimHandle.Init.ClockDivision = 0;
TimHandle.Init.CounterMode = TIM_COUNTERMODE_UP;
TimHandle.Init.RepetitionCounter = 0;
if(HAL_TIM_IC_Init(&TimHandle) != HAL_OK)
{
/* Initialization Error */
Error_Handler();
}
/*##-2- Configure the Input Capture channel ################################*/
/* Configure the Input Capture of channel 2 */
sICConfig.ICPolarity = TIM_ICPOLARITY_RISING;
sICConfig.ICSelection = TIM_ICSELECTION_DIRECTTI;
sICConfig.ICPrescaler = TIM_ICPSC_DIV1;
sICConfig.ICFilter = 0;
if(HAL_TIM_IC_ConfigChannel(&TimHandle, &sICConfig, TIM_CHANNEL_2) != HAL_OK)
{
/* Configuration Error */
Error_Handler();
}
/*##-3- Start the Input Capture in interrupt mode ##########################*/
if(HAL_TIM_IC_Start_IT(&TimHandle, TIM_CHANNEL_2) != HAL_OK)
{
/* Starting Error */
Error_Handler();
}
/**
* @brief Conversion complete callback in non blocking mode
* @param htim : hadc handle
* @retval None
*/
void HAL_TIM_IC_CaptureCallback(TIM_HandleTypeDef *htim)
{
if (htim->Channel == HAL_TIM_ACTIVE_CHANNEL_2)
{
if(uhCaptureIndex == 0)
{
/* Get the 1st Input Capture value */
uwIC2Value1 = HAL_TIM_ReadCapturedValue(htim, TIM_CHANNEL_2);
uhCaptureIndex = 1;
}
else if(uhCaptureIndex == 1)
{
/* Get the 2nd Input Capture value */
uwIC2Value2 = HAL_TIM_ReadCapturedValue(htim, TIM_CHANNEL_2);
/* Capture computation */
if (uwIC2Value2 > uwIC2Value1)
{
uwDiffCapture = (uwIC2Value2 - uwIC2Value1);
}
else if (uwIC2Value2 < uwIC2Value1)
{
/* 0xFFFF is max TIM1_CCRx value */
uwDiffCapture = ((0xFFFF - uwIC2Value1) + uwIC2Value2) + 1;
}
else
{
/* If capture values are equal, we have reached the limit of frequency
measures */
Error_Handler();
}
/* Frequency computation: for this example TIMx (TIM1) is clocked by
APB2Clk */
uwFrequency = HAL_RCC_GetPCLK2Freq() / uwDiffCapture;
uhCaptureIndex = 0;
}
}
}
以上就是官方代码主要部分,官方的代码的意思是,两个上升沿之前的计数uwDiffCapture,假如两个上升沿时间超过几个0xffff+1时间也是存在问题的。 暂时可先不考虑这个问题。
咱们想做的是上升沿开始采集直到下降沿的时间。
/**
* @brief Conversion complete callback in non blocking mode
* @param htim : hadc handle
* @retval None
*/
void HAL_TIM_IC_CaptureCallback(TIM_HandleTypeDef *htim)
{
if (htim->Channel == HAL_TIM_ACTIVE_CHANNEL_1)
{
if(uhCaptureIndex == 0)
{
/* Get the 1st Input Capture value */
uwIC2Value1 = HAL_TIM_ReadCapturedValue(htim, TIM_CHANNEL_1);
uhCaptureIndex = 1;
TIM_IC_InitTypeDef sConfigIC = {0};
sConfigIC.ICPolarity = TIM_INPUTCHANNELPOLARITY_FALLING;
sConfigIC.ICSelection = TIM_ICSELECTION_DIRECTTI;
sConfigIC.ICPrescaler = TIM_ICPSC_DIV1;
sConfigIC.ICFilter = 0;
if (HAL_TIM_IC_ConfigChannel(&htim17, &sConfigIC, TIM_CHANNEL_1) != HAL_OK)
{
Error_Handler();
}
/*##-3- Start the Input Capture in interrupt mode ##########################*/
if(HAL_TIM_IC_Start_IT(&htim17, TIM_CHANNEL_1) != HAL_OK)
{
/* Starting Error */
Error_Handler();
}
}
else if(uhCaptureIndex == 1)
{
/* Get the 2nd Input Capture value */
uwIC2Value2 = HAL_TIM_ReadCapturedValue(htim, TIM_CHANNEL_1);
/* Capture computation */
if (uwIC2Value2 > uwIC2Value1)
{
uwDiffCapture = (uwIC2Value2 - uwIC2Value1);
}
else if (uwIC2Value2 < uwIC2Value1)
{
/* 0xFFFF is max TIM1_CCRx value */
uwDiffCapture = ((0xFFFF - uwIC2Value1) + uwIC2Value2) + 1;
}
else
{
/* If capture values are equal, we have reached the limit of frequency
measures */
Error_Handler();
}
/* Frequency computation: for this example TIMx (TIM1) is clocked by
APB2Clk */
uwFrequency = HAL_RCC_GetPCLK2Freq() / uwDiffCapture;
uhCaptureIndex = 0;
TIM_IC_InitTypeDef sConfigIC = {0};
sConfigIC.ICPolarity = TIM_INPUTCHANNELPOLARITY_RISING;
sConfigIC.ICSelection = TIM_ICSELECTION_DIRECTTI;
sConfigIC.ICPrescaler = TIM_ICPSC_DIV1;
sConfigIC.ICFilter = 0;
if (HAL_TIM_IC_ConfigChannel(&htim17, &sConfigIC, TIM_CHANNEL_1) != HAL_OK)
{
Error_Handler();
}
/*##-3- Start the Input Capture in interrupt mode ##########################*/
if(HAL_TIM_IC_Start_IT(&htim17, TIM_CHANNEL_1) != HAL_OK)
{
/* Starting Error */
Error_Handler();
}
}
}
}
其实就是把上升沿下降沿配置一下,可以从初始化代码拷贝过来,可以封装成一个函数。
关于超过最长时间的问题本文暂为实现。