关于输入捕获试验的分析

#include "stm32f10x.h"

u8 TIM3CH1_CAPTURE_STA=0; //输入捕获状态
u16 TIM3CH1_CAPTURE_VAL;//输入捕获值

//定时器 3 通道 1 输入捕获配置

void TIM3_Cap_Init(u16 arr,u16 psc)
{
    GPIO_InitTypeDef GPIO_InitStructure;
    TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
    TIM_ICInitTypeDef TIM3_ICInitStructure;
    NVIC_InitTypeDef NVIC_InitStructure;

    RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE); //使能 TIM3 时钟
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); //使能 GPIOA 时钟

    //初始化 GPIOA.6 
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6; //PA6设置
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU; //PA6 输入

pa6作为gpio输入端口,此处的设置要根据按键来写,此次中按下为低电平
    GPIO_Init(GPIOA, &GPIO_InitStructure); //初始化 GPIOA.6
    GPIO_ResetBits(GPIOA,GPIO_Pin_0); //PA6 下拉

    //②初始化 TIM3 参数
    TIM_TimeBaseStructure.TIM_Period = arr; //设定计数器自动重装值
    TIM_TimeBaseStructure.TIM_Prescaler =psc; //预分频器
    TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1; // TDTS = Tck_tim
    TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; //TIM 向上计数模式
    TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure); //初始化 TIMx

    //③初始化 TIM3 输入捕获通道 1
    TIM3_ICInitStructure.TIM_Channel = TIM_Channel_1; //选择输入端 IC1 映射到 TI1 上
    TIM3_ICInitStructure.TIM_ICPolarity = TIM_ICPolarity_Falling; //下降沿捕获
    TIM3_ICInitStructure.TIM_ICSelection = TIM_ICSelection_DirectTI; //映射到 TI1 上
    TIM3_ICInitStructure.TIM_ICPrescaler = TIM_ICPSC_DIV1; //配置输入分频,不分频
    TIM3_ICInitStructure.TIM_ICFilter = 0x00; //IC1F=0000 配置输入滤波器 不滤波
    TIM_ICInit(TIM3, &TIM3_ICInitStructure); //初始化 TIM3 输入捕获通道 1

    //⑤初始化 NVIC 中断优先级分组
    NVIC_InitStructure.NVIC_IRQChannel = TIM3_IRQn; //TIM3 中断
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2; //先占优先级 2 级
    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; //从优先级 0 级
    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //IRQ 通道被使能
    NVIC_Init(&NVIC_InitStructure); //初始化 NVIC

    TIM_ITConfig( TIM3,TIM_IT_Update|TIM_IT_CC1,ENABLE);//④允许更新中断捕获中断
    TIM_Cmd(TIM3,ENABLE ); //⑥使能定时器 3

}


//⑤定时器 3 中断服务程序
void TIM3_IRQHandler(void)
{
    if((TIM3CH1_CAPTURE_STA&0X80)==0)//还未成功捕获
    {
        if (TIM_GetITStatus(TIM3, TIM_IT_Update) != RESET)//判断为更新事件
        {
            if(TIM3CH1_CAPTURE_STA&0X40) //已经捕获到低电平了
            {
                if((TIM3CH1_CAPTURE_STA&0X3F)==0X3F)//低电平太长了
                {
                    TIM3CH1_CAPTURE_STA|=0X80; //标记成功捕获了一次
                    TIM3CH1_CAPTURE_VAL=0XFFFF;
                }
                else 
                TIM3CH1_CAPTURE_STA++;
            }
        }
        if (TIM_GetITStatus(TIM3, TIM_IT_CC1) != RESET) //捕获 1 发生捕获事件
        {
            if(TIM3CH1_CAPTURE_STA&0X40) //捕获到一个上升沿
            {
                TIM3CH1_CAPTURE_STA|=0X80; //标记成功捕获到一次下降沿
                TIM3CH1_CAPTURE_VAL=TIM_GetCapture1(TIM3);
                TIM_OC1PolarityConfig(TIM3,TIM_ICPolarity_Falling); //设置为下降沿捕获
            }
            else //还未开始,第一次捕获下降沿
            {                                                                                        //0100 0000
                TIM3CH1_CAPTURE_STA=0; //清空
                TIM3CH1_CAPTURE_VAL=0;
                TIM_SetCounter(TIM3,0);   //把cnt置零
                TIM3CH1_CAPTURE_STA|=0X40; //标记捕获到了下降沿
                TIM_OC1PolarityConfig(TIM3,TIM_ICPolarity_Rising); //设置为上升沿捕获
            }
        }
    }
    TIM_ClearITPendingBit(TIM3, TIM_IT_CC1|TIM_IT_Update); //清除中断标志位
}

捕获状态TIM5CH1_CAPTURE_STA这个寄存器是作者自己定义的一个,stm32中无硬件对应,无相应硬件置位复位。这个寄存器大家可以把它当做两个标志位flag1+flag2+一个存次数的数length。

//[7]: 0,没有成功捕获,1,已经成功捕获一次
//[6]: 0,还没有捕获到高电平,1,已经捕获到高电平了
//[5:0]: 捕获高电平后溢出的次数

中断服务函数中首先经过 if((TIM3CH1_CAPTURE_STA&0X80)==0)判断出还未成功捕获

从而进入,首先我们看到的是有两种中断,更新中断与捕获中断,他们是互不干扰的,但一旦发生捕获中断会导致TIM5CH1_CAPTURE_STA|=0X80;使中断函数结束。

其时间计算为更新(溢出)中断次数乘以计数器时间(设置的arr)再加上VAL的值即为高电平时间,其开始计时于if(TIM3CH1_CAPTURE_STA&0X40) -初捕获上升沿

更新:第一次进中断是进捕获中断,而且是进入else语句,将极性改为下降沿且STA=0x40;计数溢出后才会进更新中断,执行if((TIM5CH1_CAPTURE_STA&0X80)==0)语句,最后进入if(TIM5CH1_CAPTURE_STA&0X40)语句里(如果判断为否即使发生了更新中断sta也不会计数)。
//3.在if(TIM5CH1_CAPTURE_STA&0X40)语句里,如果溢出次数未达到3F,STA++继续,达到3F,高电平时间太长超出计数范围,默认捕获一次高电平,VAL=0xffff计数输出。

捕获://1.初始化后,程序第一次上升沿进捕获中断,第一次进中断,进else语句,将STA和VAL清零(开始新一轮捕获),清零CNT,标记捕获到了高电平(也就是上升沿,因为初始化是上升沿被捕获嘛),将极性改为下降沿捕获,退出中断后,在主函数中由于if(TIM5CH1_CAPTURE_STA&0x80)语句不成立,所以不进if中,STA状态保持。
//2.下降沿到来时,进中断里的if(TIM5CH1_CAPTURE_STA&0x40)语句,是高电平再进if语句里,STA=1,成功捕获一次高电平信号,将数据给VAL,将极性改为上升沿捕获。
//3.退出中断进主函数后,如果一次捕获成功,有溢出就计算溢出次数再加上VAL的值就是高电平时间,打印输出。并将STA清零,保证在下一个上升沿进捕获中断后,程序又进入else语句,不进入if(TIM5CH1_CAPTURE_STA&0x40)语句中,因为STA在主函数中被清零了。然后循环上述步骤,一个周期产生一次捕获,得到高电平时间。

TIM5CH1_CAPTURE_VAL=TIM_GetCapture1(TIM5); 中我们要知道的是

TIM_GetCapture1与TIM_GetCapture函数不同,一个获取的是cnt(软件叠加)另一个是crr(硬件设置)由于cnt到达crr才能发生一次捕获所以在此处作用相同。

最后总结一下,先进行捕获,捕获到上升下降沿开始算是第一个更新中断(在此之前即使触发更新中断也不会计时),直到捕获到与之前相反的沿终止计时,temp=TIM3CH1_CAPTURE_STA&0X3F;  //保留后6位计时位(总发生更新中断次数)  temp*=65536;  //再乘以arr(每次发生更新中断其中循环的次数),如果分频器psc没有把总线频率变成1还需要乘以(psc/36MHZ)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值