📄 温控开关.c
字号:
/*****************************************************************************
程 序 名:51AVR实验板配套程序 - 18B20温控开关
开发环境:Keil
编 写 者:www.01mcu.net
功能简述:读取DS18B20测得的温度,转换并显示到数码管上,
同时根据设定值来控制继电器的吸合与释放
硬件说明:将选购的 DS18B20 装到实验板的 U4 插座上,方向是平面朝向自己:G O V
晶体为12MHz
其它说明:本实验牵扯到 18B20 的相关知识,请参阅本目录下18B20的器件手册
完成日期:2008.06.22
******************************************************************************/
#include <reg51.h>
//定义位操作
sbit DQ=P3^7; //18B20数据端
sbit ls1=P0^2; //个位公共极
sbit ls2=P0^3; //十位公共极
sbit ls3=P0^4; //百位公共极
sbit ls4=P0^5; //千位公共极
sbit J=P2^6; //继电器 ,
#define Out P1 //数据输出端
unsigned char ALLTEMP; //温度
unsigned char tab[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,0xff,0xbf}; //共阳
//显示 0 1 2 3 4 5 6 7 8 9 空 -
//序号 0 1 2 3 4 5 6 7 8 9 a b
unsigned char Disbuf[]={0,0,0,0}; //显示缓存
//------------------------------------------------------------------------
//延时
delay(unsigned int t)
{
while(t--);
}
//显示----------------------------
void Display()
{
unsigned char j;
for(j=0;j<30;j++)
{
Out=tab[Disbuf[0]]; //要显示的数据第一位
ls4=0;
delay(300);
ls4=1;
Out=tab[Disbuf[1]]; //要显示的数据第二位
ls3=0;
delay(300);
ls3=1;
Out=tab[Disbuf[2]]; //要显示的数据第三位
ls2=0;
delay(300);
ls2=1;
Out=tab[Disbuf[3]]; //要显示的数据第四位
ls1=0;
delay(300);
ls1=1;
}
}
//---将 DS18B20 采集到的温度转换显示到数码管上 -----------
void conv(void)
{
unsigned char bdata p;
unsigned char tem1,tem2,tem3;
p=ALLTEMP;
p=p&0x80;
p>>=7;
if(p==1) //判断+-温度
{
Disbuf[0]=0x0b; //显示“-”号
ALLTEMP=~ALLTEMP; //取补码
ALLTEMP++;
tem2=ALLTEMP/10;
tem3=ALLTEMP%10;
Disbuf[1]=0x0a; //负温度本位不显示
Disbuf[2]=tem2;
if (Disbuf[2]==0) Disbuf[2]=0x0a; //高位0不显示
Disbuf[3]=tem3;
}
else{
tem1=ALLTEMP/100;
tem2=(ALLTEMP-tem1*100)/10;
tem3=ALLTEMP-tem1*100-tem2*10;
Disbuf[0]=0x0a; //不显示
Disbuf[1]=tem1;
Disbuf[2]=tem2;
Disbuf[3]=tem3;
if(Disbuf[1]==0)
{Disbuf[1]=0x0a; //高位0不显示
if(Disbuf[2]==0) Disbuf[2]=0x0a; //高位0不显示
}
}
}
//*************************************************
//复位
unsigned char ow_reset(void)
{
unsigned char p;
DQ=0; // 拉DQ线为低
delay(29); // 等待480nS
DQ=1; // DQ返回高
delay(3); // 等待
p=DQ; // 获得信号
delay(25); // 等待结束时间片
return(p);
} // 0=找到器件, 1 = 无器件
//从 1-wire 总线上读取一个字节
unsigned char read_byte(void)
{
unsigned char i;
unsigned char value = 0;
for (i=8;i>0;i--)
{
value>>=1;
DQ = 0; //拉低 DQ
DQ = 1; //返回高
DQ = 1;
if(DQ)value|=0x80;
delay(6); // 等待读时间片
}
return(value);
}
//向 1-WIRE 总线上写一个字节
void write_byte(char val)
{
unsigned char i;
for (i=8;i>0;i--) // 写1字节
{
DQ = 0; // 拉低 DQ
DQ = val&0x01;
delay(2); // 等待
DQ = 1;
val=val/2;
}
delay(5);
}
//读取温度
char Read_Temperature(void)
{
union{
unsigned char c[2];
unsigned int x;
}temp; //定义一个联合数据类型,便于数据处理
ow_reset();
write_byte(0xCC); // 此命令执行后的存储器操作将针对在线的所有DS1820
write_byte(0xBE); // 从高速暂存器读9bits温度值和CRC值
temp.c[1]=read_byte();
temp.c[0]=read_byte();
ow_reset();
write_byte(0xCC); //跳过 ROM
write_byte(0x44); //转换温度
return temp.x/16; //保留整度,显示前要转换其特殊格式!
}
main()
{
unsigned char i;
unsigned char T=32; //比较温度,你可以自行修改到你认为合适的温度控制点
J=0; //先关闭继电器
conv();
while(1)
{
Display();
if(i>2) //由于18B20转换速度限制读取温度不能太快,一般要隔2秒读取一次
{ //这里采用显示2次后读一次数据
ALLTEMP=Read_Temperature(); //读温度
conv(); //转换
i=0;
}
i++;
//判断控制继电器
if(ALLTEMP<127) //不处理负温度
{
if(ALLTEMP>T) J=1; // 高于设定,吸合继电器,温控时可作为加热开
if(ALLTEMP<T) J=0; // 低于设定,释放继电器,温控时可作为加热关
}
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -