1、  DS18B20接口很简单,VCC、DQ、GND三个引脚,VCC采用外部供电3.3V,DQ需上拉电阻,当时按照参考资料上外接4.7K的上拉电阻,GPIO设置的OD无上拉,始终读不到ROM中的64位序列号,后面发送的转换指令更别想了,后来GPIO改成推挽输出时,诶,就能读到数据,推挽输出无非就是增大驱动能力,仔细看手册,其中有提到,DS18B20空闲处于低功耗状态,在执行温度转换或从高速暂存器向EPPROM传送数据时,工作电流可高达1.5mA,但并有说读ROM中的64位数据时,电流需要多少,也许在读ROM中的数据电流也需要要求。知道了加大驱动能力才能读到,加上之前写I2C和FLASH擦除时,数据线都是设置OD类型,通用性较好,好移植,所以还是改成OD类型,把4.7K的电阻换小点,换成1K电阻,就可以正确的读写操作。

GPIO配置:

 void Ds18b20_GPIO_Config(void)
{
GPIO_InitTypeDef GPIO_InitStructure; RCC_AHB1PeriphClockCmd( RCC_AHB1Periph_GPIOE,ENABLE); GPIO_InitStructure.GPIO_Pin = DS18B20_DATA;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;
GPIO_InitStructure.GPIO_OType = GPIO_OType_OD; //OD门
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOE,&GPIO_InitStructure);
}

2、操作步骤,在使用任何一条功能指令前,都必须先执行有复位、ROM指令。

(1)、复位信号就是双方握手,达成协议后才能相互通信。时序如下,一定要注意minimum和maximum,Master主机先发送低电平脉冲,低电平持续480us~960us(这里设置700us,延迟后记得释放数据线,也就是拉高),DS18B20等待15~60us后(用while语句检测低电平的到来),会发出低电平脉冲信号给Master,该低电平脉冲60~240us,Master接收到后,就说明握手成功,用while语句检测高电平结束。

代码:

 void Ds18b20_rst(void)
{
DS18B20_DATA_H;
DS18B20_DATA_L;
Ds18b20_delay(T700US); //700us
DS18B20_DATA_H; //释放数据线
while(DS18B20_DATA_Read); //检测低电平
Ds18b20_delay(T700US);
while(!DS18B20_DATA_Read); //检测高电平
DS18B20_DATA_H;
}

(2)、发ROM指令和功能指令,就是1bit 1bit 的往外发,读也是1bit 1bit的往里读,发送顺序是先低后高。读写时有高有低,一定要按照时序严格进行操作:

  a)、写“0”  和“1”时序,先拉低15us,发送高电平持续45us,注意不低于60us,发送完1bit,释放数据线。

代码:

 void Ds18b20_Send_0(void)
{
DS18B20_DATA_L;
Ds18b20_delay(T15US); //15us
DS18B20_DATA_L;
Ds18b20_delay(T45US); //45us
DS18B20_DATA_H; //释放总线
} void Ds18b20_Send_1(void)
{
DS18B20_DATA_L;
Ds18b20_delay(T15US); //15us
DS18B20_DATA_H;
Ds18b20_delay(T45US);
DS18B20_DATA_H; //释放总线
} void Ds18b20_send_byte(uint8_t data)
{
uint8_t i = ; while(i--)
{
if(data & 0x01) //从低位开始发送
Ds18b20_Send_1();
else
Ds18b20_Send_0(); data >>= ;
}
}

  b)、读“0”  和“1”时序,在MASTER SAMPLES就可以采样数据,但一般会大于15us后开始采集数据,读写前 和 读写完后,都要记得释放数据

代码:

 uint8_t Ds18b20_read_byte(void)
{
uint8_t i = ;
uint8_t data_buffer = ; DS18B20_DATA_H; //释放数据线
while(i--)
{
data_buffer >>= ;
DS18B20_DATA_L;
Ds18b20_delay(T1US); //1us
DS18B20_DATA_H; //释放数据线
Ds18b20_delay(T15US);
if(DS18B20_DATA_Read) //接收低位开始
{
data_buffer |= 0x80;
}
Ds18b20_delay(T45US);
DS18B20_DATA_H;
} return data_buffer;
}

