官方给的原理图里面18b20的电路结构:
下面是控制DS18B20的指令:(蓝桥杯会用到的指令就三个)
CCH---跳过ROM;---你要知道DS18B20是采用单总线传输的,假如在一个仓库里面测量这个仓库的温度,不可能只要一个温度传感器就测的完,所以会要多个DS18B20,那么怎么区分这些相同的DS18B20呢?靠的就是其自身的地址,而蓝桥杯单片机上就一个ds18b20,所以省略这步,直接跳过找地址的步骤。---0xcc.
44H--温度转换;--0x44
BEH--读暂存器 ;--0xbe
蓝桥杯官方比赛的时候会给我们驱动代码,我们只需要知道其意思,并且会运用就行了。
onewire.c
/*
程序说明: 单总线驱动程序
软件环境: Keil uVision 4.10
硬件环境: CT107单片机综合实训平台(外部晶振12MHz) STC89C52RC单片机
日 期: 2011-8-9
*/
#include "reg52.h"
sbit DQ = P1^4; //单总线接口
//单总线延时函数
void Delay_OneWire(unsigned int t) //STC89C52RC
{
t=t*12;//注意在驱动里面改一下延时,15单片机是单周期的单片机,一个时钟周期就是一个机械周期
while(t--);
}
//通过单总线向DS18B20写一个字节
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);
}
//从DS18B20读取一个字节
unsigned char Read_DS18B20(void)
{
unsigned char i;
unsigned char dat;
for(i=0;i<8;i++)
{
DQ = 0;
dat >>= 1;
DQ = 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;
}
onewire.h
#ifndef __ONEWIRE_H
#define __ONEWIRE_H
unsigned char rd_temperature(void); //; ;
void Write_DS18B20(unsigned char dat);
unsigned char Read_DS18B20(void);
bit init_ds18b20(void);
void Delay_OneWire(unsigned int t);
#endif
针对驱动函数:
在比赛的时候驱动函数大概率我们要将onewire.c里面的延时函数变量扩大12倍,因为如果给出的是传统51单片机下的驱动,12个时钟周期是一个机器周期;而我们比赛用的15单片机是1个时钟周期为一个机器周期。
还有就是需要检查onewire.h里面是否包含了我们需要用到的onewire.c里面的函数,如果没有的话需要手动添加onewire.c里面的函数声明添加到onewire.h里面。
比赛时候我们需要写的读取温度程序:
uint lsb=0;//低8位
uint msb=0;//高8位
uint temp=0;//16位温度变量
void read_temp()
{
init_ds18b20(); //单片机告诉dsb20要用它了,初始化一下
Write_DS18B20(0xcc);//跳过ROM指令,意思只用1个ds18b20,不用再选地址了
Write_DS18B20(0x44);//开始温度转换
//Delayms(2); //延时,延时长短决定读取温度间隔缝隙
init_ds18b20(); //再次初始化
Write_DS18B20(0xcc); //跳过ROM指令
Write_DS18B20(0xbe); //读取高速暂存器
lsb=Read_DS18B20(); //读取低8位
msb=Read_DS18B20(); //读取高8位
//要求保留两位小数
temp=(msb<<8)|lsb;//此时temp16位包括整数和小数部分
temp=temp>>4;//此时整数部分右移4位,消除了小数部分,且乘了分辨率0.0625
//若要求不要小数转换到这步骤即可
temp=temp*100;//整数部分扩大100倍,现在可看作是10进制数
temp=temp+(lsb&0x0f)*6.25;//整数部分加上(小数部分乘以分辨率和100倍)
//最后temp现在是一个4位数的整数
}
l