基于蓝牙控制的stm32单片机水流量计设计

硬件构成:

STM32F103C8T6单片机最小系统板(包含+3.3V稳压电路+时钟晶振电路+复位电路(上电自复位,手动复位)),水流量传感器、继电器、LCD1602液晶显示、按键、蜂鸣器、蓝牙模块及电源组成;

功能介绍:

1、通过LCD1602液晶实时显示瞬时流量和累计流量、设置的累计流量。

2、通过按键设置累计流量阈值,如果累计流量超过设置阈值,蜂鸣器报警、继电器断开,否则不报警继电器闭合。

3、继电器模拟水阀开关,如果当前累计流量低于设置流量,打开继电器打开水阀的意思。

4、按键有设置按键、设置+、设置-,在设置情况下可以对设置值进行加减运算。

5、蓝牙模块可与手机APP连接,实现手机APP对实物的实时数据的监控和控制;

主要物料清单及型号

显示屏:LCD1602-5V;

单片机:STM32F103C8T6;

蓝牙模块:JDY-31-SPP;

水流量传感器:YF-S201;

继电器:SRD-05V;

蜂鸣器:5V有源蜂鸣器;

PCB:

程序:

#include "led.h"
#include "delay.h"
#include "sys.h"
#include "usart.h"
#include <stdio.h>
#include "timer.h"
#include "key.h"
#include "lcd1602.h"
#include "exti.h" 

char dis0[17]; //显示暂存数组
char dis1[17];

unsigned long plu=0; //脉冲计数
float shunShiVal=0;		  //瞬时流量
float leiJiVal=0;			  //累计流量
u16 ushunShiVal=0;		  //瞬时流量
u16 uleiJiVal=0;			  //累计流量
u16 leiJiWarn=50;			  //累计流量
u16 warn_flag=0;
u8 refresh=1;
u8 t_1s=0;

unsigned char dealLiuliang=0;	//流量处理

unsigned char i ;		

unsigned char setMan  = 1; //设置标志
unsigned char valCheckFlag  =0;//是否对比

u8 CheckKey(void);
u8 key;
u8 set=0;

extern u8 revData;


void key_handle(void)
{
	switch(key)
	{
		case 1:
		{
			buzzer = 0;
			delay_ms(50);
			buzzer = 1;
			while(key1==0);
			set++;
			if(set>=2)
				set=0;
			if(set==1)
			{
				Lcd_SetXY(14,0);
				Lcd_Write_Command(0x0f,1);//打开显示 无光标 光标闪烁
			}
			else
			{
				Lcd_SetXY(14,0);
				Lcd_Write_Command(0x0c,1);//打开显示 无光标 光标闪烁
			}
		}
		break;
		
		case 2:
		{
			buzzer = 0;
			delay_ms(50);
			buzzer = 1;
			while(key2==0);
			if(set==0)
			{
				leiJiVal=0.0;
			}
			else if(set==1)
			{
				leiJiWarn++;
				if(leiJiWarn>999)
					leiJiWarn=0;
				Lcd_SetXY(11,0);
				Lcd_Write_Data(leiJiWarn/100+0x30);
				Lcd_Write_Data(leiJiWarn%100/10+0x30);
				Lcd_Write_Data('.');
				Lcd_Write_Data(leiJiWarn%10+0x30);
				Lcd_SetXY(14,0);
				Lcd_Write_Command(0x0f,1);//打开显示 无光标 光标闪烁
				
			}
		}
		break;
		
		case 3:
		{
			buzzer = 0;
			delay_ms(50);
			buzzer = 1;
			while(key3==0);
			if(set==1)
			{
				if(leiJiWarn>0)
					leiJiWarn--;
				else
					leiJiWarn=999;
				Lcd_SetXY(11,0);
				Lcd_Write_Data(leiJiWarn/100+0x30);
				Lcd_Write_Data(leiJiWarn%100/10+0x30);
				Lcd_Write_Data('.');
				Lcd_Write_Data(leiJiWarn%10+0x30);
				Lcd_SetXY(14,0);
				Lcd_Write_Command(0x0f,1);//打开显示 无光标 光标闪烁
				
			}
		}
		break;
		
	}
	key=0;
}

