Altium Designer画的原理图和PCB图如下:(51hei附件中可下载工程文件)
制作出来的恒温控制电路实物图如下:
电路原理图,我加了7805就不需要双电源了,PCB版没有
仿真原理图如下(proteus仿真工程文件可到本帖附件中下载)
元件清单:
0.1uF(104)瓷片电容 1 C3
10K 碳膜电阻 4 R2, R9, R10,R5
12.00MHz 晶体振荡器 1 CRY1
1N4007 二极管 2 D1, D2
0.47uF(1uF) 电解电容 1 CE1
100uF(220uF) 电解电容 1 CE2
22pF 瓷片电容 2 C1, C2
4.7K 碳膜电阻 1 R3
1K 碳膜电阻 4 R4, R6, R7, R8
5K 电位器 1 RP1
5V DC蜂鸣器 1 BZ1
S8550三极管 1 Q1
6x6轻触按键 4 S1,S2,S3,S4
DS18B20 温度传感器 1 J1
SRD-05VDC 继电器 2 RELAY1, RELAY2
LCD1602 液晶屏 1 LCD1
IDC-3P 2.54mm 单排排针 1 J1
IDC-16P 2.54mm 单排排针 1 LCD1
S9014 三极管 2 Q2, Q3
STC89C52 单片机 1 IC1
XH-2P 2.54mm插座 1 J2
KF25-6P-7.62mm 接线座 1 J6
红色LED 2 LD2,LD3, LD4
绿色LED 1 LD1
万能板(洞洞板) 1
锡线 1份
连线 1份
单片机源程序如下:
- #include <reg52.h>
- #include <intrins.h>
- #define uint unsigned int
- #define uchar unsigned char
- sbit DQ=P2^3;//ds18b20与单片机连接口
- sbit RS=P2^5;//液晶控制线接口
- sbit RW=P2^6;
- sbit EN=P2^7;
- uchar data disdata[5];
- uint tvalue,CurrentT=0;//温度值
- uchar tflag;//温度正负标志
-
- #define LCD_BUS P0
- sbit SetKey = P2^2;//设置按键
- sbit UpKey = P2^1; //加按键
- sbit DnKey = P2^0;//减按键
- sbit BEEP = P2^4;//蜂鸣器
- sbit Heat = P1^0;//加热继电器控制
- sbit Cool = P1^1;//降温继电器控制
- unsigned char AlarmTempLow=10,AlarmTempTop=40,Set=0;
- void delayms(uint ms) //延时xx毫秒
- {
- uchar i;
- while(ms--)
- {
- for(i=0;i<120;i++);
- }
- }
- void command(uint com) //LCD写指令
- {
- RS=0; //RS为0
- LCD_BUS=com; //装载指令
- delayms(5); //延时5ms
- EN=1; //LCD使能
- delayms(5); //延时5ms
- EN=0; //LCD不使能
- }
- void write_dat(uchar dat) //LCD写数据
- {
- RS=1; //RS为1
- LCD_BUS=dat; //装载数据
- delayms(5); //延时5ms
- EN=1; //LCD使能
- delayms(5); //延时5ms
- EN=0; //LCD不使能
- }
- void writestring(uchar x,uchar y,uchar *s) //LCD 写字符串
- {
- if (y == 0) command(0x80 + x); //表示第一行
- else command(0xC0 + x); //表示第二行
-
- while (*s) //判断是否字符串的结尾
- {
- write_dat( *s); //显示当前字符
- s ++; //字符串地址加1
- }
- }
- void writeChar(uchar x,uchar y,uchar s) //LCD 写字符串
- {
- if (y == 0) command(0x80 + x); //表示第一行
- else command(0xC0 + x); //表示第二行
-
- {
- write_dat( s); //显示当前字符
- }
- }
- void LCD_Initial() //LCD初始化
- {
- EN=0; //LCD不使能
- RW=0; //RW为0
- command(0x38); //发送初始化指令
- command(0x0c); //发送初始化指令
- command(0x06); //发送初始化指令
- command(0x01); //发送初始化指令
- command(0x80+0x02); //发送LCD初始位置
- }
- /*************************DS1820程序****************************/
- void delay_18B20(unsigned int i)//延时1微秒
- {
- while(i--);
- }
- void ds1820rst(void)/*ds1820复位*/
- {
- unsigned char x=0;
- DQ = 1; //DQ复位
- delay_18B20(4); //延时
- DQ = 0; //DQ拉低
- delay_18B20(100); //精确延时大于480us
- DQ = 1; //拉高
- delay_18B20(40);
- }
- uchar ds1820rd(void)/*读数据*/
- {
- unsigned char i=0;
- unsigned char dat = 0;
- for (i=8;i>0;i--)
- {
- DQ = 0; //给脉冲信号
- dat>>=1;
- DQ = 1; //给脉冲信号
- if(DQ)
- dat|=0x80;
- delay_18B20(10);
- }
- return(dat);
- }
- void ds1820wr(uchar wdata)/*写数据*/
- {
- unsigned char i=0;
- for (i=8; i>0; i--) //写一个字节数据到DS18B20
- {
- DQ = 0;
- DQ = wdata&0x01; //写一位数据
- delay_18B20(10); //延时
- DQ = 1; //拉高数据线
- wdata>>=1;//准备下一位
- }
- }
- unsigned int Read_Temperature(void)/*读取温度值并转换*/
- {
- uchar a,b;
- ds1820rst();
- ds1820wr(0xcc);//*跳过读序列号*/
- ds1820wr(0x44);//*启动温度转换*/
- ds1820rst();
- ds1820wr(0xcc);//*跳过读序列号*/
- ds1820wr(0xbe);//*读取温度*/
- a=ds1820rd(); //读取低位数据
- b=ds1820rd(); //读取高位数据
- tvalue=b;
- tvalue<<=8;
- tvalue=tvalue|a;//取得16位数据
- if(tvalue<0x0fff) tflag=0; //判断是否正温度
- else {tvalue=~tvalue+1;tflag=1;} //负温度,数据取反,温度标志位为1
- tvalue=tvalue*(0.625);//温度值扩大10倍,精确到1位小数
- CurrentT=tvalue;//保存当前温度
- return(tvalue);//返回温度值
- }
- void Display_Temperature() //显示温度
- {
- uchar flagdat;
- disdata[0]=tvalue/1000+0x30;//百位数
- disdata[1]=tvalue%1000/100+0x30;//十位数
- disdata[2]=tvalue%100/10+0x30;//个位数
- disdata[3]=tvalue%10+0x30;//小数位
-
- if(tflag==0) flagdat=0x20;//正温度不显示符号
- else flagdat=0x2d;//负温度显示负号:-
- if(tflag==1)
- {
- writeChar(10,0,flagdat);//显示符号位
- writeChar(11,0,disdata[0]);//显示百位
- writeChar(12,0,disdata[1]);//显示十位
- writeChar(13,0,disdata[2]);//显示个位
- writeChar(14,0,0X2E);//显示小数点
- writeChar(15,0,disdata[3]);//显示小数位
- }
- else
- {
- writeChar(10,0,disdata[0]);//显示百位
- writeChar(11,0,disdata[1]);//显示十位
- writeChar(12,0,disdata[2]);//显示个位
- writeChar(13,0,0X2e);//显示小数点
- writeChar(14,0,disdata[3]);//显示小数位
- writeChar(15,0,' ');//显示小数位
- }
- }
- void SetFun(void) //进入设置参数子函数
- {
- unsigned char i1=0,i2=0,i3=0,i4=0,i5=0,i6=0;
- if(SetKey==0) //设置按键
- {
- delayms(20); //延时防抖
- if(SetKey==0) //设置按键
- {
- if(Set<2) Set++; //设置按键次数累计
- else Set=0;
- }
- switch(Set) //根据设置按键次数,指向对应设置位置
- {
- case 0: writestring(0,1," ");writestring(8,1," ");break;//清除设置符号
- case 1: writestring(0,1,">");writestring(8,1," ");break;//指向设置下限
- case 2: writestring(0,1," ");writestring(8,1,">");break;//指向设置上限
- }
- while(SetKey==0);//等待按键松开
- }
-
- if((UpKey==0)&&(Set!=0))//加按键按下
- {
- delayms(20);//延时防抖
- if(UpKey==0)//加按键按下
- {
- switch(Set)//根据设置按键次数,设置上下限
- {
- case 1: if(AlarmTempLow<99) AlarmTempLow++;else AlarmTempLow=99; break;//设置下限
- case 2: if(AlarmTempTop<99) AlarmTempTop++;else AlarmTempTop=99; break;//设置上限
- }
- i1 = AlarmTempLow/100; //获得下限温度值的百位
- i2 = AlarmTempLow%100/10; //获得下限温度值的十位
- i3 = AlarmTempLow%10; //获得下限温度值的个位
-
- i4 = AlarmTempTop/100; //获得上限温度值的百位
- i5 = AlarmTempTop%100/10; //获得上限温度值的十位
- i6 = AlarmTempTop%10; //获得上限温度值的个位
- writestring(5,1," "); //清除之前的内容
- writestring(13,1," ");//清除之前的内容
- if(i1!=0) writeChar(5,1,i1+'0');//在第二行第5位 ,显示下限温度值的百位
- if((i1==0)&&(i2!=0)) writeChar(5,1,i2+'0');//在第二行第5位 ,显示下限温度值的十位
- if(i1!=0) writeChar(6,1,i2+'0');//在第二行第6位 ,显示下限温度值的十位
- if((i1==0)&&(i2==0)) writeChar(5,1,i3+'0');//在第二行第5位 ,显示下限温度值的个位
- else if((i1==0)&&(i2!=0)) writeChar(6,1,i3+'0');//在第二行第6位 ,显示下限温度值的个位
- if((i1!=0)) writeChar(7,1,i3+'0');//在第二行第7位 ,显示下限温度值的个位
-
- if(i4!=0) writeChar(13,1,i4+'0');//在第二行第13位 ,显示上限温度值的百位
- if((i4==0)&&(i5!=0)) writeChar(13,1,i5+'0');//在第二行第13位 ,显示上限温度值的十位
- if(i4!=0) writeChar(14,1,i5+'0');//在第二行第14位 ,显示上限温度值的十位
- if((i4==0)&&(i5==0)) writeChar(13,1,i6+'0');//在第二行第13位 ,显示上限温度值的个位
- else if((i4==0)&&(i5!=0)) writeChar(14,1,i6+'0');//在第二行第14位 ,显示上限温度值的个位
- if((i4!=0)) writeChar(15,1,i6+'0');//在第二行第15位 ,显示上限温度值的个位
- while(UpKey==0);//等待按键松开
- }
- }
-
- if((DnKey==0)&&(Set!=0))//减按键
- {
- delayms(20);
- if(DnKey==0)//减按键
- {
- switch(Set)//根据设置按键次数,设置上下限
- {
- case 1: if(AlarmTempLow>0) AlarmTempLow--;else AlarmTempLow=0; break;//设置下限
- case 2: if(AlarmTempTop>0) AlarmTempTop--;else AlarmTempTop=0; break;//设置上限
- }
- i1 = AlarmTempLow/100; //获得下限温度值的百位
- i2 = AlarmTempLow%100/10; //获得下限温度值的十位
- i3 = AlarmTempLow%10; //获得下限温度值的个位
-
- i4 = AlarmTempTop/100; //获得上限温度值的百位
- i5 = AlarmTempTop%100/10; //获得上限温度值的十位
- i6 = AlarmTempTop%10; //获得上限温度值的个位
- writestring(5,1," "); //清除之前的内容
- writestring(13,1," ");//清除之前的内容
- if(i1!=0) writeChar(5,1,i1+'0');//在第二行第5位 ,显示下限温度值的百位
- if((i1==0)&&(i2!=0)) writeChar(5,1,i2+'0');//在第二行第5位 ,显示下限温度值的十位
- if(i1!=0) writeChar(6,1,i2+'0');//在第二行第6位 ,显示下限温度值的十位
- if((i1==0)&&(i2==0)) writeChar(5,1,i3+'0');//在第二行第5位 ,显示下限温度值的个位
- else if((i1==0)&&(i2!=0)) writeChar(6,1,i3+'0');//在第二行第6位 ,显示下限温度值的个位
- if((i1!=0)) writeChar(7,1,i3+'0');//在第二行第7位 ,显示下限温度值的个位
-
- if(i4!=0) writeChar(13,1,i4+'0');//在第二行第13位 ,显示上限温度值的百位
- if((i4==0)&&(i5!=0)) writeChar(13,1,i5+'0');//在第二行第13位 ,显示上限温度值的十位
- if(i4!=0) writeChar(14,1,i5+'0');//在第二行第14位 ,显示上限温度值的十位
- if((i4==0)&&(i5==0)) writeChar(13,1,i6+'0');//在第二行第13位 ,显示上限温度值的个位
- else if((i4==0)&&(i5!=0)) writeChar(14,1,i6+'0');//在第二行第14位 ,显示上限温度值的个位
- if((i4!=0)) writeChar(15,1,i6+'0');//在第二行第15位 ,显示上限温度值的个位
-
- while(DnKey==0);
- }
- }
- }
- void Alarm(void)//报警子函数
- {
- if((CurrentT>=(AlarmTempTop*10))||(CurrentT<=(AlarmTempLow*10))||(tflag==1)) //超出设定范围
- {
- BEEP=0;//启动报警
- }
- else //在设定范围内
- {
- BEEP=1;//取消报警
- }
- }
- ……………………
- …………限于本文篇幅 余下代码请从51黑下载附件…………
复制代码
全部资料51hei下载地址(dsn文件 仿真是用Proteus7.5画的):
恒温控制.7z
(3.38 MB, 下载次数: 217)
|