简介
输入捕获功能同样只有高级/通用定时器才具有.
输入捕获英文名字为Input Capture. 是定时器外设另一个大的功能, 与输出比较OC共用CCR寄存器, 因此一个定时器只可以使用一种功能, CCR(Capture Compare Register捕获比较寄存器).
信号输入引脚出现指定电平跳变时, 当前CNT的值将被锁存到CCR中, 可用于测量PWM波形的频率, 占空比, 脉冲间隔, 电平持续时间等参数. 这里我们将使用PWMI模式, 捕获上一节产生的PWM波, 来测量频率占空比.
注意这里只能测量方波, 如果是正弦波需要经过电压比价器转化为方波再测.
如果电压过高, 需要隔离放大器或者电压互感器, 否则将会烧毁.
测量频率原理
测量频率有两种方法:
1. 测频法.(适用于高频信号, 使用的技术是: 外部时钟源定时器计数)
使用一个定时器正常计时Ts, 以另一个定时器待测量的信号为时钟源, 产生一次电平跳变记次+1, 总共计次N, 待测频率为Fx = N / T;
2. 测周法(适用于低频信号, 使用的技术是: 输入捕获)
使用一个定时器设置为输入捕获功能, 设置该定时器的时基单元固定好标准频率fc, 将自动重装值设定为最大值, 防止CNT溢出. 每次经过一个上升沿, CCR捕获CNT的值为N, 并且将CNT清零, 此时为一个待测信号的周期走了N个标准频率fc, 所以待测频率为fx = 1 / T = 1 / (1/fc * N) = fc / N;
总结: 测频法是一段时间内的平均值, 时间慢, 值平滑. 测周法, 是一个周期出结果, 时间与一个周期长度相关, 更新快.
可能出现的误差
1. 正负一误差: 如最后测了半个, 算一个还是算0个, 就会出现正负一误差.
2. 单片机的时钟源是晶振, 晶振可能产生误差.
3. 外界信号的干扰产生误差.
如何减小误差, 测频法增加测量的时间, 测周法减小标准频率fc. 增加滤波功能.
测量占空比
使用PWMI模式配置交叉通道, 让CCR2捕获下降沿, CCR1捕获上升沿, 使用从模式将CNT清零. 这样CCR1捕获的是一个周期N个fc, CCR2捕获的是一个周期高电平的N2个fc, 占空比 = CCR2 / CCR1 * 100 %.
输入捕获电路
输入信号源CH1会经过数据选择器到达TI1, 经过滤波器和边沿检测器可以输出TI1FP1信号, 经过预分频器可以触发输入捕获中断, 触发事件CCR将会捕获CNT的值, 中断可以将CNT清零, 等待下次的捕获, 但过于浪费软件资源, 让CPU持续工作在中断的状态下, 所以有从模式可以硬件将CNT清零. 但是只有通道1和2有, 如果是通道3或者4只能使用中断手动清零, 所以不要使用3/4通道.
IC模式和PWMI模式
IC模式下只能初始化一条通道, 两次初始化也可以实现PWMI模式, 就是要麻烦一些.
PWMI模式下可以初始化两条通道, 一条通道为监测上升沿/直连, 会自动配置另一个通道为监测下降沿/交叉连接, 方便快速配置好可以检测频率和占空比两项的操作.
主从触发模式
主从触发模式实现硬件全自动测量.
首先是触发源的选择为: TI1FP1, 从模式选择Reset.
注意要先捕获后清零, 否则会捕获到0.
代码逻辑
- RCC开启GPIO, TIM时钟
- GPIO上拉/浮空输入模式
- 时基单元配置
- 从模式触发源选择
- 从模式选择
- 启动定时器
代码参考
void ICInit()
{
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
//选择时基单元的时钟源
TIM_InternalClockConfig(TIM3);
//配置GPIO
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure);
//配置时基单元, fc = 1Mhz.
TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure;
TIM_TimeBaseInitStructure.TIM_ClockDivision = TIM_CKD_DIV1;
TIM_TimeBaseInitStructure.TIM_CounterMode = TIM_CounterMode_Up;//向上计数
TIM_TimeBaseInitStructure.TIM_Period = 65536-1;//ARR自动重装值
TIM_TimeBaseInitStructure.TIM_Prescaler = 72-1;//PSC预分频器值
TIM_TimeBaseInitStructure.TIM_RepetitionCounter = 0;//重复计数器的值(高级定时器才有)
TIM_TimeBaseInit(TIM3, &TIM_TimeBaseInitStructure);
//配置PWMI模式
TIM_ICInitTypeDef TIM_ICInitStruct;
TIM_ICInitStruct.TIM_Channel = TIM_Channel_1; //通道1
TIM_ICInitStruct.TIM_ICFilter = 0xf; //最大滤波
TIM_ICInitStruct.TIM_ICPolarity = TIM_ICPolarity_Rising; //捕获上升沿
TIM_ICInitStruct.TIM_ICPrescaler = TIM_ICPSC_DIV1;//不分频
TIM_ICInitStruct.TIM_ICSelection = TIM_ICSelection_DirectTI;//直连通道
TIM_PWMIConfig(TIM3, &TIM_ICInitStruct);
//选择输入触发源,和从模式
TIM_SelectInputTrigger(TIM3, TIM_TS_TI1FP1);
TIM_SelectSlaveMode(TIM3, TIM_SlaveMode_Reset);
TIM_Cmd(TIM3, ENABLE);
}
uint16_t getFreq()
{
return 1000000 / (TIM_GetCapture1(TIM3)+1);
}uint16_t getDuty()
{
return (TIM_GetCapture2(TIM3)+1)*100 / (TIM_GetCapture1(TIM3)+1);
}