1. 项目概述
这个基于STM32单片机的非接触式感应水龙头控制系统,是我最近完成的一个嵌入式硬件项目。它通过超声波传感器实现无接触控制,结合温湿度检测功能,模拟了公共场所常见的智能水龙头工作模式。整个系统在Proteus环境下完成了仿真验证,硬件部分采用STM32F103C8T6作为主控,搭配LCD1602显示屏、DHT11温湿度传感器、HC-SR04超声波模块和直流电机(模拟水龙头开关)。
提示:在实际应用中,这种非接触式控制不仅更加卫生,还能有效节约用水,特别适合医院、餐厅等公共场所。
2. 系统设计与核心组件
2.1 硬件架构解析
系统硬件架构采用模块化设计思路,各功能模块通过STM32的GPIO和定时器资源进行连接和控制:
-
主控模块:STM32F103C8T6最小系统板,72MHz主频,64KB Flash,20KB RAM,完全满足本项目的性能需求。我选择这款芯片是因为它性价比高,资源丰富,且开发工具链成熟。
-
显示模块:LCD1602字符型液晶,采用4位数据线连接方式,节省了GPIO资源。显示内容分为两行:
- 第一行显示温度(T=XX℃)和设置距离(SET=XXmm)
- 第二行显示实际测量距离(DIS=XXmm)
-
传感模块:
- HC-SR04超声波测距模块:测量范围2-400cm,精度3mm
- DHT11温湿度传感器:测量范围0-50℃(温度),20-90%RH(湿度)
-
执行机构:小型直流电机模拟水龙头开关,实际应用中可替换为电磁阀。
2.2 关键电路设计要点
在Proteus仿真中,有几个电路连接细节需要特别注意:
-
超声波模块接口:
- Trig引脚连接PA0(TIM2_CH1)
- Echo引脚连接PA1(TIM2_CH2)
- 这种连接方式可以利用STM32的输入捕获功能精确测量回波时间
-
LCD1602接线优化:
c复制GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8|GPIO_Pin_9|GPIO_Pin_10|GPIO_Pin_11|GPIO_Pin_12|GPIO_Pin_13|GPIO_Pin_14|GPIO_Pin_15;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_OD;
GPIO_Init(GPIOA, &GPIO_InitStructure);
这里使用了开漏输出模式,因为LCD1602的数据接口需要双向通信能力。
- 电机驱动电路:
- 仿真中使用了一个NPN三极管驱动电机
- 实际硬件建议使用光耦隔离+MOSFET的方案,提高抗干扰能力
3. 软件实现与核心算法
3.1 主程序流程设计
系统软件采用轮询式架构,主循环中依次处理各个功能模块:
c复制while(1) {
// 1. 读取温湿度数据
if(DHT11_Read_TempAndHumidity(&DHT11_Data) == SUCCESS) {
// 更新温度显示
}
// 2. 超声波测距
UltrasonicWave_StartMeasure();
// 更新距离显示
// 3. 检查距离阈值
if(UltrasonicWave_Distance%256 < set) {
GPIO_ResetBits(GPIOB,GPIO_Pin_5); // 打开电机
} else {
GPIO_SetBits(GPIOB,GPIO_Pin_5); // 关闭电机
}
// 4. 处理按键输入
if(key1 == 1) set++; // 增加阈值
if(key2 == 1) set--; // 减少阈值
}
3.2 超声波测距算法优化
超声波测距的精度直接影响系统性能,我采用了以下优化措施:
- 定时器输入捕获:使用TIM2的输入捕获功能测量回波时间
c复制void TIM2_Configuration(void) {
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
TIM_ICInitTypeDef TIM_ICInitStructure;
// 定时器基础配置
TIM_TimeBaseStructure.TIM_Period = 0xFFFF;
TIM_TimeBaseStructure.TIM_Prescaler = 72-1; // 1MHz计数频率
TIM_TimeBaseStructure.TIM_ClockDivision = 0;
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure);
// 输入捕获配置
TIM_ICInitStructure.TIM_Channel = TIM_Channel_1;
TIM_ICInitStructure.TIM_ICPolarity = TIM_ICPolarity_Rising;
TIM_ICInitStructure.TIM_ICSelection = TIM_ICSelection_DirectTI;
TIM_ICInitStructure.TIM_ICPrescaler = TIM_ICPSC_DIV1;
TIM_ICInitStructure.TIM_ICFilter = 0x0;
TIM_ICInit(TIM2, &TIM_ICInitStructure);
TIM_Cmd(TIM2, ENABLE);
}
-
多次测量取中值:在实际代码中,我进行了5次测量然后取中间值,有效滤除偶然误差。
-
温度补偿:声速受温度影响,根据DHT11测量的温度值对计算结果进行补偿:
声速 = 331.4 + 0.6×温度(℃) m/s
3.3 按键处理与阈值设置
系统通过两个独立按键调整感应距离阈值:
- 按键消抖处理:采用状态机方式实现软件消抖
c复制typedef enum {
KEY_STATE_RELEASE,
KEY_STATE_WAIT,
KEY_STATE_PRESS
} KeyState;
KeyState key1_state = KEY_STATE_RELEASE;
KeyState key2_state = KEY_STATE_RELEASE;
void Key_Process(void) {
// 按键1处理
switch(key1_state) {
case KEY_STATE_RELEASE:
if(KEY1_READ() == 0) {
key1_state = KEY_STATE_WAIT;
key1_tick = GetTick();
}
break;
case KEY_STATE_WAIT:
if(GetTick() - key1_tick > 20) { // 20ms消抖
if(KEY1_READ() == 0) {
key1_state = KEY_STATE_PRESS;
set++; // 阈值增加
if(set > 99) set = 99;
} else {
key1_state = KEY_STATE_RELEASE;
}
}
break;
case KEY_STATE_PRESS:
if(KEY1_READ() == 1) {
key1_state = KEY_STATE_RELEASE;
}
break;
}
// 按键2处理类似...
}
- 阈值范围限制:将设置值限制在1-99mm之间,防止溢出
4. Proteus仿真要点
4.1 仿真环境搭建
在Proteus中搭建这个仿真项目时,有几个关键点需要注意:
-
元件选择:
- STM32F103C8:Cortex-M3内核MCU
- LCD1602:字符型液晶显示器
- HC-SR04:超声波测距模块
- DHT11:温湿度传感器
- MOTOR:直流电机模型
-
时钟配置:
- 在STM32属性中设置HCLK=72MHz
- SysTick定时器配置为1us中断一次
-
超声波模块参数:
- 声速设置为340m/s(25℃时)
- 最大测量距离设置为4m
4.2 常见仿真问题排查
-
LCD不显示:
- 检查对比度调节电压(通常需要可调电阻)
- 确认初始化时序正确,特别是EN使能信号的脉冲宽度
-
超声波测距不准确:
- 检查Trig信号脉冲宽度(至少10us)
- 确认Echo信号连接到了具有输入捕获功能的引脚
- 调整声速参数匹配当前环境温度
-
DHT11读取失败:
- 检查数据线是否上拉(通常需要4.7kΩ上拉电阻)
- 确保时序严格符合手册要求,特别是起始信号
5. 实际应用与扩展
5.1 从仿真到实物的注意事项
将仿真项目转化为实际硬件时,需要考虑以下差异:
-
电源设计:
- 添加适当的去耦电容(每个电源引脚0.1μF)
- 电机电源与MCU电源建议分开供电
-
信号完整性:
- 超声波模块信号线建议使用双绞线
- 长距离传输时考虑添加终端匹配电阻
-
EMC设计:
- 电机回路添加续流二极管
- 敏感信号线远离高频噪声源
5.2 功能扩展建议
这个基础框架可以进一步扩展:
-
流量统计功能:
- 添加霍尔流量传感器
- 实现用水量统计和显示
-
节能模式:
- 增加红外人体感应
- 无人时自动进入低功耗状态
-
无线控制:
- 集成蓝牙或WiFi模块
- 实现手机APP远程监控
-
水质监测:
- 增加TDS传感器
- 显示水质指标
6. 开发经验分享
在完成这个项目的过程中,我积累了一些值得分享的经验:
-
调试技巧:
- 使用STM32的SWD接口进行在线调试
- 利用串口打印调试信息(项目中已预留USART初始化代码)
-
性能优化:
- 将频繁调用的函数声明为inline
- 使用寄存器操作替代库函数提高速度
-
代码组织建议:
- 模块化编程,每个功能单独成文件
- 使用头文件定义接口和全局变量
-
常见问题预防:
- 在GPIO初始化后添加适当延时
- 对关键参数进行范围检查
- 添加看门狗防止程序跑飞
这个项目完整展示了从需求分析、方案设计、仿真验证到代码实现的嵌入式系统开发全流程。通过合理利用STM32的外设资源和优化算法,实现了稳定可靠的非接触控制功能。在实际应用中,还可以根据具体需求进行功能扩展和性能优化。
