之前对输入捕获大概原理了解,实际操作不会,我看网上基本都是正点原子的,这次自己写了一次,感觉收获很大,代码送给大家,欢迎指正!!!
先给出代码,最后把代码解释一波
#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以及嵌入式单片机知识关注公众号“爱玩嵌入式”: