基于C51单片机的烟雾检测系统 设计与实现
天师–大三期末大作业
A/D转换器即实现模拟信号到数字信号的转换,一定要注意周期,即ClK的变化,每一个上升沿会读取次内容
LCD1602显示器即通过7–14位管脚进行内容设置,注意:可以了解图的显示,它是按照坐标形式设置内容(可以搜索查看下),只能显示英文字符
烟雾传感器用滑动变阻器代替,因为protetus中没有MQ-2烟雾感应器,因此用滑动变阻器代替
大作业思路:A/D转换器,每个上升沿会读取内容,同时LCD显示器主要思路类似于计算机组成原理中的数据显示,可以学习下,B站有挺多网课
#include <reg51.h>//包含51单片机寄存器的头文件
#include <wyb.h>//
#include <intrins.h>
#define uchar unsigned char
#define uint unsigned int
//ADC0832引脚定义
sbit CS = P1^0;//片选使能位,定义为P1^0引脚
sbit CLK = P1^1;//时钟脉冲输入位,定义为P1^1引脚
sbit DIO = P1^2;//数据信号输入/输出,并联使用。定义为P1^2引脚
//有害气体含量变量
uchar temp; //用于读取ADC数据
uchar yushe_yanwu= 230; //烟雾预设值7
//按钮模式
uchar mode=0;
//管脚声明
sbit led_yanwu= P2^3; //烟雾报警灯
sbit baojing= P2^4; //蜂鸣器接口
//按键
sbit key1=P2^5; //设置键
sbit key2=P2^6; //加按键
sbit key3=P2^7; //减按键
//1毫秒延时程序(不精确)
void delayms(uint ms)
{
uchar t;
while(ms--)
{
for(t=0;t<120;t++);}
}
//ADC0832函数
uchar AD()
{
uchar i,dat1 = 0,dat2 = 0;
//第一个周期:转换开始
CS = 0;
CLK = 0;
DIO = 1;
_nop_(); _nop_();//短暂定时2us——也可以写成delay2us();,那么程序就要有delay2us();的定义了。
CLK = 1; _nop_(); _nop_();
//第二个周期:选择选择单通道还是双通道 DIO=0双通道差分 或 DIO=1单通道
CLK = 0; DIO=1; _nop_();_nop_();
CLK = 1; _nop_();_nop_();
//第三个周期:DIO选择CH1-->如果DIO=0 选择CH0
CLK = 0;DIO = 0; _nop_();_nop_();
CLK = 1;DIO = 1; _nop_();_nop_();
//等待
CLK = 0; DIO = 1; _nop_();_nop_();
//4-11,共8个下降沿读取数据(MSB->LSB) 先进来的为最高位,后进来为最低位
for(i=0;i<8;i++)
{
CLK = 1; _nop_();_nop_();
CLK = 0; _nop_();_nop_();
dat1 = dat1<<1|DIO;
}
//11-18 共8个下降沿读取数据(LSB->MSB) 先进来的为最低位,后进来为最高位
for(i=0;i<8;i++)
{
dat2 = dat2|((uchar)(DIO)<<i);
CLK = 1; _nop_();_nop_();
CLK = 0; _nop_();_nop_();
}
CS = 1;
return (dat1==dat2) ? dat1 : 0 ;
}
//按键选择程序
void key()
{
//确定键
if(key1==0)
{
while(key1==0);
if(mode>=2) mode=0;
else
{
writecmd(0x0f);
mode++;
switch(mode)
{
case 1 :
writecmd(0x80+5);break;
case 2 :
writecmd(0x0c);mode=0;break;
}
}
}
//加键
if(key2==0&&mode!=0)
{
while(key2==0);
yushe_yanwu++;
if(yushe_yanwu>=255) yushe_yanwu=255;
writecmd(0x80+7);
writedata(0x30+yushe_yanwu/100);
writedata(0x30+yushe_yanwu%100/10);
writedata(0x30+yushe_yanwu%10);
}
//减键
if(key3==0&&mode!=0)
{
while(key3==0);
yushe_yanwu--;
if(yushe_yanwu<=0) yushe_yanwu=0;
writecmd(0x80+7);
writedata(0x30+yushe_yanwu/100);
writedata(0x30+yushe_yanwu%100/10);
writedata(0x30+yushe_yanwu%10);
}
}
//主程序
void main()
{
init();
while(1)
{
temp=AD();
key();
if(mode==0)
{
display_1602(yushe_yanwu,temp);
if(temp>=yushe_yanwu)
{
led_yanwu=1;
baojing=1;
baojing=0;
}
if(temp<yushe_yanwu)
{
led_yanwu=0;
baojing=0;
}
}
}
}
//wyb.h文件
#include <reg51.h>
#include <intrins.h>
#define uchar unsigned char
#define uint unsigned int
sbit RS = P2^0;
sbit RW = P2^1;
sbit EN = P2^2;
uchar table1[]="SET E:000 mg/L";
uchar table2[]="NONGDU:000 mg/L";
//判断液晶是否忙碌
void busy()
{
uchar sta;
P0= 0xFF;
RS = 0;
RW = 1;
do
{
EN = 1;
_nop_();
sta = P0;
EN = 0;
} while (sta & 0x80);
}
// 向 LCD1602 液晶写入一字节命令(8位命令), cmd-待写入命令值
void writecmd(unsigned char cmd)
{
busy();
RS = 0;
RW = 0;
P0 = cmd;
EN = 1;
_nop_();
_nop_();
EN = 0;
}
//向 LCD1602 液晶写入一字节数据(8位数据), dat-待写入数据值
void writedata(unsigned char dat)
{
busy();
RS = 1;
RW = 0;
P0= dat;
EN = 1;
_nop_();
_nop_();
EN = 0;
}
//初始化 1602 液晶
void init()
{
uchar i=0;
writecmd(0x38);
writecmd(0x0C);
writecmd(0x06);
writecmd(0x01);
writecmd(0x80);
for(i=0;i<16;i++)
{
writedata(table1[i]);
}
writecmd(0x80+0x40);
for(i=0;i<16;i++)
{
writedata(table2[i]);
}
}
//1602显示函数
void display_1602(yushe_yanwu,temp)
{
writecmd(0x80+7);
writedata(0x30+yushe_yanwu/100);
writedata(0x30+yushe_yanwu%100/10);
writedata(0x30+yushe_yanwu%10);
writecmd(0x80+0x40+7);
writedata(0x30+temp/100);
writedata(0x30+temp%100/10);
writedata(0x30+temp%10);
}