相关理论知识
输入捕获简介
IC(Input Capture) 输入捕获
输入捕获模式下,当通道输入引脚出现指定电平跳变时,当前CNT的值将被锁存到CCR中,可用于测量PWM波形的频率、占空比、脉冲间隔、电平持续时间等参数。
每个高级定时器和通用定时器都拥有4个输入捕获通道。
可配置为PWMI模式,同时测量频率和占空比。
可配合主从触发模式,实现硬件全自动测量。
频率测量
测频法:每经过一个闸门时间更新周期一次,周期更新频率慢,测量结果是一段周期的平均值,值比较平滑 。
测周法:测量一个周期出一个结果,测量结果更新频率快,但结果值受噪声影响,波动比较大。
这两种方法面对周期不同时,测得的误差也不相同,这时我们就需要算出中界频率(两种方法误差相等时的频率),当待测频率小于中界频率时选择测频法,反之选择测周法。
输入捕获通道
DTS为滤波器采样时钟来源
CCMR1寄存器里的ICF位可以控制滤波器的参数
CCMR1寄存器中的CCIS位可以对数据选择器进行选择,ICPS为可以配置相应的寄存器。
首先滤波器的输入为TI1(CH1的引脚),滤波后的信号TI1F通过边沿检测器捕获上升沿或者下降沿,用CCER寄存器中的CC1P位来选择极性。最终得到TI1FP1通过数据选择器进入通道一后续的捕获电路。
CCER寄存器中的CC1E位控制输出使能或失能。
主从触发模式
主模式:可以将定时器内部的信号,映射到TRGO引脚,用于触发别的外设。
从模式:接受自身外设或其他外设的信号,用于控制自身定时器的运行。通过触发源选择,选择指定的信号,从而得到TRGI,再通过TRGI去触发从模式。
输入捕获基本结构
基本过程为,首先配置好时基单元,启动定时器,则此时CNT计数器会不断自增,而经过PSC预分频器的频率为驱动CNT的标准频率。输入捕获通道GPIO口输入一个如图左上的方波信号,经过滤波器和边沿检测,通过上升沿触发,接着向右传递,分频器选择不分频,当TI1FP1出现上升沿之后,CNT当前的计数值传递到CCR1里,同时触发源选择,选择TI1FP1为触发信号,从模式选择复位操作,从而使CNT清零。
注意:
ARR一般最大设置为65535,则CNT最大数也为65535。
从模式选择信号只有TI1FP1和TI2FP2,如果想使用从模式自动清除CNT计数器那么只能用通道一和通道二。
PWMI基本结构
PWMI相较于输入捕获基本结构多了一个通道,同时捕获GPIO的信号,则可以同时测量周期和占空比。将TI1FP2配置为下降沿触发,可知CCR2的值就是一个周期中高电平期间的计数值,通过CCR2/CCR1则可以算出占空比。
输入捕获代码部分
思路
第一步:把TIM和GPIO的时钟打开
第二步:GPIO初始化,把GPIO配置成输入模式
第三步:配置时基单元,让CNT计数器在内部时钟的驱动下自增运行
第四步:配置输入捕获单元
第五步:选择从模式的触发源
第六步:选择触发之后执行的操作
最后调用TIM_Cmd函数,开启定时器
基本函数功能介绍
void TIM_PWMIConfig(TIM_TypeDef* TIMx, TIM_ICInitTypeDef* TIM_ICInitStruct);
此函数可以快速配置两个通道,可以把外设电路配置成上面PWMI的模式。
void TIM_ICStructInit(TIM_ICInitTypeDef* TIM_ICInitStruct);
此函数可以给输入捕获结构体赋一个初始值
void TIM_SelectInputTrigger(TIM_TypeDef* TIMx, uint16_t TIM_InputTriggerSource);
此函数能选择从模式的输入触发源TRGI(如TI1FP1)
void TIM_SelectOutputTrigger(TIM_TypeDef* TIMx, uint16_t TIM_TRGOSource);
此函数能选择主模式的输出触发源TRGO
void TIM_SelectSlaveMode(TIM_TypeDef* TIMx, uint16_t TIM_SlaveMode);
此函数能选择从模式
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);
这四个函数分别单独配置通道1、2、3、4的分频器
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);
这四个函数分别读取四个通道的CCR
输入捕获的初始化函数
void IC_Init(void)
{
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3,ENABLE );
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE );
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);
TIM_InternalClockConfig(TIM3);
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);
TIM_ICInitTypeDef TIM_ICInitStructure;
TIM_ICInitStructure.TIM_Channel = TIM_Channel_1 ;
TIM_ICInitStructure.TIM_ICFilter = 0xF;
TIM_ICInitStructure.TIM_ICPolarity = TIM_ICPolarity_Rising ;
TIM_ICInitStructure.TIM_ICPrescaler = TIM_ICPSC_DIV1 ;
TIM_ICInitStructure.TIM_ICSelection = TIM_ICSelection_DirectTI ;
TIM_ICInit(TIM3,&TIM_ICInitStructure);
TIM_SelectInputTrigger(TIM3,TIM_TS_TI1FP1);
TIM_SelectSlaveMode(TIM3,TIM_SlaveMode_Reset);
TIM_Cmd (TIM3,ENABLE);
}
PWMI的初始化函数
void IC_Init(void)
{
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3,ENABLE );
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE );
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);
TIM_InternalClockConfig(TIM3);
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);
TIM_ICInitTypeDef TIM_ICInitStructure;
TIM_ICInitStructure.TIM_Channel = TIM_Channel_1 ;
TIM_ICInitStructure.TIM_ICFilter = 0xF;
TIM_ICInitStructure.TIM_ICPolarity = TIM_ICPolarity_Rising ;
TIM_ICInitStructure.TIM_ICPrescaler = TIM_ICPSC_DIV1 ;
TIM_ICInitStructure.TIM_ICSelection = TIM_ICSelection_DirectTI ;
TIM_ICInit(TIM3,&TIM_ICInitStructure);
TIM_PWMIConfig (TIM3,&TIM_ICInitStructure);
TIM_SelectInputTrigger(TIM3,TIM_TS_TI1FP1);
TIM_SelectSlaveMode(TIM3,TIM_SlaveMode_Reset);
TIM_Cmd (TIM3,ENABLE);
}