00 读题
试设计一个基于51单片机的烟雾浓度值检测系统,使之能提供以下功能:
- 用51单片机做控制芯片,用MQ-2模块来实现烟雾浓度值的检测;
- 烟雾浓度值通过计算后,要能够准确的显示在LCD1602上面;
- 当浓度值过高时蜂鸣器开启报警通知,同时直流电机开始转动来模拟空气排放;
- 具有创新功能的可适当加分。
01 分析
1. 系统组成
-
主控制单元:SCT89C52单片机
- 51系列单片机,主要负责整个系统的控制和数据处理。
-
气体检测单元:MQ-2传感器
- MQ-2传感器用于检测烟雾或可燃气体的浓度,使用串口通信。
-
显示单元:LCD1602
- 用于实时显示气体浓度的值。
-
报警单元:蜂鸣器
- 当气体浓度超过预设阈值时,蜂鸣器发出声音报警。
-
空气排放模拟单元:步进电机
- 当气体浓度超标时,步进电机开始转动,模拟空气排放。
02 系统框架
-
传感器数据采集:
- MQ-2传感器通过串口收发将浓度信号送入单片机
-
数据处理与显示:
- 单片机对MQ-2传感器的数据进行处理,将16进制信号转换为十进制信号后通过算法计算气体浓度。
- 根据计算的浓度值,单片机驱动LCD1602显示气体浓度。
-
报警与控制:
- 单片机根据设定的阈值判断气体浓度是否超标。如果超标,激活蜂鸣器报警。
- 同时,控制步进电机转动,通过空气排放来模拟处理气体的功能。
-
控制逻辑:
- 系统的控制逻辑包括数据采集、浓度计算、显示、报警和排放模拟等功能。系统需要定期检查光照强度,判断是否启用报警功能。
03. 硬件设计
3.1 单片机部分(SCT89C52)
SCT89C52是一个8位单片机,具备丰富的I/O口,可以很好地实现对MQ-2、LCD1602、蜂鸣器和步进电机的控制。
-
IO引脚分配:
- P1.0 - P1.3:用于控制步进电机
- P3.0:连接MQ-2传感器的TXD。
- P3.1:连接MQ-2传感器的RXD。
- P0.2 - P0.4:连接LCD1602的读写控制脚
- P2.0 - P2.7:连接LCD1602的数据教
- P0.7:连接蜂鸣器。
03. 软件设计
-
MQ-2传感器:
#include <reg52.h>
#include <intrins.h>
#include "delay.h"
static unsigned char Send_Byte[9] = {0xFF, 0x01, 0x86, 0, 0, 0, 0, 0, 0x79};
static unsigned char Recv_Byte[9] = { 0 }, index = 0, flag = 0, time_out = 0;
//初始化串口
void MQ2_Init(void)
{
SCON = 0x50; //设置为工作方式1
PCON &= 0x7F; //SMOD=0,波特率不加倍
TMOD = 0x20; //设置计数器工作方式2
TH1 = 0xFD; //计数器初始值设置,波特率是9600的
TL1 = 0xFD;
ES = 1; //打开接收中断
EA = 1; //打开总中断
TR1 = 1; //定时器1开始工作
}
//获取烟雾浓度的函数
int MQ2_Get(void)
{
unsigned char i = 0;
for(i = 0; i < 9; i++)
{
SBUF = Send_Byte[i];
while(TI == 0);//等待发送完成
TI = 0;
}
time_out = 2;
while(!flag && time_out++)//等待接收数据
delay_ms(10);
if(time_out == 1)
return 0; //超时返回0
return Recv_Byte[2] * 256 + Recv_Byte[3];
}
//中断代码
void UART_Routine(void) interrupt 4
{
if(RI == 1)
{
Recv_Byte[index++] = SBUF;
if(Recv_Byte[0] != 0xFF)
{
index = 0;
RI = 0;
return;
}
if(index == 9)
{
index = 0;
flag = 1;
}
RI = 0;
}
}
-
步进电机控制:
* 步进电机启动函数,angle-需转过的角度 */
void StartMotor(signed long angle)
{
//在计算前关闭中断,完成后再打开,以避免中断打断计算过程而造成错误
EA = 0;
beats = -(angle * 4076) / 360; //实测为4076拍转动一圈
EA = 1;
}
/* 步进电机停止函数 */
void StopMotor()
{
EA = 0;
beats = 0;
EA = 1;
}
/* 电机转动控制函数 */
void TurnMotor()
{
unsigned char tmp; //临时变量
static unsigned char index = 0; //节拍输出索引
unsigned char code BeatCode[8] = { //步进电机节拍对应的IO控制代码
0x1, 0x3, 0x2, 0x6, 0x4, 0xc, 0x7, 0x8
};
if (beats != 0) //节拍数不为0则产生一个驱动节拍
{
if (beats > 0) //节拍数大于0时正转
{
index++; //正转时节拍输出索引递增
index = index & 0x07; //用&操作实现到8归零
beats--; //正转时节拍计数递减
}
else //节拍数小于0时反转
{
index--; //反转时节拍输出索引递减
index = index & 0x07; //用&操作同样可以实现到-1时归7
beats++; //反转时节拍计数递增
}
tmp = P_Motor; //用tmp把P_Motor口当前值暂存
tmp = tmp & 0xF0; //用&操作清零低4位
tmp = tmp | BeatCode[index]; //用|操作把节拍代码写到低4位
P_Motor = tmp; //把低4位的节拍代码和高4位的原值送回P_Motor
}
else //节拍数为0则关闭电机所有的相
{
P_Motor = P_Motor | 0x00;
}
}
-
蜂鸣器控制:
- 通过P0.7口输出控制蜂鸣器开关,当气体浓度超标时,蜂鸣器会发出警报。
smog = MQ2_Get( );
LCD_ShowNum(8,1,smog,3);
if( (smog >=smog_limen )&(mode!=10) )
{
BuzzPlay(200);//蜂鸣器响400ms
mode=10;
}else if( smog <=smog_limen )
{
mode=0;//待改
}
-
LCD1602显示部分
LcdShowStr(1,1,"Smoke:",6);//LCD_ShowHexNum(0,0,id,16);//LCD_ShowNum
……………………………………………………………………………………
LCD_ShowNum(8,1,smog,3);
如果需要指导帮助,可以添加我的QQ或者加入我的新建的交流群
2796920378