您的位置:首页 > 其它

关于蓝桥杯STC15单片机的18B20程序

2016-03-04 13:03 567 查看
DS18B20是一种单总线数字温度传感器,测试温度范围-55℃-125℃,具有体积小,硬件开销低,抗干扰能力强,精度高的特点。单总线,意味着没有时钟线,只有一根通信线。单总线读写数据是靠控制起始时间和采样时间来完成,所以时序要求很严格,这也是DS18B20驱动编程的难点。


一.DS18B20温度传感器

1.引脚图



2.DS18B20内部结构图



主要由2部分组成:64位ROM、9字节暂存器,如图所示。

(1) 64 位ROM。它的内容是64 位序列号,它可以被看作是该DS18B20 的地址序列码,其作用是使每个DS18B20 都各不相同,这样就可以实现一根总线上挂接多个DS18B20 的目的。

(2) 9字节暂存器包含:温度传感器、上限触发TH高温报警器、下限触发TL低温报警器、高速暂存器、8位CRC产生器。

3.64位ROM结构图



8位CRC:是单总线系列器件的编码,DS18B20定义为28H。

48位序列号:是一个唯一的序列号。

8位系列码:由CRC产生器生产,作为ROM中的前56位编码的校验码。

4.9字节暂存器结构图



以上是内部9 个字节的暂存单元(包括EEPROM)。

字节0~1 是温度存储器,用来存储转换好的温度。

字节2~3 是用户用来设置最高报警和最低报警值。这个可以用软件来实现。

字节4 是配置寄存器,用来配置转换精度,让它工作在9~12 位。

字节5~7 保留位。

字节8 CRC校验位。是64位ROM中的前56位编码的校验码。由CRC发生器产生。

5.温度寄存器结构图



温度寄存器由两个字节组成,分为低8位和高8位。一共16位。

其中,第0位到第3位,存储的是温度值的小数部分。

第4位到第10位存储的是温度值的整数部分。

第11位到第15位为符号位。全0表示是正温度,全1表示是负温度。

表格中的数值,如果相应的位为1,表示存在。如果相应的位为0,表示不存在。

6.配置寄存器



精度值:

9-bit 0.5℃

10-bit 0.25℃

11-bit 0.125℃

12-bit 0.0625℃

7.温度/数据关系



注意:如果温度是一个负温度,要将读到的数据减一再取反


二.单总线协议

1.单总线通信初始化



初始化时序包括:主机发出的复位脉冲和从机发出的应答脉冲。主机通过拉低单总线480-960μs产生复位脉冲;然后由主机释放总线,并进入接收模式。主机释放总线时,会产生一由低电平跳变为高电平的上升沿,单总线器件检测到该上升沿后,延时15~60μs,接着单总线器件通过拉低总线60~240μsμ来产生应答脉冲。主机接收到从机的以应答脉冲后,说明有单总线器件在线,到此初始化完成。然后主机就可以开始对从机进行ROM命令和功能命令操作。

2.位写入时序



写时隙:当主机把数据线从逻辑高电平拉到逻辑低电平的时候,写时间隙开始。有两种写时间隙:写1的时间隙和写0时间隙。所有写时间隙必须最少持续60us,包括两个写周期间至少1us的恢复时间。DQ引脚上的电平变低后,DS18B20在一个15us到60us的时间窗口内对DQ引脚采样。如果DQ引脚是高电平,就是写1,如果DQ引脚是低电平,就是写0。主机要生成一个写1时间隙,必须把数据线拉到低电平然后释放,在写时间隙开始后的15us内允许数据线拉到高电平。主机要生成一个写0时间隙,必须把数据线拉到低电平并保持60us。

3.位读取时序



当主机把总线从高电平拉低,并保持至少1us后释放总线;并在15us内读取从DS18B20输出的数据。

4.DS18B20的ROM操作命令

用途:主要是用于选定在单总线上的DS18B20,分为5个命令

(1).读出ROM,代码为33H,用于读出DS18B20的序列号,即64位激光ROM代码。

(2).匹配ROM,代码为55H,用于识别(或选中)某一特定的DS18B20进行操作。

(3).搜索ROM,代码为F0H,用于确定总线上的节点数以及所有节点的序列号。

(4).跳过ROM,代码为CCH,当总线仅有一个DS18B20时,不需要匹配 。

(5).报警搜索,代码为ECH,主要用于鉴别和定位系统中超出程序设定的报警温度界限的节点。


三.驱动程序

单片机:STC15

竞赛给出的驱动
18B20.C文件
/*

????: ???????

????: Keil uVision 4.10

????: CT107?????????

? ?: 2011-8-9

*/

#include "onewire.h"

//???????

void Delay_OneWire(unsigned int t)

{

unsigned char i;

while(t--)

for(i=0;i<12;i++);//此处是驱动有问题,所以需要进行修改

}

//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;

}

//??????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;

}

Main.c文件

#include "onewire.h"

#include "absacc.h"

#define uchar unsigned char

#define uint unsigned int

code unsigned char duan[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71};

code unsigned char wei[]={0xfe,0xfd,0xfb,0xf7,0xef,0xdf,0xbf,0x7f};

uchar dis[4];

uint value;

void delay(unsigned int x)

{

unsigned int y;

for(x;x>0;x--)

for(y=110;y>0;y--);

}

uint Get_Temp(void)//温度是由两个字节构成的返回值必须是uint型(PS:关于int型的范围,由具体的编译器决定,keil中51系列对应2字节16位,MDK对应的4字节32位)

{

uint temp=0;//与返回值定义的一样

uchar LS,MS;

Init_DS18B20();

Write_DS18B20(0xcc);//跳过ROM

Write_DS18B20(0x44);//启动转换

Init_DS18B20();

Write_DS18B20(0xcc);

Write_DS18B20(0xbe);//读取温度

LS=Read_DS18B20();

MS=Read_DS18B20();

temp=(MS<<8)|LS;

return temp;

}

uint Temp_Change(void)

{

uint t;

float tp;//此处非常重要,用浮点型来存放十进制的温度

t=Get_Temp();

if(t<0) //考虑温度为负,用减一取反

{

t=~(t-1);

tp=t*0.0625; //16??????10?????

t=tp*100+0.5; //

}

else

{

tp=t*0.0625; //转换公式 精度0.0625

t=tp*100+0.5; //例如温度为12.654*100+0.5 =1265.9 四省五入

}

return t;

}

void Display(void)

{

uchar i;

dis[0]=duan[value/1000];

dis[1]=duan[value%1000/100]|0x80;

dis[2]=duan[value%100/10];

dis[3]=duan[value%10];

for(i=0;i<4;i++)

{

XBYTE[0xE000]=~dis[i];

XBYTE[0xC000]=~wei[i];

delay(1);

XBYTE[0xC000]=~0xff;

}

}

void Cls_LED()

{

XBYTE[0x8000]=0xff;

}

void Cls_Buzz(void)

{

XBYTE[0xA000]=0x00;

}

void main(void)

{

Cls_Buzz();

Cls_LED();

while(1)

{

value=Temp_Change();

Display();

}

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: