输入捕获模式下,当通道输入引脚出现指定电平跳变(上升沿或者下降沿)时,(控制)当前CNT的值将被锁存到CCR中,可用于测量PWM波形的频率、占空比、脉冲间隔、电平持续时间等参数
每个高级定时器和通用定时器都拥有4个输入捕获通道
可配置为PWMI(input)模式,同时测量频率和占空比
可配合主从触发模式,实现硬件全自动测量
(输入捕获,接收到输入信号,执行CNT锁存到CCR的动作)
(输出比较,是根据CNT和CCR的比较关系执行输出动作)
测频法:在闸门时间T内,对上升沿计次,得到N,则频率 (适合测量高频信号)
f x = N / T f_x=N / T fx=N/T N越大,误差和越小 ,因为容易计数遗漏 (记录的次数多了,一次记错也影响不大)
测周法:两个上升沿内,以标准频率fc计次,得到N ,则频率 f = 1/t (通过计时器记录一个上升加一个下降沿的时间)(适合测量低频信号)
f x = f c / N f_x=f_c / N fx=fc/N N越大,误差和越小 多计算一些数
那多高算高频率,多低算低频率。就涉及到中界频率:
中界频率:测频法与测周法误差相等的频率点
f m = √ f c / T f_m=√f_c / T fm=√fc/T
测量的是数字信号。
Freq = CK_PSC / (PSC + 1) / (ARR + 1)
以采样频率对输入信号进行采样,当连续N个值都为高电平,输出才为高电平,反之亦然,如果信号出现高频抖动,导致连续 采样N个值不全都一样。那输出不会变化。达到滤波的效果。
特点:
采样频率越低,采样个数N越大,滤波器效果就越好。
如果噪声比较大,就将采样频率从的值调大一点,就可以过滤噪声
用来捕获上升沿或者下降沿。
fx=fc/N N=CNT
因为CNT在清零后一直++
CCR1是一整个周期的计数值
CCR2是高电平期间的计数值
占空比:CCR2/CCR1
这里可以看出来 N = CCR1
uint32_t IC_GetFreq(void)
{ // fx =fc/n fc = CK_PSC / (PSC + 1) -> 72000000Hz/72 = 1MHZ
return 1000000/(TIM_GetCapture1(TIM3)+1); // 占空比= fc/N N就是读取CCR的值
}
uint32_t IC_GetDuty(void) //获得PWM的占空比
{
return TIM_GetCapture2(TIM3)/TIM_GetCapture1(TIM3); //CRR2/CRR1
}
滤波器不会改变信号的原有频率,只会滤除高频噪音。
分频器是对信号进行分频。改变了原有的频率
除了由±1误差,还有晶振误差
通过直接在PWM.c文件中修改 PSC和ARR不方便,因此创建一个函数
#include “stm32f10x.h” // Device header
//1.配置GPIO
//2.选择内部时钟
//3.配置时基单元
//4.配置输入捕获单元
//5.选择从模式触发源
//6.选择触发之后执行的操作
//7.开启定时器
void IC_Init(void)
{
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3,ENABLE);//给TIM2使能
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);//给GPIO使能
GPIO_InitTypeDef GPIO_InitStruct;
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_IPU; //上拉输入,
GPIO_InitStruct.GPIO_Pin = GPIO_Pin_6; //根据引脚表的出CH_1所在引脚时PA0
GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA,&GPIO_InitStruct);
TIM_InternalClockConfig(TIM3); //选择内部时钟
//时基单元
TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStruct;
TIM_TimeBaseInitStruct.TIM_ClockDivision = TIM_CKD_DIV1; //每一个时钟后面都会加一个滤波器,作用就是为是信号更加稳定,使用的采样的方式,在输入的脉冲中采样,按照n/f,因此采样系数越大,延迟越大
TIM_TimeBaseInitStruct.TIM_CounterMode = TIM_CounterMode_Up;
TIM_TimeBaseInitStruct.TIM_Period = 65536-1; //ARR =100
TIM_TimeBaseInitStruct.TIM_Prescaler = 72-1; // psc = 720//预分频器,72MHZ进行7200分频 ,72000/7200 = 10KHZ 1ms = 1KHZ 10KHZ下记10000个数 10000/10 =1000kHZ = 1S
TIM_TimeBaseInitStruct.TIM_RepetitionCounter = 0;
TIM_TimeBaseInit(TIM3,&TIM_TimeBaseInitStruct);
//初始化输入捕获单元
TIM_ICInitTypeDef TIM_ICInitStruct;
TIM_ICInitStruct.TIM_Channel = TIM_Channel_1 ;
TIM_ICInitStruct.TIM_ICFilter = 0xF; //数值越大,采样效果越好(以采样频率对输入信号进行采样,当连续N个值都为高电平,输出才为高电平,反之亦然,如果信号出现高频抖动,导致连续 采样N个值不全都一样。那输出不会变化。达到滤波的效果。)
TIM_ICInitStruct.TIM_ICPolarity = TIM_ICPolarity_Rising; //极性选择 上升沿,下降沿 双沿
TIM_ICInitStruct.TIM_ICPrescaler = TIM_ICPSC_DIV1;//设置分频值
TIM_ICInitStruct.TIM_ICSelection = TIM_ICSelection_DirectTI; ///通道选择 。直连,交叉
TIM_ICInit(TIM3,&TIM_ICInitStruct);
//配置触发源
TIM_SelectInputTrigger(TIM3, TIM_TS_TI1FP1);
//选择从模式 自动清理CNT
TIM_SelectSlaveMode(TIM3,TIM_SlaveMode_Reset);
//启动时基单元
TIM_Cmd(TIM3,ENABLE);
}
uint32_t IC_GetFreq(void)
{ // fx =fc/n fc = CK_PSC / (PSC + 1) -> 72000000Hz/72 = 1MHZ
return 1000000/(TIM_GetCapture1(TIM3)+1); // freq= fc/N N就是读取CCR的值
}
uint32_t IC_GetFreq(void)
{ // fx =fc/n fc = CK_PSC / (PSC + 1) -> 72000000Hz/72 = 1MHZ
return 1000000/(TIM_GetCapture1(TIM3)+1); // 占空比= fc/N N就是读取CCR的值
}
uint32_t IC_GetDuty(void)
{
return (TIM_GetCapture2(TIM3)+1)*100/(TIM_GetCapture1(TIM3)+1); //*100可以变为整数
}
//配置成两个通道同时捕获一个引脚
//初始化输入捕获单元
TIM_ICInitTypeDef TIM_ICInitStruct;
TIM_ICInitStruct.TIM_Channel = TIM_Channel_1 ;
TIM_ICInitStruct.TIM_ICFilter = 0xF; //数值越大,采样效果越好(以采样频率对输入信号进行采样,当连续N个值都为高电平,输出才为高电平,反之亦然,如果信号出现高频抖动,导致连续 采样N个值不全都一样。那输出不会变化。达到滤波的效果。)
TIM_ICInitStruct.TIM_ICPolarity = TIM_ICPolarity_Rising; //极性选择 上升沿,下降沿 双沿
TIM_ICInitStruct.TIM_ICPrescaler = TIM_ICPSC_DIV1;//设置分频值
TIM_ICInitStruct.TIM_ICSelection = TIM_ICSelection_DirectTI; ///通道选择 。直连,交叉
TIM_ICInit(TIM3,&TIM_ICInitStruct);
//如何配置成两个通道同时捕获一个引脚,采用下面的函数
//只支持通道1和通道2
TIM_PWMIConfig(TIM3,&TIM_ICInitStruct); //这个函数会自动将配置呈相反的,上升沿变下降沿,直连变交叉
//配置触发源
TIM_SelectInputTrigger(TIM3, TIM_TS_TI1FP1);
//选择从模式 自动清理CNT
TIM_SelectSlaveMode(TIM3,TIM_SlaveMode_Reset
);
//也有四个通道,初始化输入捕获单元
void TIM_ICInit(TIM_TypeDef* TIMx, TIM_ICInitTypeDef* TIM_ICInitStruct);
//给初始化PWMI
void TIM_PWMIConfig(TIM_TypeDef* TIMx, TIM_ICInitTypeDef* TIM_ICInitStruct);
//给结构体初始化值
void TIM_ICStructInit(TIM_ICInitTypeDef* TIM_ICInitStruct);
//选择输入触发源 (从模式)
void TIM_SelectInputTrigger(TIM_TypeDef* TIMx, uint16_t TIM_InputTriggerSource);
//选择输出触发源
void TIM_SelectOutputTrigger(TIM_TypeDef* TIMx, uint16_t TIM_TRGOSource);
//选择从模式
void TIM_SelectSlaveMode(TIM_TypeDef* TIMx, uint16_t TIM_SlaveMode);
//分别单独配置通道1,2,3,4的分频器
void TIM_SetIC1Prescaler(TIM_TypeDef* TIMx, uint16_t TIM_ICPSC);
void TIM_SetIC2Prescaler(TIM_TypeDef* TIMx, uint16_t TIM_ICPSC);
void TIM_SetIC3Prescaler(TIM_TypeDef* TIMx, uint16_t TIM_ICPSC);
void TIM_SetIC4Prescaler(TIM_TypeDef* TIMx, uint16_t TIM_ICPSC);
void TIM_SetClockDivision(TIM_TypeDef* TIMx, uint16_t TIM_CKD);
//分别读取4个通道的CCR
uint16_t TIM_GetCapture1(TIM_TypeDef* TIMx);
uint16_t TIM_GetCapture2(TIM_TypeDef* TIMx);
uint16_t TIM_GetCapture3(TIM_TypeDef* TIMx);
uint16_t TIM_GetCapture4(TIM_TypeDef* TIMx);