写好写字节函数 和 读字节函数,那么就可以发送ROM指令和功能指令了,具体指令参考数据手册。

一些具体操作指令代码

ds18b20.c

 #include "ds18b20.h"

 #define DS18B20_DATA                GPIO_Pin_3
#define DS18B20_DATA_H GPIOE->BSRRL = GPIO_Pin_3
#define DS18B20_DATA_L GPIOE->BSRRH = GPIO_Pin_3
#define DS18B20_DATA_Read GPIOE->IDR & GPIO_Pin_3 #define T1US 15
#define T15US 230
#define T45US 790
#define T700US 12000 void Ds18b20_GPIO_Config(void)
{
GPIO_InitTypeDef GPIO_InitStructure; RCC_AHB1PeriphClockCmd( RCC_AHB1Periph_GPIOE,ENABLE); GPIO_InitStructure.GPIO_Pin = DS18B20_DATA;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;
GPIO_InitStructure.GPIO_OType = GPIO_OType_OD;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOE,&GPIO_InitStructure);
} void Ds18b20_delay(__IO uint32_t nCount)
{
while(nCount--)
{ }
} void Ds18b20_rst(void)
{
DS18B20_DATA_H;
DS18B20_DATA_L;
Ds18b20_delay(T700US); //700us
DS18B20_DATA_H; //释放数据线
while(DS18B20_DATA_Read); //检测低电平
Ds18b20_delay(T700US);
while(!DS18B20_DATA_Read); //检测高电平
DS18B20_DATA_H;
} void Ds18b20_Send_0(void)
{
DS18B20_DATA_L;
Ds18b20_delay(T15US); //15us
DS18B20_DATA_L;
Ds18b20_delay(T45US); //45us
DS18B20_DATA_H; //释放总线
} void Ds18b20_Send_1(void)
{
DS18B20_DATA_L;
Ds18b20_delay(T15US); //15us
DS18B20_DATA_H;
Ds18b20_delay(T45US);
DS18B20_DATA_H; //释放总线
} void Ds18b20_send_byte(uint8_t data)
{
uint8_t i = ; while(i--)
{
if(data & 0x01) //从低位开始发送
Ds18b20_Send_1();
else
Ds18b20_Send_0(); data >>= ;
}
} uint8_t Ds18b20_read_byte(void)
{
uint8_t i = ;
uint8_t data_buffer = ; DS18B20_DATA_H; //释放数据线
while(i--)
{
data_buffer >>= ;
DS18B20_DATA_L;
Ds18b20_delay(T1US); //1us
DS18B20_DATA_H; //释放数据线
Ds18b20_delay(T15US);
if(DS18B20_DATA_Read) //接收低位开始
{
data_buffer |= 0x80;
}
Ds18b20_delay(T45US);
DS18B20_DATA_H;
} return data_buffer;
} void Ds18b20_Read_ROM(uint8_t *pBuff)
{
uint8_t i =;
Ds18b20_rst();
Ds18b20_send_byte(0x33); //读Rom指令
for(i=; i<; i++)
{
pBuff[i] = Ds18b20_read_byte();
}
} void Ds18b20_Convert_temprature(void)
{
Ds18b20_rst();
Ds18b20_send_byte(0xcc); //忽略ROM指令
Ds18b20_send_byte(0x44); //转换指令
} void Ds18b20_Read_register(uint8_t *pBuff)
{
uint8_t i = ;
Ds18b20_Convert_temprature();
Ds18b20_rst();
Ds18b20_send_byte(0xcc); //忽略ROM指令
Ds18b20_send_byte(0xbe); //读取存储器指令
for(i=; i<; i++)
{
pBuff[i] = Ds18b20_read_byte();
}
} void Ds18b20_weite_threshold(uint8_t TH, uint8_t TL, uint8_t Resolution)
{
Ds18b20_rst();
Ds18b20_send_byte(0xcc); //忽略ROM指令
Ds18b20_send_byte(0x4e); //写暂存器指令
Ds18b20_send_byte(TH);
Ds18b20_send_byte(TL);
if(Resolution == )
{
Ds18b20_send_byte(0x1f);
}
else if(Resolution == )
{
Ds18b20_send_byte(0x3f);
}
else if(Resolution == )
{
Ds18b20_send_byte(0x5f);
}
else //if(Resolution == 12) //其他任何都默认设置12bit分辨率
{
Ds18b20_send_byte(0x7f);
}
}

