系统硬件设计
(末尾附文件) 整个系统以STC89C52单片机为核心器件,配合电阻电容晶振等器件,构成单片机的最小系统。其它个模块围绕着单片机最小系统展开。其中包括,温湿度传感器输采用DHT11温湿度一体的传感器,负责采集温度和湿度的数据后发给单片机;空气质量检测采用PM2.5传感器GP2Y1051AU0F,通过串口把检测结果发给单片机;按键部分使用市面上常见的轻触按键作为系统的输入设置模块;显示设备为1602液晶;报警则采用蜂鸣器+LED的形式;电源供电则采用USB 5V供电。
系统框图 原理图: 仿真图: ![在这里插入图片描述](https://img-blog.csdnimg.cn/20200801152536353.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl80NzUyODA2Ng==,size_16,color_FFFFFF,t_70)
DHT11传感器电路 3.3.1 DHT11简介 ◆相对湿度和温度测量 ◆全部校准,数字输出 ◆卓越的长期稳定性 ◆无需额外部件 ◆超长的信号传输距离 ◆超低能耗 ◆4 引脚安装 ◆完全互换 (1)DHT11产品概述 DHT11(图3-4)数字温湿度传感器是一款含有已校准数字信号输出的温湿度复合传感器。它应用专用的数字模块采集技术和温湿度传感技术,确保产品具有极高的可靠性与卓越的长期稳定性。传感器包括一个电阻式感湿元件和一个NTC测温元件,并与一个高性能8位单片机相连接。因此该产品具有品质卓越、超快响应、抗干扰能力强、性价比极高等优点。每个DHT11传感器都在极为精确的湿度校验室中进行校准。校准系数以程序的形式储存在OTP内存中,传感器内部在检测信号的处理过程中要调用这些校准系数。单线制串行接口,使系统集成变得简易快捷。超小的体积、极低的功耗,信号传输距离可达20米以上,使其成为各类应用甚至最为苛刻的应用场合的最佳选则。产品为 4 针单排引脚封装。连接方便,特殊封装形式可根据用户需求而提供。
接口说明 (1)接口说明 建议连接线长度短于20米时用5K上拉电阻,大于20米时根据实际情况使用合适的上拉电阻。 PM2.5传感器模块 3.4.1 简介 日本夏普公司灰尘传感器GP2Y1051AU0F,体积小巧,灵敏度高,可以用来测量0.03微米以上的微小粒子,可用于室内环境中烟气、粉尘、花粉等浓度的检测。此款产品不但可以检测出单位体积粒子的绝对个数,而且内置气流发生器,可以自行吸入外部空气。灰尘传感器GP2Y1051AU0F安装保养方便,使用寿命长,精度高,稳定性好。其内部对角安放着红外线发光二极管和光电晶体管,使得其能够探测到空气中尘埃反射光,即使非常细小的如烟草烟雾颗粒也能够被检测到,通常在空气净化系统中应用。 3.4.2 原理说明 GP2Y1051AU0F的结构示意图如图3-11所示。首先由LED光源发射出光线,沿着LED光轴方向射出,如果空气洁净的情况下,光电二极管PD是收不到LED发出的光线的,因此输出的电压值很低。而如果空气中存在有灰尘颗粒,当这些灰尘颗粒通过传感器中间的圆孔时,由于散射的原因,LED光源发出的光线就有一部分被光电二极管PD检测到,因此就有电压值输出,并且随着灰尘颗粒浓度的升高,散射的光线越多,传感器最终输出的电压值也就越高
按键输入模块 键盘是人与单片机打交道的主要设备。站在系统监控软件设计的立场上来看,仅仅完成键盘扫描,读取当前时刻的键盘状态是不够的,还有不少问题需要妥善解决,否则,人们在操作键盘就容易引起误操作和操作失控现象。在单片机应用中键盘用得最多的形式是独立键盘及矩阵键盘。它们各有自己的特点,其中独立键盘硬件电路简单,而且在程序设计上也不复杂,一般用在对硬件电路要求不高的简单电路中;矩阵键盘与独立键盘有很大区别,首先在硬件电路上它要比独立键盘复杂得多,而且在程序算法上比它要烦琐,但它在节省端口资源上有优势得多,因此它更适合于多按键电路。其次就是消除在按键过程中产生的“毛刺”现象。这里采用最常用的方法,即延时重复扫描法,延时法的原理为:因为“毛刺”脉冲一般持续时间短,约为几ms,而我们按键的时间一般远远大于这个时间,所以当单片机检测到有按键动静后再延时一段时间后再判断此电平是否保持原状态,如果是则为有效按键,否则无效。 本设计中由于采用的按键数量较少,只有3个按键,分别是“设置”、“减”、“加”,故采用了独立键盘的方式。按键的连接图3-17所示: ![在这里插入图片描述](https://img-blog.csdnimg.cn/20200801152326616.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl80NzUyODA2Ng==,size_16,color_FFFFFF,t_70)
程序设计
![在这里插入图片描述](https://img-blog.csdnimg.cn/2020080115245013.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl80NzUyODA2Ng==,size_16,color_FFFFFF,t_70)
#include
#include
#define uchar unsigned char // 以后unsigned char就可以用uchar代替
#define uint unsigned int // 以后unsigned int 就可以用uint 代替
sfr ISP_DATA = 0xe2; // 数据寄存器
sfr ISP_ADDRH = 0xe3; // 地址寄存器高八位
sfr ISP_ADDRL = 0xe4; // 地址寄存器低八位
sfr ISP_CMD = 0xe5; // 命令寄存器
sfr ISP_TRIG = 0xe6; // 命令触发寄存器
sfr ISP_CONTR = 0xe7; // 命令寄存器
sbit LcdRs_P = P1^2; // 1602液晶的RS管脚
sbit LcdRw_P = P1^3; // 1602液晶的RW管脚
sbit LcdEn_P = P1^4; // 1602液晶的EN管脚
sbit KeySet_P = P3^2; // “设置”按键的管脚
sbit KeyDown_P = P3^3; // “减”按键的管脚
sbit KeyUp_P = P3^4; // “加”按键的管脚
sbit Buzzer_P = P1^5; // 蜂鸣器
sbit DHT11_P = P1^1; // 温湿度传感器DHT11数据接入
sbit LedTH_P = P2^0; // 温度过高报警指示灯
sbit LedTL_P = P2^1; // 温度过低报警指示灯
sbit LedHH_P = P2^2; // 湿度过高报警指示灯
sbit LedHL_P = P2^3; // 湿度过低报警指示灯
sbit LedPM_P = P2^4; // PM2.5过高报警指示灯
uchar temp; // 保存温度
uchar humi; // 保存湿度
uint pm; // 保存PM2.5
uchar gIndex=0; // 串口接收索引
uint Value[20]={0}; // 串口数据缓存区
uchar AlarmTL; // 温度下限报警值
uchar AlarmTH; // 温度上限报警值
uchar AlarmHL; // 湿度下限报警值
uchar AlarmHH; // 湿度上限报警值
uint AlarmPM; // PM2.5报警值
/*********************************************************/
// 单片机内部EEPROM不使能
/*********************************************************/
void ISP_Disable()
{
ISP_CONTR = 0;
ISP_ADDRH = 0;
ISP_ADDRL = 0;
}
/*********************************************************/
// 从单片机内部EEPROM读一个字节,从0x2000地址开始
/*********************************************************/
unsigned char EEPROM_Read(unsigned int add)
{
ISP_DATA = 0x00;
ISP_CONTR = 0x83;
ISP_CMD = 0x01;
ISP_ADDRH = (unsigned char)(add>>8);
ISP_ADDRL = (unsigned char)(add&0xff);
// 对STC89C51系列来说,每次要写入0x46,再写入0xB9,ISP/IAP才会生效
ISP_TRIG = 0x46;
ISP_TRIG = 0xB9;
_nop_();
ISP_Disable();
return (ISP_DATA);
}
/*********************************************************/
// 往单片机内部EEPROM写一个字节,从0x2000地址开始
/*********************************************************/
void EEPROM_Write(unsigned int add,unsigned char ch)
{
ISP_CONTR = 0x83;
ISP_CMD = 0x02;
ISP_ADDRH = (unsigned char)(add>>8);
ISP_ADDRL = (unsigned char)(add&0xff);
ISP_DATA = ch;
ISP_TRIG = 0x46;
ISP_TRIG = 0xB9;
_nop_();
ISP_Disable();
}
/*********************************************************/
// 擦除单片机内部EEPROM的一个扇区
// 写8个扇区中随便一个的地址,便擦除该扇区,写入前要先擦除
/*********************************************************/
void Sector_Erase(unsigned int add)
{
ISP_CONTR = 0x83;
ISP_CMD = 0x03;
ISP_ADDRH = (unsigned char)(add>>8);
ISP_ADDRL = (unsigned char)(add&0xff);
ISP_TRIG = 0x46;
ISP_TRIG = 0xB9;
_nop_();
ISP_Disable();
}
/*********************************************************/
// 毫秒级的延时函数,time是要延时的毫秒数
/*********************************************************/
void DelayMs(uint time)
{
uint i,j;
for(i=0;i100)) // 如果温度上限报警值读出来异常(等于0或大于100),则重新赋值
AlarmHH=85;
if((AlarmPM==0)||(AlarmPM>1300)) // 如果读取到的报警值异常,则重新赋值
AlarmPM=200;
}
/*********************************************************/
// 主函数
/*********************************************************/
void main(void)
{
uchar i; // 循环变量
uint ret; // 保存PM2.5测量结果
LcdInit(); // 液晶功能初始化
LcdShowInit(); // 液晶显示初始化
UartInit(); // 串口初始化
AlarmInit(); // 报警值初始化
while(1)
{
/*PM2.5的读取*/
ret=0; // 清零测量结果
for(i=0;i |