int main(void)
 { 
  
	delay_init();	    	 //延时函数初始化	  
	uart_init(9600);	 	//串口初始化为9600
  TIM3_Int_Init(499,7199);//50ms 
 	NVIC_Configuration();	  
	LED_Init();		  		//初始化与LED连接的硬件接口
	KEY_Init();
 	EXTIX_Init();		//外部中断初始化

	Lcd_GPIO_init();  //初始化lcd引脚
	Lcd_Init();		  //初始化lcd屏幕
	 Lcd_Puts(0,0, "    WELCOME    ");
	relay = 0;buzzer = 0; //硬件动作下
	delay_ms(2000);
	relay = 1;buzzer = 1; //关闭
	while(1)
	{		
		key=CheckKey();//按键处理
		key_handle();
		APP_handle();
		if(disFlag==1)					//显示
		{
			disFlag = 0;	
			t_1s++;
			if(t_1s>10)
			{
				t_1s=0;
				APP_Update();
			}
			if(uleiJiVal>leiJiWarn)
			{
				if(warn_flag==0)
					warn_flag=1;
				relay = 0;
			}
			else
			{
				warn_flag=0;
				relay = 1;
			}
			
			if(warn_flag>0)
			{
				buzzer=warn_flag%2;
			}
			else
				buzzer=1;
			
			if(warn_flag>0)
				warn_flag++;

			dealLiuliang++;//处理数据
			if(dealLiuliang >= 5)//计数		
			{
				
				dealLiuliang =	0;		//定时发送数据清空					
				leiJiVal=leiJiVal+(float)plu*0.00315;	 //累计计算累计流量			
				plu = 0;//清空周期计数
				ushunShiVal=(u16)(shunShiVal*100);
				uleiJiVal=(u16)(leiJiVal*10);
			}			

			
			Lcd_Puts(0,1,(unsigned char*)"SJ:00.0L/s  "); 		//显示			
			Lcd_SetXY(3,1);
			Lcd_Write_Data(ushunShiVal/100+0x30);
			Lcd_Write_Data('.');
			Lcd_Write_Data(ushunShiVal%100/10+0x30);
			Lcd_Write_Data(ushunShiVal%10+0x30);
			Lcd_Puts(7,1,(unsigned char*)"L/s  "); 		//显示 
			
			
			Lcd_Puts(0,0,(unsigned char*)"LJ:"); 		//显示 
			Lcd_SetXY(3,0);
			if((uleiJiVal/100)>0)
				Lcd_Write_Data(uleiJiVal/100+0x30);
			else
				Lcd_Write_Data(' ');
			
			Lcd_Write_Data(uleiJiVal%100/10+0x30);
			Lcd_Write_Data('.');
			Lcd_Write_Data(uleiJiVal%10+0x30);
			Lcd_Puts(7,0,(unsigned char*)"L S:"); 		//显示 
			
			
			if(set==0)
			{
				Lcd_SetXY(11,0);
				Lcd_Write_Data(leiJiWarn/100+0x30);
				Lcd_Write_Data(leiJiWarn%100/10+0x30);
				Lcd_Write_Data('.');
				Lcd_Write_Data(leiJiWarn%10+0x30);
				Lcd_Write_Data('L');
			}
			else
			{
				Lcd_SetXY(14,0);
				Lcd_Write_Command(0x0f,1);//打开显示 无光标 光标闪烁
			}
				
		}	
	}											    
}	
 

u8 CheckKey(void)
{ 
	unsigned  char rekey=0;
	if((key1==0)||(key2==0)||(key3==0))		 //检测到按键按下
	{
		delay_ms(10);   //小抖动
		if(rekey==0)
		{
			if(key1==0)    //检测是否按下
			{
				rekey=1;
			}	
			else if(key2==0)//设置值键
			{
				rekey=2;
			}
			else if(key3==0)//设置值键
			{
				rekey=3;	
			}				
		}
	}
	else
	{
		rekey=0;    //防止重复检测到按键
	}
	
	return rekey;
}

