基于51单片机温度控制,使用18b20来做温度传感器,四位共阳数码管显示。功能说明书:系统启动后默认温度下限28℃、上限30℃。当温度低于设定下限温度时继电器开启、加热指示灯亮起,当温度达到设定上限温度时蜂鸣器响起、保温指示灯亮起,当温度高于设定下限温度低于上限温度时蜂鸣器关闭保温指示灯继续亮起,温度低于下限温度时切换继电器开启加热指示灯亮起。(假设设置烧水,温度下限设置在90℃、上限设置100℃就行)
制作出来的实物图如下:
电路原理图如下:
仿真原理图如下(proteus仿真工程文件可到本帖附件中下载)
Altium Designer画的原理图和PCB图如下:(51hei附件中可下载工程文件)
单片机源程序如下:
#include<reg52.h> //51单片机的头文件
#include<intrins.h> //函数程序中需要使用到空指令
/***_crol_ 字符循环左移
_cror_ 字符循环右移
_irol_ 整数循环左移
_iror_ 整数循环右移
_lrol_ 长整数循环左移
_lror_ 长整数循环右移
_nop_ 空操作 (相当于8051 NOP 指令)
_testbit_ 测试并清零位 (相当于8051 JBC 指令) ***/
#define dm P0 //段码输出口
#define uchar unsigned char //宏定义,用uchar来代替unsigned char(无符号字符型变量,也即是无符号的8位变量),
//宏定义的原因就是书写方便,宏定义后,uchar可直接用来定义变量
#define uint unsigned int //原因同上,不过要注意,unsigned int为无符号的整型变量
//sbit是用来管脚的。
sbit DQ=P1^0; //温度输入口
sbit w0=P2^4; //数码管4
sbit w1=P2^5; //数码管3
sbit w2=P2^6; //数码管2
sbit w3=P2^7; //数码管1
sbit beep=P2^0; //蜂鸣器
sbit jidianqi=P2^1; //继电器
sbit yellow=P3^5; //加热指示灯
sbit led=P3^6; //高温指示灯
sbit zc=P3^7; //系统运行正常指示灯
sbit set=P3^4; //选择设置
sbit add=P3^3; //加
sbit dec=P3^2; //减
int temp1=0;//最高温度和最低温度标志位
uint h;
uint temp; //温度函数
uchar r;
uchar high=30,low=28; //开机默认最高温度和最低温度
uchar sign;
uchar q=0;
uchar tt=0;
uchar scale;
uchar code ditab[16]={0x00,0x01,0x01,0x02,0x03,0x03,0x04,0x04,0x05,0x06,0x06,0x07,0x08,0x08,0x09,0x09}; //共阳小数断码表
uchar code table_dm[12]={0xC0,0xF9,0xA4,0xB0,0x99,0x92,0x82,0xF8,0x80,0x90,0xff,0xbf}; //共阳LED段码表"0""1""2""3""4""5""6""7""8""9""不亮""-"
uchar code table_dm1[]={0x40,0x79,0x24,0x30,0x19,0x12,0x02,0x78,0x00,0x10}; //共阳个位带小数点的断码表
uchar data temp_data[2]={0xff,0xff};//读出温度暂放
uchar data display[5]={0xff,0xff,0xff,0xff,0xff};//显示单元数据,共四个数据和一个运算暂用
/***************11us延时函数***************/
void delay(uint t)
{
for(;t>0;t--);
}
/***************数码管显示***************/
void scan()
{
int j;
for(j=0;j<4;j++)
{
switch(j)
{
case 0:
dm=table_dm[display[0]];;
w0=0; //打开数码管显示小数数字的数码管位选端
delay(50);
w0=1; //关闭数码管显示小数数字的数码管位选端
case 1:
dm=table_dm1[display[1]];
w1=0; //打开数码管显示个位数字的数码管位选端
delay(50);
w1=1; //关闭数码管显示个位数字的数码管位选端
case 2:
dm=table_dm[display[2]];
w2=0; //打开数码管显示十位数字的数码管位选端
delay(50);
w2=1; //关闭数码管显示十位数字的数码管位选端
case 3:
dm=table_dm[display[3]];
w3=0; //打开数码管显示百位数字的数码管位选端
delay(50);
w3=1; //关闭数码管显示百位数字的数码管位选端
}
}
}
/****温度传感器采用的是DS18b20,此传感器采用的
是“单总线”来传输数据。****/
/**************DS18B20初始化**************/
ow_reset(void) //初始化
{
char presence=1;
while(presence)
{
while(presence)
{
DQ=1;_nop_();_nop_(); //将数据线拉高并延时
DQ=0; //将DQ(P1.0)引脚拉低。请注意,这里的DQ不是变量,而是单片机的引脚!!!
delay(50); //延时
DQ=1; //将DS拉高
delay(6);
presence=DQ;
}
delay(45);
presence=~DQ;
}
DQ=1;
return presence;
}
/****************写命令函数*****************/
void write_byte(uchar val)
{
uchar i;
for(i=8;i>0;i--)
{
DQ=1;_nop_();_nop_(); //将数据线拉高并延时
DQ=0;_nop_();_nop_();_nop_();_nop_(); //将数据线拉低并延时
DQ=val&0x01;
delay(6);
val=val>>1;
}
DQ=1;
delay(1);
}
/****************读一个字节函数*******************/
uchar read_byte(void)
{
uchar i;
uchar value=0;
for(i=8;i>0;i--) //采用for 循环,读取原始温度数据
{
DQ=1;_nop_();_nop_();
value>>=1;
DQ=0;_nop_();_nop_();_nop_();_nop_();
DQ=1;_nop_();_nop_();_nop_();_nop_();
if(DQ)value|=0x80;
delay(6);
}
DQ=1;
return value;
}
/***************读取温度函数***************/
read_temp() //读取18b20传感器函数
{
ow_reset();
delay(200);
write_byte(0xcc);
write_byte(0x44);
ow_reset();
delay(1);
write_byte(0xcc);
write_byte(0xbe);
temp_data[0]=read_byte();
temp_data[1]=read_byte();
temp=temp_data[1];
temp<<=8;
temp=temp|temp_data[0];
return temp;
}
/***************温度数据处理函数***************/
work_temp(uint tem) //温度转换函数
{
uchar n=0;
if(tem>6348)
{
tem=65536-tem;
n=1;
}
display[4]=tem&0x0f;
display[0]=ditab[display[4]];
display[4]=tem>>4;
display[3]=display[4]/100;
display[1]=display[4]%100;
display[2]=display[1]/10;
display[1]=display[1]%10;
r=display[1]+display[2]*10+display[3]*100;
if(!display[3])
{
display[3]=0x0a;
if(!display[2])
{
display[2]=0x0a;
}
}
if(n)
{
display[3]=0x0b;
}
return n;
}
/***************报警提示电路***************/
void BEEP()
{
{zc=0;} //系统正常指示灯
if(r>=high&&r<129) //如果实际温度高于等于于设定温度
{
led=0;//保温灯亮
beep=0;//蜂鸣器响
jidianqi=1; //继电器停止加热
yellow=1;//加热灯灭
}
else //否则
{
beep=1;//蜂鸣器停
}
if(r<low) //如果实际温度小于设定温度
{
yellow=0;//加热灯亮
led=1;//保温灯灭
jidianqi=0; //继电器开始加热
}
}
/***************温度显示转换**************/
void xianshi(int horl) //数码管显示函数
{
int n=0;
if(horl>128)
{
horl=256-horl;
n=1;
}
display[3]=horl/100; // 显示千位
display[3]=display[3]&0x0f; //显示千位
display[2]=horl%100/10; // 显示百位
display[1]=horl%10; // 显示个位
display[0]=0; // 显示分
if(!display[3])
{
display[3]=0x0a;
if(!display[2])
{
display[2]=0x0a;
}
}
if(n)
{
display[3]=0x0b;
}
仿真程序和AD PCB文件下载:
51 18b20 .rar
(1.78 MB, 下载次数: 314)
|