正点原子的输入捕获程序解读


正点原子的输入捕获程序是利用TIM5的单通道实现的,通过先捕获上升沿,清除计数器值,再更改捕获极性为下降沿,第二次进中断时读出高电平脉宽。一次捕获过程完成,下面解释程序中的问题和疑惑。

extern u8  TIM5CH1_CAPTURE_STA;     //输入捕获状态                        
extern u16  TIM5CH1_CAPTURE_VAL;    //输入捕获值
int main(void)
{       
        u32 temp=0; 
        delay_init();            //延时函数初始化 
        NVIC_Configuration();    //中断优先级配置
        uart_init(9600);     //波特率为9600
        LED_Init();              //LED初始化

        TIM3_PWM_Init(899,0);       //PWM频率=72000/(899+1)=80Khz
        TIM5_Cap_Init(0XFFFF,72-1); //以1Mhz频率计数 
        while(1)
        {
                delay_ms(10);
                TIM_SetCompare2(TIM3,TIM_GetCapture2(TIM3)+1);//设置占空比,300是900的1/3,高电平最大持续时间是4.16us

                if(TIM_GetCapture2(TIM3)==300)
                {
                        TIM_SetCompare2(TIM3,0);    
                }

                if(TIM5CH1_CAPTURE_STA&0X80)//成功捕获了一次上升沿
                {
                        temp=TIM5CH1_CAPTURE_STA&0X3F;//统计溢出次数
                        temp*=65536;//溢出时间总和
                        temp+=TIM5CH1_CAPTURE_VAL;//得到总的高电平时间
                        printf("HIGH:%d us\r\n",temp);//打印高电平时间
                        TIM5CH1_CAPTURE_STA=0;//开启下一次捕获
                }
}

程序中省略了相关定时器的配置,相关配置参考正点原子的输入捕获程序。下面重点对信号进行捕获的定时器5的中断服务程序进行解读

u8  TIM5CH1_CAPTURE_STA=0;  //输入捕获状态                        
u16 TIM5CH1_CAPTURE_VAL;    //输入捕获值
  1. 捕获状态TIM5CH1_CAPTURE_STA这个寄存器是作者自己定义的一个,stm32中无硬件对应,无相应硬件置位复位。这个寄存器大家可以把它当做两个标志位flag1+flag2+一个存次数的数length。
    flag1(or2)=1有一次成功捕获过程完成或已经捕获到高电平。
    flag1(or2)=0未有一次成功捕获过程完成或未捕获到高电平。
  2. 捕获状态TIM5CH1_CAPTURE_STA各位功能
    //[7]: 0,没有成功捕获,1,已经成功捕获一次
    //[6]: 0,还没有捕获到高电平,1,已经捕获到高电平了
    //[5:0]: 捕获高电平后溢出的次数

//定时器5的中断服务程序
void TIM5_IRQHandler(void)
{
//1.程序进更新中断的原因是,TIM5只有65536/1M=0.06s的时长,按占空比50%计算,不溢出能计算1/0.12=8.33Hz以上的频率脉宽,8hz以下的要有更新中断。
//2.程序初始化后,第一次进中断是进捕获中断,而且是进入else语句,将极性改为下降沿且STA=0x40;计数溢出后才会进更新中断,执行if((TIM5CH1_CAPTURE_STA&0X80)==0)语句,最后进入if(TIM5CH1_CAPTURE_STA&0X40)语句里。
//3.在if(TIM5CH1_CAPTURE_STA&0X40)语句里,如果溢出次数未达到3F,STA++继续,达到3F,高电平时间太长超出计数范围,默认捕获一次高电平,VAL=0xffff计数输出。
//4.退出更新中断进主函数中,与下面步骤3相同。
//

 if((TIM5CH1_CAPTURE_STA&0X80)==0)//还未成功捕获
{     
        if (TIM_GetITStatus(TIM5, TIM_IT_Update) != RESET)
        {       
                if(TIM5CH1_CAPTURE_STA&0X40)//已经捕获到高电平了
                {
                        if((TIM5CH1_CAPTURE_STA&0X3F)==0X3F)//高电平太长了
                        {
                                TIM5CH1_CAPTURE_STA|=0X80;//标记成功捕获了一次
                                TIM5CH1_CAPTURE_VAL=0XFFFF;
                        }else 
                        {
                                TIM5CH1_CAPTURE_STA++;
                        }
                }    
        }

//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在主函数中被清零了。然后循环上述步骤,一个周期产生一次捕获,得到高电平时间。

if (TIM_GetITStatus(TIM5, TIM_IT_CC1) != RESET)//捕获1发生捕获事件
    {   
        if(TIM5CH1_CAPTURE_STA&0X40)        //捕获到一个下降沿      
        {               
            TIM5CH1_CAPTURE_STA|=0X80;      //标记成功捕获到一次上升沿
            TIM5CH1_CAPTURE_VAL=TIM_GetCapture1(TIM5);
            TIM_OC1PolarityConfig(TIM5,TIM_ICPolarity_Rising); //CC1P=0 设置为上升沿捕获
        }else   //还未开始,第一次捕获上升沿
        {
            TIM5CH1_CAPTURE_STA=0;          //清空
            TIM5CH1_CAPTURE_VAL=0;
            TIM_SetCounter(TIM5,0);
            TIM5CH1_CAPTURE_STA|=0X40;      //标记捕获到了上升沿
            TIM_OC1PolarityConfig(TIM5,TIM_ICPolarity_Falling);     //CC1P=1 设置为下降沿捕获
        }           
    }                                              
}

TIM_ClearITPendingBit(TIM5, TIM_IT_CC1|TIM_IT_Update); //清除中断标志位

整个程序就是这样,一个通道完成后,可以开始写四路通道同时捕获高电平的程序了,用一个定时器就可以完成,还是比较简单的。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值