You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
4.4 KiB
4.4 KiB
CAP
开启 TIM5 时钟,配置 PA0 为复用功能(AF2),并开启下拉电阻。
配置
TIM5_CH1
分频71 1us, 计数周期尽可能长 16位 65535
库函数
HAL_TIM_IC_Start_IT(&htim5,TIM_CHANNEL_1); //开启TIM5通道1的捕获中断
HAL_TIM_IC_Stop_IT(); //关闭捕获中断
__HAL_TIM_ENABLE_IT(&htim5,TIM_IT_UPDATE); //开启TIM5的更新中断
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *hitm)//中断更新回调函数
void HAL_TIM_IC_CaptureCallback(TIM_HandleTypeDef *htim)//捕获中断回调函数
__HAL_TIM_ENABLE(&htim5); //使能定时器
__HAL_TIM_DISABLE(&htim5); //关闭定时器
__HAL_TIM_SET_COUNTER(&htim5,0); //计数器值清零
TIM_SET_CAPTUREPOLARITY(__HANDLE__, __CHANNEL__, __POLARITY__) //设置捕获极性
TIM_RESET_CAPTUREPOLARITY(__HANDLE__, __CHANNEL__); //清除极性
//在修改定时器某一通道的输入捕获极性时,一定要先清除该通道之前捕获极性
__HAL_TIM_GET_COMPARE(__HANDLE__, __CHANNEL__); //获取定时器某一通道的捕获/比较寄存器值
//等价于
uint32_t HAL_TIM_ReadCapturedValue(TIM_HandleTypeDef *htim, uint32_t Channel);//读取对应CCRx寄存器的值
捕获 CAP
输入捕获模式可以用来测量脉冲宽度或者测量频率。 捕获电平上升或下降沿中断 中间可能会有溢出, 需要配置溢出中断
HAL_TIM_Base_Start_IT(&htim5); // 开启中断 HAL_TIM_IC_Start_IT(&htim5, TIM_CHANNEL_1); // 开启捕获中断 void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim) //溢出回调
捕获回调 void HAL_TIM_IC_CaptureCallback(TIM_HandleTypeDef *htim) { HAL_GPIO_TogglePin(LED1_GPIO_Port,LED1_Pin);//点灯 } 通过分频,设置为1us
// 参考例程
//可以写在主函数,也可以在time.c
/*
sta当前的捕获状态:
[14]0x4000 =1表示捕获到了上升沿 现在待测量是高电平
[15]0x8000 =1表示捕获到了下降沿 现在待测量是低电平,此时第6位依然是1
[0~13] 用于记录计数器溢出次数
val记录计数器的值
*/
uint16_t tim5_ch1_cap_sta = 0;
uint32_t tim5_ch1_cap_val;
//定时器捕获中断回调函数
//第1次捕获的是上升沿
void HAL_TIM_IC_CaptureCallback(TIM_HandleTypeDef *htim)
{
if(htim == &htim5)
{
HAL_GPIO_TogglePin(LED1_GPIO_Port,LED1_Pin);//点亮或关闭DS1
if((tim5_ch1_cap_sta&0x8000) == 0)
{
if((tim5_ch1_cap_sta&0x4000))//捕获到了下降沿
{
tim5_ch1_cap_sta |= 0x8000;
//获取当前计数器的值
tim5_ch1_cap_val=HAL_TIM_ReadCapturedValue(&htim5,TIM_CHANNEL_1);
//清除之前的沿触发捕获模式
TIM_RESET_CAPTUREPOLARITY(&htim5,TIM_CHANNEL_1);
//设置为上升沿触发
TIM_SET_CAPTUREPOLARITY(&htim5,TIM_CHANNEL_1,TIM_ICPOLARITY_RISING);
}
else//捕获到了上升沿
{
/*重启定时器5*/
//关闭
__HAL_TIM_DISABLE(&htim5);
//计数器清0
__HAL_TIM_SET_COUNTER(&htim5,0);
//清除之前的沿触发捕获模式
TIM_RESET_CAPTUREPOLARITY(&htim5,TIM_CHANNEL_1);
//定时器5通道1设置为下降沿捕获
TIM_SET_CAPTUREPOLARITY(&htim5,TIM_CHANNEL_1,TIM_ICPOLARITY_FALLING);
//使能定时器5
__HAL_TIM_ENABLE(&htim5);
tim5_ch1_cap_sta = 0;
tim5_ch1_cap_val = 0;
tim5_ch1_cap_sta |= 0x4000;
}
}
}
}
//计数器溢出中断回调函数(TIM5_CNT 只有16位)
//计数器记录的是自己的执行了多少个周期 如:1Mhz 1us计数器+1
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
if(htim == &htim5)
{
if((tim5_ch1_cap_sta&0x8000) == 0)
{
if((tim5_ch1_cap_sta&0x4000))
{
if((tim5_ch1_cap_sta&0x3fff) == 0x3fff)//记录溢出次数过多(高电平太长)
{
tim5_ch1_cap_sta |= 0x8000;//强行表示高电平结束
tim5_ch1_cap_val &= 0xffffffff;
}
else
{
tim5_ch1_cap_sta++;
}
}
}
}
}
/*主函数测试部分代码*/
long long temp;
while (1)
{
if((tim5_ch1_cap_sta&0x8000))//确认当前为低电平
{
u1_printf("Capture ok\r\n");
temp = tim5_ch1_cap_sta&0x3fff;
temp = temp*65535;
temp = temp + tim5_ch1_cap_val;
u1_printf("%.2lf s\r\n",(double)temp/(1000*1000));
HAL_Delay(1000);
break;
}
}
u1_printf("done\r\n");