【STM32】输入捕获的简单写法

       之前对输入捕获大概原理了解,实际操作不会,我看网上基本都是正点原子的,这次自己写了一次,感觉收获很大,代码送给大家,欢迎指正!!!

       先给出代码,最后把代码解释一波

#include<stm32f10x.h>
#include<timerbuhuo.h>
#include<delay.h>

u8 BUHUO_Flag=0,UPDATE_Flag=0;//前者用于标志捕获上升沿下降沿,后者用于标志溢出更新次数
unsigned int BUHUO_Up=0,BUHUO_Down=0,BUHUO_Num=0;//用于记录捕获到的高电平和低电平时刻
void TIMER_Buhuo()
{
	NVIC_InitTypeDef  NVIC_InitStructure;
	TIM_TimeBaseInitTypeDef TIM_TimeBaseStrycture;
	TIM_ICInitTypeDef TIM_ICInitStructure;
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3,ENABLE);
	/**********时基初始化************/
	TIM_TimeBaseStrycture.TIM_ClockDivision=0;
	TIM_TimeBaseStrycture.TIM_CounterMode=TIM_CounterMode_Up;
	TIM_TimeBaseStrycture.TIM_Period=65535;
	TIM_TimeBaseStrycture.TIM_Prescaler=71;
	TIM_TimeBaseInit(TIM3,&TIM_TimeBaseStrycture);
	/**********设置tim3比较参数,开启输入捕获************/
	TIM_ICInitStructure.TIM_Channel=TIM_Channel_1;
	TIM_ICInitStructure.TIM_ICFilter=0;
	TIM_ICInitStructure.TIM_ICPolarity=TIM_ICPolarity_Falling;
	TIM_ICInitStructure.TIM_ICPrescaler=TIM_ICPSC_DIV1;
	TIM_ICInitStructure.TIM_ICSelection=TIM_ICSelection_DirectTI;
	TIM_ICInit(TIM3,&TIM_ICInitStructure);
	
	NVIC_InitStructure.NVIC_IRQChannel=TIM3_IRQn;
	NVIC_InitStructure.NVIC_IRQChannelCmd=ENABLE;
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=2;
	NVIC_InitStructure.NVIC_IRQChannelSubPriority=2;
	NVIC_Init(&NVIC_InitStructure);
	
	TIM_Cmd(TIM3,ENABLE);
	TIM_ITConfig(TIM3,TIM_IT_Update|TIM_IT_CC1,ENABLE);
}

void KEY_Test()
{
	GPIO_InitTypeDef GPIO_InitStructure;
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);
	
	GPIO_InitStructure.GPIO_Mode=GPIO_Mode_IPU;//此处设置为上拉,与前者检测下降沿对应
	GPIO_InitStructure.GPIO_Pin=GPIO_Pin_6;
	GPIO_Init(GPIOA,&GPIO_InitStructure);
}


void TIM3_IRQHandler()
{
	if(TIM_GetITStatus(TIM3,TIM_IT_Update)==1)
	{
		if(BUHUO_Flag==1)//只有当检测到下降沿之后才有效
		{
			UPDATE_Flag+=1;//记录溢出次数
		}
	}
	if(TIM_GetITStatus(TIM3,TIM_IT_CC1)==1)
	{
		if(BUHUO_Flag==0)//为0时是正在检测下降沿
		{
			BUHUO_Down=TIM_GetCapture1(TIM3);//记录下降沿出现的时刻
			BUHUO_Flag=1;
			TIM_OC1PolarityConfig(TIM3,TIM_ICPolarity_Rising);//设置为上升沿检测
		}
		else 
		{
			if(UPDATE_Flag==0)BUHUO_Up=TIM_GetCapture1(TIM3);//此处需要判别是否已经在检测下降沿后,参数溢出
			else if(UPDATE_Flag>=1)//如果溢出,那么要知道溢出的次数,并且使用设定的溢出值乘次数,我这里是65535
			{
				BUHUO_Up=TIM_GetCapture1(TIM3)+65535*UPDATE_Flag;
				UPDATE_Flag=0;//结束后,别忘了给更新溢出标志位置0
			}
			BUHUO_Num=BUHUO_Up-BUHUO_Down;//计算时间
			TIM_OC1PolarityConfig(TIM3,TIM_ICPolarity_Falling);//重置为下降沿检测
			BUHUO_Flag=0;//给捕获标志位置0,为下一次捕获做准备
		}
		
	}
	TIM_ClearITPendingBit(TIM3,TIM_IT_Update|TIM_IT_CC1);
}

注意:1、本次实验使用的是引脚PA6,对应TIM3_1.,使用对应引脚按键来测试

           2、初始检测为下降沿沿检测,因为我的按键低电平有效。

           3、由于本实验知识点都在中断部分,所以只解释中断部分代码

中断代码解释:

按键不按下,没有产生下降沿,捕获中断不进入。按键按下,进入捕获中断,捕获状态标志位(BUHUO_Flag)初始值为0,获取当前下降沿出现时刻(BUHUO_Down),捕获状态标志位置1,标志我将要获取的应该是上升沿,并设置上升沿检测。此时的更新中断也在运行,若是判断到更新溢出,那么溢出次数(UPDATE_Flag)参数加1。松开按键,获取到上升沿,记录上升沿出现的时刻(BUHUO_Up),此时更新中断已经发生过很多次,所以要使用溢出值乘溢出次数,我设置的溢出值为65535,然后用获取到的当前的值加上溢出值乘溢出次数(BUHUO_Up=TIM_GetCapture1(TIM3)+65535*UPDATE_Flag;)。记录结束后,别忘了给捕获状态标志位和更新中断标志位置0,以便下次的检测。接下来计算本次捕获的高电平长度,这里就很简单了,上升沿出现时刻减去下降沿出现时刻就是(BUHUO_Num=BUHUO_Up-BUHUO_Down;)。

学习更多嵌入式Linux、Qt以及嵌入式单片机知识关注公众号“爱玩嵌入式”:

发布了24 篇原创文章 · 获赞 35 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/Groot_Lee/article/details/88689806