目录
一、主要功能
二、硬件资源
三、程序编程
四、实现现象
一、主要功能
基于AT89C52单片机,采用DS18B20温度传感器检测温度,通过LCD1602显示屏显示,并且按键
可以加减温度的上限;
点击清洗按键后,倒计时1分钟,电机正转20s,反转20s,直到倒计时结束停止,蜂鸣器报警。
点击脱水按键后,倒计时1分钟,电机正转20s,反转20s,直到倒计时结束停止,蜂鸣器报警。
然后加三个按键,分别代表进水,出水,排水,三个LED状态灯表示。
采用滑动变阻器连接ADC0832数模转换器检测水位。
二、硬件资源
基于KEIL5编写C++代码,PROTEUS8.15进行仿真,全部资源在页尾,提供安装包。
三、程序编程
#include "reg51.h"
#include<intrins.h>
#include<stdio.h>
#include "lcd1602.h"
#include "Delay.h"
#define uchar unsigned char
#define uint unsigned int
sbit k1=P1^2;
sbit k2=P1^3;
sbit k3=P1^4;
sbit k4=P1^5;
sbit k5=P1^6;
sbit k6=P1^7;
sbit k7=P3^0;
sbit beep=P2^7;//蜂鸣器
sbit led1=P3^7;//led
sbit led2=P3^6;
sbit led3=P3^5;
sbit out1=P3^3;//电机
sbit out2=P3^4;
sbit out3=P1^0;
sbit out4=P1^1;
sbit CS= P2^4; //ADC0832
sbit CLK= P2^5;
sbit DIO= P2^6;
sbit DS=P3^2; //DS18B20温度传感器
uchar time=0,mode=0,sec=0;//系统变量
uchar fen=0,miao=0,set=1;//时间
uchar miao1=0;//倒计时
uchar disp1[]="00:00";
uchar disp2[]="00s";
uchar wd[]="00";
uchar wdyz[]="00";
uchar shuiwei[]="000";
static uint u,U,R;//水位变量
static int wdmax=50;
unsigned char count;
typedef unsigned char u8;
typedef unsigned int u16;
static uint temp;
static float ftemp = 0.0f;//温度转变
static int wdnumber;
uint temp;
static int mode1=0;
void tmpchange();
uint tmp();
void beep_warning();
void dsreset(void) //发出命令
{
uint i;
DS=0;
i=103; //将总线拉低480us~960us
while(i>0)i--;
DS=1; //然后拉高总线,若DS18B20做出反应会将在15us~60us后将总线拉低
i=4; //15us~60us等待
while(i>0)i--;
//while(DS);
}
bit tmpreadbit(void) //读取数据
{
uint i;
bit dat;
DS=0;i++; //i++ for delay
DS=1;i++;i++;
dat=DS;
i=8;while(i>0)i--;
return (dat);
}
uchar tmpread(void) //读取数据
{
uchar i,j,dat;
dat=0;
for(i=1;i<=8;i++)
{
j=tmpreadbit();
dat=(j<<7)|(dat>>1); //读出的数据最低位在最前面,这样刚好一个字节在DAT里
}
return(dat);
}
void tmpwritebyte(uchar dat) //传输数据给DS18B20
{
uint i;
uchar j;
bit testb;
for(j=1;j<=8;j++)
{
testb=dat&0x01;
dat=dat>>1;
if(testb) //write 1
{
DS=0;
i++;i++;
DS=1;
i=8;while(i>0)i--;
}
else
{
DS=0; //write 0
i=8;while(i>0)i--;
DS=1;
i++;i++;
}
}
}
void tmpchange(void) //DS18B20开始工作
{
dsreset();
Delay(1);
tmpwritebyte(0xcc);
tmpwritebyte(0x44);
}
uint tmp() //获得温度
{
float tt;
uchar a,b;
dsreset();
Delay(1);
tmpwritebyte(0xcc);
tmpwritebyte(0xbe);
a=tmpread();//低八位
b=tmpread();//高八位
temp=b;
temp<<=8; //two byte compose a int variable
temp=temp|a;
tt=temp*0.0625; //算出来的是测到的温度,数值可到小数点后两位
temp=tt*10+0.5; //为了显示温度后的小数点后一位并作出四舍五入,因为取值运算不能取小数点后的数
return temp;
}
uchar get_AD_Res() //ADC0832启动读取函数
{
uchar i, data1=0, data2=0;
CS=0;
CLK=0;DIO=1;_nop_();
CLK=1;_nop_();
CLK=0;DIO=1;_nop_();
CLK=1;_nop_();
CLK=0;DIO=0;_nop_();
CLK=1;_nop_();
CLK=0;DIO=1;_nop_();
for(i=0; i<8; i++)
{
CLK=1;_nop_();
CLK=0;_nop_();
data1=(data1<<1)|(uchar)DIO;
}
for(i=0; i<8; i++)
{
data2=data2|(uchar)DIO<<i;
CLK=1;_nop_();
CLK=0;_nop_();
}
CS=1;
return(data1 == data2)?data1:0;
}
void swpd() //水位判断
{
if(R>100)
{
out3 = 1;
out4 = 0;
}
else
{
out3 = 1;
out4 = 1;
}
}
void main()//主函数
{
init_1602();//初始化LCD
write_string(2,0,"ms:");
write_string(2,11,"sw");
TMOD|=0X01;
TH0=0X3C;
TL0=0XB0;
ET0=1;//打开定时器0中断允许
EA=1;//打开总中断
TR0=1;//打开定时器
beep = 1;
while(1)
{
u=get_AD_Res();
U=(250*u)/128; //水位
R=200*U/250; //水位转变
swpd();//水位判断
if(mode==0) // 停止模式
{
if(!k1)
{
wdmax++;
while(!k1);
}
if(!k2)
{
wdmax--;
while(!k2);
}
if(!k3)
{
init_1602();
mode1=0;
write_string(2,1,"qx");
if(mode==0)
{
mode=1;
fen=set;
miao=0;
miao1=20;
}
while(!k3);
}
if(!k4)
{
init_1602();
mode1=0;
write_string(2,1,"ts");
if(mode==0)
{
mode=1;
fen=set;
miao=0;
miao1=20;
}
while(!k4);
}
if(!k5)
{
mode1=1;
while(!k5);
}
if(!k6)
{
mode1=2;
while(!k6);
}
if(!k7)
{
mode1=3;
while(!k7);
}
}
switch(mode)//模式控制
{
case 0:
out1=1;out2=1;
led1=1;led2=1;led3=1;
break;
case 1:
out1=1;out2=0;
break;
case 2:
out1=1;out2=1;
break;
case 3:
out1=0;out2=1;
break;
case 4:
out1=1;out2=1;
}
switch(mode1)
{
case 0:
out3 = 0;
out4 = 0;
led1 = 1;
led2 = 1;
led3 = 1;
break;
case 1:
out3 = 1;
out4 = 0;
led1 = 0;
led2 = 1;
led3 = 1;
break;
case 2:
out3 = 1;
out4 = 0;
led1 = 1;
led2 = 0;
led3 = 1;
break;
case 3:
out3 = 1;
out4 = 0;
led1 = 1;
led2 = 1;
led3 = 0;
break;
}
}
}
//定时器中断
void Timer0() interrupt 1
{
if(time<10)//0.5s
time++;
else
{
tmpchange(); //让18b20开始转换温度
temp = tmp(); //读取温度
ftemp = temp/10.0f; //转换温度
wdnumber = ftemp;
time=0;
//显示
if(mode==0)
{
write_string(1,0,"wd:");
write_string(1,7,"yz:");
wd[0]=wdnumber/10+0x30;
wd[1]=wdnumber%10+0x30;
wdyz[0]=wdmax/10+0x30;
wdyz[1]=wdmax%10+0x30;
if(wdnumber > wdmax)
{
beep = 0;
}
else
{
beep = 1;
}
write_string(1,3,wd);
write_string(1,10,wdyz);
disp1[0]=set/10+0x30;
disp1[1]=set%10+0x30;
disp1[3]='0';
disp1[4]='0';
write_string(2,5,disp1);
shuiwei[0]=R/100+0x30;
shuiwei[1]=(R%100)/10+0x30;
shuiwei[2]=R%10+0x30;
write_string(2,13,shuiwei);
}
else//运行倒计时
{
write_string(1,0,"run:");
disp1[0]=fen/10+0x30;
disp1[1]=fen%10+0x30;
disp1[3]=miao/10+0x30;
disp1[4]=miao%10+0x30;
write_string(2,5,disp1);
disp2[0]=miao1/10+0x30;
disp2[1]=miao1%10+0x30;
write_string(1,6,disp2);
shuiwei[0]=R/100+0x30;
shuiwei[1]=(R%100)/10+0x30;
shuiwei[2]=R%10+0x30;
write_string(2,13,shuiwei);
}
}
if(mode>0)
{
if(sec<19)//1s
sec++;
else
{
sec=0;
if(miao>0)//秒计时
miao--;
else
{
if(fen>0)
{
miao=59;//分计时
fen--;
}
else
{
beep=0; //结束
mode=0;
beep=1;
}
}
if(mode==1)//正转
{
if(miao1>0)
miao1--;
else
{
miao1=20;
mode=3;
}
}
else if(mode==2)//暂停
{
if(miao1>0)
miao1--;
else
{
miao1=25;
mode=3;
}
}
else if(mode==3)//反转
{
if(miao1>0)
miao1--;
else
{
miao1=20;
mode=1;
}
}
else if(mode==4)//暂停
{
if(miao1>0)
miao1--;
else
{
miao1=20;
mode=1;
}
}
else
{
miao1=0;
init_1602();
beep = 0;
Delay(500);
beep = 1;
}
}
}
TH0=0X3C;
TL0=0XB0;
}
四、实现现象
具体动态效果看B站演示视频:
基于51单片机的自动清洗系统(自动洗衣机)
全部资料(源程序、仿真文件、安装包、演示视频):
链接:https://pan.baidu.com/s/1ddJ3RP7JqBRiUF7uI6a2tw?pwd=ahdy
提取码:ahdy