当前位置: 首页 > news >正文

单页面竞价网站班级优化大师免费下载安装

单页面竞价网站,班级优化大师免费下载安装,做淘宝还有必要做网站吗,如何做试玩类网站GD32_定时器输入捕获波形频率(多通道轮询) 之前项目上用到一个使用定时器捕获输入采集风扇波形频率得到风扇转速的模块,作为笔记简单记录以下当时的逻辑结构和遇到的问题,有需要参考源码、有疑问或需要提供帮助的可以留言告知 。…

GD32_定时器输入捕获波形频率(多通道轮询)

之前项目上用到一个使用定时器捕获输入采集风扇波形频率得到风扇转速的模块,作为笔记简单记录以下当时的逻辑结构和遇到的问题,有需要参考源码、有疑问或需要提供帮助的可以留言告知 。


前言

提示: 测试基于GD32F103CBT6硬件平台,标准的108MHz系统时钟, 使用标准库GD32F10x_Firmware_Library_V1.0.0提示:(提示:此库坑多,外设编号从1开始,与用户手册略有出入、慎用!)


一、定时器输入捕获原理

定时器输入捕获模式可以用来测量脉冲宽度或者测量频率,我们以测量频率为例,用一个简图来说明输入捕获的原理:
在这里插入图片描述

如图示,斜线表示向上计数的定时器的计数值,ARR表示定时器的自动重装载值,定时计数器由0递加到这里就会发生溢出,并重0重新开始计数。将输入捕获配置为上升沿捕获,当检测到一个波形的上升沿时候,触发第一次捕获中断,T1时刻会采集计数器当前CNT值并保存记为CCRx1,当再次出现上升沿时触发第二次捕获,T2时刻会再次采集计数器当前CNT值并保存记为CCRx2,理想状态波形周期就是T2 -T1。但是如果波形较长可能产生 N 次定时器溢出,这就要求我们对定时器溢出,做处理,防止高电平太长,导致数据不准确。 T1~T2之间CNT计数的次数等于: (ARR - CCRx1)+( N * ARR)+ CCRx2,有了这个计数次数,再乘以 CNT 的计数周期,即可得到 T1 -T2的时间长度,即波形周期以及频率。

二、外设配置

GD32的定时器,我们使用通用定时器Timer1的,使用的GPIO为PB10和PB11,根据用户手册,需要进行功能重映射才能使其分别对应Timer1的通道2和通道3。在定时器初始化中使用函数GPIO_PinRemapConfig()即可;
在这里插入图片描述

使用的主时钟频率为108MHz,定时器的重装载值寄存器为16位,最大为65535,当定时器时钟分频系数为108分频时候,相当于定时器每65.535ms会溢出一次,如下是整个定时器PWM输入捕获的配置方式,目的是分别对通道3和通道4上的两个风扇进行脉冲周期数据采集和计算,详细内容参见代码注释:

void FanPwm_Input_Init(void)
{TIMER_BaseInitPara  sTIM_TimeBaseStructure;NVIC_InitPara   NVIC_InitStructure;TIMER_ICInitPara sTIM_ICInitCaptureStructure;/*初始化Timer2输入捕获*/RCC_APB1PeriphClock_Enable(RCC_APB1PERIPH_TIMER2, ENABLE);      //实际是复位Timer1(手册与固件库有误)TIMER_DeInit(TIMER2);                                           //复位GPIO_PinRemapConfig(GPIO_FULL_REMAP_TIMER2,ENABLE);             //PB10和PB11是全映射复用sTIM_TimeBaseStructure.TIMER_Period 			= 65535;                 //计数器自动重装值sTIM_TimeBaseStructure.TIMER_Prescaler 			= 107;                   //计数器时钟预分频值,计数器时钟等于 PSC 时钟除以 (PSC+1)sTIM_TimeBaseStructure.TIMER_ClockDivision 		= TIMER_CDIV_DIV1;   	 //设置时钟分割:fDTS = fTIMER_CKsTIM_TimeBaseStructure.TIMER_CounterMode 		= TIMER_COUNTER_UP;      //TIM向上计数模式   TIMER_BaseInit(TIMER2, &sTIM_TimeBaseStructure);                    	 //根据TIM_TimeBaseInitStruct中指定的参数初始化TIMx的时间基数单位sTIM_ICInitCaptureStructure.TIMER_ICSelection 	= TIMER_IC_SELECTION_DIRECTTI;  //通道x配置为输入, ISx 映射在 CIxFEx 上sTIM_ICInitCaptureStructure.TIMER_ICPrescaler 	= TIMER_IC_PSC_DIV1;            //时钟分频sTIM_ICInitCaptureStructure.TIMER_ICPolarity 	= TIMER_IC_POLARITY_RISING;     //上升沿捕获sTIM_ICInitCaptureStructure.TIMER_ICFilter 		= 0x00;                         //不滤波sTIM_ICInitCaptureStructure.TIMER_CH 			= TIMER_CH_3;                   //PB10对应Timer2的通道3(手册是通道2,标准库有错位)TIMER_ICInit(TIMER2,&sTIM_ICInitCaptureStructure);                            sTIM_ICInitCaptureStructure.TIMER_CH = TIMER_CH_4;                              //PB11对应Timer2的通道4(手册是通道3,标准库有错位)TIMER_ICInit(TIMER2,&sTIM_ICInitCaptureStructure);                            NVIC_InitStructure.NVIC_IRQ 					= TIMER2_IRQn;          //TIM2中断NVIC_InitStructure.NVIC_IRQPreemptPriority 		= 0;     				//Q抢占优先级优先级0级NVIC_InitStructure.NVIC_IRQSubPriority			= 5;        			//副优先级2级NVIC_InitStructure.NVIC_IRQEnable 				= ENABLE;         		//IRQ通道被使能NVIC_Init(&NVIC_InitStructure);   TIMER_INTConfig(TIMER2,TIMER_INT_UPDATE,ENABLE);   						//使能定时器溢出中断,暂不使能通道捕获中断TIMER_Enable(TIMER2, ENABLE);                       					//使能定时器外设,暂不使能中断
}

