DS18B20
-
更新(需要注意的部分)
-
进行带小数点的高精度转换时,需要750ms的延时,建议将开始转换和读取数据的函数分开写,利用定时器保证750ms之后再去读取,不然会出现很奇怪的数字
-
数据处理的时候,可将高八位和低八位数据储存在long类型数据中,得到的数乘以625,可得到一个6位整数,后四位为小数部分,例如:
temp=high&0x0f;temp=(high<<8)|low;temp1 = temp*625;return temp1;
-
-
简介
DS18B20是数字温度传感器,为单总线设备
-
温度转换与读取流程
- DS18B20复位。
- 写入字节0xCC,跳过ROM指令(单总线上连接的设备都有唯一的64位标号,但由于蓝桥杯开发版单总线只连接了18B20,所以可以跳过设备查找)。
- 写入字节0x44,开始温度转换。
- 延时700-900ms。
- DS18B20复位。
- 写入字节0xCC,跳过ROM指令。
- 写入字节0xBE,读取高速暂存器。
- 读取高速暂存器第0字节,即温度数据LSB。
- 读取高速暂存器第1字节,即温度数据MSB。
- DS18B20复位。表示读取数据结束。
- 将LSB和MSB整合成一位16位数据。
- 判断读取结果的符号,进行正负温度的数据处理。
-
数据处理
-
DS18B20 以16位带符号拓展的二进制补码读出
-
低四位为小数部分,中间七位为整数部分,高五位为符号位,全为0时为正数,全为1时为负数。
-
DS18B20的分辨率为0.0625。读出温度为正温度时,将整合后的16位整数直接乘以0.0625即可。读出温度为负温度时,需取反+1后再乘以0.0625。
-
-
代码部分
-
onewire.c
/***********蓝桥杯onewire驱动************/
#include "onewire.h"//单总线内部延时函数
void Delay_OneWire(unsigned int t)
{unsigned char i;while(t--){for(i=0;i<12;i++);//此处应该修改延时长度}
}//单总线写操作
void Write_DS18B20(unsigned char dat)
{unsigned char i;for(i=0;i<8;i++){DQ = 0;DQ = dat&0x01;Delay_OneWire(5);DQ = 1;dat >>= 1;}Delay_OneWire(5);
}//单总线读操作
unsigned char Read_DS18B20(void)
{unsigned char i;unsigned char dat;for(i=0;i<8;i++){DQ = 0;dat >>= 1;DQ = 1;Delay_OneWire(1);//此处应加一小延时if(DQ){dat |= 0x80;} Delay_OneWire(5);}return dat;
}//DS18B20初始化
bit init_ds18b20(void)
{bit initflag = 0;DQ = 1;Delay_OneWire(12);DQ = 0;Delay_OneWire(80);DQ = 1;Delay_OneWire(10); initflag = DQ; Delay_OneWire(5);return initflag;
}
/**********自定义部分**********/
char rd_temperature(void){//读取整数unsigned char low,high;char temp;init_ds18b20();Write_DS18B20(0xcc);Write_DS18B20(0x44);Delay_OneWire(200);init_ds18b20();Write_DS18B20(0xcc);Write_DS18B20(0xBE); low = Read_DS18B20();high = Read_DS18B20();init_ds18b20();temp=high;temp<<=4;temp=temp | (low>>4);return temp;
}
- onewire.h
#ifndef __ONEWIRE_H
#define __ONEWIRE_H#include "stc15f2k60s2.h"sbit DQ = P1^4;
//读取温度
char rd_temperature(void); #endif
- main.c
#include "stc15f2k60s2.h"
#include "onewire.h"
//缩写
typedef unsigned char uchar;
typedef unsigned int uint;
//数码管部分
code uchar smg_dm[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,0xff,0x40,0x79,0x24,0x30,0x19,0x12,0x02,0x78,0x00,0x10};
uchar smg_num[]={10,10,10,10,10,10,10,10};
uchar com=0;
//全局变量
uchar temp_c=0;
bit temp_flag = 0;
char temp;
//函数声明
void hc138(uchar n){//38译码器if(n==0) P2=P2&0x1f|0x00;if(n==4) P2=P2&0x1f|0x80;if(n==5) P2=P2&0x1f|0xa0;if(n==6) P2=P2&0x1f|0xc0;if(n==7) P2=P2&0x1f|0xe0;
}
void init(){//初始化hc138(5);P0=0x00;hc138(4);P0=0xff;hc138(0);
}
void dsp(){//数码管显示P0=0xff;//消隐hc138(6);P0=0x01<<com;hc138(7);P0=smg_dm[smg_num[com]];(com==7)?(com=0):(com++);
}
void Timer0Init(void) //1毫秒@12.000MHz
{AUXR |= 0x80; //定时器时钟1T模式TMOD &= 0xF0; //设置定时器模式TL0 = 0x20; //设置定时初始值TH0 = 0xD1; //设置定时初始值TF0 = 0; //清除TF0标志TR0 = 1; //定时器0开始计时EA = 1; //总中断使能onET0 = 1; //定时器0中断使能on
}
void Timer0ser() interrupt 1{temp_c++;if(temp_c==50){temp_c=0;temp_flag=1;}dsp();
}
//主函数
void main(){init();temp = rd_temperature();Timer0Init();while(1){if(temp_flag){temp_flag=0;temp = rd_temperature();}if(temp>=10){smg_num[6] = temp/10;smg_num[7] = temp%10; }else{smg_num[6]=10;smg_num[7] = temp%10;}}
}