电子工程师技术服务社区
公告
登录
|
注册
首页
技术问答
厂商活动
正点原子
板卡试用
资源库
下载
文章
社区首页
文章
[网友问答4]基于NPN型脉冲风速变送器获取实时风速
分 享
扫描二维码分享
[网友问答4]基于NPN型脉冲风速变送器获取实时风速
外部中断
风速仪
脉冲计数
嵌入式从0到1
关注
发布时间: 2021-05-13
丨
阅读: 416
## 问题原由 粉丝提问,`NPN型脉冲风速变送器怎么求得风速`,平时很支持小哈哥工作的小伙伴有需求,小哈哥必须安排,这次发文总结一下,希望可以帮助大家。 ![](https://img-blog.csdnimg.cn/20210413220005443.png) ## 开发环境与工具 * Keil 5 * 主芯片为STM32F103RET6 * 下载工具为JLINK * PC为Win10 * 风速变送器的型号为:**VMS-3000-FSJT-NPN** ## 展示视频 NPN型脉冲风速变送器的使用方法,详见如下视频教程: ## 程序源码 本文测试工程源码的获取方式在上面展示视频中获取。 **欢迎关注小哈哥的视频号**,更多精彩敬请期待。 ## 主要参数 * 直流供电:5V DC * 通信接口:脉冲输出 * 分辨率:0.0875 m/s * 精度:±(0.2+0.03V) m/s V表示风速 * 测量范围:0~70 m/s * 动态响应时间: ≤0.5s * 启动风速:≤0.2 m/s ![](https://img-blog.csdnimg.cn/20210413220119255.png) ## 产品选型 产品型号命名规则如下: ![](https://img-blog.csdnimg.cn/20210413220139710.png) 由上面风速变送器上的标签可知,该风速仪的型号为:**VMS-3000-FSJT-NPN**,对比命名规则,我们可知这是一个不带内部上拉电阻的NPN输出的风速变送器。 ## 换算关系 脉冲输出型风速变送器风速和脉冲个数的换算关系如下: ![](https://img-blog.csdnimg.cn/20210413220155215.png) 由上我们可以得出,我们只要计算出来,一秒钟之内脉冲的个数N就好了,通过脉冲个数N和上面截图中的已知信息,我们可以得到风速的换算关系如下: `风速=(1.75 / 20) * N` 所以本模块应用的难点就是如何精准的计算单位时间内的脉冲个数。 ## 引脚定义 ![](https://img-blog.csdnimg.cn/20210413220208676.png) 由于本模块是NPN型,所以我们只需要使用棕色(+5V)、黑色(GND)、蓝色(与一个GPIO相连)三根线即可。 ## 等效电路 输出电路图 在编写代码之前,我们首先要确定风速变送器有脉冲输出,并确定输出的脉冲波形有什么特点,所以我们需要使用示波器先看一下输出的脉冲信号。 将棕色线与+5V电源相连,黑色线接地,蓝色线进入示波器。 查询手册,NPN型输出的等效电路如下所示: ![](https://img-blog.csdnimg.cn/2021041322022520.png) **注意:** 经测试,必须在图中**RL**位置添加一个上拉电阻才能输出正常的方波!!! 当风速仪转动时,蓝线输出的方波信号如下: ![](https://img-blog.csdnimg.cn/20210413220238642.png) 我们由上可以看出,风速变送器输出的脉冲为0~5V的脉冲信号,所以为了系统的稳定性,我们需要选择一个具有**FT**标识的引脚。 FT:five volt tolerant 意思的兼容5V信号电压。因为一般STM32 的引脚是3.3V,后面带有FT标识的,说明可以容忍5V。 ![](https://img-blog.csdnimg.cn/20210413220253621.png) 本实例,我们选择**PB12**为例。 ## 接线 | **风速仪** | **STM32** | **说明** | | :---: | :---: | :---: | | 棕色线 | +5V | 电源正 | | 黑色线 | GND | 电源负 | | 蓝色线 | PB12 | NPN-OUT | ## 代码实现 ### 1. 外部中断初始化 为了计数脉冲的个数,我们使用外部中断来对脉冲进行计数,每来一个脉冲,外部中断执行一次。 ```C void NPNInit() { EXTI_InitTypeDef EXTI_InitStructure; NVIC_InitTypeDef NVIC_InitStructure; GPIO_InitTypeDef GPIO_InitStructure; //使用外部中断需要开启RCC_APB2Periph_AFIO时钟 RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB|RCC_APB2Periph_AFIO, ENABLE); //初始化IO口为输入 GPIO_InitStructure.GPIO_Pin = NPN_Pin; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU; GPIO_Init(NPN_PORT, &GPIO_InitStructure); //GPIOB.12中断线 EXTI_ClearITPendingBit(EXTI_Line12); GPIO_EXTILineConfig(GPIO_PortSourceGPIOB, GPIO_PinSource12); EXTI_InitStructure.EXTI_Line=EXTI_Line12; EXTI_InitStructure.EXTI_Mode=EXTI_Mode_Interrupt; EXTI_InitStructure.EXTI_Trigger=EXTI_Trigger_Rising; //上升沿中断 EXTI_InitStructure.EXTI_LineCmd=ENABLE; EXTI_Init(&EXTI_InitStructure); //中断初始化配置 NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1); NVIC_InitStructure.NVIC_IRQChannel = EXTI15_10_IRQn; NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0; NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1; NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; NVIC_Init(&NVIC_InitStructure); } ``` ### 2. 外部中断函数 在外部中断函数中,自定义全局变量**msNPNCount**加1,该值即记录了收到的脉冲个数。 ```C void EXTI15_10_IRQHandler(void) { if(EXTI_GetITStatus(EXTI_Line12)==SET) { msNPNCount++; EXTI_ClearITPendingBit(EXTI_Line12); // 清除中断标志 } } ``` ### 3. 定时器初始化 因为要记录单位时间内收到的脉冲个数,所以我们要占用一个定时器用来计时,我们随便选择一个定时器皆可,这里我们选择**TIM4**,下面代码对TIM4进行初始化: ```C //通用定时器中断初始化 //arr:自动重装值。 //psc:时钟预分频数 void TIM4_Init(u16 arr,u16 psc) { NVIC_InitTypeDef NVIC_InitStructure; TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure; RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM4, ENABLE); //时钟使能//TIM4时钟使能 //定时器TIM4初始化 TIM_TimeBaseStructure.TIM_Period = arr; //设置自动重装载值 TIM_TimeBaseStructure.TIM_Prescaler =psc; //设置TIMx时钟频率的预分频值,16位 TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1; //设置时钟分割:TDTS = Tck_tim TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; //TIM向上计数模式 TIM_TimeBaseInit(TIM4, &TIM_TimeBaseStructure); //根据指定的参数初始化TIMx的时间基数单位 TIM_ClearFlag(TIM4, TIM_FLAG_Update); TIM_ITConfig(TIM4,TIM_IT_Update,ENABLE ); //使能指定的TIM4中断,允许更新中断 NVIC_InitStructure.NVIC_IRQChannel = TIM4_IRQn; NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=1 ; NVIC_InitStructure.NVIC_IRQChannelSubPriority = 2; NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; NVIC_Init(&NVIC_InitStructure); //根据指定的参数初始化NVIC寄存器 TIM_Cmd(TIM4,DISABLE); } ``` main函数中调用定时器4的初始化函数如下: ```C TIM4_Init(1000-1,7200-1); //7200分频,10KHz,计数1K耗时100ms TIM4_Set(1); //开启定时器 ``` TIM4每100ms执行一次中断。 ### 4. 定时器中断 我们定义了两个全局变量,一个数组用于记录每100ms内收到的脉冲数,一个用于记录当前数组的索引: ```C u32 CounterArr[10]; u8 CounterIndex = 0; ``` 在TIM4的定时器中断函数中,每次中断发生时,将脉冲计数保存在数组**CounterArr**中,然后脉冲计数清零。 ```C //定时器4中断 void TIM4_IRQHandler(void) { if (TIM_GetITStatus(TIM4, TIM_IT_Update) != RESET) { TIM_ClearITPendingBit(TIM4, TIM_IT_Update ); //保存NPN脉冲计数 CounterArr[CounterIndex] = msNPNCount; msNPNCount = 0; CounterIndex++; if(CounterIndex>=10) CounterIndex=0; } } ``` ### 5. 脉冲数与风速转换 在**main**函数中,周期计算风速值,**CounterArr**数组中存的十个脉冲数,即1秒中内的脉冲总数,然后将**脉冲总数\*0.0875**,所得的结果即为风速值。 ```C if(times%200==0) { //计算风速值 nTotalNPNCounter = 0; for(i=0;i<9;i++) { nTotalNPNCounter += CounterArr[i]; } printf("风速为 %.2f m/s\r\n",nTotalNPNCounter*0.0875); } ``` ## 相关常识 ![](https://img-blog.csdnimg.cn/20210413220314694.png) ## 参考阅读 [HC-SR04超声波测距原理及实现](https://mp.weixin.qq.com/s/TZybdfsPzlJbr3TmSIfhWQ) [红外遥控功能的实现](https://mp.weixin.qq.com/s/3cz3cp8H4OsFSosDEG3Z9A) [485型风速和风向变送器数据包解析](https://mp.weixin.qq.com/s/HxmNOIvTEwLR4JVBzf5LoA) ## 欢迎关注 程序员小哈带你玩转嵌入式,微信搜索:**嵌入式从0到1**,更多干货等着你。
原创作品,未经权利人授权禁止转载。详情见
转载须知
。
举报文章
点赞
(
0
)
嵌入式从0到1
关注
评论
(0)
登录后可评论,请
登录
或
注册
相关文章推荐
MK-米客方德推出工业级存储卡
Beetle ESP32 C3 蓝牙数据收发
Beetle ESP32 C3 wifi联网获取实时天气信息
开箱测评Beetle ESP32-C3 (RISC-V芯片)模块
正点原子数控电源DP100测评
DP100试用评测-----开箱+初体验
Beetle ESP32 C3环境搭建
【花雕体验】16 使用Beetle ESP32 C3控制8X32位WS2812硬屏之二
X
你的打赏是对原创作者最大的认可
请选择打赏IC币的数量,一经提交无法退回 !
100IC币
500IC币
1000IC币
自定义
IC币
确定
X
提交成功 ! 谢谢您的支持
返回
我要举报该内容理由
×
广告及垃圾信息
抄袭或未经授权
其它举报理由
请输入您举报的理由(50字以内)
取消
提交