STM32F1 YF-S201C 水流量检测计 瞬时、累计流量检测
因为毕设中要用到YF-S201C这个传感器检测瞬时水流量和累计水流量,找遍了整个网络,没有找到一个比较中意的,于是参考了一些大神的自己组装了一个,适用于STM32F103zet6。
首先先简单介绍一下这所需器件:
YF-S201C:
该模块以霍尔传感器为核心器件,每流经1L水就会产生300个脉冲(4分管),它一般分为两种型号,一种为4分管,一种为6分管,型号不同单位水流量产生的脉冲数不同,本文以4分管为例。
流量计算公式:
瞬时流量 = (脉冲频率 / 300个脉冲) * 60s= 脉冲频率 / 5.0(流量系K)
累计流量 = 对瞬时流量做累加= (脉冲频率 / 300个脉冲)
程序设计:
外部中断检测脉冲个数,time3定时器计时1S
核心代码如下:
main函数:
#include "led.h" #include "delay.h" #include "key.h" #include "sys.h" #include "usart.h" #include "YFS201C.h" /************************************************ 日期:2023.3.22 功能:采用YF_S201C检测水流量,并通过串口发送检测结果 接线:RX->PA9 TX->PA10 LED->PE5 YF_S201C 黄线->PD2 红线->VCC 黑线->GND ************************************************/ int main(void) { delay_init(); //延时函数初始化 NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); //设置NVIC中断分组2:2位抢占优先级,2位响应优先级 uart_init(115200); //串口初始化为115200 LED_Init(); //LED端口初始化 KEY_Init(); //初始化与按键连接的硬件接口 Exit2_Config(); //外部中断检测脉冲个数 TIM3_Int_Init(9999,7199); //计时1S while(1) { Flow_Read(); } }
YFS201C.h
#ifndef _YFS201C_H #define _YFS201C_H #include "stm32f10x.h" #include "usart.h" #include "led.h" typedef struct { uint8_t receive_flag; uint16_t pluse_1s; float instant; float acculat; }GOLBAL_FLOW; extern GOLBAL_FLOW golbal_flow; void Exit2_Config(void); void Flow_Read(void); void TIM3_Int_Init(u16 arr,u16 psc); #endif
YFS201C.c
#include "YFS201C.h" GOLBAL_FLOW golbal_flow; #define Flow_Model_4 1 //4分管定义为1;6分管定义为0 #define MODE_4_K 5.0f #define MODE_4_PLUSE_CNT_1L 300.0f #define MODE_6_K 5.5f #define MODE_6_PLUSE_CNT_1L 330.0f #define FLOW_FULL 1000000 //用PD2的外部中断来获取低电平的脉冲 void Exit2_Config(void) { EXTI_InitTypeDef EXTI_InitStructure; NVIC_InitTypeDef NVIC_InitStructure; RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE); GPIO_EXTILineConfig(GPIO_PortSourceGPIOD,GPIO_PinSource2); //Config EXTI2 line EXTI_ClearITPendingBit(EXTI_Line2); EXTI_InitStructure.EXTI_Line = EXTI_Line2; EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt; EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling; //下降沿触发中断 EXTI_InitStructure.EXTI_LineCmd = ENABLE; EXTI_Init(&EXTI_InitStructure); NVIC_InitStructure.NVIC_IRQChannel = EXTI2_IRQn; NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x02; NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x02; NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; NVIC_Init(&NVIC_InitStructure); } void EXTI2_IRQHandler(void) { if(EXTI_GetITStatus(EXTI_Line2) != RESET) { golbal_flow.pluse_1s++; //下降沿采集脉冲数 } EXTI_ClearITPendingBit(EXTI_Line2); //清除Line2的中断标志位 } void Flow_Read(void) { if(golbal_flow.receive_flag) { if(golbal_flow.pluse_1s > 0) { #ifdef Flow_Model_4 /*计算公式: 累计流量 = 对瞬时流量做积分 = (脉冲频率 / 300个脉冲) //1L需要300个脉冲,脉冲频率HZ */ golbal_flow.acculat += golbal_flow.pluse_1s / MODE_4_PLUSE_CNT_1L; //单位L /*计算公式: 瞬时流量 = (脉冲频率 / 300个脉冲) * 60s = 脉冲频率 / 5.0(流量系K) */ golbal_flow.instant = golbal_flow.pluse_1s / MODE_4_K; //单位(L/min) #else /*计算公式: 累计流量 = 对瞬时流量做积分 = (脉冲频率 / 330个脉冲) //1L需要330个脉冲,脉冲频率HZ */ golbal_flow.acculat += golbal_flow.pluse_1s / MODE_6_PLUSE_CNT_1L; //单位L /*计算公式: 瞬时流量 = ((脉冲频率 + 3) / 330个脉冲) * 60s = (脉冲频率 + 3) / 5.5(流量系K) */ golbal_flow.instant = (golbal_flow.pluse_1s + 3) / MODE_6_K; //单位(L/min) #endif if(golbal_flow.acculat >= FLOW_FULL) { golbal_flow.acculat = 0; } } else { golbal_flow.instant = 0; } printf("瞬间流量:%.2f(L/min) 累计流量:%.2f(L)\n",golbal_flow.instant,golbal_flow.acculat); golbal_flow.receive_flag = 0; //接收完成标志位清零 golbal_flow.pluse_1s = 0; LED0=!LED0; //LED1灯 取反提示系统正常运行 } } void TIM3_Int_Init(u16 arr,u16 psc) { TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure; NVIC_InitTypeDef NVIC_InitStructure; RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE); //①时钟 TIM3 使能 //定时器 TIM3 初始化 TIM_TimeBaseStructure.TIM_Period = arr; //设置自动重装载寄存器周期的值 TIM_TimeBaseStructure.TIM_Prescaler =psc; //设置时钟频率除数的预分频值 TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1; //设置时钟分割 TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; //TIM 向上计数 TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure); //初始化 TIM3 TIM_ITConfig(TIM3,TIM_IT_Update,ENABLE ); //允许更新中断 //中断优先级 NVIC 设置 NVIC_InitStructure.NVIC_IRQChannel = TIM3_IRQn; //TIM3 中断 NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0; //先占优先级 0 级 NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3; //从优先级 3 级 NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //IRQ 通道被使能 NVIC_Init(&NVIC_InitStructure); //④初始化 NVIC 寄存器 TIM_Cmd(TIM3, ENABLE); //⑤使能 TIM3 } //定时器 3 中断服务程序 void TIM3_IRQHandler(void) //TIM3 中断 { if (TIM_GetITStatus(TIM3, TIM_IT_Update) != RESET) //检查 TIM3 更新中断发生与否 { TIM_ClearITPendingBit(TIM3, TIM_IT_Update ); //清除 TIM3 更新中断标志 golbal_flow.receive_flag = 1; } }
顺便附上源码,如需自提
链接:https://pan.baidu.com/s/1Cd9dxTipS4WHoBfXgBRAcQ
提取码:li3z