输入捕获(Input Capture)
输入捕获模式下,当通道输入引脚出现指定电平跳变时,当前CNT的值将被锁存到CCR中,可用于测量PWM波形的频率、占空比、脉冲间隔、电平持续时间等参数每个高级定时器和通用定时器都拥有4个输入捕获通道可配置为PWMI模式,同时测量频率和占空比可配合主从触发模式,实现硬件全自动测量。
一、输入捕获(算出周期)
CNT有上限(ARR一般设置成最大65535 因此CNT也是这样)
需先将CNT的值转运到CCR里面,再将CNT清零(用从模式RESET且从模式智能使用通道1和通道2)
代码步骤:
1、RCC开启时钟
//1、RCC开始时钟,把gpio和tim的时钟开启
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3,ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);
2、初始化GPIO,设置成输入上拉
//2、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);
3、开启时钟并配置时基单元
//开启时钟
TIM_InternalClockConfig(TIM3);
//3、初始化配置时基单元,让cnt计数器在内部时钟的驱动下子层运行
TIM_TimeBaseInitTypeDef TIM_BaseInitInstructure;
TIM_BaseInitInstructure.TIM_ClockDivision= TIM_CKD_DIV1;
TIM_BaseInitInstructure.TIM_CounterMode=TIM_CounterMode_Up;
//这里是预分频的值所以-1
TIM_BaseInitInstructure.TIM_Period=65536-1;//ARR
TIM_BaseInitInstructure.TIM_Prescaler=72-1;//PSC
TIM_BaseInitInstructure.TIM_RepetitionCounter=0;
TIM_TimeBaseInit(TIM3,&TIM_BaseInitInstructure);
4、配置输入捕获单元(需要注意选择的通道是根据选择的引脚来确定)
//4、配置输入捕获单元
//选择通道的参数
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);
5、配置触发源
//5、配置触发源
TIM_SelectInputTrigger(TIM3,TIM_TS_TI1FP1);
6、配置从模式为RESET(即将CNT清0,方便下次的计算)
//6、配置从模式为reset
TIM_SelectSlaveMode(TIM3,TIM_SlaveMode_Reset);
7、开启时钟
//7、TIM_Cmd
TIM_Cmd(TIM3,ENABLE);
二、PWMI(算出周期和占空比)
使用两个通道同时捕获一个引脚,因此可以同时测量周期与占空比。
CCR1为整个周期 CCR2/CCR1=占空比
代码步骤:
和一的步骤一致,只是多了一个函数;该函数的作用是多加了一个通道TI1FP2,该通道与TI1FP1的参数完全相反(就是为了算出高电平在周期的时间从而算出占空比)
TIM_PWMIConfig(TIM3,&TIM_ICInitStructure);
该函数又等同于
TIM_ICInitStructure.TIM_Channel=TIM_Channel_2;
TIM_ICInitStructure.TIM_ICFilter=0xF;
TIM_ICInitStructure.TIM_ICPolarity=TIM_ICPolarity_Falling;//下降沿触发
TIM_ICInitStructure.TIM_ICPrescaler=TIM_ICPSC_DIV1;
TIM_ICInitStructure.TIM_ICSelection=TIM_ICSelection_IndirectTI;//交叉输入
TIM_ICInit(TIM3,&TIM_ICInitStructure);
最终只需要在main.c中将获取输入到的频率和占空比通过调用 最终显示在oled上。
int main(void)
{
OLED_Init();
PWM_Init();
IC_Init();
OLED_ShowString(1,1,"Freq:");
OLED_ShowString(2,6,"00000HZ");
OLED_ShowString(3,1,"Duty:");
OLED_ShowString(4,9,"%");
PWM_SetPrescaler(720-1); //频率Freq=72M/(PSC+1)/100 (100的来源是ARR+1)
PWM_SetCompare1(80) ; //占空比Duty=CCR/100
while(1){
OLED_ShowNum(2,6,IC_GetFreq(),5);
OLED_ShowNum(4,6,IC_GetDuty(),3);
}
}