自制可调温度控制器.docx
《自制可调温度控制器.docx》由会员分享,可在线阅读,更多相关《自制可调温度控制器.docx(19页珍藏版)》请在冰豆网上搜索。
自制可调温度控制器
自制可调温度控制器
作者:
温正伟 原载:
无线电杂志
近期我发现很多DIY或是电子爱好的朋友们比较关注电子温度控制器制作的文章,前面我也发过一篇AT89C2051控制的简单温度计制作的文章,但是由于电路比较简易,而且没有调温功能.应部分朋友的要求我在此转载一篇温正伟在无线电杂志上发表过的一款可以方便调节、设定温度的控制器。
1.功能介绍
笔者设计的这一款温度控制器是使用仍是比较常用的DS18B20集成温度传感器,还是用七段数码管做显示,完成温度采集与处理控制的CPU仍是AT89C2051单片机,但该电路具有电路简单,制作起来也无需调试,安装好后就可以使用等方便DIY的优点。
该电路最大的特点是用可以直观方便的调节所要限定的温度值,温度值是用3个7段共阳极数码管显示的,上电后会显示当前的温度值,按设定键时会闪烁显示设定温度值,这时可以按上/下调节键调整设定温度值,再次按下设定键时返回当前温度显示同时会对设定温度值进行保存,这个设定值会保存在DS18B20中,掉电后也不会丢失,下次上电时,单片机会自动读入上次的温度设定值。
长按设定键为关闭显示和温控,再次按下时功能再次打开。
电路中还设计了一路继电器控制,程序中设定超出设定温度时继电器被驱动吸合。
2.元器件背景及选用
表一是元器件列表。
在这个电路中关键的两个元器件分别是单片机AT89C2051和温度传感传感芯片DS18B20。
AT89C2051具有2K的可多次擦写的FLASH存储器,有15个I/O口,用于做一些小型的控制显示和数据采集系统是很好的选择,本制作中2051单片机除要完成数据采集、处理、控制和显示的任务外,还要完按键值的采集、处理。
如果要用常规的数字加模拟电路实现起来就相对困难多了。
DS18B20是DALLAS半导体公司(现属MAXIM公司)设计生产的单总线数字温度传感器,单总线也就是说只用一根I/O引线完成数据的输入输出功能,所以它的体积很小,而且电压适用范围在3-5.5V,封装形式除有SO/uSO的8PIN贴片式,还有更方便的三极管形式的TO-92封装(封装形式和引脚说明请看图一)。
DS18B20测量温度范围为-55°C~+125°C,其A/D转换的分辩率可用程序控制分别为9位、10位、11位和12位,最高分别率可以高达0.0625°C,但在-10~+85°C范围内其精度为±0.5°C,这个精度已可以满足普通型的环境温度控制或测温类消费电子产品的要求。
DS18B20中有三个8位E2RAM单元(非易失性可电擦写储存器),可以读写上下限警报温度值和一个自定义值,在本制作的中就只使用了上限温度值单元。
每个DS18B20出厂时都有一个唯一的序列编号,就是说在同一个单总线系统中可以控制多个DS18B20。
对DS18B20的单总线的操作方法这里因篇幅问题不可能一一说明,有兴趣的读者可以自己多查看些的DS18B20资料。
表1元件清单
元件名
数 量
说 明
AT89C2051
1
AT89C4051也可
DS18B20
1
温度传感器
七段数码管
3
共阳极
LM7805
1
稳压三极管
小按钮
3
100uF,10uF电解电容
各1
0.1uF瓷片电容
1
30pF
2
12M晶振
1
也可以用11.0592M
9012
1
也可用同类小功率三极管
S8550
3
同上
8.2K,4.7K电阻
各1
470欧电阻
7
可以根据数码管的亮度选用或不用
1K电阻
4
继电器
1
驱动电压为5V
图1:
温度传感器封装形式及引脚说明
3.电路原理
制作中DS18B20使用外接电源的供电方式,数据端用4.7K电阻上拉,并联接到2051的11脚上。
晶振选用12M的,使用简单的上电复位电路。
选用共阳极的数码管,用S8550作位驱动,段引脚通过470欧的电限流电阻接入2051的P1口上,如选用的数码管亮度不足可以调小限流电阻值。
笔者也使用过共阴极的数码管,在P1口用1K电阻上拉提供电流,亮度不高,但可以节省三个位驱动IO脚,电路更是简单。
电路中有三个按键,分别是显示开关/温度设定,温度上调,温度下调,在电路上电运行时程序初始是处于关闭状态的,要按一下S2电路开始显示和监测,如再按一下S2进入温度设定状态,设定值每秒闪烁一次,这时可以按S1或S3进行调节,再按下S2时退回显示当前温度状态并保存温度值到DS18B20。
使用2051的第9脚做控制输出端,低电平有效,笔者用它通过9012去驱动一个5V的继电器。
笔者把这个电路安装到电脑前面板上,继电器触头端接机箱的散热风扇,设定一个温度值如28度,当机箱内的温度超出28度时,控制端为低电平,继电器闭合,风扇启动进行散热。
图三就是装在电脑面板上的实物照片。
图2:
电原理图
4.软件实现
图三实物图
用实验板搭建的实物图
源程序如下:
/*-------------------------------
温度控制器V1.51
显示为三个共阳极LED
温度传感器用单总线DS18B20
CPU为2051,三个按键,分别为UP,DOWN,SET
温度调节上限为125度,下限为-55度
只能用于单只18B20
本软件仅供学习与参考,引用时请注明版权
#include
#include
#defineKey_UP P3_0 //上调温度
#defineKey_DOWN P3_1 //下调温度
#defineKey_SET P1_7 //设定键(温度设定,长按开电源)
#defineRelayOutPort P3_5 //继电器输出
#defineLEDPort P1 //LED控制口
#defineLEDOneC P3_2 //LEDDS1控制(百位)
#defineLEDTwoC P3_3 //LEDDS2控制(十位)
#defineLEDThreeC P3_4 //LEDDS3控制(个位)
#defineTMPort P3_7 //DS1820DataPort
unsignedcharcodeLEDDis[]={0xC0,0xF9,0xA4,0xB0,0x99,0x92,0x82,0xF8,0x80,0x90,0xFF,0xBF};//0-9的LED笔划,0xFF为空,0xF7为负号
staticunsignedcharbdataStateREG;//可位寻址的状态寄存器
sbitDS1820ON=StateREG^0; //DS1820是否存在
sbitSetTF=StateREG^1; //是否是在温度设置状态
sbitKeySETDown=StateREG^2; //是否已按过SET键标识
sbitPowTF=StateREG^3; //电源电源标识
sbitKeyTF=StateREG^4; //键盘是否允许
//sbitKeySETDowning=StateREG^5; //SET是否正在按下
staticunsignedcharbdataTLV_at_0x0029; //温度变量高低位
staticunsignedcharbdataTHV_at_0x0028;
staticsignedcharTMV; //转换后的温度值
staticunsignedcharKeyV,TempKeyV; //键值
staticsignedcharTMRomV_at_0x0027; //高温限制
staticsignedcharTMSetV_at_0x0026; //温度设定值
staticunsignedcharKSDNum; //SET键连按时的采集次数
staticunsignedcharIntNum,IntNum2,IntNum3; //中断发生次数,IntNum用于SET长按检测,IntNum2用于设定状态时LED闪烁
staticsignedcharLED_One,LED_Two,LED_Three;//LED的显示位LED_One为十位,LED_Two为个位
staticunsignedcharSign;//负号标识
voidmain(void)
{
voidInitDS1820(void); //定义函数
voidROMDS1820(void);
voidTMVDS1820(void);
voidTMRDS1820(void);
voidTMWDS1820(void);
voidTMREDS1820(void);
voidTMERDS1820(void);
voidReadDS1820(void);
voidWriteDS1820(void);
voidDelay_510(void);
voidDelay_110(void);
voidDelay_10ms(void);
voidDelay_4s(void);
voidV2ToV(void);
StateREG=0; //初始化变量
SetTF=1;
PowTF=1; //关电源
THV=0;
TLV=0;
TMV=0;
KeyV=0;
TempKeyV=0;
KSDNum=0;
IntNum=0;
IntNum2=0;
IntNum3=0;
LED_One=0;
LED_Two=0;
InitDS1820();//初始化
ROMDS1820();//跳过ROM
TMERDS1820();//E2PRAM中温度上限值调入RAM
InitDS1820();//初始化
ROMDS1820();//跳过ROM
TMRDS1820();//读出温度指令
ReadDS1820();//读出温度值和上限值
TMSetV=TMRomV;//拷贝保存在DS18B20ROM里的上限值到TMSetV
EA=1; //允许CPU中断
ET0=1; //定时器0中断打开
TMOD=0x1; //设定时器0为模式1,16位模式
TH0=0xB1;
TL0=0xDF; //设定时值为20000us(20ms)
TR0=1; //开始定时
while
(1);
}
//定时器0中断外理中键扫描和显示
voidKeyAndDis_Time0(void)interrupt1using2
{
TH0=0xB1;
TL0=0xDF; //设定时值为20000us(20ms)
LEDPort=0xFF;
if(!
Key_UP)
KeyV=1;
if(!
Key_DOWN)
KeyV=2;
if(!
Key_SET)
KeyV=3;
//KeySETDowning=0;//清除
if(KeyV!
=0) //有键按下
{
Delay_10ms(); //延时防抖按下10ms再测
if(!
Key_UP)
TempKeyV=1;
if(!
Key_DOWN)
TempKeyV=2;
if(!
Key_SET)
TempKeyV=3;
if(KeyV==TempKeyV) //两次值相等为确定接下了键
{
if(KeyV==3) //按下SET键,如在SET状态就退出,否则进入
{
//KeySETDowning=1;//表明SET正在按下
PowTF=0; //电源标识开
if(!
KeyTF)
if(SetTF)
{
SetTF=0; //标识位标识退出设定
InitDS1820();//初始化
ROMDS1820();//跳过ROM
TMWDS1820();//写温度上限指令
WriteDS1820();//写温度上限到DS18B20ROM
WriteDS1820();//写温度上限到DS18B20ROM
WriteDS1820();//写温度上限到DS18B20ROM
InitDS1820();//初始化
ROMDS1820();//跳过ROM
TMREDS1820();//温度上限值COPY回E2PRAM
}
else
SetTF=1;
if(!
KeySETDown)//没有第一次按下SET时,KeySETDown标识置1
KeySETDown=1;
else
KSDNum=KSDNum+1;//前一秒内有按过SET则开始计数
}
if(SetTF)//在SET状态下
{
if((KeyV==1)&&(!
KeyTF))
TMSetV=TMSetV+1; //上调温度
if((KeyV==2)&&(!
KeyTF))
TMSetV=TMSetV-1; //下调温度
if(TMSetV<=-55) //限制温度上下限
TMSetV=-55;
if(TMSetV>=125)
TMSetV=125;
}
if((!
KeyTF)&&(IntNum3==0))KeyTF=1;//当键盘处于可用时,锁定
}
if(KeySETDown) //在2秒内按下了SET则计中断发生次数用于长按SET时计时用
IntNum=IntNum+1;
if(IntNum>55) //中断发生了55次时(大约1.2秒)75为1.5秒左右
{
IntNum=0;
KeySETDown=0;
if(KSDNum==55) //如一直长按了SET1.2秒左右
{
RelayOutPort=1;//关闭继电器输出
PowTF=1; //电源标识关
LEDOneC=0;
LEDTwoC=0;
LEDThreeC=0;
LEDPort=0xBF; //显示"--"
Delay_4s(); //延时
LEDOneC=1;
LEDTwoC=1; //关显示
LEDThreeC=1;
Delay_4s();
IntNum=0;
IntNum2=0;
IntNum3=0;
}
KSDNum=0;
}
}
KeyV=0;
TempKeyV=0; //清空变量准备下次键扫描
if(!
PowTF)
{
InitDS1820();//初始化
ROMDS1820();//跳过ROM
TMVDS1820();//温度转换指令
Delay_510();
Delay_510();//延时等待转换完成
InitDS1820();//初始化
ROMDS1820();//跳过ROM
TMRDS1820();//读出温度指令
ReadDS1820();//读出温度值
V2ToV(); //转换显示值
if(TMV>TMSetV) //根据采集到的温度值控制继电器
{
RelayOutPort=0;
}
else
{
RelayOutPort=1;
}
if(SetTF)IntNum2=IntNum2+1;//用于闪烁计数
if(IntNum2>50)IntNum2=0;
if(KeyTF)IntNum3=IntNum3+1;//用于防止按键连按
if(IntNum3>25)
{
IntNum3=0;
KeyTF=0;
}
if((SetTF)&&(IntNum2<25))gotoInitEnd;//计数在后半段时显示
LEDPort=LED_One;
LEDOneC=0;
Delay_510();
LEDOneC=1; //显示百位数
LEDPort=LED_Two;
LEDTwoC=0;
Delay_510();
LEDTwoC=1; //显示十位数
LEDPort=LED_Three;
LEDThreeC=0;
Delay_510();
LEDThreeC=1; //显示个位数
}
InitEnd:
;
}
voidV2ToV(void)//数值转换
{
TLV=TLV>>4;
THV=THV<<4; //读出的高低位数值移位
TMV=TLV|THV; //合并高低位放入TM为实际温度值
Sign=0;
if(SetTF||!
Key_SET)
Sign=TMSetV>>7; //取符号
else
Sign=TMV>>7;
if(Sign)
{
if(SetTF||!
Key_SET)
{
LED_One=(~(TMSetV-1))/100; //SET状态下显示设定值
LED_Two=((~(TMSetV-1))-LED_One*100)/10;
LED_Three=(~(TMSetV-1))-LED_One*100-LED_Two*10;
}
else
{
LED_One=(~(TMV-1))/100; //转换百位值
LED_Two=((~(TMV-1))-LED_One*100)/10;
LED_Three=(~(TMV-1))-LED_One*100-LED_Two*10;
}
}
else
{
if(SetTF||!
Key_SET)
{
LED_One=(TMSetV)/100; //SET状态下显示设定值
LED_Two=(TMSetV-LED_One*100)/10;
LED_Three=TMSetV-LED_One*100-LED_Two*10;
}
else
{
LED_One=(TMV)/100; //转换百位值
LED_Two=(TMV-LED_One*100)/10;
LED_Three=TMV-LED_One*100-LED_Two*10;
}
}
//转LED字段
if(LED_One)//超过百时十位的处理
LED_Two=LEDDis[LED_Two];
else
{
if(LED_Two==0)
LED_Two=LEDDis[10];
else
LED_Two=LEDDis[LED_Two];
}
if(Sign)
LED_One=LEDDis[11];
else
{
if(LED_One==0)
LED_One=LEDDis[10];
else
LED_One=LEDDis[LED_One];
}
LED_Three=LEDDis[LED_Three];
}
voidInitDS1820(void) //初始化DS1820
{
TMPort=1; //拉高TMPort
_nop_(); //保持一个周期
TMPort=