1、基于AT89C51的可调上下限温度监控系统设计温度监控系统设计本系统是基于AT89C51单片机的温度监控系统。由于本系统应用Proteus软件仿真,因此在温度传感器上运用一个滑动变阻器代替,代替的理由是:温度传感器检测温度变化输出的是电压变化,而滑动变阻器输出的也是电压变化,所以可以替换。该系统应用PCF8591作为模拟量转换芯片,将温度模拟量转化为数字量。引脚SDA:串行输出的数据线;引脚SCL:串行输出的时钟线。使用LCD1602作为显示芯片,用于显示温度上下限和实测温度,第一排显示Temp,第二排显示H: L: c: 。使用ULN2003A作为驱动芯片,驱动继电器工作,继电器可驱动下位机
2、加热器工作。运用三个按钮调节温度上下限,按钮功能分别为切换、加一、减一。下面是proteus总体仿真图:以下是仿真成果:当测定温度为51oC,温度上限为55oC,下限为45oC,此时测定温度在设定范围内时,继电器断开。如图所示: 当测定温度为40oC,温度上限为55oC,下限为45oC,此时测定温度低于设定温度下限时,继电器闭合,1C口为低电平,压缩机开始工作,如图所示: 当测定温度为56oC,温度上限为55oC,下限为45oC,此时温度测定温度高于设定温度上限时,继电器断开,压缩机停止工作,如图所示:部分程序如下所示本系统中测得温度信号经过PCF8591芯片转换为数字量后输入到单片机中。主函
3、数如下:unsigned char ReadADC(unsigned char Chl) unsigned char Val; 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); 启动总线函
4、数如下:void Start_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();结束总线函数如下:void Stop_I2c() SDA=0; /发送结束条件的数据信号 _Nop(); /发送结束条件的时钟信号 SCL=1; /结
5、束条件建立时间大于4 _Nop(); _Nop(); _Nop(); _Nop(); _Nop(); SDA=1; /发送I2C总线结束信号 _Nop(); _Nop(); _Nop(); _Nop();字节数据传输函数的功能是将数据c发送出去,可以是地址,也可以是数据,发完后等待应答,并对此状态位进行操作。发送数据正常,ack=1; ack=0表示被控器无应答或损坏。程序如下:void SendByte(unsigned char c) unsigned char BitCnt; for(BitCnt=0;BitCnt8;BitCnt+) /要传送的数据长度为8位 if(cBitCnt)&0
6、x80)SDA=1; /判断发送位 else SDA=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; else ack=1; /判断是否接收到应答信号 SCL=0; _Nop(); _Nop();字节数据传送函数功能是接收从器件传来的
7、数据,并判断总线错误(不发应答信号),发完后使用应答函数。具体程序如下: unsigned char RcvByte() unsigned char retc; unsigned char BitCnt; retc=0; SDA=1; /置数据线为输入方式 for(BitCnt=0;BitCnt8;BitCnt+) _Nop(); SCL=0; /置时钟线为低,准备接收数据位 _Nop(); _Nop(); /时钟低电平周期大于4.7us _Nop(); _Nop(); _Nop(); SCL=1; /置时钟线为高使数据线上数据有效 _Nop(); _Nop(); retc=retc1; if
8、(SDA=1)retc=retc+1; /读数据位,接收的数据位放入retc中 _Nop(); _Nop(); SCL=0; _Nop(); _Nop(); return(retc);非应答子函数程序如下:void NoAck_I2c(void) SDA=1; _Nop(); _Nop(); _Nop(); SCL=1; _Nop(); _Nop(); /时钟低电平周期大于4 _Nop(); _Nop(); _Nop(); SCL=0; /清时钟线,钳住I2C总线以便继续接收 _Nop(); _Nop(); LCD写入程序:void write_com(uchar com) lcdwr=0;
9、/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写入数据:void write_data(uchar date) lcdrs=1;P2=date;delay(5);lcden=1;delay(5);lcden=0;LCD初始化:void init_1
10、602()lcdwr=0;lcden=0;write_com(0x38);write_com(0x0c);write_com(0x06);write_com(0x01);void gudingtime_1602() uchar num; write_com(0x80); for(num=0;num16;num+) write_data(tablenum); write_com(0x80+0x40);for(num=0;num16;num+)write_data(table1num);显示程序:void write_sfm(uchar add,uchar time) uchar shiwei,gewei; shiwei=time/10; /将读取的BCD码数据转化成10进制个位和10 gewei=time%10; /进制十位 write_com(add+0x80);/定义显示在液晶的什么位置 write_data(0x30+shiwei);/由1602液晶字库可知,09的数据码分别对应0x300x39 write_data(0x30+gewei); /初使化中设定了写一个字符后,地址指针加1。如有不懂之处可与我联系,邮箱594510244 。
copyright@ 2008-2022 冰豆网网站版权所有
经营许可证编号:鄂ICP备2022015515号-1