主函数:

 int main(void)
{
u8 i = ;
u8 id[];
RCC_ClocksTypeDef rcc_clocks; Clock_Config();
USART_Config(); Ds18b20_GPIO_Config();
Ds18b20_Read_ROM(id);
printf("DS18B20 64bit ROM Data:\n");
for(i=; i<; i++)
{
printf("0x%02x,",id[i]);
}
printf("\n");
printf("DS18B20 Memory Data:\n"); Ds18b20_Read_register(id);
for(i=; i<; i++)
{
printf("0x%02x,",id[i]);
} printf("\n"); Ds18b20_weite_threshold(0x3b,0x36,);
Ds18b20_Read_register(id);
for(i=; i<; i++)
{
printf("0x%02x,",id[i]);
} printf("\n"); while()
{
Ds18b20_Read_register(id);
printf("temprature:%.4f\n",((id[]<<) | id[]) * 6.25 /);
Delay(0x1fffff0); /* delay 1000ms */
}
}

3、打印信息

(1)、读5个不同DS18B20中ROM数据:

    0x28,0x37,0x4f,0xca,0x06,0x00,0x00,0x03
    0x28,0x3b,0xf4,0xc9,0x06,0x00,0x00,0xc9
    0x28,0xee,0xa0,0xcc,0x06,0x00,0x00,0xed
    0x28,0xca,0x02,0xcb,0x06,0x00,0x00,0xb1
    0x28,0xf0,0xbf,0xcb,0x06,0x00,0x00,0x30

    最前面8位是单线系列编码固定28H,接着48位是唯一序列号,最后8位是CRC,有关CRC计算参考手册,这里也没有去验证CRC是否正确。

(2)、

  DS18B20 64bit ROM Data:

  0x28,0xf0,0xbf,0xcb,0x06,0x00,0x00,0x30,   //64位中的序列号

  DS18B20 Memory Data:

  0xcd,0x01,0x4b,0x46,0x7f,0xff,0x03,0x10,  //读暂存器中的默认值

  0xcd,0x01,0x3b,0x36,0x7f,0xff,0x03,0x10, //改写后,读暂存器中的数据

  temprature:28.8125            //转换温度

printf("temprature:%.4f\n",((id[]<<) | id[]) * 6.25 /);

这里只考虑了正数温度,关于*6.25/100,参考数据手册:"温度传感器的精度为用户可编程的9、10、11或12位,分别以0.5°、0.25°、0.125°和0.0625°增量递增",程序选的是12bit分辨率,单位增量即为0.0625

