文章目录
- 温度传感器
- 一、温度传感器DS18B20
- 二、DS18B20驱动程序
- 三、使用数码管显示
- 四、使用LCD1602显示
- 五、使用LCD12864显示
温度传感器
一、温度传感器DS18B20
DS18B20介绍
DS18B20是一款数字温度传感器,是一种高精度、数字输出的温度传感器,被广泛用于各种应用场景,特别是需要测量温度并将数据数字化输出的情况。
以下是DS18B20的一些主要特点和特性:
-
数字输出: DS18B20以数字形式输出温度数据,使用1-Wire总线协议进行通信,这使得多个DS18B20传感器可以通过同一根总线进行连接。
-
高精度: DS18B20提供高精度的温度测量,通常在±0.5摄氏度范围内。这使得它适用于对温度精度要求较高的应用。
-
范围广泛: DS18B20的温度测量范围较广,通常在-55摄氏度到+125摄氏度之间。
-
电源和信号共用: 这个传感器通过单一的数据线同时提供电源和传输温度数据,使其在布线上更为简单。
-
可编程分辨率: DS18B20允许用户选择不同的温度分辨率,以平衡精度和测量速度之间的需求。
-
防水版本: DS18B20也有防水版本,使其适用于需要在潮湿或液体环境中测量温度的应用。
DS18B20广泛应用于温度监测系统、气象站、家用电器、工业自动化等领域。由于其数字输出和方便的接口,它易于集成到各种数字系统中。
二、DS18B20驱动程序
芯片引脚连接图
DS18B20.h
#ifndef __DS18B20_H_
#define __DS18B20_H_
void Delay1ms(unsigned int y); //1ms延时
void Delay480us(); //480us延时
unsigned char Ds18b20Init(); //初始化DS18B20
void Ds18b20WriteByte(unsigned char dat); //写字节
unsigned char Ds18b20ReadByte(); //读字节
void Ds18b20ChangTemp(); //温度转换
void Ds18b20ReadTempCom(); //发送读取温度命令
int Ds18b20ReadTemp(); //读取温度
#endif
DS18B20.c
#include "DS18B20.h"
sbit DQ=P3^7;
/*1ms延时*/
void Delay1ms(unsigned int y)
{
unsigned int x;
for( ; y>0; y--)
{
for(x=110; x>0; x--);
}
}
/*480us延时*///@11.0592MHz
void Delay480us()
{
unsigned char i, j;
i = 6;
j = 38;
do
{
while (--j);
} while (--i);
}
/*DS18B20初始化*/
unsigned char Ds18b20Init()
{
DQ = 0; //将总线拉低480us~960us
Delay480us(); //480us的延时
DQ = 1; //然后拉高总线,如果DS18B20做出反应会将在15us~60us后总线拉低
while(DQ) //等待DS18B20拉低总线
{
Delay1ms(5);
if(DQ==1)//等待>5MS
{
return 0;//初始化失败
}
}
return 1;//初始化成功
}
/*写字节函数*/
void Ds18b20WriteByte(unsigned char dat)
{
unsigned char i,j;
for(j=0; j<8; j++)
{
DQ = 0; //每写入一位数据之前先把总线拉低1us
i++;
DQ = dat & 0x01; //然后写入一个数据,从最低位开始
i=6;
while(i--); //延时68us,持续时间最少60us
DQ = 1; //然后释放总线,至少1us给总线恢复时间才能接着写入第二个数值
dat >>= 1;
}
}
/*读取字节函数*/
unsigned char Ds18b20ReadByte()
{
unsigned char byte, bi;
unsigned int i, j;
for(j=8; j>0; j--)
{
DQ = 0;//先将总线拉低1us
i++;
DQ = 1;//然后释放总线
i++;
i++;//延时6us等待数据稳定
bi = DQ; //读取数据,从最低位开始读取
/*将byte左移一位,然后与上右移7位后的bi,注意移动之后移掉那位补0。*/
byte = (byte >> 1) | (bi << 7);
i = 4; //读取完之后等待48us再接着读取下一个数
while(i--);
}
return byte;
}
/*让18b20开始转换温度*/
void Ds18b20ChangTemp()
{
Ds18b20Init();
Delay1ms(1);
Ds18b20WriteByte(0xcc); //跳过ROM操作命令
Ds18b20WriteByte(0x44); //温度转换命令
}
/*发送读取温度命令*/
void Ds18b20ReadTempCom()
{
Ds18b20Init();
Delay1ms(1);
Ds18b20WriteByte(0xcc); //跳过ROM操作命令
Ds18b20WriteByte(0xbe); //发送读取温度命令
}
/*读取温度*/
int Ds18b20ReadTemp()
{
int temp = 0;
unsigned char tmh, tml;
Ds18b20ChangTemp(); //先写入转换命令
Ds18b20ReadTempCom(); //然后等待转换完后发送读取温度命令
tml = Ds18b20ReadByte(); //读取温度值共16位,先读低字节
tmh = Ds18b20ReadByte(); //再读高字节
temp = tmh;
temp <<= 8;
temp |= tml;
return temp;
}
三、使用数码管显示
数码管电路引脚连接图
main.c
#include "reg51.h"
#include"DS18B20.h"
sbit LSA=P2^2; //数码管位选
sbit LSB=P2^3;
sbit LSC=P2^4;
unsigned char num=0;
unsigned char DisplayData[8];
unsigned char code smgduan[10]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f}; //数码管段选
/*延时函数*/
void delay(unsigned int i)
{
while(i--);
}
/*温度读取处理转换函数*/
void datapros(int temp)
{
float tp;
if(temp<0) //当温度值为负数
{
DisplayData[0] = 0x40; // -
temp=temp-1;
temp=~temp;
tp=temp;
temp=tp*0.0625*100+0.5;
}
else
{
DisplayData[0] = 0x00;
tp=temp; //因为数据处理有小数点所以将温度赋给一个浮点型变量
temp=tp*0.0625*100+0.5;
}
DisplayData[1] = smgduan[temp/10000];
DisplayData[2] = smgduan[temp/1000%10];
DisplayData[3] = smgduan[temp/100%10] | 0x80;
DisplayData[4] = smgduan[temp/10%10];
DisplayData[5] = smgduan[temp % 10];
}
/*数码管显示函数*/
void DigDisplay()
{
unsigned char i;
for(i=0;i<6;i++)
{
switch(i) //位选,选择点亮的数码管,
{
case(0):
LSA=0;LSB=0;LSC=0; break;//显示第0位
case(1):
LSA=1;LSB=0;LSC=0; break;//显示第1位
case(2):
LSA=0;LSB=1;LSC=0; break;//显示第2位
case(3):
LSA=1;LSB=1;LSC=0; break;//显示第3位
case(4):
LSA=0;LSB=0;LSC=1; break;//显示第4位
case(5):
LSA=1;LSB=0;LSC=1; break;//显示第5位
}
P0=DisplayData[5-i];//发送数据
delay(100); //间隔一段时间扫描
P0=0x00;//消隐
}
}
void main()
{
while(1)
{
datapros(Ds18b20ReadTemp()); //数据处理函数
DigDisplay();//数码管显示函数
}
}
四、使用LCD1602显示
LCD1602电路引脚连接图
LCD1602.h
#ifndef __LCD1602_h
#define __LCD1602_h
#include<reg51.h>
void delay(unsigned int n);
void WriteStruction(unsigned char date);
void WriteData(unsigned char dat);
void LCDInitiate();
#endif
LCD1602.c
#include "LCD1602.h"
sbit RS=P2^6; //寄存器选择位
sbit RW=P2^5; //读写选择位
sbit EN=P2^7; //使能信号位
/*延时函数*/
void delay(unsigned int n)
{
int i,j;
for (i=n;i>0;i--)
for (j=10;j>0;j--);
}
/*LCD写指令函数*/
void WriteStruction(unsigned char date)
{
RS=0; //选择指令
RW=0; //选择写入
EN=0; //使能端初始化
P0=date; //写指令
delay(1);
EN=1; //写时序,置高电平
delay(1);
EN=0; //液晶屏出现由1到0的负跳变,使液晶模块开始工作
}
/*LCD写数据函数*/
void WriteData(unsigned char dat)
{
RS=1; //选择数据
RW=0; //选择写入
EN=0; //初始化使能端
P0=dat; //写数据
delay(1);
EN=1; //写时序
delay(1);
EN=0; //液晶屏出现由1到0的负跳变,使液晶模块开始工作
}
/*LCD初始化函数*/
void LCDInitiate()
{
WriteStruction(0x38); //功能设定指令,DL->8位 N->2行 F->5x7
WriteStruction(0x0c); //显示开关指令,DCB=100,整体显示,关光标,不闪烁
WriteStruction(0x06); //进入模式设置指令,设定输入方式,增量不移位
WriteStruction(0x01); //清屏指令,清除屏幕显示
}
main.c
#include <reg51.h>
#include "DS18B20.h"
#include "LCD1602.h"
unsigned DisplayData[8];
unsigned char code digit[]="0123456789";
unsigned char code D1[]=" Temp: C";
/*延时函数*/
void delay_us(unsigned int i)
{
while(i--);
}
/*温度读取处理转换函数*/
void datapros(int temp)
{
float tp;
if(temp<0) //当温度值为负数
{
WriteStruction(0x80+0x05);
WriteData('-'); // -
temp=temp-1;
temp=~temp;
tp=temp;
temp=tp*0.0625*100+0.5;
}
else
{
WriteStruction(0x80+0x05);
WriteData('+');
tp=temp; //因为数据处理有小数点所以将温度赋给一个浮点型变量
temp=tp*0.0625*100+0.5;
}
DisplayData[1] = digit[temp/10000];
DisplayData[2] = digit[temp/1000%10];
DisplayData[3] = digit[temp/100%10];
DisplayData[4] = digit[temp/10%10];
DisplayData[5] = digit[temp % 10];
}
/*正确显示函数*/
void display_right()
{
unsigned char i;
LCDInitiate();
WriteStruction(0x80+0x00);
i=0;
while(D1[i]!='\0')
{
WriteData(D1[i]);
i++;
}
WriteStruction(0x80+0x0c);
WriteData(0xdf);
}
/*LCD1602显示温度*/
void display_temp()
{
WriteStruction(0x80+0x06);
WriteData(DisplayData[1]);
WriteStruction(0x80+0x07);
WriteData(DisplayData[2]);
WriteStruction(0x80+0x08);
WriteData(DisplayData[3]);
WriteStruction(0x80+0x09);
WriteData('.');
WriteStruction(0x80+0x0a);
WriteData(DisplayData[4]);
WriteStruction(0x80+0x0b);
WriteData(DisplayData[5]);
}
void main()
{
display_right();
while(1)
{
datapros(Ds18b20ReadTemp()); //数据处理函数
display_temp();
delay_us(1000);
}
}
五、使用LCD12864显示
LCD12864电路引脚连接图
LCD12864.h
#ifndef __LCD12864_H
#define __LCD12864_H
# include <reg51.h>
/*接口定义模块*/
#define LCD12864_DATAPORT P0 //数据IO口
sbit LCD12864_RS = P2^6; //(数据命令)寄存器选择输入
sbit LCD12864_RW = P2^5; //液晶读/写控制
sbit LCD12864_EN = P2^7; //液晶使能控制
sbit LCD12864_PSB = P3^2; //串/并方式控制
sbit LCD12864_RST = P3^4; //复位端
/*函数声明模块*/
void LCD12864_Delay1ms(unsigned int c); //延时函数
void LCD12864_WriteCmd(unsigned char cmd); //写指令函数
void LCD12864_WriteData(unsigned char dat); //写数据函数
void LCD12864_Init(); //12864初始化函数
void LCD12864_SetWindow(unsigned char x, unsigned char y); //坐标函数
#endif
LCD12864.c
#include"lcd12864.h"
/*延时函数*/
void LCD12864_Delay1ms(unsigned int c)
{
unsigned int a,b;
for(; c>0; c--)
{
for(b=199; b>0; b--)
{
for(a=1; a>0; a--);
}
}
}
/*写指令函数*/
void LCD12864_WriteCmd(unsigned char cmd)
{
LCD12864_RS = 0; //选择命令
LCD12864_RW = 0; //选择写入
LCD12864_EN = 0; //初始化使能端
LCD12864_DATAPORT = cmd; //放置数据
LCD12864_EN = 1; //写时序
LCD12864_Delay1ms(5);
LCD12864_EN = 0;
}
/*写数据函数*/
void LCD12864_WriteData(unsigned char dat)
{
LCD12864_RS = 1; //选择数据
LCD12864_RW = 0; //选择写入
LCD12864_EN = 0; //初始化使能端
LCD12864_DATAPORT = dat; //放置数据
LCD12864_EN = 1; //写时序
LCD12864_Delay1ms(5);
LCD12864_EN = 0;
}
/*初始化函数*/
void LCD12864_Init()
{
LCD12864_PSB = 1; //选择并行输入
LCD12864_RST = 1; //复位
LCD12864_WriteCmd(0x30); //选择基本指令操作
LCD12864_WriteCmd(0x0c); //显示开,关光标
LCD12864_WriteCmd(0x01); //清除LCD12864的显示内容
}
/*在基本指令模式下设置显示坐标。注意:x是设置行,y是设置列*/
void LCD12864_SetWindow(unsigned char x, unsigned char y)
{
unsigned char pos;
if(x == 0) // 第一行的地址是80H
{
x = 0x80;
}
else if(x == 1) //第二行的地址是90H
{
x = 0x90;
}
else if(x == 2) //第三行的地址是88H
{
x = 0x88;
}
else if(x == 3)
{
x = 0x98;
}
pos = x + y;
LCD12864_WriteCmd(pos);
}
main.c
#include <reg51.h>
#include "DS18B20.h"
#include "LCD12864.h"
unsigned DisplayData[8];
unsigned char code digit[]="0123456789";
unsigned char code D1[]="温度: ";
void delay_us(unsigned int i) /*延时函数*/
{
while(i--);
}
/*温度读取处理转换函数*/
void datapros(int temp)
{
float tp;
if(temp<0) //当温度值为负数
{
LCD12864_WriteCmd(0x80+0x00);
LCD12864_WriteData('-'); // -
temp=temp-1;
temp=~temp;
tp=temp;
temp=tp*0.0625*100+0.5;
}
else
{
LCD12864_WriteCmd(0x80+0x03);
LCD12864_WriteData('+');
tp=temp; //因为数据处理有小数点所以将温度赋给一个浮点型变量
temp=tp*0.0625*100+0.5;
}
DisplayData[1] = digit[temp/10000];
DisplayData[2] = digit[temp/1000%10];
DisplayData[3] = digit[temp/100%10];
DisplayData[4] = digit[temp/10%10];
DisplayData[5] = digit[temp % 10];
}
/*正确显示函数*/
void display_right()
{
unsigned char i;
LCD12864_Init();
LCD12864_SetWindow(0x80+0x00,0);
i=0;
while(D1[i]!='\0')
{
LCD12864_WriteData(D1[i]);
i++;
}
}
void display_temp()
{
LCD12864_WriteData(DisplayData[1]);
LCD12864_WriteData(DisplayData[2]);
LCD12864_WriteData(DisplayData[3]);
LCD12864_WriteData('.');
LCD12864_WriteData(DisplayData[4]);
LCD12864_WriteData(DisplayData[5]);
LCD12864_WriteData(' ');
LCD12864_WriteData(0xa1);
LCD12864_WriteData(0xe6);
}
void main()
{
display_right();
while(1)
{
datapros(Ds18b20ReadTemp()); //数据处理函数
display_temp();
delay_us(1000);
}
}