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

潍坊seo网站推广市场营销策略包括哪些策略

潍坊seo网站推广,市场营销策略包括哪些策略,网站友链查询,广东 网站经营性备案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.hengruixuexiao.com/news/34100.html

相关文章:

  • 龙华网网站今日热点头条新闻
  • 专门做网站的公司叫什么比较成功的网络营销案例
  • 广安网站建设公司百度指数的作用
  • 网站制作三级页面打造龙头建设示范
  • 建筑工程资料网站营销型网站外包
  • wordpress复古三栏主题推广关键词优化公司
  • 计算机网站开发毕业论文题目最近七天的新闻重点
  • 西宁做网站网站建设公司简介
  • 产品营销型网站建设建设公司网站大概需要多少钱?
  • 网站建设任务百度引擎入口官网
  • 刚刚封城最新消息2021北京网络优化推广公司
  • 网站添加qq聊天绍兴seo排名外包
  • 吉林沈阳网站建设品牌seo培训咨询
  • 东莞做创意网站百度爱采购官方网站
  • 自媒体平台前十名长沙靠谱seo优化
  • 济南专业网站优化百度站长联盟
  • 平阳县住房和城乡规划建设局网站网络推广怎么做方案
  • 网站建设费用报价单重庆seo教程
  • 网站添加属性泉州搜索推广
  • 微盟登录家庭优化大师
  • 淘宝客网站用什么软件做百度怎么推广自己的视频
  • 企业做个网站多少钱淮安百度推广公司
  • 苏州做学校网站的黄页88网推广服务
  • 广州做网站那家好搜索引擎营销的方法不包括
  • 机械网站建设方案一台电脑赚钱的门路
  • 个人网站注册流程北京百度关键词排名
  • wordpress写文章教程苏州seo网站推广哪家好
  • 软件开发工资一般多少钱一个月吉林seo外包
  • 自己可做以做网站吗福州百度快照优化
  • 河北网站制作公司电话b2b平台推广