功能:测量频率、周期、占空比
百度云:https://pan.baidu.com/s/1e4BSJzzk3W2YQi2S7qHG5A?pwd=6666
提取码:6666
目录
原理分析:
1.周期与频率测量分析
我们在第一次捕获上升沿时将计数值清零,第二次捕获到上升沿时记下当前值,也就是count3,在捕获count3之前可能会有溢出,我们要将它记录下来否则计算会出现差错。
也就是总计数值为N*ARR+count3,再乘上计数时间就可以算出周期了。
T = (N*ARR+count3)*t
F = 1/T
2.占空比分析
在第一次捕获到上升沿时将计数值清零,并且设置下次为捕获下降沿。在捕获下降沿时,中间也可能有N次溢出。
Th = (N*ARR+count2)*t
占空比 = Th/T*100%
HAL配置
1.配置时钟
然后回车一下。
因为开发板上接的是24MHz所以这里填1处24,官方给的历程都是80MHz所以4处填80。
2.SYS配置
防止只能下载一次程序所以这里设置为Serial Wire。
3.输入捕获的配置
配置时钟源以及输入捕获模式,通道选择对应引脚的通道,4处的分频可以小一些防止捕获不到,计数值我们设置为1000-1,是为了演示溢出所以小了一些一般默认就好。
默认捕获上升沿。
4.PWM配置
我们这里方便验证捕获的准确性,所以捕获PWM的周期频率及占空比。
代码编写
定义的数据
typedef struct
{
double Period;//周期
unsigned char N;//溢出N
unsigned long Count;//测量的计数值
bool N_Flag;//溢出标志位
bool Flag;//测量上升沿的标志位
unsigned int Frequency;//频率
unsigned char state;
double High_Time;//高电平时间
unsigned char Duty_Cycle;//占空比
}PWM_TypeDef;
//开启定时器中断
HAL_TIM_Base_Start_IT(&htim3);
//开启PWM
HAL_TIM_PWM_Start(&htim16,TIM_CHANNEL_1);
//开启输入捕获中断
HAL_TIM_IC_Start_IT(&htim3,TIM_CHANNEL_1);
输入捕获回调函数
void HAL_TIM_IC_CaptureCallback(TIM_HandleTypeDef *htim)
{
//判断是否是TIM3的输入捕获中断
if(htim->Instance == TIM3)
{
//判断是否是通道一
if(htim->Channel == HAL_TIM_ACTIVE_CHANNEL_1)
{
PA6.state++;
if(PA6.state<=10)//测量多次周期和频率
{
if(PA6.Flag == 1)//第二次捕获上升沿
{
PA6.Flag = 0;//设置下次为第一次捕获
PA6.N_Flag = 0;//失能溢出标志位
//读取第二次捕获的计数值
PA6.Count = __HAL_TIM_GetCounter(htim);
//周期 = 计数值*t
//TIM3的时钟源为80MHz,分频为80
//一个计数周期为 = 1/(80M/80) = 80.0/80000000.0
PA6.Period = (PA6.N*1000+PA6.Count)*(80.0/80000000.0);
PA6.Frequency = 1/PA6.Period;
PA6.N = 0;//清除溢出计数值
}
else//第一次捕获上升沿
{
PA6.N_Flag = 1;//使能溢出标志位
PA6.Flag = 1;//设置下次为第二次捕获
//第一次捕获清除计数值
__HAL_TIM_SetCounter(htim,0);
}
}
else//测量占空比
{
PA6.state = 11;
if(PA6.Flag == 1)
{
PA6.Flag = 0;
PA6.N_Flag = 0;
PA6.Count = __HAL_TIM_GetCounter(htim);
PA6.High_Time = (PA6.N*1000+PA6.Count)*(80.0/80000000.0);
PA6.Duty_Cycle = PA6.High_Time/PA6.Period*100;
PA6.N = 0;
//设置下次捕获上升沿
__HAL_TIM_SET_CAPTUREPOLARITY(htim,TIM_CHANNEL_1,TIM_INPUTCHANNELPOLARITY_RISING);
}
else
{
PA6.N_Flag = 1;
PA6.Flag = 1;
__HAL_TIM_SetCounter(htim,0);
//设置下次捕获下降沿
__HAL_TIM_SET_CAPTUREPOLARITY(htim,TIM_CHANNEL_1,TIM_INPUTCHANNELPOLARITY_FALLING);
}
}
//开启下次捕获
HAL_TIM_IC_Start_IT(&htim3,TIM_CHANNEL_1);
}
}
}
定时器中断回调函数
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
if(htim->Instance==TIM3)//判断是否是TIM3的溢出中断
{
if(PA6.N_Flag == 1)
PA6.N++;
}
}
结果演示
到此输入捕获完毕。
如有错误还请指正,谢谢。