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 小于960usDQ = 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; //先假设读入的是八个0for (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,赋给DQDelayUS(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.0625k=(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的温度上下限难以读出来(希望指教)
仅供学习