一、工程配置
使用定时器5作为输入捕获定时器,将通道1(PA0)设置为输入捕获,设置预分频器和计数值,这里设置为1us计数一次,最大可以捕获周期为0xFFFFFFFFus的PWM,所以一般不需要考虑溢出的问题,使能自动重装载。
使能定时器中断,选择合适的优先级,
将引脚设置下拉,保证没有信号输入时保持电压的稳定,最大输出速度选择高。
在这里在这里可以选择任意定时器输出PWM,便于检验输入捕获的准确性,将TIM14通道1设置为PWM输出,频率为100Hz,其他默认即可。
二、代码初始化和捕获实现
在主函数中开启定时器捕获和更新中断,更新中断本例未使用到,根据需求开启。开启TIM14通道1,用于输出PWM,这里设置占空比为32.7%。
初始化代码中,首先设置 为上升沿捕获,进入InputCap.flag==0,记录定时器计数值,并设置为下降沿捕获,随后等待PWM波形下降沿到来,再次记录定时器计数值,两次计数值的差值就为PWM正脉宽的时长。再将触发方式设置为上升沿触发,同样记录计数值,得到负脉宽的时长,就完成一次捕获。需要注意的是代码中的溢出,若第一次记录的计数值为4294967200,如果脉宽时长为100us,那么第二次的计数值就会溢出,变成5,因为计数值最大为4294967295,超过该值将重新从0开始计数,这时候计算出来的脉宽就会为负值。我们只需要判断两次计数值的大小,做简单的处理即可(InputCap.tim_n_l=InputCap.tim_n1+0xffffffff-InputCap.tim_n2;)。
//在tim.h文件中加入
//定义一个结构体
typedef struct
{
uint32_t tim_n_h;
uint32_t tim_n_l;
uint32_t tim_n1;
uint32_t tim_n2;
uint32_t tim_n3;
uint32_t T;//周期
//uint16_t overflow;//溢出计数
uint8_t flag;//捕获完成标志
}InputCapture;
extern InputCapture InputCap;
//在tim.c文件中实现捕获功能/
//重定义结构体
InputCapture InputCap;
//捕获中断(当发生上升/下降沿时进入该函数)
void HAL_TIM_IC_CaptureCallback(TIM_HandleTypeDef *htim)
{
if(htim==&htim5)
{
if(InputCap.flag==0)//上升沿
{
InputCap.flag=1;//记录索引
InputCap.tim_n1=TIM5->CCR1;//获取计数值
//切换为下降沿捕获
__HAL_TIM_SET_CAPTUREPOLARITY(&htim5,TIM_CHANNEL_1,TIM_INPUTCHANNELPOLARITY_FALLING);
}
else if(InputCap.flag==1)
{
InputCap.flag=2;//记录索引
InputCap.tim_n2=TIM5->CCR1;//获取计数值
//溢出
if(InputCap.tim_n2<InputCap.tim_n1)
{
InputCap.tim_n_h=InputCap.tim_n2+0xffffffff-InputCap.tim_n1;
}
else
{
InputCap.tim_n_h=InputCap.tim_n2-InputCap.tim_n1;
}
//切换为上升沿捕获
__HAL_TIM_SET_CAPTUREPOLARITY(&htim5,TIM_CHANNEL_1,TIM_INPUTCHANNELPOLARITY_RISING);
}
else if(InputCap.flag==2)
{
InputCap.flag=0;//记录索引
InputCap.tim_n1=TIM5->CCR1;
//溢出
if(InputCap.tim_n2>InputCap.tim_n1)
{
InputCap.tim_n_l=InputCap.tim_n1+0xffffffff-InputCap.tim_n2;
}
else
{
InputCap.tim_n_l=InputCap.tim_n1-InputCap.tim_n2;
}
InputCap.T=InputCap.tim_n_l+InputCap.tim_n_h;
//切换为上升沿捕获
__HAL_TIM_SET_CAPTUREPOLARITY(&htim5,TIM_CHANNEL_1,TIM_INPUTCHANNELPOLARITY_RISING);
}
}
}
之后,只要不关闭输入捕获功能,就可以持续捕获,可以在main函数中100ms输出一次捕获结果
while (1)
{
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
printf("%dus %dus %0.3f%% %fHz\r\n",
InputCap.tim_n_h,//高电平时长
InputCap.tim_n_l,//低电平时长
100.0*InputCap.tim_n_h/(InputCap.tim_n_h+InputCap.tim_n_l),//占空比
1.0/((InputCap.tim_n_h+InputCap.tim_n_l)*0.000001)//频率
);
HAL_Delay(100);
}
三、效果验证
把单片机的PA0(捕获)和PF9(PWM,也可以使用外部的波形发生器),连接起来,打开串口调试助手即可看到PWM相关信息,如正负脉宽,频率,占空比等。