基于 STM32 的智能水表流量计设计与实现 —— 数据采集与远程传输
一、引言
随着智慧水务的发展,传统机械水表因计量精度低、抄表效率差等问题逐渐被智能水表取代。基于 STM32 的智能水表流量计通过嵌入式技术实现水流数据的实时采集、计算、存储与远程传输,可满足居民用水计量、漏损监测等需求。本文详细介绍其硬件选型、接线设计、软件流程及核心代码。
二、硬件设计
2.1 核心芯片与模块选型
(1)主控制器
选用STM32F103C8T6(ARM Cortex-M3 内核,72MHz 主频,64KB Flash,20KB RAM),具备丰富的 GPIO、UART、I²C 等接口,满足低功耗与数据处理需求。
(2)流量检测模块
选用YF-S201 霍尔水流传感器,通过水流推动涡轮转动切割磁场产生脉冲信号,脉冲频率与流量成正比(量程 1-30L/min,精度 ±5%)。
(3)显示模块
选用0.96 寸 OLED 屏(I²C 接口),用于显示瞬时流量、累计流量及设备状态,功耗低且显示清晰。
(4)数据存储模块
选用AT24C02(I²C 接口,2KB EEPROM),用于掉电保存累计流量数据,防止数据丢失。
(5)远程传输模块
选用NBIoT 模块(BC26),通过 UART 接口与 STM32 通信,实现数据远程上传至云平台。
(6)辅助模块
- 电源模块:AMS1117-3.3V(将 5V 输入转为 3.3V 给系统供电);
- 报警模块:有源蜂鸣器(用于异常流量报警)。
2.2 硬件接线设计
| 模块 | 接口 | STM32 引脚 | 功能说明 |
|---|---|---|---|
| YF-S201 | 脉冲输出 | PA0 | 外部中断触发,计数脉冲 |
| OLED | SDA | PB7 | I²C 数据线 |
| SCL | PB6 | I²C 时钟线 | |
| AT24C02 | SDA | PB7 | 与 OLED 共用 I²C 总线 |
| SCL | PB6 | 与 OLED 共用 I²C 总线 | |
| BC26(NBIoT) | TX | PA3 | UART 接收(STM32 的 USART2_RX) |
| RX | PA2 | UART 发送(STM32 的 USART2_TX) | |
| 蜂鸣器 | 控制端 | PC13 | 低电平触发报警 |
| 电源 | VCC/GND | 3.3V/GND | 系统供电 |
接线说明:
- 霍尔传感器的 VCC 接 5V(内部包含稳压电路),GND 接系统地;
- I²C 设备通过上拉电阻(4.7kΩ)接 3.3V,确保通信稳定;
- NBIoT 模块需外接 SIM 卡和天线,独立 5V 供电。
三、软件设计
3.1 软件流程图
(1)主程序流程图

(2)流量计算子流程图

