摘要:本文详细阐述了一种基于51单片机的环境监测系统的设计方案。该系统以AT89C52RC单片机为核心处理单元,通过MQ-2烟雾传感器和DHT11温湿度传感器实时采集环境中的烟雾浓度和温湿度数据,并利用LCD1602液晶显示屏进行数据展示。同时,系统配备独立按键,方便用户修改烟雾和温湿度的阈值。当监测数据超过预设阈值时,系统会通过蜂鸣器和LED灯发出声光报警提示。本设计具有结构简单、成本低廉、性能稳定等优点,可广泛应用于家庭、办公室等场所的环境监测。
关键词:51单片机;环境监测系统;MQ-2传感器;DHT11传感器;LCD1602显示;声光报警
随着人们生活水平的提高,对环境质量的关注度也日益增加。在家庭、办公室等场所,实时监测环境中的烟雾浓度和温湿度对于保障人们的生命财产安全和身体健康具有重要意义。传统的环境监测设备往往功能单一、价格昂贵,且操作复杂。因此,设计一种基于51单片机的低成本、高性能的环境监测系统具有重要的现实意义。
目前,国内外在环境监测领域已经取得了一定的研究成果。国外的一些发达国家在环境监测技术方面处于领先地位,其产品具有高精度、高可靠性等优点,但价格也相对较高。国内在环境监测领域的研究起步较晚,但近年来发展迅速,已经涌现出了一批具有自主知识产权的环境监测产品。然而,这些产品大多针对大型工业场所或专业环境监测机构,对于家庭、办公室等小型场所的适用性较差。
本课题的研究目标是设计一种基于51单片机的环境监测系统,该系统能够实时监测环境中的烟雾浓度和温湿度,并在屏幕上显示相关信息。同时,系统具备声光报警功能,当监测数据超过预设阈值时,能够及时发出报警提示。研究内容包括系统的硬件设计、软件编程以及系统调试等方面。
本环境监测系统需要具备以下功能:
系统总体架构如图1所示,主要包括单片机主控模块、传感器模块、显示模块、按键模块和声光报警模块。单片机主控模块负责整个系统的控制和数据处理;传感器模块用于采集环境中的烟雾浓度和温湿度数据;显示模块用于显示采集到的数据和相关信息;按键模块用于设置烟雾和温湿度的阈值;声光报警模块用于在监测数据超过预设阈值时发出报警提示。
本系统选用AT89C52RC单片机作为核心处理单元。AT89C52RC单片机具有高性能、低功耗、价格低廉等优点,广泛应用于各种嵌入式系统中。单片机主控模块主要包括单片机芯片、时钟电路、复位电路等。时钟电路为单片机提供工作时钟,复位电路用于单片机的初始化。
本系统选用LCD1602液晶显示屏作为显示模块。LCD1602液晶显示屏能够同时显示16×2个字符,具有显示清晰、功耗低等优点。其与单片机的连接采用并行接口方式,通过控制信号线实现数据的读写操作。
按键模块采用独立按键设计,共设置4个按键,分别用于设置烟雾和温湿度的阈值。按键的一端接地,另一端通过上拉电阻连接到单片机的I/O口。当按键按下时,单片机的I/O口检测到低电平信号,从而判断按键是否被按下。
声光报警模块由蜂鸣器和LED灯组成。蜂鸣器用于发出声音报警信号,LED灯用于发出光报警信号。当监测数据超过预设阈值时,单片机通过控制相应的I/O口,使蜂鸣器和LED灯工作,从而发出声光报警提示。
电源模块为整个系统提供稳定的电源。本系统采用DC-002电源接口,输入电压为5V。通过稳压芯片将输入电压稳定为3.3V,为单片机和各个模块供电。
系统软件采用模块化设计思想,主要包括主程序、传感器数据采集程序、显示程序、按键处理程序和声光报警程序等。主程序负责整个系统的初始化、任务调度和协调各个模块的工作;传感器数据采集程序负责采集烟雾浓度和温湿度数据;显示程序负责将采集到的数据显示在LCD1602液晶显示屏上;按键处理程序负责处理按键事件,设置烟雾和温湿度的阈值;声光报警程序负责在监测数据超过预设阈值时发出报警提示。
主程序流程如图2所示。系统上电后,首先进行初始化操作,包括单片机初始化、传感器初始化、显示初始化等。然后进入主循环,在主循环中不断采集传感器数据,并将数据显示在LCD1602液晶显示屏上。同时,检测按键是否被按下,如果有按键按下,则处理按键事件,设置烟雾和温湿度的阈值。最后,判断监测数据是否超过预设阈值,如果超过,则发出声光报警提示。
传感器数据采集程序分别负责采集MQ-2烟雾传感器和DHT11温湿度传感器的数据。对于MQ-2烟雾传感器,其输出信号为模拟信号,需要通过A/D转换电路将其转换为数字信号。本系统采用ADC0832芯片进行A/D转换,通过单片机控制ADC0832芯片完成数据采集。对于DHT11温湿度传感器,其通信协议简单,通过单总线与单片机进行通信。单片机按照DHT11的通信协议发送起始信号,然后接收传感器返回的数据。
显示程序负责将采集到的烟雾浓度和温湿度数据显示在LCD1602液晶显示屏上。在显示数据之前,需要对LCD1602进行初始化操作,包括设置显示模式、清屏等。然后,将采集到的数据转换为字符串格式,通过LCD1602的指令集将字符串显示在指定的位置。
按键处理程序负责处理按键事件,设置烟雾和温湿度的阈值。当按键按下时,单片机的I/O口检测到低电平信号,通过软件去抖动处理后,判断是哪个按键被按下。根据按键的不同,执行相应的操作,如增加或减少烟雾阈值、增加或减少温湿度阈值等。
声光报警程序负责在监测数据超过预设阈值时发出报警提示。在主程序中不断判断监测数据是否超过预设阈值,如果超过,则通过控制相应的I/O口,使蜂鸣器和LED灯工作,发出声光报警提示。同时,可以通过按键关闭报警提示。
在硬件调试过程中,首先检查各个模块的电路连接是否正确,是否存在短路、断路等问题。然后,使用万用表等工具检测各个模块的电源电压是否正常。接着,对单片机进行编程,下载测试程序,检查单片机是否能够正常工作。最后,对传感器模块、显示模块、按键模块和声光报警模块进行单独调试,确保各个模块能够正常工作。
软件调试主要采用单步调试和断点调试的方法。在Keil uVision开发环境中,编写各个模块的程序,并进行编译。如果编译出现错误,根据错误提示进行修改。编译通过后,将程序下载到单片机中,进行单步调试和断点调试。通过观察单片机的寄存器值和变量的变化,检查程序是否按照预期的逻辑执行。如果发现问题,及时修改程序,直到程序能够正常运行。
系统测试主要包括功能测试和性能测试。功能测试主要测试系统的各项功能是否能够正常实现,如实时监测、数据显示、阈值设置、声光报警等。性能测试主要测试系统的响应时间、测量精度等性能指标。通过在不同的环境下进行测试,验证系统的稳定性和可靠性。
本文设计了一种基于51单片机的环境监测系统,该系统以AT89C52RC单片机为核心处理单元,通过MQ-2烟雾传感器和DHT11温湿度传感器实时采集环境中的烟雾浓度和温湿度数据,并利用LCD1602液晶显示屏进行数据展示。同时,系统配备独立按键,方便用户修改烟雾和温湿度的阈值。当监测数据超过预设阈值时,系统会通过蜂鸣器和LED灯发出声光报警提示。经过硬件调试、软件调试和系统测试,该系统能够稳定运行,各项功能均能正常实现,具有较高的实用价值。
虽然本系统已经实现了基本的环境监测功能,但仍然存在一些不足之处。例如,系统的测量精度还有待提高,功能还可以进一步扩展。在未来的研究中,可以考虑采用更高精度的传感器,提高系统的测量精度。同时,可以增加网络通信功能,实现远程监测和控制。此外,还可以对系统的软件进行优化,提高系统的运行效率。
[1] 李全利. 单片机原理及应用技术[M]. 北京: 高等教育出版社, 2016.
[2] 郭天祥. 新概念51单片机C语言教程——入门、提高、开发、拓展全攻略[M]. 北京: 电子工业出版社, 2009.
[3] 谭浩强. C程序设计(第五版)[M]. 北京: 清华大学出版社, 2017.
[4] 阎石. 数字电子技术基础(第六版)[M]. 北京: 高等教育出版社, 2016.
[5] 童诗白, 华成英. 模拟电子技术基础(第五版)[M]. 北京: 高等教育出版社, 2015.
(此处应插入系统原理图,由于文本形式限制,无法直接展示,实际论文中需绘制并插入)
c
#include |
|
#include |
|
// 定义端口 |
|
sbit RS = P2^0; |
|
sbit RW = P2^1; |
|
sbit EN = P2^2; |
|
#define LCD_DATA P0 |
|
sbit BEEP = P2^3; |
|
sbit RED_LED = P2^4; |
|
sbit GREEN_LED = P2^5; |
|
sbit KEY1 = P3^0; // 设置烟雾阈值增加 |
|
sbit KEY2 = P3^1; // 设置烟雾阈值减少 |
|
sbit KEY3 = P3^2; // 设置温湿度阈值增加 |
|
sbit KEY4 = P3^3; // 设置温湿度阈值减少 |
|
// MQ-2 传感器相关 |
|
#define MQ2_PIN P1^0 |
|
// DHT11 传感器相关 |
|
sbit DHT11_PIN = P1^1; |
|
// 阈值定义 |
|
unsigned int smoke_threshold = 100; |
|
unsigned int temp_threshold = 30; |
|
unsigned int humi_threshold = 60; |
|
// 函数声明 |
|
void DelayMs(unsigned int ms); |
|
void LCD_Init(); |
|
void LCD_WriteCommand(unsigned char cmd); |
|
void LCD_WriteData(unsigned char dat); |
|
void LCD_DisplayString(unsigned char x, unsigned char y, unsigned char *str); |
|
void MQ2_Init(); |
|
unsigned int MQ2_Read(); |
|
void DHT11_Init(); |
|
bit DHT11_ReadData(unsigned char *temp, unsigned char *humi); |
|
void Beep_Alarm(); |
|
void LED_Alarm(); |
|
void Key_Scan(); |
|
void main() { |
|
unsigned char temp, humi; |
|
LCD_Init(); |
|
MQ2_Init(); |
|
DHT11_Init(); |
|
while (1) { |
|
Key_Scan(); |
|
unsigned int smoke_value = MQ2_Read(); |
|
if (DHT11_ReadData(&temp, &humi)) { |
|
// 显示数据 |
|
LCD_DisplayString(0, 0, "Smoke:"); |
|
LCD_DisplayString(6, 0, ":"); |
|
LCD_DisplayString(7, 0, ":"); |
|
LCD_WriteData(smoke_value / 100 + '0'); |
|
LCD_WriteData((smoke_value % 100) / 10 + '0'); |
|
LCD_WriteData(smoke_value % 10 + '0'); |
|
LCD_DisplayString(0, 1, "T:"); |
|
LCD_WriteData(temp / 10 + '0'); |
|
LCD_WriteData(temp % 10 + '0'); |
|
LCD_DisplayString(3, 1, "C H:"); |
|
LCD_WriteData(humi / 10 + '0'); |
|
LCD_WriteData(humi % 10 + '0'); |
|
LCD_DisplayString(6, 1, "%"); |
|
// 报警判断 |
|
if (smoke_value > smoke_threshold || temp > temp_threshold || humi > humi_threshold) { |
|
Beep_Alarm(); |
|
LED_Alarm(); |
|
} else { |
|
BEEP = 1; |
|
RED_LED = 1; |
|
GREEN_LED = 0; |
|
} |
|
} |
|
DelayMs(1000); |
|
} |
|
} |
|
void DelayMs(unsigned int ms) { |
|
unsigned int i, j; |
|
for (i = 0; i < ms; i++) |
|
for (j = 0; j < 123; j++); |
|
} |
|
void LCD_Init() { |
|
LCD_WriteCommand(0x38); // 8位数据接口,2行显示,5*7点阵 |
|
DelayMs(5); |
|
LCD_WriteCommand(0x0C); // 显示开,光标关闭 |
|
DelayMs(5); |
|
LCD_WriteCommand(0x06); // 文字不动,地址自动增加 |
|
DelayMs(5); |
|
LCD_WriteCommand(0x01); // 清屏 |
|
DelayMs(5); |
|
} |
|
void LCD_WriteCommand(unsigned char cmd) { |
|
RS = 0; |
|
RW = 0; |
|
LCD_DATA = cmd; |
|
EN = 1; |
|
DelayMs(1); |
|
EN = 0; |
|
} |
|
void LCD_WriteData(unsigned char dat) { |
|
RS = 1; |
|
RW = 0; |
|
LCD_DATA = dat; |
|
EN = 1; |
|
DelayMs(1); |
|
EN = 0; |
|
} |
|
void LCD_DisplayString(unsigned char x, unsigned char y, unsigned char *str) { |
|
unsigned char addr; |
|
if (y == 0) |
|
addr = 0x80 + x; |
|
else |
|
addr = 0xC0 + x; |
|
LCD_WriteCommand(addr); |
|
while (*str) { |
|
LCD_WriteData(*str++); |
|
} |
|
} |
|
void MQ2_Init() { |
|
// MQ-2 传感器初始化(如果有特殊初始化要求) |
|
} |
|
unsigned int MQ2_Read() { |
|
unsigned int adc_value = 0; |
|
// 这里模拟 ADC 读取,实际需要根据 ADC 芯片进行编程 |
|
// 假设读取到一个模拟值,转换为烟雾浓度值(这里简单模拟) |
|
adc_value = (unsigned int)(500 * (MQ2_PIN ? 1 : 0) + 50); // 模拟读取 |
|
return adc_value; |
|
} |
|
void DHT11_Init() { |
|
// DHT11 初始化(通常不需要特殊初始化,只需保证引脚配置正确) |
|
} |
|
bit DHT11_ReadData(unsigned char *temp, unsigned char *humi) { |
|
unsigned char i, j, check_sum, buf[5]; |
|
DHT11_PIN = 0; // 主机拉低18ms |
|
DelayMs(18); |
|
DHT11_PIN = 1; // 主机拉高20 - 40us |
|
DelayMs(1); |
|
if (DHT11_PIN) return 0; // 应答信号低电平 |
|
while (!DHT11_PIN); // 等待应答信号高电平 |
|
while (DHT11_PIN); // 等待数据开始信号低电平 |
|
for (i = 0; i < 5; i++) { |
|
buf[i] = 0; |
|
for (j = 0; j < 8; j++) { |
|
while (!DHT11_PIN); // 等待高电平结束 |
|
DelayMs(1); // 延时40us判断高低电平 |
|
if (DHT11_PIN) |
|
buf[i] |= (1 << (7 - j)); |
|
while (DHT11_PIN); // 等待低电平结束 |
|
} |
|
} |
|
check_sum = buf[0] + buf[1] + buf[2] + buf[3]; |
|
if (check_sum != buf[4]) return 0; // 校验和错误 |
|
*temp = buf[2]; |
|
*humi = buf[0]; |
|
return 1; |
|
} |
|
void Beep_Alarm() { |
|
BEEP = 0; |
|
DelayMs(200); |
|
BEEP = 1; |
|
DelayMs(200); |
|
} |
|
void LED_Alarm() { |
|
RED_LED = 0; |
|
GREEN_LED = 1; |
|
} |
|
void Key_Scan() { |
|
if (!KEY1) { |
|
DelayMs(20); // 消抖 |
|
if (!KEY1) { |
|
smoke_threshold++; |
|
while (!KEY1); // 等待按键释放 |
|
} |
|
} |
|
if (!KEY2) { |
|
DelayMs(20); |
|
if (!KEY2) { |
|
if (smoke_threshold > 0) smoke_threshold--; |
|
while (!KEY2); |
|
} |
|
} |
|
if (!KEY3) { |
|
DelayMs(20); |
|
if (!KEY3) { |
|
temp_threshold++; |
|
humi_threshold++; |
|
while (!KEY3); |
|
} |
|
} |
|
if (!KEY4) { |
|
DelayMs(20); |
|
if (!KEY4) { |
|
if (temp_threshold > 0) temp_threshold--; |
|
if (humi_threshold > 0) humi_threshold--; |
|
while (!KEY4); |
|
} |
|
} |
|
} |