【小蜜蜂蓝桥杯笔记】DS18B20温度传感器的使用
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; //总中断使能on
ET0 = 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;
}
}
}