基于AT89C51的可调上下限温度监控系统设计.docx
《基于AT89C51的可调上下限温度监控系统设计.docx》由会员分享,可在线阅读,更多相关《基于AT89C51的可调上下限温度监控系统设计.docx(10页珍藏版)》请在冰豆网上搜索。
![基于AT89C51的可调上下限温度监控系统设计.docx](https://file1.bdocx.com/fileroot1/2023-2/9/e8f554df-7324-4ded-9ea7-830ec32230a0/e8f554df-7324-4ded-9ea7-830ec32230a01.gif)
基于AT89C51的可调上下限温度监控系统设计
温度监控系统设计
本系统是基于AT89C51单片机的温度监控系统。
由于本系统应用Proteus软件仿真,因此在温度传感器上运用一个滑动变阻器代替,代替的理由是:
温度传感器检测温度变化输出的是电压变化,而滑动变阻器输出的也是电压变化,所以可以替换。
该系统应用PCF8591作为模拟量转换芯片,将温度模拟量转化为数字量。
引脚SDA:
串行输出的数据线;引脚SCL:
串行输出的时钟线。
使用LCD1602作为显示芯片,用于显示温度上下限和实测温度,第一排显示Temp,第二排显示H:
L:
c:
。
使用ULN2003A作为驱动芯片,驱动继电器工作,继电器可驱动下位机加热器工作。
运用三个按钮调节温度上下限,按钮功能分别为切换、加一、减一。
下面是proteus总体仿真图:
以下是仿真成果:
当测定温度为51oC,温度上限为55oC,下限为45oC,此时测定温度在设定范围内时,继电器断开。
如图所示:
当测定温度为40oC,温度上限为55oC,下限为45oC,此时测定温度低于设定温度下限时,继电器闭合,1C口为低电平,压缩机开始工作,如图所示:
当测定温度为56oC,温度上限为55oC,下限为45oC,此时温度测定温度高于设定温度上限时,继电器断开,压缩机停止工作,如图所示:
部分程序如下所示
本系统中测得温度信号经过PCF8591芯片转换为数字量后输入到单片机中。
主函数如下:
unsignedcharReadADC(unsignedcharChl)
{
unsignedcharVal;
Start_I2c();//启动总线
SendByte(AddWr);//发送器件地址
if(ack==0)return(0);
SendByte(0x40|Chl);//发送器件子地址
if(ack==0)return(0);
Start_I2c();
SendByte(AddWr+1);
if(ack==0)return(0);
Val=RcvByte();
NoAck_I2c();//发送非应位
Stop_I2c();//结束总线
return(Val);
}
启动总线函数如下:
voidStart_I2c()
{SDA=1;//发送起始条件的数据信号
_Nop();
SCL=1;
_Nop();//起始条件建立时间大于4.7us,延时
_Nop();
_Nop();
_Nop();
_Nop();
SDA=0;//发送起始信号
_Nop();//起始条件锁定时间大于4μ
_Nop();
_Nop();
_Nop();
_Nop();
SCL=0;//钳住I2C总线,准备发送或接收数据
_Nop();
_Nop();
}
结束总线函数如下:
voidStop_I2c()
{SDA=0;//发送结束条件的数据信号
_Nop();//发送结束条件的时钟信号
SCL=1;//结束条件建立时间大于4μ
_Nop();
_Nop();
_Nop();
_Nop();
_Nop();
SDA=1;//发送I2C总线结束信号
_Nop();
_Nop();
_Nop();
_Nop();
}
字节数据传输函数的功能是将数据c发送出去,可以是地址,也可以是数据,发完后等待应答,并对此状态位进行操作。
发送数据正常,ack=1;ack=0表示被控器无应答或损坏。
程序如下:
voidSendByte(unsignedcharc)
{unsignedcharBitCnt;
for(BitCnt=0;BitCnt<8;BitCnt++)//要传送的数据长度为8位
{
if((c<elseSDA=0;
_Nop();
SCL=1;//置时钟线为高,通知被控器开始接收数据位
_Nop();
_Nop();//保证时钟高电平周期大于4μ
_Nop();
_Nop();
_Nop();
SCL=0;
}
_Nop();
_Nop();
SDA=1;//8位发送完后释放数据线,准备接收应答位
_Nop();
_Nop();
SCL=1;
_Nop();
_Nop();
_Nop();
if(SDA==1)ack=0;
elseack=1;//判断是否接收到应答信号
SCL=0;
_Nop();
_Nop();
}
字节数据传送函数功能是接收从器件传来的数据,并判断总线错误(不发应答信号),发完后使用应答函数。
具体程序如下:
unsignedcharRcvByte()
{unsignedcharretc;
unsignedcharBitCnt;
retc=0;
SDA=1;//置数据线为输入方式
for(BitCnt=0;BitCnt<8;BitCnt++)
{_Nop();
SCL=0;//置时钟线为低,准备接收数据位
_Nop();
_Nop();//时钟低电平周期大于4.7us
_Nop();
_Nop();
_Nop();
SCL=1;//置时钟线为高使数据线上数据有效
_Nop();
_Nop();
retc=retc<<1;
if(SDA==1)retc=retc+1;//读数据位,接收的数据位放入retc中
_Nop();
_Nop();
}
SCL=0;
_Nop();
_Nop();
return(retc);
}
非应答子函数程序如下:
voidNoAck_I2c(void)
{SDA=1;
_Nop();
_Nop();
_Nop();
SCL=1;
_Nop();
_Nop();//时钟低电平周期大于4μ
_Nop();
_Nop();
_Nop();
SCL=0;//清时钟线,钳住I2C总线以便继续接收
_Nop();
_Nop();
}
LCD写入程序:
voidwrite_com(ucharcom)
{
lcdwr=0;//lcdwr为读写控制端,lcdwr=0,这里可不写
lcdrs=0;//液晶rs接口为0时,写指令,rs为1时写数据
P2=com;//将要写的指令赋给P2口,
delay(5);//由1602读写操作时序图,先将指令赋给P2口,延时后将使能
lcden=1;//端lcden置高,再延时一段时间,然后将lcden置低,这样指令
delay(5);//就写入到LCD了
lcden=0;
}
LCD写入数据:
voidwrite_data(uchardate)
{
lcdrs=1;
P2=date;
delay(5);
lcden=1;
delay(5);
lcden=0;
}
LCD初始化:
voidinit_1602()
{lcdwr=0;
lcden=0;
write_com(0x38);
write_com(0x0c);
write_com(0x06);
write_com(0x01);
}
voidgudingtime_1602()
{
ucharnum;
write_com(0x80);
for(num=0;num<16;num++)
write_data(table[num]);
write_com(0x80+0x40);
for(num=0;num<16;num++)
write_data(table1[num]);
}
显示程序:
voidwrite_sfm(ucharadd,uchartime)
{
ucharshiwei,gewei;
shiwei=time/10;//将读取的BCD码数据转化成10进制个位和10
gewei=time%10;//进制十位
write_com(add+0x80);//定义显示在液晶的什么位置
write_data(0x30+shiwei);//由1602液晶字库可知,0~9的数据码分别对应0x30~0x39
write_data(0x30+gewei);//初使化中设定了写一个字符后,地址指针加1。
如有不懂之处可与我联系,邮箱594510244@。