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

正点原子的输入捕获程序是利用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;	//输入捕获值

//捕获状态TIM5CH1_CAPTURE_STA这个寄存器是作者自己定义的一个,stm32中无硬件对应,无相应硬件置位复位。这个寄存器大家可以把它当做两个标志位flag1+flag2+一个存次数的数length。
flag1(or2)=1有一次成功捕获过程完成或已经捕获到高电平。
flag1(or2)=0未有一次成功捕获过程完成或未捕获到高电平。
//捕获状态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); //清除中断标志位

}

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

你可能感兴趣的:(stm32,输入捕获)