STM32F207V 进行DS18B20处理的更多相关文章

  1. 基于FS4412的DS18B20温度采集编程实现(1-时序分析)

    作者:秦老师,华清远见嵌入式学院讲师. 一.DS18B20简介 DS18B20是常用的数字温度计.DS18B20数字温度计提供9至12位(可配置)温度读数,表明该设备的温度. 信息通过单总线接口被发送 ...

  2. (原创)巩固理解基于DS18B20的1-wire协议(MCU,经验)

    1.Abstract     如前篇随笔所写,将以前遇到最难懂的两个部分重拾一下.前一篇写的是I2C协议(http://www.cnblogs.com/hechengfei/p/4117840.htm ...

  3. DS18B20函数库建立实验

    1.主代码: /* 温度传感器  */#include "DS18B20.h"#include"def.h"u16 get_temp (void){    fl ...

  4. 基于ARM-LINUX的温度传感器驱动-DS18B20

    转载:http://blog.csdn.net/ayangke/article/details/6883244 作者:冯建,华清远见嵌入式学院讲师. DS18B20数字温度传感器接线方便,封装成后可应 ...

  5. DS18B20 for STM32 源代码 【worldsing笔记】

    DS18B20是DALLAS公司生产的一线式数字温度传感器,具有3引脚TO-92小体积封装形式:温度测量范围为-55℃-+125℃,可编程为9位-12位A/D转换精度,测温分辨率可达0.0625℃.主 ...

  6. 使用DS18B20设计温控系统

    datasheet真的是得看看啊,比如DS18B20,不然程序都不好写,美国DALLAS半导体公司推出的数字化温度传感器DS18B20采用单总线协议,即与单片机接口仅需要一个IO口,无需任何外部原件, ...

  7. 基于ARM-LINUX的温度传感器驱动(DS18B20) .

    DS18B20数字温度传感器接线方便,封装成后可应用于多种场合,如管道式,螺纹式,磁铁吸附式,不锈钢封装式,型号多种多样,有LTM8877,LTM8874等等.主要根据应用场合的不同而改变其外观.封装 ...

  8. DS18B20测温

    项目需要实现分布式大规模测温,需要52个测温点,采样DS18B20进行设计. 30cm一个点,一共8个点串联.采用国标单芯单股纯铜硬线BV0.5做导线,测试一会儿正常,一会儿不正常.后面换线了,测试正 ...

  9. DS18B20

    DS18B20驱动 [ 2012-5-14 12:01:00 | By: 吴师傅 ]   14 推荐 一.概述 DS18B20是一种单总线数字温度传感器.測试温度范围-55℃-125℃,温度数据位可配 ...

随机推荐

  1. ogg 初始化

    192.168.27.33test11ghdb11gtrandata: 同步delete,update 使用config 文件:同步表使用进程根据SCN号和RBA和主键同步##目的:数据定时同步,从源 ...

  2. Hive 安装过程中的问题

    org.apache.thrift.transport.TTransportException: Could not create ServerSocket on address 0.0.0.0/0. ...

  3. linux和windows双系统时间错误解决方法

    转自http://www.2cto.com/os/201204/126212.html windows时间会慢8小时,原因: 两个概念: UTC即Universal Time Coordinated, ...

  4. Python第一天课程

    1.在linux下写python脚本,开头的解释器宣告的写法应该是#!/usr/bin/env python 定义变量name="XXX"  age=21   所有使用引号引起的内 ...

  5. C#中Invoke的用法

    在用.NET Framework框架的WinForm构建GUI程序界面时,如果要在控件的事件响应函数中改变控件的状态,例如:某个按钮上的文本原先叫"打开",单击之后按钮上的文本显示 ...

  6. White space is required before the encoding pseudo attribute in the XML declaration.

    错误出现的位置: <?xml version="1.0"encoding="UTF-8"?> 正确方式: <?xml version=&quo ...

  7. zoj 2913 Bus Pass

    对于每个输入的站点求出所有点到这个站点的最短路.用anss数组存下来,然后就可以用anss数组求出答案了. 题目分析清楚了 还是比较水的,折腾了一早上.. #include<stdio.h> ...

  8. JObject对json的操作

    一,需去程序集添加using Newtonsoft.Json.Linq;引用 using System; using System.Collections.Generic; using System. ...

  9. js nextSibling属性和previousSibling属性概述及使用注意

    1:nextSibling属性 该属性表示当前节点的下一个节点(其后的节点与当前节点同属一个级别):如果其后没有与其同级的节点,则返回null. 需要特别注意的是:该属性在不同的浏览器中的执行结果并不 ...

  10. Node使用Mongoose操作MongoDB数据库——增删改查的实现

    当初刚出社会时就规划了下自己的职业生涯:先成为一名优秀的前端工程师,再成为一名全栈工程师(精通前端开发.后台开发和客户端开发),最后成为一名优秀的系统架构师.转眼间已经工作快三年,是时候迈出关键性的一 ...