三、逻辑结构

配置完成后,会分别轮询打开两个通道的输入捕获中断,当脉冲的第一个上升沿触发对应通道的输入捕获中断时,会捕获第一个定时器计数值并将变量WaveEgde 置为1 ,说明此时已经采集到第一个上升沿。当WaveEgde = 1的情况下,当再次触发中断时候会判断是定时器溢出中断还是上升沿触发的输入捕获中断,如果是定时器溢出,说明定时器重新计数了,会将录有效溢出次数+1;如果发生上升沿捕获中断,则说明第二个上升沿到来,会捕获第一个定时器计数值且已采集到一个完整波形周期。数据采集结束,关闭该通道的输入捕获中断,并将捕获完成标记位置位,变量WaveEgde 置为0(无采集状态)。然后根据是否有有效溢出次数,选择计算方式计算两次捕获总的时间差。整个采集流程如图所示:
在这里插入图片描述
以上是一个通道的采集流程,使用多个通道采集时采集流程基本原理一致,但是如果同时打开多个通道的捕获中断,会导致某些通道的数据差异非常大,这个差异随着增加的通道数量越多而变得明显。因为如果通道数量太多,会在集中一段时间内频繁进中断导致数据采集不准确,所以我们使用轮询方式打开通道的捕获中断,轮询间隔时间设置为200ms,这段逻辑代码如下所示:

定义了捕获数据结构体,所有的数据都保存在此结构体中

typedef struct
{uint8_t WaveEgde;                   //Eegd = 0,表示当前处于低电平,Egde = 1,表示当前处于高电平uint8_t ucFinishFlag;               //捕获结束标记位uint16_t ucCaptureRisingVal[2];     //输入捕获值,[0]:第1次触发捕获值,[1]:第2次触发捕获值uint32_t ucUpdateCnt;               //记录溢出次数uint32_t ulFanSpeed;                //风扇转速uint32_t ulFrequency;               //输入波形频率
}Capture_DateType;Capture_DateType WaveCap[FAN_Count_Num];            //定义两个风扇的捕获数据结构体

这里只给出了Timer2的中断回调函数中的逻辑结构

