何为输入捕捉?其实就是检测到信号跳变后,锁住计数的寄存器并保存,发生捕获事件其实相当于发生了中断,可以根据相应的标志位来判断当前捕获了什么,其实捕获什么无非就是上升沿、下降沿!
关于捕捉的更多信息请参考官方的手册,个人觉得手册上讲的还是很容易懂得,因为寄存并不多!
下面我针对我的
STM32f103VBT6来进一步了解输入捕捉模式!
我选择定时器TIM4,它对应的输入捕捉有很多通道,其实就是TIM4对应的IO口!我这里设置3个输入捕捉的通道,分别是PB6 PB7 PB8 对应CH1 CH2 CH3 通道,这个根据芯片手册是有对应关系的(除了重映射,这个先别管)!
第一步:初始化函数void TIM4_Cap_Init(unsigned int arr,unsigned int psc){}
这个函数代码如下:
void TIM4_Cap_Init(unsigned int arr,unsigned int psc)
{
//这些都是一些结构体的声明,去下载一本库函数手册一看就知道 很简单的
GPIO_InitTypeDef GPIO_InitStructure;
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
TIM_ICInitTypeDef TIM4_ICInitStructure;
NVIC_InitTypeDef NVIC_InitStructure;
//这个就是时钟使能了 我使能TIM4 和GPIOB
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM4, ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
//输入捕捉,当然端口要设置为输入模式了
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6|GPIO_Pin_7|GPIO_Pin_8;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPD;
GPIO_Init(GPIOB, &GPIO_InitStructure);
GPIO_ResetBits(GPIOB,GPIO_Pin_6|GPIO_Pin_7|GPIO_Pin_8);
TIM_TimeBaseStructure.TIM_Period = arr; //这个就是设置计数值的最大值,就是这个寄存器能计多少个数,一般设置成0XFFFF
TIM_TimeBaseStructure.TIM_Prescaler =psc; //上面这个计数寄存器的频率的分频系数 分频的值=psc+1 所以你要2分频的话,psc= 1,以此类推
TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1; //时钟分割 这在有一些情况用,这里我们不受影响
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; //计数向上计数
TIM_TimeBaseInit(TIM4, &TIM_TimeBaseStructure); //初始化
TIM4_ICInitStructure.TIM_Channel = TIM_Channel_1; //选择通道1
TIM4_ICInitStructure.TIM_ICPolarity = TIM_ICPolarity_Rising;
//上升沿触发还是下降沿触发的设置
TIM4_ICInitStructure.TIM_ICSelection = TIM_ICSelection_DirectTI; //映射到TT1上
TIM4_ICInitStructure.TIM_ICPrescaler = TIM_ICPSC_DIV1;
//配置输入分频 不分频
TIM4_ICInitStructure.TIM_ICFilter = 0x01; //滤波的问题 先不管
TIM_ICInit(TIM4, &TIM4_ICInitStructure);
TIM4_ICInitStructure.TIM_Channel = TIM_Channel_2;
TIM4_ICInitStructure.TIM_ICPolarity = TIM_ICPolarity_Rising;
TIM4_ICInitStructure.TIM_ICSelection = TIM_ICSelection_DirectTI;
TIM4_ICInitStructure.TIM_ICPrescaler = TIM_ICPSC_DIV1;
TIM4_ICInitStructure.TIM_ICFilter = 0x01;
TIM_ICInit(TIM4, &TIM4_ICInitStructure);
TIM4_ICInitStructure.TIM_Channel = TIM_Channel_3;
TIM4_ICInitStructure.TIM_ICPolarity = TIM_ICPolarity_Falling;
TIM4_ICInitStructure.TIM_ICSelection = TIM_ICSelection_DirectTI;
TIM4_ICInitStructure.TIM_ICPrescaler = TIM_ICPSC_DIV1;
TIM4_ICInitStructure.TIM_ICFilter = 0x01;
TIM_ICInit(TIM4, &TIM4_ICInitStructure);
//中断设置
NVIC_InitStructure.NVIC_IRQChannel = TIM4_IRQn; //TIM4发生中断 其实就是上面发生你设置上升沿和下降沿触发事件
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2; //先占中断等级
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; //从中断等级
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //使能中断通道Ü
NVIC_Init(&NVIC_InitStructure); //初始化
TIM_ITConfig(TIM4,TIM_IT_CC1|TIM_IT_CC2|TIM_IT_CC3,ENABLE);//使能各个中断
TIM_Cmd(TIM4,ENABLE );
//使能定时器TIM4
}
第二步:中断程序:
void TIM4_IRQHandler(void)
{
if(TIM_GetITStatus(TIM4, TIM_IT_CC1) != RESET) //CH1通道(PB6)发生触发事件
{
/* 处理代码 **/
}
if(TIM_GetITStatus(TIM4, TIM_IT_CC2) != RESET) //CH2通道(PB7)发生触发事件
{
/* 处理代码 **/
}
if(TIM_GetITStatus(TIM4, TIM_IT_CC3) != RESET) //CH3通道(PB8)发生触发事件
{
/* 处理代码 **/
}
TIM_ClearITPendingBit(TIM4, TIM_IT_CC1|TIM_IT_CC2|TIM_IT_CC3); //清楚中断标志
}
特别说明TIM_GetCapture1(TIM4);这个函数是用来就是用来记录当前发生触发事件时的计数,这样我们可以利用每一次触发获得计数值计算触发事件之间的时间,最简单的应用就是占空比的获取,我们可以获得高电平的持续时间!
输入捕捉其实就这么简单,我建议只要了解流程就能明白,之所以代码写的少,是因为我觉得输入捕捉的概念比程序重要!希望先完完全全的明白输入捕捉,个人觉得编程没问题!