介绍
DS18B20采集温度每隔一分钟在LCD12864上显示
第一行显示温度第二行显示范围第三行显示1一分钟
Proteus仿真运行图
源程序
主函数
#include<reg51.h>
#include <intrins.h>
#include "mine.h"
uchar count,num,n=1;
int tempValue,Tempture;
void main()
{
T0_init();
ds18b20Init();
ds18b20Start();
delayxms(1000);//保证最开始显示当前的温度
Tempture=ds18b20ReadTemperture()*10;
InitLCD();
while(1)
{
TemptureDisplay();
/*****显示60秒计时*****/
DisplayZf(1,6,48,num/10);
DisplayZf(1,6,56,num%10);
}
}
void T0_t() interrupt 1
{
ds18b20Start();
TH0=0x3c;//重装初值
TL0=0xb0;
count++;
if (count==20)//到了20次即1s时间
{
count=0;//清零开始
num++;
if(num==5)
{
num=0;
n=1;
}
}
}
void TemptureDisplay()
{
uint i,Bai,Ge,Shi;
uint FanWei[]={10,12,5,5,16,1,2,5,14,15};
if(n)
{ n=0;
Tempture=ds18b20ReadTemperture()*10;
if(Tempture<0)
{
Tempture=-Tempture;
DisplayZf(1,2,40,12);
}
else
{
DisplayZf(1,2,40,11);
}}
Bai=Tempture/100;
Ge=Tempture%10;
Shi=(Tempture%100)/10;
/******温度:*.*°*C*********/
for(i=0;i<2;i++)
DisplayHz(1,2,i*16,i);
DisplayZf(1,2,32,10);
DisplayZf(1,2,48,Bai);
DisplayZf(1,2,56,Shi);
DisplayZf(2,2,0,13);
DisplayZf(2,2,8,Ge);
DisplayZf(2,2,16,14);
DisplayZf(2,2,24,15);
/*显示范围*/
for(i=2;i<4;i++)
DisplayHz(1,4,(i-2)*16,i);//范围:
for(i=0;i<4;i++)
DisplayZf(1,4,(i*8+32),FanWei[i]);//-55
for(i=4;i<10;i++)
DisplayZf(2,4,(i*8-32),FanWei[i]);//~125°C
}
自定义头文件
#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;
/*************************LCD12864模块声明**************************
查忙*写数据*写命令*设定页数(共四行八页0~7)*起始行*列数(64列0~63)****
开关*清屏*初始化*显示汉字(16*16(宽*高))*显示字符(8*16(宽*高))*
*******************************************************************/
void busy();
void W_Data(uchar dat);
void W_Cmd(uchar cmd);
void S_Page(uchar page);
void S_StartHang(uchar hang);
void S_Lie(uchar lie);
void S_OnOff(uchar onoff);
void S_Screen(uchar screen);
void ClS(uchar screen);
void InitLCD();
void DisplayHz(uchar s,uchar page,uchar lie,uchar number);
void DisplayZf(uchar s,uchar page,uchar lie,uchar number);
sbit rs=P2^0;
sbit rw=P2^1;
sbit e=P2^2;
sbit cs1=P2^3;
sbit cs2=P2^4;
/***********共用模块声明*********
定时器T0初始化*延时10us*延时xms*/
void T0_init();
void delay10us(uint us);
void delayxms(uint x);
#endif
LCD12864函数(不带字库)
#include<reg51.h>
#include "mine.h"
uchar code Hzk[]=
{
/***********************************温*****************************************/
0x10,0x60,0x02,0x8C,0x00,0x00,0xFE,0x92,0x92,0x92,0x92,0x92,0xFE,0x00,0x00,0x00,
0x04,0x04,0x7E,0x01,0x40,0x7E,0x42,0x42,0x7E,0x42,0x7E,0x42,0x42,0x7E,0x40,0x00,
/***********************************度*****************************************/
0x00,0x00,0xFC,0x24,0x24,0x24,0xFC,0x25,0x26,0x24,0xFC,0x24,0x24,0x24,0x04,0x00,
0x40,0x30,0x8F,0x80,0x84,0x4C,0x55,0x25,0x25,0x25,0x55,0x4C,0x80,0x80,0x80,0x00,
/***********************************范*****************************************/
0x04,0x44,0x84,0x14,0x64,0x0F,0x04,0xE4,0x24,0x2F,0x24,0x24,0xE4,0x04,0x04,0x00,
0x00,0x08,0x09,0x78,0x04,0x03,0x00,0x3F,0x40,0x40,0x42,0x44,0x43,0x40,0x78,0x00,
/***********************************围*****************************************/
0x00,0xFE,0x02,0x12,0x52,0x52,0x52,0xFE,0x52,0x52,0x52,0x12,0x02,0xFE,0x00,0x00,
0x00,0xFF,0x40,0x41,0x41,0x41,0x41,0x7F,0x41,0x49,0x51,0x4F,0x40,0xFF,0x00,0x00,
/*****************************宋体小四(64*64)********************************/
};
uchar code Zfk[]=
{
/**************************************0~9************************************/
0x00,0xE0,0x10,0x08,0x08,0x10,0xE0,0x00,0x00,0x0F,0x10,0x20,0x20,0x10,0x0F,0x00,
0x00,0x00,0x10,0x10,0xF8,0x00,0x00,0x00,0x00,0x00,0x20,0x20,0x3F,0x20,0x20,0x00,
0x00,0x70,0x08,0x08,0x08,0x08,0xF0,0x00,0x00,0x30,0x28,0x24,0x22,0x21,0x30,0x00,
0x00,0x30,0x08,0x08,0x08,0x88,0x70,0x00,0x00,0x18,0x20,0x21,0x21,0x22,0x1C,0x00,
0x00,0x00,0x80,0x40,0x30,0xF8,0x00,0x00,0x00,0x06,0x05,0x24,0x24,0x3F,0x24,0x24,
0x00,0xF8,0x88,0x88,0x88,0x08,0x08,0x00,0x00,0x19,0x20,0x20,0x20,0x11,0x0E,0x00,
0x00,0xE0,0x10,0x88,0x88,0x90,0x00,0x00,0x00,0x0F,0x11,0x20,0x20,0x20,0x1F,0x00,
0x00,0x18,0x08,0x08,0x88,0x68,0x18,0x00,0x00,0x00,0x00,0x3E,0x01,0x00,0x00,0x00,
0x00,0x70,0x88,0x08,0x08,0x88,0x70,0x00,0x00,0x1C,0x22,0x21,0x21,0x22,0x1C,0x00,
0x00,0xF0,0x08,0x08,0x08,0x10,0xE0,0x00,0x00,0x01,0x12,0x22,0x22,0x11,0x0F,0x00,
/**********************************:,+,-,.,°,C,~*********************************/
0x00,0x00,0x00,0xC0,0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x30,0x30,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0xE0,0x00,0x00,0x00,0x00,0x01,0x01,0x01,0x0F,0x01,0x01,0x01,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x01,0x01,0x01,0x01,0x01,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x30,0x30,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x0C,0x12,0x12,0x0C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0xC0,0x30,0x08,0x08,0x08,0x08,0x38,0x00,0x07,0x18,0x20,0x20,0x20,0x10,0x08,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x01,0x02,0x02,0x04,0x02,0x00,
};
/*检查是否忙*/
void busy()
{uchar dat;
rs=0;rw=1;
do{
P0=0x00;
e=1;
dat=P0;
e=0;
dat=0x80 & dat;
}while(!(dat==0x00));
}
/*写数据到LCD中*/
void W_Data(uchar dat)
{
busy();
rs=1;rw=0;
P0=dat;
e=1;e=0;
}
/*写命令到LCD中*/
void W_Cmd(uchar cmd)
{
busy();
rs=0;rw=0;
P0=cmd;
e=1;e=0;
}
/*设置页(8行为一页,共64行即8页(0~7页)*/
void S_Page(uchar page)
{
page=0xb8|page;//只有0~7页
W_Cmd(page);
}
/*起始行*/
void S_StartHang(uchar hang)
{
hang=0xc0|hang;
W_Cmd(hang);
}
/*设定列*/
void S_Lie(uchar lie)
{
lie=lie&0x3f;//lie&(0011 1111),列大于63自动从零列
lie=0x40|lie;
W_Cmd(lie);
}
/*开(关)显示*/
void S_OnOff(uchar onoff)
{
onoff=0x3e|onoff;//(0011 1110)|onoff,0关1开
W_Cmd(onoff);
}
/*屏幕选择*/
void S_Screen(uchar screen)
{
switch(screen)
{
case 0:cs1=0;cs2=0;break;//全屏
case 1:cs1=0;cs2=1;break;//左屏
case 2:cs1=1;cs2=0;break;//右屏
}
}
/*清屏*/
void ClS(uchar screen)
{
uchar i,j;
S_Screen(screen);//选择清除那个屏
for(i=0;i<8;i++)
{
S_Page(i);
S_Lie(0);
for(j=0;j<64;j++)
W_Data(0x00);
}
}
/*初始化*/
void InitLCD()
{
busy();
S_Screen(0);S_OnOff(0);
S_Screen(0);S_OnOff(1);
S_Screen(0);ClS(0);
S_StartHang(0);
}
/*显示*/
void DisplayHz(uchar s,uchar page,uchar lie,uchar number)
{int i;
S_Screen(s);
lie=lie&0x3f;
S_Page(page);S_Lie(lie);
for(i=0;i<16;i++)
W_Data(Hzk[i+32*number]);//显示汉字上半部分
S_Page(page+1);S_Lie(lie);
for(i=0;i<16;i++)
W_Data(Hzk[i+32*number+16]);//显示汉字下半部分
}
void DisplayZf(uchar s,uchar page,uchar lie,uchar number)
{
int i;
S_Screen(s);
lie=lie&0x3f;
S_Page(page);S_Lie(lie);
for(i=0;i<8;i++)
W_Data(Zfk[i+16*number]);
S_Page(page+1);S_Lie(lie);
for(i=8;i<16;i++)
W_Data(Zfk[i+16*number]);
}
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://pan.baidu.com/s/15w685otALwl1cU_H0WCJKQ
提取码:1111