本文是关于DS18B20温度传感器的一个扩展实验。
首先系统运行后,可以通过按键设置温度上下限,当按下开始运行按键后温控系统开始工作。默认温度上下限为23~25°C。温控系统开始运行后会在数码管中显示当前温度。
使用到的硬件资源有:
当按键按下时,按键两端管脚电平一致,按键处理时需要延时消抖+二次确认。
要驱动蜂鸣器发声,分为有源蜂鸣器和无源蜂鸣器。对于有源蜂鸣器控制其中一端管脚为高电平或低电平即可发声;对于无源蜂鸣器,需要一定频率的脉冲才可发声。驱动蜂鸣器需要比较大的电流,使用ULN2003芯片实现放大电流的功能。本实验使用有源蜂鸣器。
要驱动直流电机转动,在其一端管脚输入高电平,另一端管脚输入低电平,使直流电机有电流通过即可转动,高低电平在不同位置,仅控制转动的方向。要驱动直流电机也需要比较大的电流,使用ULN2003芯片实现放大电流的功能。
使用一个PNP三极管驱动继电器,添加一个二极管用于保护继电器。
使用74HC138芯片控制数码管的位选,74HC245控制数码管的段选。
DS1302温度传感器是单总线通信,不需要外围元件。具有可编程的分辨率,内含64位的ROM(64位的序列号,识别当前使用的芯片)、一个包含9字节的高速暂存器RAM和一个非易失性可电擦除EEPROM。
不考虑64位ROM序列号,DS1302读取温度过程:初始化→发送CCH命令跳过ROM→发送温度转换命令44H→延时→初始化→发送CCH命令跳过ROM→发送读RAM命令BEH→连续读出数据。
设置温度上下限过程:初始化→发送CCH命令跳过ROM→发送48H命令将RAM2、3字节的内容复制到EEPROM中→延时→初始化→发送CCH命令跳过ROM→发送4EH命令将温度限值写入RAM→发送连个字节的数据。
本实验实现的是一个温度控制系统,当温度超过设定范围时触发一定操作。温度超过上限时,电机开启同时蜂鸣器报警;温度低于下限时,继电器工作同时蜂鸣器报警;温度处于上下限之间时,系统正常工作。系统通过按键调节上限、下限和工作开始或停止。
本系统的需求包括:
proteus仿真原理图如下。P3.0~P3.3口控制独立按键K1 ~ K4,P3.0 ~ 03.3口为低电平时表示按键按下。K1向上调温度上限,K2向下调温度下限,按K3确定温度的上下限,按K4 温度控制系统开始工作。P3.7口作为温度传感器DS18B20的输入/输出。
通过ULN2003芯片起到放大电流的作用,用来控制蜂鸣器、继电器和直流电机。P1.0控制直流电机,P1.0为高电平时直流电机工作,为低电平时直流电机不工作。P1.5控制蜂鸣器,P1.5为低电平是蜂鸣器不发声,为高电平时蜂鸣器发声。P1.1口控制继电器,P1.1为低电平时继电器工作,为高电平时继电器不工作。
P0口通过74HC245控制数码管的段选,P2.2~P2.4通过74HC138控制数码管的位选。P0口为高电平时,对应数码管的段亮。
按键函数处理如下:
void DataPros()
{
int temp=curTmp*100;
if(temp<0)
{
display[0]=0x40; // -
}
else
{
display[0]=0x00;
}
display[1]=smg[temp%10000/1000];
display[2]=smg[temp%1000/100]|0x80; // |0x80显示小数点
display[3]=smg[temp%100/10];
display[4]=smg[temp%10/1];
display[5]=0x39;
}
// 按键处理函数
void KeyPros()
{
u8 i;
// K1上调温度上限
if(0==K1)
{
delay1ms(10);
if(0 == K1)
{
tmpH=tmpH+1;
if(tmpH>125)
tmpH=125;
curTmp=tmpH;
DataPros();
}
while(!K1);
}
// K2下调温度下限
if(0==K2)
{
delay1ms(10);
if(0 == K2)
{
tmpL=tmpL-1;
if(tmpL<-55)
tmpL=-55;
curTmp=tmpL;
DataPros();
}
while(!K2);
}
// 按K4,系统开始运行,读取当前温度,判断是否超过温度范围
if(0==K4)
{
delay1ms(10);
if(0==K4)
{
enRead=~enRead;
if(0==enRead)
{
for(i=0;i<8;i++)
{
display[i]=0;
}
}
}
while(!K4);
}
}
温度处理函数如下:
// 温度处理函数
void TempPros(int temp)
{
float tp;
if(temp<0)
{
display[0]=0x40; // -
temp=temp-1;
temp=~temp;
tp=temp;
temp=tp*0.0625*100+0.5;
}
else
{
display[0]=0x00;
tp=temp;
temp=tp*0.0625*100+0.5;
}
// 如果温度超过上限,蜂鸣器发声,电机转动
if((tp*0.0625)>tmpH)
{
BEEP=1;
MOTOR=1;
RELAY=1;
}
else if((tp*0.0625)<tmpL) // 如果温度低于下限,蜂鸣器发声,继电器工作
{
BEEP=1;
MOTOR=0;
RELAY=0;
}
else
{
BEEP=0;
MOTOR=0;
RELAY=1;
}
display[1]=smg[temp%10000/1000];
display[2]=smg[temp%1000/100]|0x80; // |0x80显示小数点
display[3]=smg[temp%100/10];
display[4]=smg[temp%10/1];
display[5]=0x39;
}
主函数:
void main()
{
enRead=0;
BEEP=0;
MOTOR=0;
RELAY=1;
while(1)
{
if(0!=enRead)
TempPros(DS18B20ReadTemp()); // 系统运行时默认数码管不显示,当按了K4时显示实时温度
KeyPros();
DigDisplay();
}
}
仿真结果: