标题:
51单片机DS18B20温度计源码(华氏和摄氏度的转换功能)
[打印本页]
作者:
LOGLOG6
时间:
2018-9-4 10:34
标题:
51单片机DS18B20温度计源码(华氏和摄氏度的转换功能)
利用51单片机DS18B20和1602做的温度计,可以实现温度上限报警,进行华氏和摄氏度的转换,利用三个按键实现这些功能。
单片机源程序如下:
/*作者:王先生
51单片机:清华电子的板
#include<reg52.h>
#include<intrins.h>
#include<math.h>
typedef unsigned char uchar;
typedef unsigned int uint;
sbit DS = P2^2;//DS18B20接口
sbit BP = P2^3;//蜂鸣器
sbit DU = P2^6;//数码管段选码
sbit WE = P2^7;//数码管位选码
sbit key_s1 = P3^0;
sbit key_s2 = P3^1;
sbit key_s3 = P3^2;
sbit EN = P3^4;//LCD使能端
sbit RS = P3^5;//LCD数据命令选择端
sbit RW = P3^6;//LCD读写选择端
uint FF;
uint DD,LL;
uint K=0;
uint M=0;
uint s=0;
void delayus(uchar us)
{
while(us--);//us--要6.5us,进入一次函数11.95us;
} //微秒延时
void LCD_READ_BUSY() //忙不忙
{
uchar busy;
P0 = 0XFF;
RS = 0;
RW = 1;
do
{
EN = 1;
busy = P0;
EN = 0;
}while(busy&0X80);
EN = 1;
}
void LCD_WRITE_CMD(uchar cmd)//写一个字节命令流程
{
LCD_READ_BUSY();//判断忙不忙
RS = 0;
RW = 0;
P0 = cmd;
EN = 1;
EN = 0;
}
void LCD_WRITE_DATE(uchar dat)//写一个字节数据
{
LCD_READ_BUSY();
RS = 1;
RW = 0;
P0 = dat;
EN = 1;
EN = 0;
}
void LCD_OneChar(uchar x, uchar y,uchar dat)//指定位置显示字符
{
if(y)
x |= 0x40;//位选或
x |= 0x80;
LCD_WRITE_CMD(x);
LCD_WRITE_DATE(dat);
}
void LCD_Str(uchar x, uchar y, uchar *str)//指定位置显示字符串
{
if(y)
x |= 0x40;
x |= 0x80;
LCD_WRITE_CMD(x);
while(*str != '\0')
{
LCD_WRITE_DATE(*str++);
}
}
void LCD_Init() // 初始化
{
LCD_WRITE_CMD(0x38); // 设置16*2显示,5*7点阵,8位数据接口
LCD_WRITE_CMD(0x0c); //开显示
LCD_WRITE_CMD(0x06); //读写一字节后地址指针加1
LCD_WRITE_CMD(0x01); //清除显示
}
bit ds_init()//单总线初始化程序
{
bit i;
DS = 1;
_nop_();
DS = 0;
delayus(75);//拉低总线;保持480us以上,75*6.5+11.95=499.45ms
DS = 1;//释放总线
delayus(1);//1*6.5+11.95=18.45us等待发回信号(15-60us)
i = DS;
delayus(20);//读取存在信号的时间20*6.5+11.95=141.95us
DS = 1; //释放总线
_nop_();
return(i);//i=0代表DS18B20已经准备好了
}
void displayN(int c)//温度正常显示
{
uint i;
uchar M1,M2,M3,M4;
uchar TestStr[] = {"Tem:"};
uchar TestStr1[] = {"DB:WYX"};
/*if(c<0)
{m = 2;}
else if(c>=0)
{m = 0;}*/
i = abs(c);
M1 = i/1000;//千位
M2 = i%1000/100;//百位
M3 = i%1000%100/10;//十位
M4 = i%10; //个位
DU = 0;
WE = 0;//关闭数码管显示
LCD_Init();//1602初始化
LCD_Str(0, 0, &TestStr[0]); //显示字符串
LCD_Str(0, 1, &TestStr1[0]); //显示字符串
LCD_OneChar(6 , 0, 43+s);//正负号
LCD_OneChar(7, 0, M1+48); //显示温度
LCD_OneChar(8, 0, M2+48);
LCD_OneChar(9 , 0, M3+48);//正负号
LCD_OneChar(10, 0, 46);
LCD_OneChar(11, 0, M4+48);
LCD_OneChar(12, 0, 39);
LCD_OneChar(13, 0, 67);
LCD_OneChar(15, 0, 78+DD*10); //显示蜂鸣器开关
LCD_OneChar(15, 1, 78+LL*10); //显示指示灯开关
}
void displayM(int c)
{
uchar M1,M2,M3,M4;
int i,m;
uchar TestStr[] = {"Tem:"};
uchar TestStr1[] = {"High"};
if(c<0)
{m = 2;}
else if(c>=0)
{m = 0;}
i = abs(c);
M1 = i/1000;//千位
M2 = i%1000/100;//百位
M3 = i%1000%100/10;//十位
M4 = i%10; //个位
DU = 0;
WE = 0;//关闭数码管显示
LCD_Init();//1602初始化
LCD_Str(0, 0, &TestStr[0]); //显示字符串
LCD_Str(7, 1, &TestStr1[0]); //显示字符串
LCD_OneChar(6 , 0, 43+m);//正负号
LCD_OneChar(7, 0, M1+48); //显示温度
LCD_OneChar(8, 0, M2+48);
LCD_OneChar(9 , 0, M3+48);//正负号
LCD_OneChar(10, 0, 46);
LCD_OneChar(11, 0, M4+48);
LCD_OneChar(12, 0, 39);
LCD_OneChar(13, 0, 67);
LCD_OneChar(15, 0, 78+DD*10); //显示蜂鸣器开关
LCD_OneChar(15, 1, 78+LL*10); //显示指示灯开关
}
void displayL(int c)
{
uchar M1,M2,M3,M4;
int i,m;
uchar TestStr[] = {"Tem:"};
uchar TestStr1[] = {"Low"};
if(c<0)
{m = 2;}
else if(c>=0)
{m = 0;}
i = abs(c);
M1 = i/1000;//千位
M2 = i%1000/100;//百位
M3 = i%1000%100/10;//十位
M4 = i%10; //个位
DU = 0;
WE = 0;//关闭数码管显示
LCD_Init();//1602初始化
LCD_Str(0, 0, &TestStr[0]); //显示字符串
LCD_Str(7, 1, &TestStr1[0]); //显示字符串
LCD_OneChar(6 , 0, 43+m);//正负号
LCD_OneChar(7, 0, M1+48); //显示温度
LCD_OneChar(8, 0, M2+48);
LCD_OneChar(9 , 0, M3+48);//正负号
LCD_OneChar(10, 0, 46);
LCD_OneChar(11, 0, M4+48);
LCD_OneChar(12, 0, 39);
LCD_OneChar(13, 0, 67);
LCD_OneChar(15, 0, 78+DD*10); //显示蜂鸣器开关
LCD_OneChar(15, 1, 78+LL*10); //显示指示灯开关
}
void displayNF(int c)
{
uchar M1,M2,M3,M4;
uchar TestStr[] = {"Tem:"};
uchar TestStr1[] = {"DB:WYX"};
uint p,i;
/*if(c<0)
{m = 2;}
else
{m = 0;}*/
i = abs(c);
p = i*9/5+320;
M1 = p/1000;
M2 = p%1000/100;//百位
M3 = p%1000%100/10;//十位
M4 = p%10; //个位
DU = 0;
WE = 0;//关闭数码管显示
LCD_Init();//1602初始化
LCD_Str(0, 0, &TestStr[0]); //显示字符串
LCD_Str(0, 1, &TestStr1[0]); //显示字符串
LCD_OneChar(6 , 0, 43+s);//显示正负
LCD_OneChar(7, 0, M1+48); //显示温度
LCD_OneChar(8, 0, M2+48);
LCD_OneChar(9, 0, M3+48);
LCD_OneChar(10, 0, 46);
LCD_OneChar(11, 0, M4+48);
LCD_OneChar(12, 0, 39);
LCD_OneChar(13, 0, 67+FF);
LCD_OneChar(15, 0, 78+DD*10); //显示蜂鸣器开关
LCD_OneChar(15, 1, 78+LL*10); //显示指示灯开关
}
void displayMF(int c)
{
uchar M1,M2,M3,M4;
uchar TestStr[] = {"Tem:"};
uchar TestStr1[] = {"High"};
uint p,m,i;
if(c<0)
{m = 2;}
else
{m = 0;}
i = abs(c);
p = i*9/5+320;
M1 = p/1000;
M2 = p%1000/100;//百位
M3 = p%1000%100/10;//十位
M4 = p%10; //个位
DU = 0;
WE = 0;//关闭数码管显示
LCD_Init();//1602初始化
LCD_Str(0, 0, &TestStr[0]); //显示字符串
LCD_Str(7, 1, &TestStr1[0]); //显示字符串
LCD_OneChar(6 , 0, 43+m);//显示正负
LCD_OneChar(7, 0, M1+48); //显示温度
LCD_OneChar(8, 0, M2+48);
LCD_OneChar(9, 0, M3+48);
LCD_OneChar(10, 0, 46);
LCD_OneChar(11, 0, M4+48);
LCD_OneChar(12, 0, 39);
LCD_OneChar(13, 0, 67+FF);
LCD_OneChar(15, 0, 78+DD*10); //显示蜂鸣器开关
LCD_OneChar(15, 1, 78+LL*10); //显示指示灯开关
}
void displayLF(int c)
{
uchar M1,M2,M3,M4;
uchar TestStr[] = {"Tem:"};
uchar TestStr1[] = {"Low"};
uint p,m,i;
if(c<0)
{m = 2;}
else
{m = 0;}
i = abs(c);
p = i*9/5+320;
M1 = p/1000;
M2 = p%1000/100;//百位
M3 = p%1000%100/10;//十位
M4 = p%10; //个位
DU = 0;
WE = 0;//关闭数码管显示
LCD_Init();//1602初始化
LCD_Str(0, 0, &TestStr[0]); //显示字符串
LCD_Str(7, 1, &TestStr1[0]); //显示字符串
LCD_OneChar(6 , 0, 43+m);//显示正负
LCD_OneChar(7, 0, M1+48); //显示温度
LCD_OneChar(8, 0, M2+48);
LCD_OneChar(9, 0, M3+48);
LCD_OneChar(10, 0, 46); //.
LCD_OneChar(11, 0, M4+48);
LCD_OneChar(12, 0, 39); //'
LCD_OneChar(13, 0, 67+FF);//C或F
LCD_OneChar(15, 0, 78+DD*10);//X或者N
LCD_OneChar(15, 1, 78+LL*10); //显示指示灯开关
}
void displayLE()
{
uchar TestSt1[] = {"Error"};
uchar TestSt2[] = {"Low#High"};
LCD_Init();
LCD_Str(5, 0, &TestSt1[0]);
LCD_Str(4, 1, &TestSt2[0]);
LCD_OneChar(15, 0, 78+DD*10); //显示蜂鸣器开关
LCD_OneChar(15, 1, 78+LL*10); //显示指示灯开关
}
void write_byte(uchar dat)//写一个字节
{
uchar i;
for(i=0;i<8;i++)//一次写一位,一个字节循环8次
{
DS = 0;
_nop_();//产生写时序(15US内满足要求)
DS = dat&0X01; //与
delayus(9);//延时大于60US 9*6.5+11.95=70.45us 同时满足写0写1
DS = 1;//释放总线
_nop_();
dat>>=1;//右移一位
}
}
uchar read_byte()//读一个字节
{
uchar i,j,dat;
for(i=0;i<8;i++)
{
DS = 0;
_nop_();//产生读时序
DS = 1;
_nop_();//释放总线
j = DS;
delayus(9);//读取数据大于60US 9*6.5+11.95=70.45us
DS = 1;
_nop_();
dat = (j<<7)|(dat>>1);
}
return(dat);
}
void beep(int m,gao,di)//按键与警报程序
{
if(m>=gao)
{
if(di<=gao) //判断最低报警温度是否低于最高报警温度
{
BP = DD;
P1 = 0XEE+LL*0X11;
}
else if(di>gao)
{
BP = 1;
P1 = 0X7E+LL*0X81;
}
}
else if(m<=di)
{
if(di<=gao) //判断最低报警温度是否低于最高报警温度
{
BP = DD;
P1=0X77+LL*0X88;
}
else if(di>gao)
{
BP = 1;
P1 = 0X7E+LL*0X81;
}
}
else
{
if(di<=gao) //判断最低报警温度是否低于最高报警温度
{
BP = 1;
P1=0XBB+LL*0X44;
}
else if(di>gao)
{
BP = 1;
P1 = 0X7E+LL*0X81;
}
}
}
void main()
{
int i,h;
uint j=0;
float t;
int gao=330,di=270;
uchar L,H;
while(1)
{
ds_init();//初始化函数
write_byte(0XCC);//发送跳跃ROM指令(0xcc)
write_byte(0X44);//发送温度转换指令(0X44)
ds_init();//初始化DS18B20
write_byte(0XCC);//发送跳跃ROM指令(0xcc)
write_byte(0XBE);//读取DS18B20暂存器的值(0Xbe)
L = read_byte(); //温度低字节
H = read_byte();//温度高字节
i = H;
i <<=8;
i|=L;//与,把L写到低字节里
if(H >= 0x08) //判断是否为负数
{
i = ~i + 1;//负数是以补码的形式存放的需要我们需要取反加1
s = 2; //显示负数符号
}
else s = 0;
t=i*0.0625;
i = t*10;//10.125--101.25--101.75--10.2(四舍五入)
if(key_s1 == 0) //第一位选程序
{
delayus(10);//防抖
if(key_s1 == 0)
{
j=j+1 ;
if(j>=3)
j=0;
}
while(!key_s1);
}
if(j==1) //调最高温度
{
h = gao;
if(key_s2 == 0)//按键2增加温度
{
delayus(20);//防抖
if(key_s2 == 0)
{
h=h+1 ;
}
while(!key_s2);
}
else if(key_s3 == 0)//按键3减小温度
{
delayus(20);
if(key_s3 == 0)
{
h=h-1;
}
while(!key_s3);
}
if(K==0)
{
displayM(h);
}
else if(K==1)
{
// p = h*(5/9)+320;
displayMF(h);
}
gao = h;
}
else if(j==2)//调最低温度
{
h = di;
if(key_s2 == 0)//按键2增加温度
{
delayus(20);//防抖
if(key_s2 == 0)
{
h=h+1 ;
}
while(!key_s2);
}
else if(key_s3 == 0)//按键3减小温度
{
delayus(20);
if(key_s3 == 0)
{
h=h-1;
}
while(!key_s3);
}
if(K==0)
{
displayL(h);
}
else if(K==1)
{
// p = h*(5/9)+320;
displayLF(h);
}
di = h;
}
else if(j==0) //显示温度
{
if(key_s2 == 0)//温度转化
{
delayus(20);//防抖
if(key_s2 == 0)
{
K=K+1 ;
if(K>1)
K=0;
}
while(!key_s2);
}
if(key_s3 == 0)//蜂鸣器与指示灯开关
{
delayus(20);//防抖
if(key_s3 == 0)
{
M=M+1 ;
if(M>3)
M=0;
}
while(!key_s3);
}
if(K==0)
{
FF=0; //摄氏度
}
else if(K==1)
{
FF=3; //华氏
}
/****************判断蜂鸣器与指示灯开关程序*******************/
if(M==0) //蜂鸣器关指示灯开
{
DD=1;
LL=0; //蜂鸣器关
}
else if(M==1) //蜂鸣器开指示灯开
{
DD=0;
LL=0;
}
else if(M==2) //蜂鸣器开指示灯关
{
DD=0;
LL=1;
}
else if(M==3) //蜂鸣器关指示灯关
{
DD=1;
LL=1;
}
/*****************温度显示及判断程序执行*****************/
if(K==0) //选择显示摄氏度
{
if(di>gao)
displayLE();
else if(di<=gao)
displayN(i);
}
else if(K==1) //选择显示华氏
{
if(di>gao)
displayLE();
else if(di<=gao)
displayNF(i);
}
beep(i,gao,di);//报警判断
}
}
}
//打开是85.0,因为初始值是85.
复制代码
作者:
alex-yang
时间:
2018-11-3 10:15
lz你的板子是哪一个?
作者:
LOGLOG6
时间:
2018-11-24 12:42
这个板子就是TB上的清翔电子的51板子
作者:
QQQZRR
时间:
2019-12-29 00:01
真好的程序
作者:
2358177280
时间:
2021-6-23 08:49
有没有原理图
作者:
rrrwy
时间:
2022-6-14 13:49
请问有没有原理图呀~
作者:
电子加油
时间:
2023-6-2 18:52
有没有仿真图呀
作者:
2326838386
时间:
2023-6-10 12:26
电子加油 发表于 2023-6-2 18:52
有没有仿真图呀
你好,仿真图找到了吗?分享一下可以吗
欢迎光临 (http://www.51hei.com/bbs/)
Powered by Discuz! X3.1