暑期培训第十六天(输入捕获)

这次在初步熟悉了TI板子的使用之后,我就开始学习输入捕获了(23年C题)

关于输入捕获,我想说说我今天学习之后的理解。

通过测量高低电平,来实现测量数据。

高低电平:上升沿、下降沿(这个可以通过直接配置,不用在自己写函数来判断)

测量数据:频率、占空比


开始讲讲理论部分:

第一遍观看了江科大的教程:[6-5] TIM输入捕获_哔哩哔哩_bilibili​​​​​​

这个时候我大概知道了测量频率的实现有三种方法:测周法、测频法、测中法

测周法:通过规定时间内(1s),计数上升沿的个数来计算频率(f = 1/n)(高频适用)

测频法:用标准频率计数俩个上升沿之间的计数个数,以此来计算周期(低频适用)

测中法:通过上述的公式来计算这个高低频的中间划分值应该是多少。

还有就是对单片机内部处理输入捕获的信息的处理流程,有了一个大概的了解。

第二遍再看视频,我才对这些有一个入门的了解。

(这里再次提醒自己要多看官方原理图)

我就我学了一天的来说说我的理解:

对输入的信号进行处理(滤波:边沿跳变),然后判定是高低电平作为触发条件,结束后面的频率计数周期。将计数值进行处理,就可以得到频率了。

(这下发现自己对这个还是没理解很懂,再去多看看)

至于其中的细节,这个就要在写代码中来细讲了。

代码部分:

思路是:用通用定时器(TIM5)的频率( 72M/(pre+1)/(arr+1))来对外接入的信号进行输入捕获处理,在中断(高低电平触发都可以 )中处理数据(标志位,计数值)

GPIO:

这里我开启的是TIM5时钟的CH2和CH3,查看硬件分布图知道是PA2和PA3。

	//定义结构体变量
	GPIO_InitTypeDef  GPIO_InitStructure; 						//引脚输入方波							  
	
	//配置输入引脚:PA2 PA3
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);		//开启时钟
    GPIO_InitStructure.GPIO_Mode=GPIO_Mode_IPD;					//上拉输入
    GPIO_InitStructure.GPIO_Pin=GPIO_Pin_3|GPIO_Pin_2;			//这里查询硬件分布:PA2-TIM5-CH3 
    GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;								// PA3-TIM5_CH4
    GPIO_Init(GPIOA,&GPIO_InitStructure);						//初始化结构体
配置定时器TIM5:

定时器的基本配置:开启时钟、向上计数、时钟clockdivision=1、prescaler = 72-1(这里是用1MHz比较好算)、arr设定为ffff(因为不知道会计数多少个)

							  
	TIM_TimeBaseInitTypeDef  TIM_TimeBaseInitStructure;    		//这里使用测周法来测量频率
    
	//配置定时器5
    RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM5,ENABLE);			//开启时钟
    TIM_TimeBaseStructInit(&TIM_TimeBaseInitStructure);			//这个我也不知道
    TIM_TimeBaseInitStructure.TIM_ClockDivision=TIM_CKD_DIV1;	//不分频
    TIM_TimeBaseInitStructure.TIM_CounterMode=TIM_CounterMode_Up;	//向上计数处理
    TIM_TimeBaseInitStructure.TIM_Period=arr;					//计数重新转载值
    TIM_TimeBaseInitStructure.TIM_Prescaler=psc;				//预分频系数
    TIM_TimeBaseInit(TIM5,&TIM_TimeBaseInitStructure);			//初始化定时器5

输入捕获的配置:

因为我这次是用来计算俩个正弦波的相位差(经过运放化成方波处理),我就开启了俩个通道

选择通道:CH2 CH3(因为我最初借鉴的代码是这样的配置的,我就直接照着来了)

滤波处理:这个值可以根据自己实际电路的噪声来处理,0~f。我这里就直接拉满了。

极性触发:我都选择上升沿触发,就是直接选择测量高电平的所占频率(这里选择低电平ok的)

precalser:这个我不是太懂,我就理解到视频中说的:这个就看你几次高电平触发一次采集,选择1分频就是单次采集就触发、选择2就是两次高电平才触发

Selection:这个就是生效时间,这个不追求细节就是直接就好了。

    TIM_ICInitStructure.TIM_Channel=TIM_Channel_4;				//通道4		
    TIM_ICInitStructure.TIM_ICFilter=0xf;						//最大滤除噪声模式
    TIM_ICInitStructure.TIM_ICPolarity=TIM_ICPolarity_Rising;	//上升沿触发
    TIM_ICInitStructure.TIM_ICPrescaler=TIM_ICPSC_DIV1;			//单次触发
    TIM_ICInitStructure.TIM_ICSelection=TIM_ICSelection_DirectTI;//立刻生效
    TIM_ICInit(TIM5,&TIM_ICInitStructure);
    
    TIM_ICInitStructure.TIM_Channel=TIM_Channel_3;
    TIM_ICInitStructure.TIM_ICFilter=0xf;
    TIM_ICInitStructure.TIM_ICPolarity=TIM_ICPolarity_Rising;
    TIM_ICInitStructure.TIM_ICPrescaler=TIM_ICPSC_DIV1;
    TIM_ICInitStructure.TIM_ICSelection=TIM_ICSelection_DirectTI;
    TIM_ICInit(TIM5,&TIM_ICInitStructure);
