• stm32 输入捕获学习(二)


    (本文参考STM32  开发指南 V1.3   —— ALIENTEK 战舰 STM32 开发板库函数教程 )


    1. 实验设计

    我们用 TIM5 的通道 1(PA0)来做输入捕获,捕获 PA0 上高电平的脉宽(用 WK_UP 按键输入高电平),通过串口打印高电平脉宽时间。

    2. 原理说明

    基本原理可以参考上一篇博文,在上个实验的基础上,我们稍作修改,就可以实现功能。

    1)增加GPIO的配置。


    这里我们使用的是KEY_UP按键,WK_UP右端连接PA0. 我们把PA0配置为下拉输入,这样不按键PA0就是低电平,按键的话PA0就是高电平。

    2)修改中断处理程序

    TIM5_IRQHandler 是 TIM5 的中断服务函数,该函数用到了两个全局变量,用于辅助实现高电平捕获。其中TIM5CH1_CAPTURE_STA,是用来记录捕获状态。TIM5CH1_CAPTURE_STA 各位描述如下图所示:


    另外一个变量 TIM5CH1_CAPTURE_VAL,则用来记录捕获到下降沿的时候,TIM5_CNT的值。 

    现在我们来介绍一下,捕获高电平脉宽的思路:

    首先,设置 TIM5_CH1 为上升沿捕获(这在TIM5_Cap_Init 函数中就设置好了),等待上升沿中断到来。此时如果 TIM5CH1_CAPTURE_STA 的第 6 位为 0,则表示还没有捕获到上升沿,这时把 TIM5CH1_CAPTURE_STA、TIM5CH1_CAPTURE_VAL 和 TIM5->CNT 清零,然后再设置TIM5CH1_CAPTURE_STA 的第 6 位为 1,表示已经捕获到高电平,最后设置为下降沿捕获,等待下降沿到来。

    当下降沿到来的时候,先设置 TIM5CH1_CAPTURE_STA 的第 7 位为 1,标记成功捕获一次高电平,然后读取此时定时器值到 TIM5CH1_CAPTURE_VAL 里面(等待主函数处理),最后设置为上升沿捕获,回到初始状态。 
    如果等待下降沿到来的期间,定时器发生了溢出,就在 TIM5CH1_CAPTURE_STA里面对溢出次数进行计数,当最大溢出次数来到的时候,就强制标记捕获完成(虽然此时还没有捕获到下降沿),并且设置TIM5CH1_CAPTURE_VAL为最大值0XFFFF,最后设置成上升沿捕获,回到初始状态。
    这样,我们就完成一次高电平捕获,只要 TIM5CH1_CAPTURE_STA 的第 7 位一直为 1,就不会进行第二次捕获。我们在main函数处理完捕获数据后,将TIM5CH1_CAPTURE_STA置零,就可以开启第二次捕获。   

    3. 参考代码

    GPIO_InitTypeDef GPIO_InitStructure;
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);  
    GPIO_InitStructure.GPIO_Pin  = GPIO_Pin_0;  
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPD; //PA0 下拉输入
    GPIO_Init(GPIOA, &GPIO_InitStructure);
    上面这段代码增加到 void TIM5_Cap_Init(u16 arr,u16 psc) 函数中。

    中断处理如下

    u8  TIM5CH1_CAPTURE_STA = 0;	  				
    u16	TIM5CH1_CAPTURE_VAL;	//保存TIM5的值
     
    void TIM5_IRQHandler(void)
    { 
    
     	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;  
    					TIM_OC1PolarityConfig(TIM5,TIM_ICPolarity_Rising); //设置为上升沿捕获
    				}
    				else
    				{
    					TIM5CH1_CAPTURE_STA++;
    				}
    			}	 
    		}
    		
    		if(TIM_GetITStatus(TIM5, TIM_IT_CC1) != RESET) //捕获中断
    		{	
    			if(TIM5CH1_CAPTURE_STA & 0X40)		//此时捕获下降沿		
    			{	  			
    				TIM5CH1_CAPTURE_STA|=0X80;		//标记捕获完成
    				TIM5CH1_CAPTURE_VAL=TIM_GetCapture1(TIM5);
    		   		TIM_OC1PolarityConfig(TIM5,TIM_ICPolarity_Rising); //设置为上升沿捕获
    			}
    			else  								//捕获到了上升沿
    			{
    				TIM5CH1_CAPTURE_STA=0;			
    				TIM5CH1_CAPTURE_VAL=0;
    	 			TIM_SetCounter(TIM5,0);
    				TIM5CH1_CAPTURE_STA|=0X40;		//标记捕获到了上升沿
    		   		TIM_OC1PolarityConfig(TIM5,TIM_ICPolarity_Falling);		//设置为下降沿捕获
    			}		    
    		}			     	    					   
     	}
     
        TIM_ClearITPendingBit(TIM5, TIM_IT_CC1|TIM_IT_Update); //清除中断标志
     
    }

    主函数代码:

    extern u8  TIM5CH1_CAPTURE_STA;			    				
    extern u16	TIM5CH1_CAPTURE_VAL;	
    
    int main(void)
    {		
    	u32 temp = 0; 
    	 
    	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);	 
    	uart_init(9600);	 //串口初始化,波特率9600
    	
    	TIM5_Cap_Init(0XFFFF,72-1);	//1MHz 计数频率
    	
      	while(1)
    	{
    		if(TIM5CH1_CAPTURE_STA & 0X80) //成功捕获到一个高脉冲
    		{
    			temp = TIM5CH1_CAPTURE_STA & 0X3F;  //定时器溢出次数
    			temp *= 65536; //溢出时间总和
    			temp += TIM5CH1_CAPTURE_VAL;        //算出高电平的时间
    			printf("HIGH:%d us
    ",temp);      //串口打印
    			
    			TIM5CH1_CAPTURE_STA=0;              //开启下一次捕获
    		};
    	}
    }
    
    3.实验结果





  • 相关阅读:
    SQL SqlParameter
    C# 迭代器与yield关键字
    ADO.NET调用SQL存储过程
    C# XML
    C# MDI应用程序
    LINQ 基础
    C# 文件操作
    C# 操作注册表
    SQL从SQL SERVER中获取数据库结构信息
    Linux发展史
  • 原文地址:https://www.cnblogs.com/longintchar/p/5224420.html
Copyright © 2020-2023  润新知