/**********************************************************************1-函数名:Fan_PwmI_IRQFunction*2-函数功能:Timer2的中断回调函数*3-输入参数:无*4-返回值:无*5-输入全局变量:无*6-输出全局变量:无*7-创建者与创建日期: Awen_ 2023-9-24**********************************************************************/
void Fan_PwmI_IRQFunction(void)
{if(TIMER_GetIntBitState(TIMER2,TIMER_INT_UPDATE) != RESET){	/*定时器溢出中断*/TIMER_ClearIntBitState(TIMER2,TIMER_INT_UPDATE);PwmInput_Timer_Update_Handler();}if(TIMER_GetIntBitState(TIMER2,TIMER_INT_CH3) != RESET){/*风扇1通道输入捕获中断*/TIMER_ClearIntBitState(TIMER2,TIMER_INT_CH3);PwmInput_Capture(FAN_NO_0);}if(TIMER_GetIntBitState(TIMER2,TIMER_INT_CH4) != RESET){/*风扇2通道输入捕获中断*/TIMER_ClearIntBitState(TIMER2,TIMER_INT_CH4);PwmInput_Capture(FAN_NO_1);}else{}
}
/**********************************************************************1-函数名:PwmInput_Timer_Update_Handler*2-函数功能:判断是否是有效溢出*3-输入参数:无*4-返回值:无*5-输入全局变量:无*6-输出全局变量:无*7-创建者与创建日期:Awen_ 2023-9-24**********************************************************************/
static void PwmInput_Timer_Update_Handler(void)
{uint8_t Index = 0;for(Index = 0;Index < FAN_Count_Num;Index++)		//FAN_Count_Num:总风扇个数{if(WaveCap[Index].WaveEgde == HIGH_LEVEL)		//是否是高电平状态{WaveCap[Index].ucUpdateCnt++;				//有效溢出 }else{}  }  
}
/**********************************************************************1-函数名:PwmInput_Capture*2-函数功能:输入捕获中断中的处理*3-输入参数:无*4-返回值:无*5-输入全局变量:无*6-输出全局变量:无*7-创建者与创建日期:Awen_ 2023-9-24**********************************************************************/
static void PwmInput_Capture(uint8_t Channel)
{  /*是否是第一次捕获*/if(WaveCap[Channel].WaveEgde == LOW_LEVEL){/*第一次捕获*/WaveCap[Channel].ucCaptureRisingVal[0] = FanPwm_Input_GetCapture(Channel); //第一次捕获CNTWaveCap[Channel].WaveEgde = HIGH_LEVEL;		//高电平状态  }else if(WaveCap[Channel].WaveEgde == HIGH_LEVEL){/*第二次捕获*/WaveCap[Channel].ucCaptureRisingVal[1] = FanPwm_Input_GetCapture(Channel); //第二次捕获CNTFanPwm_Input_EnableINT(Channel, DISABLE);	//关闭中断WaveCap[Channel].WaveEgde = LOW_LEVEL;		//恢复到低电平状态   WaveCap[Channel].ucFinishFlag = TRUE;		///捕获完成标记位}else{WaveCap[Channel].WaveEgde = LOW_LEVEL;FanPwm_Input_EnableINT(Channel, DISABLE);}
}

最后频率的计算方式

static void FanPwmI_SpeedCalcul()
{uint8_t Index = 0;uint32_t Freq_vallue;for(Index = 0;Index < FAN_Count_Num;Index++){if(WaveCap[Index].ucFinishFlag == TRUE)		//判断采集完成标记位{if(WaveCap[Index].ucUpdateCnt > 0)			//是否有有效溢出{/*算式1*/Freq_vallue =(0xFFFF - WaveCap[Index].ucCaptureRisingVal[0]) + ((WaveCap[Index].ucUpdateCnt - 1) * 0xFFFF) + WaveCap[Index].ucCaptureRisingVal[1];}else{/*算式2*/Freq_vallue =WaveCap[Index].ucCaptureRisingVal[1] - WaveCap[Index].ucCaptureRisingVal[0];}WaveCap[Index].ulFrequency = 1000000 / (Freq_vallue + 1);			//频率计算WaveCap[Index].ulFanSpeed = WaveCap[Index].ulFrequency * 30;  		//根据风扇手册计算转速            }else{}WaveCap[Index].ucFinishFlag = FALSE;				//采集完成标记位复位WaveCap[Index].ucUpdateCnt = 0;					//有效溢出计数复位}      
}  

总结

输入捕获还可采集波形占空比,其原理相同,只需要在第一次捕获之后改为下降沿触发,采集到第一个上升沿到第一个下降沿的CNT值,然后再设置为上升沿触发,采集一个完整波形周期CNT值,然后计算得到占空比。比较高效的做法是:硬件上使用Timer的两个通道的GPIO同时连到需要采集的波形管脚上,一个通道采集上升沿得到整个波形的周期,另一个通道采集下降沿得到波形高电平时长,再计算占空比。

http://www.laogonggong.com/news/38468.html

相关文章:

  • 单机网页游戏网站宁波seo网络推广
  • 安远做网站b2b平台有哪些平台
  • 分析公司网站的开发策略一键优化
  • 做网站page北京建站优化
  • 集团门户网站建设公司百度电话客服24小时
  • 公司企业网站如何推广自己的产品
  • 台州首页关键词优化推广网站排名优化seo教程
  • 做网站的具体步骤近期的重大新闻
  • 小米网站的建设目的热搜榜排名今日第一
  • 做网站的一般步骤广州专门做seo的公司
  • 免费程序网站百度应用商店app下载
  • 为网站做电影花絮seo公司系统
  • 网站建设需要条件制作自己的网站
  • 10000ip网站怎么做吉林seo基础知识
  • 搜索网站怎么做百度指数是什么
  • 免费的网站域名申请体验营销策略有哪些
  • 视频在线直播网站建设国外免费网站建设
  • 宣讲家网站官德修养与作风建设在线crm网站
  • 做我的世界皮肤壁纸的网站搜索引擎优化seo专员
  • 包头有没有专业做淘宝网站的b站在哪付费推广
  • 昆山网站建设机构seo专业培训学费多少钱
  • 营销型网站建设专家互动营销用在哪些推广上面
  • cpa网站建设教程百度广告管家
  • 自己买空间做网站合肥seo推广公司
  • 做外贸网站外包seoaoo
  • 辽宁网站备案新手怎么引流推广推广引流
  • WordPress电影网站源码官方app下载安装
  • asp系统网站怎么做优化百度搜索关键词规则
  • 网页设计实训报告不足怎么优化网站排名
  • dede的网站地图要怎么做网络安全培训最强的机构