资料

### YF-S201C 霍尔流传感器与 STM32 的使用 #### 硬件连接说明 YF-S201C 是一种基于霍尔效应的流传感器,其工作原理是通过检测流引起的磁性变化来计算流速。当将其应用于 STM32 平台时,硬件接线需注意电源电压范围以及信号输入端口的选择。 以下是典型的接线方式: | **YF-S201C 引脚** | **功能描述** | **STM32 对应引脚** | |---------------------|--------------------|----------------------| | GND | 地 | GND | | VCC | 供电 (建议 5V) | 5V | | OUT | 脉冲输出 | GPIO 输入引脚 | OUT 引脚会输出脉宽调制 (PWM) 信号,频率与流速度成正比。为了读取该信号,可以配置 STM32 的外部中断或定时器捕获模式[^1]。 --- #### 示例代码:STM32 流量检测程序 以下是一个简单的 STM32 示例代码,用于读取 YF-S201C 输出的 PWM 信号并计算瞬时流量: ```c #include "stm32f1xx_hal.h" TIM_HandleTypeDef htim2; void SystemClock_Config(void); static void MX_GPIO_Init(void); static void MX_TIM2_Init(void); int main(void) { HAL_Init(); SystemClock_Config(); MX_GPIO_Init(); MX_TIM2_Init(); uint32_t frequency = 0; float waterFlowRate = 0.0; while (1) { __HAL_TIM_SET_COUNTER(&htim2, 0); // 清零计数器 HAL_Delay(1000); // 延迟一秒以获取稳定的频率数据 frequency = __HAL_TIM_GET_COUNTER(&htim2); // 获取当前计数值 // 计算流量(单位 L/min) waterFlowRate = ((float)frequency / 7.5) * 60; printf("Water Flow Rate: %.2f L/min\r\n", waterFlowRate); } } // 定时器初始化函数 static void MX_TIM2_Init(void) { TIM_ClockConfigTypeDef sClockSourceConfig = {0}; TIM_SlaveConfigTypeDef sSlaveConfig = {0}; TIM_MasterConfigTypeDef sMasterConfig = {0}; htim2.Instance = TIM2; htim2.Init.Prescaler = 84 - 1; // 设置预分频系数为 84MHz/84=1MHz htim2.Init.CounterMode = TIM_COUNTERMODE_UP; htim2.Init.Period = 65535; // 自动重装载值设为最大 htim2.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1; if (HAL_TIM_Base_Init(&htim2) != HAL_OK) { Error_Handler(); } sClockSourceConfig.ClockSource = TIM_CLOCKSOURCE_INTERNAL; if (HAL_TIM_ConfigClockSource(&htim2, &sClockSourceConfig) != HAL_OK) { Error_Handler(); } if (HAL_TIM_PWM_Init(&htim2) != HAL_OK) { Error_Handler(); } sSlaveConfig.SlaveMode = TIM_SLAVEMODE_RESET; sSlaveConfig.InputTrigger = TIM_TS_ITR0; if (HAL_TIM_SlaveConfigSynchronization(&htim2, &sSlaveConfig) != HAL_OK) { Error_Handler(); } sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET; if (HAL_TIMEx_MasterConfigSynchronization(&htim2, &sMasterConfig) != HAL_OK) { Error_Handler(); } } ``` 此代码利用了 STM32 的定时器模块捕捉来自 YF-S201C 的脉冲信号,并通过公式 `flow rate = pulses per second / 7.5` 来计算瞬时流量[^2]。 --- #### 注意事项 - **电源适配**:确保 STM32 和 YF-S201C 工作在同一电压范围内(通常是 5V)。如果两者不兼容,则需要增加电平转换电路。 - **抗干扰设计**:由于霍尔传感器容易受到电磁噪声的影响,在实际应用中可能需要加入滤波电容或其他屏蔽措施。 - **软件优化**:对于高精度需求场景,可进一步改进算法以减少误差,比如采用滑动平均法过滤异常值。 ---
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值