1.工程文件的配置
打开cubeMx
配置定时器的PWM产生
这里我用的是定时器3产生PWM波
配置定时器的PWM捕获
这里我配置的是定时器2,用来捕获
时钟树的配置
这里选的是72M
配置串口2
这里可以打印捕获到的数值
打开USB MicroLIB
2.代码部分
#include "stdio.h"
//宏定义,及全局变量
#define cnt_clk 72000000/(71+1)//计时器时钟
#define arr 30000 //重装载寄存器的值,根据实际情况设置。
uint32_t ccr_cnt1,ccr_cnt2;//存捕获寄存器获取的值的变量
uint32_t Period_cnt,Period_cnt1,Period_cnt2;//更新中断次数以及存放更新中断次数的变量
uint32_t ic_flag,end_flag;//触发标志位,捕获完成标志
float duty_cycle,frequency;//频率,占空比
//重定向
int fputc(int ch,FILE *f)
{
HAL_UART_Transmit(&huart2,(uint8_t*)&ch,1,0xffff);
return ch;
}
//开启定时器的一些配置,写在main函数里面
HAL_TIM_PWM_Start(&htim3,TIM_CHANNEL_1);//开启PWM输出,不需要中断
__HAL_TIM_CLEAR_IT(&htim2,TIM_CHANNEL_4);//清除更新中断标志位,防止一使能就进入更新中断
HAL_TIM_Base_Start_IT(&htim2);//使能定时器,更新中断
HAL_TIM_IC_Start_IT(&htim2,TIM_CHANNEL_4);//使能定时器,使能捕获输入以及捕获中断
//while循环里面
while (1)
{
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
// capture_buff[0]=HAL_TIM_ReadCapturedValue(&htim2,TIM_CHANNEL_4);
// printf("BUff[0]=%d\rfreq=%d",capture_buff[0],1000000/(HAL_TIM_ReadCapturedValue(&htim2,TIM_CHANNEL_4)+1));
// capture_buff[0]=0;
// HAL_Delay(500);
//捕获数据处理
while (1)
{
if(end_flag==1)//捕获完成标志位
{
duty_cycle=(float)(Period_cnt1*(arr+1)+ccr_cnt1+1)/(Period_cnt2*(arr+1)+ccr_cnt2+1);
frequency=(float)cnt_clk/(Period_cnt2*(arr+1)+ccr_cnt2+1);
printf("\r\n频率=%.2fHZ,占空比=%.2f%%\r\n",frequency,duty_cycle*100);
end_flag=0;//复位捕获完成标志
}
}
HAL_Delay(1000);
}
/* USER CODE END 3 */
}
//z中断处理函数
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
Period_cnt++;
}
//编写回调函数
void HAL_TIM_IC_CaptureCallback(TIM_HandleTypeDef *htim)
{
switch(ic_flag)//触发标志位判断
{
case 0://第一个上升沿捕获
{
__HAL_TIM_SET_COUNTER(&htim2,0);//清除计数器的计数
ccr_cnt1=0;//初始化相关变量
ccr_cnt2=0;
Period_cnt=0;
Period_cnt1=0;
Period_cnt2=0;
__HAL_TIM_SET_CAPTUREPOLARITY(&htim2,TIM_CHANNEL_4,TIM_INPUTCHANNELPOLARITY_FALLING); //设置成下降沿触发
ic_flag=1;//更改捕获标志位,进入case1进行相关变量的处理。
break;
}
case 1://第一个下降沿捕获
{
ccr_cnt1=__HAL_TIM_GET_COMPARE(&htim2,TIM_CHANNEL_4);//获取存放在CCR寄存器的值(捕获值)
Period_cnt1=Period_cnt;//获取第一个下降沿到来时的进入更新中断的次数
__HAL_TIM_SET_CAPTUREPOLARITY(&htim2,TIM_CHANNEL_4,TIM_INPUTCHANNELPOLARITY_RISING); //设置成上升沿触发
ic_flag=2; //更改捕获标志位,进入case2进行相关变量的处理
break;
}
case 2://第二个上沿捕获
{
ccr_cnt2=__HAL_TIM_GET_COMPARE(&htim2,TIM_CHANNEL_4);//获取存放在CCR寄存器的值(捕获值)
Period_cnt2=Period_cnt;//获取第二个上升沿到来时的进入更新中断的次数
ic_flag=0; //更改捕获标志位,进入case0进行相关变量的处理。
end_flag=1;//捕获完成标志
break;
}
default:
break;
}
}
以上这些经过实验是可行的,用于自己学习的,具体的可以参考以下大佬的文章。