DS18B20有九个字节寄存器,前四个是常用的,前两个温度转换,后两个温度上下限制
工具:
Keil uVision5
stc-isp-15xx-v6.86L
stc15w4k56s开发板
面包板
温度传感器DS18B20+电阻
液晶显示屏LCD1602
电路图连:DS18B20字面 对应引脚GND(1) IO(2) VDD(3) 电阻10K
头文件:
#include"stc15w4k32s4.h"
#include"intrins.h"
#include"delay.h"
#include"lcd1602.h"
/*----------- 端口定义 -----------*/
sbit DQ=P1^7; //ds18b20 端口
/*--------- 函数声明 ------------*/
bit Init_DS18B20(void);
unsigned char ReadOneChar(void);
void WriteOneChar(unsigned char dat);
unsigned int ReadTemperature(void);
DS18B20:
/*------- 18b20初始化 -----------*/
bit Init_DS18B20(void)
{
bit dat;
//激活六步走
DQ = 1; //复位开始
DelayUS(5);
DQ = 0;
DelayUS(260); //652us 精确延时 大于 480us 小于960us
DQ = 1;
DelayUS(50); //15~60us 后 接收60-240us的存在脉冲
//复位结束
dat=DQ; //若初始化成功,DQ保持低电平状态
//while(dat==1);
DelayUS(25); //稍作延时返回
return dat;
}
/*------- 单片机读取一个字节(低位先出) -------*/
unsigned char ReadOneChar(void)
{unsigned char i;
unsigned char dat=0; //先假设读入的是八个0
for (i=0; i<8; i++)
{
dat>>=1; //dat右移一位,【dat最高位置D7移走】
//激活四步走
DQ = 0;
DelayUS(1);
DQ = 1;
DelayUS(1);
//读取18B20的DQ线上的比特数据
if(DQ==1) dat|=0x80; //如果读入的DQ是1,将1替换dat最高位置比特D7
DelayUS(60);
}
return(dat);
}
void WriteOneChar(unsigned char dat)
{
char i;
for (i=0; i<8; i++)
{
//激活2步走
DQ = 0;
DelayUS(1);
DQ = dat&0x01; //提取dat最低位置比特D0,赋给DQ
DelayUS(60);
//善后1步走
DQ = 1; // 写结束
dat>>=1; //把dat高位比特往最低位置D0方向移动
DelayUS(1);
}
}
主程序:
/*------- 读取温度 -------*/
unsigned int ReadTemperature(void)
{
unsigned char a; //储存温度的低字节
unsigned int b=0; //储存温度的高字节
unsigned int t=0; //储存16位温度补码
//第一个周期
Init_DS18B20(); // 第1步:DS18B20复位
WriteOneChar(0xCC); // 第2步:下达不读序列号的命令 WriteOneChar(0x44); // 第3步:下达启动温度转换命令
DelayMS(10); // 第4步:适当延时
//第二个周期
Init_DS18B20(); // 第1步:DS18B20复位
WriteOneChar(0xCC); // 第2步:下达不读序列号的命令
WriteOneChar(0xBE); // 第3步:下达读SRAM的命令
// 第4步:读取温度寄存器(共可读9个寄存器)
a=ReadOneChar(); //温度值的低8位
b=ReadOneChar(); // 温度值的高8位
b<<=8; // 温度的高字节到位
t=a+b; //16位温度补码
return(t);
}
在主程序调用ReadTemperature():
int Disp_temp() //显示温度函数
{
int t,y,z;
long k;
t=ReadTemperature(); //16位温度补码
//判断温度正负,并求温度的绝对值
if(t&0x8000)
{
disp(5,'-');
t=(~t)+1; //负温度的绝对值
}
else disp(5,'+');
//t已经是温度的绝对值
y=t>>4; //提取真实温度的整数部分
z=y/100; //求温度值的百位数字
disp(6,z+0x30); //送LCD1602显示
z=y%100/10; //求温度值的十位数字
disp(7,z+0x30); //送LCD1602显示
z=y%10; //求温度值的个位数字
disp(8,z+0x30); //送LCD1602显示
disp(9,'.'); //显示小数点
k=t&0x000f; //提取真实温度的小数部分,小数部分权重0.0625
k=(k*10+8)/16; //求温度值的小数部分数字,保留1位小数第2位四舍五入
disp(10,k+0x30); //送LCD1602显示
disp(11,'C'); //显示摄氏度
return y;
}
主函数:
void main()
{
unsigned char i,xs[]={"Temp:"};
char Tl,Th;
P1M0 = 0x00;
P1M1 = 0x00;
P4M0 = 0x00;
P4M1 = 0x00;
P5M0 = 0x00;
P5M1 = 0x00;
LCD_Initial(); //LCD1602初始化
for(i=0;i<5;i++)disp(i,xs[i]); //在液晶屏的第1行显示Temp:
while(1)
{
Disp_temp(); //调用显示温度函数
delay_ms(1000);
}
}
不足:ds18b20的温度上下限难以读出来(希望指教)
仅供学习