中断NVIC的配置:

这个我觉得比较重要的是,下面config中的几个参数要记住:

    NVIC_InitStructure.NVIC_IRQChannel=TIM5_IRQn;
    NVIC_InitStructure.NVIC_IRQChannelCmd=ENABLE;
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=2;
    NVIC_InitStructure.NVIC_IRQChannelSubPriority=1;
    NVIC_Init(&NVIC_InitStructure);
    
    TIM_ITConfig(TIM5,TIM_IT_Update|TIM_IT_CC4|TIM_IT_CC3,ENABLE);	//开启中断

这里要记得把CC4和CC3一起算进去就好了。(这个我也不是太懂)

中断服务助手:

这里说说通道3的处理就好了(因为通道4就是类似的),直接上代码

    if((TIM5CH4_Cap_State&0x80)==0) //第一路信号未捕获到下降沿
    {
        if(TIM_GetITStatus(TIM5,TIM_IT_Update)==SET)
        {
            if(TIM5CH4_Cap_State&0x40) 				//第一路信号已捕获到上升沿
            {
                if((TIM5CH4_Cap_State&0x3f)==0x3f) 	//第一路信号上升沿到下降沿时间过长,捕获失败
                {
                    TIM5CH4_Cap_State|=0x80;       
                    TIM5CH4_Cap_Value=0xffff;
                }
                else 
					TIM5CH4_Cap_State++;
            }
        }
        if(TIM_GetITStatus(TIM5,TIM_IT_CC4) == SET) //捕获中断
        {
            if(TIM5CH4_Cap_State & 0x40) 					//第一路信号已经捕获到上升沿,则此次为下降沿被捕获
            {
                TIM5CH4_Cap_State|=0x80; 				    //标志一次检测完成
                TIM5CH4_Cap_Value=TIM_GetCapture4(TIM5); 	//取出定时器的值
                TIM_OC4PolarityConfig(TIM5,TIM_ICPolarity_Rising); //设置为上升沿捕获
            }
            else //第一路未捕获到上升沿,则此次为上升沿被捕获
            {
                TIM5CH4_Cap_State=0;
                TIM5CH4_Cap_Value=0;
			    TIM_SetCounter(TIM5,0);
                TIM5CH4_Cap_State|=0X40; //标记捕获到上升沿
                TIM_OC4PolarityConfig(TIM5,TIM_ICPolarity_Falling); //设置为下降沿捕获
            }
        }
    }

重点关注:标志位和计数值就好了

首先就是判断是不是检测到上升沿,检测到了就给一个标志位,设定为下降沿检测。(这个进入中断服务助手是通过检测到上升沿来触发的)

然后就是循环判断是不是满足下降沿的触发,是的话就赋值跳出中断。

(这里说的比较简单,可以好好看看)

这个标志位的设定和串口传输数据的中断服务助手好像,这个可以学习一下标志位的设定进入不同的if中

主函数:
//		 if(TIM5CH4_Cap_State&0X80)					//成功捕获到了一次上升沿
//		{
//			temp = TIM5CH4_Cap_State&0X3F;
//			temp *= 65536;//溢出时间总和
//			temp += TIM5CH4_Cap_Value;//得到总的高电平时间
//			printf("HIGH111:%d us\r\n",temp);//打印总的高点平时间
//			TIM5CH4_Cap_State=0;//开启下一次捕获
//		}
//		if(TIM5CH3_Cap_State&0X80)//成功捕获到了一次上升沿
//		{
//			temp=TIM5CH3_Cap_State&0X3F;
//			temp*=65536;//溢出时间总和
//			temp+=TIM5CH3_Cap_Value;//得到总的高电平时间
//			printf("HIGH222:%d us\r\n",temp);//打印总的高点平时间
//			TIM5CH3_Cap_State=0;//开启下一次捕获
//		}

这个就是输出计数的数值,没什么好讲的。

总结:

代码的理解还是有待提升,中间很多细节我发现我还是不懂。

下次碰到要学习的知识点,可以先找找有没有教学视频之类的和相关的例程代码,然后看一遍自己取折腾一下;再带着问题去第二遍视频,这个中间自己不懂得细节有哪些?第三遍开始就可以试着建立起自己的理解和整体的思路。

要看原理图!!!一手的数据手册!!!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值