介绍
通过DS18B20采集温度在LCD1602上显示
第一行显示温度第二行显示精度
Proteus运行仿真图
文章来源地址https://www.toymoban.com/news/detail-508192.html
源程序
主函数
#include<reg51.h>
#include "mine.h"
uchar code WenDu[]={"Tempture:"};
uchar code JingDu[]={"Accuracy:0.0625"};
uchar code Sz[]={"0123456789"};
int Tempture;
void main()
{ LCD_Init();
ds18b20Init();
ds18b20Start();
delayxms(1000);
while(1)
{
TemptureDisplay();
}
}
void TemptureDisplay()
{
uint i,Bai,Ge,Shi;
Tempture=ds18b20ReadTemperture()*10;
/*温度是正还是负*/
if(Tempture<0)
{
Tempture=-Tempture;
DisplayChar(1,9,'-');
}
else DisplayChar(1,9,'+');
/*取出温度每一位*/
Bai=Tempture/100;
Ge=Tempture%10;
Shi=(Tempture%100)/10;
/*显示Tempture:*/
for(i=0;i<9;i++)
DisplayChar(1,i,WenDu[i]);
/*显示Accuracy:*/
for(i=0;i<15;i++)
DisplayChar(2,i,JingDu[i]);
/*显示.°C*/
DisplayChar(1,12,'.');
DisplayChar(1,14,0xdf);
DisplayChar(1,15,'C');
/*显示温度整数部分*/
DisplayChar(1,10,Sz[Bai]);
DisplayChar(1,11,Sz[Shi]);
/*显示小数部分*/
DisplayChar(1,13,Sz[Ge]);
}
自定义头文件
#ifndef _MINE_H
#define _MINE_H
#include<reg51.h>
#define uint unsigned int
#define uchar unsigned char
/**************************************ds18b20模块声明*******************************
复位*检查是否存在*读一位*读一个字节*写一个字节*开始读温度*初始*读温度并转换*显示温度*
************************************************************************************/
void ds18b20Rest();
uchar ds18b20Check();
uchar ds18b20ReadBit();
uchar ds18b20ReadByte();
void ds18b20WriteByte(uchar dat);
void ds18b20Start();
uchar ds18b20Init();
float ds18b20ReadTemperture();
void TemptureDisplay();
sbit DQ=P3^3;
/*************************LCD1602模块声明**************************
****************查忙*写数据*写命令*初始化*显示一个字符*************
*******************************************************************/
void Busy();
void W_Data(uchar dat);
void W_Cmd(uchar cmd);
void LCD_Init();
void DisplayChar(uchar y , uchar x , uchar dat );
sbit rs=P2^0;
sbit rw=P2^1;
sbit e=P2^2;
/***********共用模块声明*********
定时器T0初始化*延时10us*延时xms*/
void delay10us(uint us);
void delayxms(uint x);
#endif
LCD1602函数
#include<reg51.h>
#include "mine.h"
/*检查是否忙*/
void Busy()
{do
{
e=0;
rs=0;
rw=1;
P0=0Xff;
e=1;
} while (P0^7==1);
}
/*lcd1602写指令函数*/
void W_Cmd(uchar cmd)
{
P0=cmd;//要写入的命令
rs=0; //低电平写指令
rw=0; //选择写
e=0;
delayxms(2);
e=1;
delayxms(2);
e=0;
}
/*lcd1602写数据函数*/
void W_Data(uchar dat )
{
P0=dat;//要写入的数据
rs=1; //高电平写数据
rw=0; //选择写
e=0;
delayxms(2);
e=1;
delayxms(2);
e=0;
}
/*初始化*/
void LCD_Init()
{
W_Cmd(0x38);//16列两行,8位数据口(指令6)
W_Cmd(0x0c);//开显示 关光标 不闪烁(指令4)
W_Cmd(0x06);//写一个数据后,显示位置右移一位(指令3)
W_Cmd(0x01);//清屏(指令1)
}
/*在指定的位置显示一个字符*/
void DisplayChar(uchar y , uchar x , uchar dat )
{
uchar address;
if (y==1) //等于1使用第一行显示
address=0x80+x; //第一行起始地址80H,加x为最终显示字符地址
else
address=0xc0+x; //第二行起始地址c0H,加x为最终显示字符地址
W_Cmd(address); //写入地址
W_Data(dat); //写入数据
}
DS18B20
#include<intrins.h>
#include "mine.h"
/***************复位**********/
void ds18b20Reset()
{
DQ=0;
delay10us(75);//拉低DQ,750us(480~960)
DQ=1;
delay10us(2);//DQ=1,20US(15~60)
}
/*******检测18b20是否存在**********/
uchar ds18b20Check()
{
uchar time_temp=0;
while(DQ&&time_temp<20) //等待DQ为低电平,如果一直高电平且超过200us退出,
{
time_temp++;
delay10us(1);
}
if(time_temp>=20)return 1;//ds18b20没有响应
else time_temp=0;//检测到ds18b20
while((!DQ)&&time_temp<20)
{
time_temp++;
delay10us(1);
}
if(time_temp>=20)return 1; //如果超时则强制返回1
return 0;//检测到响应
}
/*********温度读取(一位)**********/
uchar ds18b20ReadBit()
{
uchar dat=0;
DQ=0;
_nop_();_nop_();
DQ=1;
_nop_();_nop_(); //该段时间不能过长,必须在15us内读取数据
if(DQ)dat=1; //读1
else dat=0;//读0
delay10us(6);
return dat;
}
/*******温度读取(一个字节)**********/
uchar ds18b20ReadByte()
{
uchar i=0;
uchar dat=0;
uchar temp=0;
for(i=0;i<8;i++)//循环8次,每次读取一位,且先读低位再读高位
{
temp=ds18b20ReadBit();
dat=(temp<<7)|(dat>>1);//temp左移7位或上dat右移1位
}
return dat;
}
/*******温度写入(一个字节)**********/
void ds18b20WriteByte(uchar dat)
{
uchar i=0;
uchar temp=0;
for(i=0;i<8;i++)//循环8次,每次写一位,且先写低位再写高位
{
temp=dat&0x01;//取出低位,选择低位准备写入
dat>>=1;//将次高位移到低位右移
if(temp)
{
DQ=0;
_nop_();_nop_();//延时2us(>1us)
DQ=1;//释放总线
delay10us(6);//至少60us
}
else
{
DQ=0;//写0与写1延时相反
delay10us(6);
DQ=1;
_nop_();_nop_();
}
}
}
void ds18b20Start()
{
ds18b20Reset();//复位
ds18b20Check();//检查DS18B20
ds18b20WriteByte(0xcc);//SKIP ROM
ds18b20WriteByte(0x44);//转换命令
}
uchar ds18b20Init()
{
ds18b20Reset();
return ds18b20Check();
}
/***********温度读取*********/
float ds18b20ReadTemperture()
{
float temp;
uchar datH=0;
uchar datL=0;
uint value=0;
ds18b20Start();//开始转换
ds18b20Reset();//复位
ds18b20Check();
ds18b20WriteByte(0xcc);//SKIP ROM
ds18b20WriteByte(0xbe);//读存储器
datL=ds18b20ReadByte();//低字节
datH=ds18b20ReadByte();//高字节
value=(datH<<8)+datL;//合并为16位数据
if((value&0xf800)==0xf800)//0xf800(1111 1000 0000 0000)判断符号位,负温度(前五位正负后五位温度)
{
value=(~value)+1; //数据取反再加1
temp=value*(-0.0625);//乘以精度
}
else //正温度
{
temp=value*0.0625;
}
return temp;
}
共用函数
#include<reg51.h>
#include "mine.h"
void T0_init()
{
TMOD=0x01;//设置定时器0
TH0=0x3c;//装初值
TL0=0xb0;
EA=1;//开总中断
ET0=1;//开定时器0中断
TR0=1;//启动定时器0
}
void delay10us(uint us)
{
while(us--);
}
void delayxms(uint x)
{
uint i,j;
for(i=0;i<x;i++)
for(j=0;j<110;j++);
}
显示负数的时候小数位会有偏差但不知道原因
文章来源:https://www.toymoban.com/news/detail-508192.html
到了这里,关于51单片机DS18B20测温LCD1602显示的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!