3.2 核心代码实现
(1)初始化代码(GPIO、中断、I²C、UART)
#include "stm32f10x.h"
#include "oled.h"
#include "at24c02.h"
#include "nbiot.h"// 全局变量
uint32_t pulse_count = 0; // 脉冲计数器
float instant_flow = 0.0f; // 瞬时流量(L/min)
float total_flow = 0.0f; // 累计流量(m³)
uint8_t timer_flag = 0; // 1s定时标志void RCC_Configuration(void) {RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_GPIOB | RCC_APB2Periph_GPIOC | RCC_APB2Periph_AFIO, ENABLE);RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2 | RCC_APB1Periph_TIM2, ENABLE);
}// 霍尔传感器中断初始化(PA0,上升沿触发)
void EXTI_Configuration(void) {GPIO_InitTypeDef GPIO_InitStructure;EXTI_InitTypeDef EXTI_InitStructure;NVIC_InitTypeDef NVIC_InitStructure;GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU; // 上拉输入GPIO_Init(GPIOA, &GPIO_InitStructure);GPIO_EXTILineConfig(GPIO_PortSourceGPIOA, GPIO_PinSource0);EXTI_InitStructure.EXTI_Line = EXTI_Line0;EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Rising;EXTI_InitStructure.EXTI_LineCmd = ENABLE;EXTI_Init(&EXTI_InitStructure);NVIC_InitStructure.NVIC_IRQChannel = EXTI0_IRQn;NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x01;NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x01;NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;NVIC_Init(&NVIC_InitStructure);
}// 定时器2初始化(1s定时)
void TIM2_Configuration(void) {TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;NVIC_InitTypeDef NVIC_InitStructure;TIM_TimeBaseStructure.TIM_Period = 72000 - 1; // 72MHz / 1000 = 72000,1sTIM_TimeBaseStructure.TIM_Prescaler = 1000 - 1;TIM_TimeBaseStructure.TIM_ClockDivision = 0;TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure);TIM_ITConfig(TIM2, TIM_IT_Update, ENABLE);TIM_Cmd(TIM2, ENABLE);NVIC_InitStructure.NVIC_IRQChannel = TIM2_IRQn;NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x02;NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x02;NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;NVIC_Init(&NVIC_InitStructure);
}void System_Init(void) {RCC_Configuration();GPIO_Configuration(); // 初始化OLED、蜂鸣器等GPIOEXTI_Configuration();TIM2_Configuration();I2C_Configuration(); // 初始化I²C(OLED和AT24C02)USART2_Configuration();// 初始化UART(NBIoT)OLED_Init();AT24C02_Init();NBIoT_Init();
}
(2)中断服务函数(脉冲计数与定时)
// 霍尔传感器脉冲中断(计数)
void EXTI0_IRQHandler(void) {if (EXTI_GetITStatus(EXTI_Line0) != RESET) {pulse_count++; // 每收到一个脉冲,计数器加1EXTI_ClearITPendingBit(EXTI_Line0);}
}// 定时器2中断(1s定时,计算流量)
void TIM2_IRQHandler(void) {if (TIM_GetITStatus(TIM2, TIM_IT_Update) != RESET) {timer_flag = 1; // 置位1s标志// 计算瞬时流量:YF-S201每升水产生7.5个脉冲,1s脉冲数换算为L/mininstant_flow = (pulse_count * 60.0f) / 7.5f;// 累计流量:1L = 0.001m³,1s流量累加total_flow += instant_flow * (1.0f / 60.0f) * 0.001f;pulse_count = 0; // 清零计数器TIM_ClearITPendingBit(TIM2, TIM_IT_Update);}
}
(3)主函数(数据处理与传输)
int main(void) {uint32_t save_cnt = 0; // 保存数据计数器(30s)uint32_t upload_cnt = 0; // 上传数据计数器(5min=300s)System_Init();total_flow = AT24C02_ReadFloat(0x00); // 从EEPROM读取累计流量while (1) {if (timer_flag) { // 每1s执行一次timer_flag = 0;// OLED显示OLED_ShowString(0, 0, "Flow: ");OLED_ShowFloat(50, 0, instant_flow, 2); // 瞬时流量(L/min)OLED_ShowString(0, 2, "Total: ");OLED_ShowFloat(50, 2, total_flow, 3); // 累计流量(m³)// 每30s保存累计流量到AT24C02if (++save_cnt >= 30) {AT24C02_WriteFloat(0x00, total_flow);save_cnt = 0;}// 每5min上传数据到云端if (++upload_cnt >= 300) {NBIoT_UploadData(instant_flow, total_flow);upload_cnt = 0;}// 异常流量报警(如瞬时流量>50L/min)if (instant_flow > 50.0f) {GPIO_ResetBits(GPIOC, GPIO_Pin_13); // 蜂鸣器报警Delay_Ms(10000);GPIO_SetBits(GPIOC, GPIO_Pin_13); // 关闭报警}}}
}
四、总结与展望
本文设计的基于 STM32 的智能水表流量计通过霍尔传感器实现流量采集,结合 STM32 的处理能力完成数据计算、存储与远程传输,具备计量精准、功耗低、可远程监控等特点。未来可优化方向:引入低功耗模式延长电池寿命,增加水质检测模块实现多参数监测,提升水务管理智能化水平。
