STM32驱动DS18B20

发布者:素心静听最新更新时间:2017-01-13 来源: eefocus关键字:STM32  驱动DS18B20 手机看文章 扫描二维码
随时随地手机看文章

DS18B20 是由 DALLAS 半导体公司推出的一种的“一线总线”接口的温度传感器。与传
统的热敏电阻等测温元件相比,它是一种新型的体积小、适用电压宽、与微处理器接口简单的
数字化温度传感器。一线总线结构具有简洁且经济的特点,可使用户轻松地组建传感器网络,
从而为测量系统的构建引入全新概念,测量温度范围为-55~+125℃  ,精度为±0.5℃。现场温
度直接以“一线总线”的数字方式传输,大大提高了系统的抗干扰性。它能直接读出被测温度,
并且可根据实际要求通过简单的编程实现 9~l2 位的数字值读数方式。它工作在 3—5. 5 V 的电
压范围,采用多种封装形式,从而使系统设计灵活、方便,设定分辨率及用户设定的报警温度

存储在 EEPROM 中,掉电后依然保存

其内部结构如下所示

DS18B20的通讯方式是单总线的,一般而言,我们遇到的封装都是如下

其中DQ就是主要的通讯线路,对DS的读取和写入都需要主机来控制DQ线路的DQ高低电平的时间来确定,具体如下

一般而言,DQ线需要接一个上拉电阻,所以,才写操作的最后一步都需要将总线拉高


向DS写0需要总线拉低至少60US最多120US就算完成,也就是说,1-->0(持续60-120us)-->1 写入了0

像DS写入1需要总线拉低最少1us最多15US,然后总线拉高,拉高时间至少15us,一般40us以上即可  1->0(1-15us,推荐5us)-->1(持续15us以上,推荐40us)

由此可见,DS的总线采样实在总线拉低之后的15us开始的

读取DS分别为读取1和读取0,但是这两者时序是统一的

首先总线拉低至少1us,最多15us,还是选择2us,然后释放总线(也就是说进入输入模式),等待15us以上的事件,然后采样,高电平为1低电平为0

1-->0(持续2us,最多15us)-->等待15us以上60us以下-->采样总线电平,得到1或者0,记得采样完成之后切换到输出模式将总线拉高便于下一次使用


DS18B20的命令

DS1820有三个主要数字部件:1)64位激光ROM,2)温度传感器,3)非易失性温度报警触发器TH和TL



启动温度转换的命令是0X44,读取命令是0XBE

所以一般而言,对于DS的驱动包含以下几步

复位-->发 SKIP ROM 命令(0XCC)-->发开始转换命令(0X44)-->延时-->复
位-->发送 SKIP  ROM 命令(0XCC)-->发读存储器命令(0XBE)-->连续读出两个字节数据(即
温度)-->结束

我们在读取的时候只读取两个字节的原因在于DS的存储器布局

前两个就是我们需要的温度,当然也可以读取全部的,扩展驱动达到其他目的


以下是驱动代码,STM32驱动代码中使用了位段操作

#ifndef __Ds18b20H
#define __Ds18b20H 
#include "ioremap.h"   
#include "delay.h"
#include "uart.h"


//IO方向设置
#define Ds18b20IO_IN()  {GPIOG->CRH&=0XFFFF0FFF;GPIOG->CRH|=8<<12;}
#define Ds18b20IO_OUT() {GPIOG->CRH&=0XFFFF0FFF;GPIOG->CRH|=3<<12;}



////IO操作函数											   
#define	Ds18b20DQ_OUT PGout(11) //数据端口	PG11 
#define	Ds18b20DQ_IN  PGin(11)  //数据端口	PG11 




u8 Ds18b20Init(void);			//初始化DS18B20


short Ds18b20GetTemp(void);	//获取温度


void Ds18b20Start(void);		//开始温度转换


void Ds18b20WriteByte(u8 dat);//写入一个字节


u8 Ds18b20ReadByte(void);		//读出一个字节


u8 Ds18b20ReadBit(void);		//读出一个位


u8 Ds18b20Check(void);			//检测是否存在DS18B20


void Ds18b20Rst(void);			//复位DS18B20   

void Ds18b20Show(void);


#endif

 

#include "ds18b20.h"

//复位DS18B20
void Ds18b20Rst(void)	   
{                 
    Ds18b20IO_OUT(); //SET PA0 OUTPUT
    Ds18b20DQ_OUT=0; //拉低DQ
    DelayUs(750);    //拉低750us
    Ds18b20DQ_OUT=1; //DQ=1 
    DelayUs(15);     //15US
}


//等待DS18B20的回应
//返回1:未检测到DS18B20的存在
//返回0:存在
u8 Ds18b20Check(void) 	   
{   
    u8 retry=0;
    Ds18b20IO_IN();//SET PA0 INPUT	 
    while (Ds18b20DQ_IN&&retry<200)
    {
        retry++;
        DelayUs(1);
    };	 
    if(retry>=200)return 1;
    else retry=0;
    while (!Ds18b20DQ_IN&&retry<240)
    {
        retry++;
        DelayUs(1);
    };
    if(retry>=240)return 1;	    
    return 0;
}


//从DS18B20读取一个位
//返回值:1/0
u8 Ds18b20ReadBit(void) 			 // read one bit
{
    u8 data;
    Ds18b20IO_OUT();//SET PA0 OUTPUT
    Ds18b20DQ_OUT=0; 
    DelayUs(2);
    Ds18b20DQ_OUT=1; 
    Ds18b20IO_IN();//SET PA0 INPUT
    DelayUs(12);
    if(Ds18b20DQ_IN)data=1;
    else data=0;	 
    DelayUs(50);           
    return data;
}


//从DS18B20读取一个字节
//返回值:读到的数据
u8 Ds18b20ReadByte(void)    // read one byte
{        
    u8 i,j,dat;
    dat=0;
    for (i=1;i<=8;i++) 
    {
        j=Ds18b20ReadBit();
        dat=(j<<7)|(dat>>1);
    }						    
    return dat;
}


//写一个字节到DS18B20
//dat:要写入的字节
void Ds18b20WriteByte(u8 dat)     
{             
    u8 j;
    u8 testb;
    Ds18b20IO_OUT();//SET PA0 OUTPUT;
    for (j=1;j<=8;j++) 
    {
        testb=dat&0x01;
        dat=dat>>1;
        if (testb) 
        {
            Ds18b20DQ_OUT=0;// Write 1
            DelayUs(2);                            
            Ds18b20DQ_OUT=1;
            DelayUs(60);             
        }
        else 
        {
            Ds18b20DQ_OUT=0;// Write 0
            DelayUs(60);             
            Ds18b20DQ_OUT=1;
            DelayUs(2);                          
        }
    }
}


//开始温度转换
void Ds18b20Start(void)// ds1820 start convert
{   						               
    Ds18b20Rst();	   
    Ds18b20Check();	 
    Ds18b20WriteByte(0xcc);// skip rom
    Ds18b20WriteByte(0x44);// convert
} 


//初始化DS18B20的IO口 DQ 同时检测DS的存在
//返回1:不存在
//返回0:存在    	 
u8 Ds18b20Init(void)
{
    GPIO_InitTypeDef  GPIO_InitStructure;
    
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOG, ENABLE);	 //使能PORTG口时钟 
    
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11;				//PORTG.11 推挽输出
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; 		  
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_Init(GPIOG, &GPIO_InitStructure);
    
    GPIO_SetBits(GPIOG,GPIO_Pin_11);    //输出1
    
    Ds18b20Rst();
    
    return Ds18b20Check();
}  


//从ds18b20得到温度值
//精度:0.1C
//返回值:温度值 (-550~1250) 
short Ds18b20GetTemp(void)
{
    u8 temp;
    u8 TL,TH;
    short tem;
    Ds18b20Start ();                    // ds1820 start convert
    Ds18b20Rst();
    Ds18b20Check();	 
    Ds18b20WriteByte(0xcc);// skip rom
    Ds18b20WriteByte(0xbe);// convert	    
    TL=Ds18b20ReadByte(); // LSB   
    TH=Ds18b20ReadByte(); // MSB  
    
    if(TH>7)
    {
        TH=~TH;
        TL=~TL; 
        temp=0;//温度为负  
    }else temp=1;//温度为正	  	  
    tem=TH; //获得高八位
    tem<<=8;    
    tem+=TL;//获得底八位
    tem=(short)((float)tem*0.625);//转换     
    if(temp)return tem; //返回温度值
    else return -tem;    
} 

void Ds18b20Show(void)
{
	short t = 0;
	t = Ds18b20GetTemp();
	printf("ds18b20 temp is %d\r\n",t);
}


关键字:STM32  驱动DS18B20 引用地址:STM32驱动DS18B20

上一篇:LPC2478内存布局以及启动方式
下一篇:STM32标准IIC驱动

推荐阅读最新更新时间:2024-03-16 15:30

STM32中使用printf打印串口数据的实现原理及方法
STM32中使用printf打印串口数据的实现原理 在C库中,printf()等输出流函数都是通过fputc()这个函数实现的,所以我们通过重映射的方式,修改这个函数的定义使它输出在STM32的寄存器中,便可以实现使用printf()函数在STM32串口上输出数据的功能。 盘点一下实现printf()函数打印字符串重定义到USART1的方法 方法一 1添加包含printf()函数的头文件:#include “stdio.h” 2.重写 stdio.h 头文件中的 int fputc(int ch, FILE *f) 函数 3.将该函数” int fputc(int ch, FILE *f) “放在main()函数能够调用到的文
[单片机]
stm32中的io函数 STM32中的IO操作
STM32系列单片机芯片的库函数有很多种,而负责IO操作的库函数是GPIO,GPIO函数在STM32单片机头文件stm32f10x_gpio.h中声明,在STM32单片机的主函数stm32f10x_gpio.c中完成定义。 GPIO的配置种类有8个,分别是: 1.GPIO_Mode_AIN 模拟输入 2.GPIO_Mode_IN_FLOATING 浮空输入 3.GPIO_Mode_IPD 下拉输入 4.GPIO_Mode_IPU 上拉输入 5.GPIO_Mode_Out_OD 开漏输出 6.GPIO_Mode_Out_PP 推挽输出 7.GPIO_Mode_AF_OD 复用开漏输出 8.GPIO_Mode_AF_PP 复用推挽
[单片机]
基于STM32的CAN通信网-----一种ID配置方法
分布式CAN通信网ID分配方法 在介绍本方法前,先构建CAN通信网系统模型:只有一个管理中心节点,其他均为从节点。主节点可与所有从节点之间相互通信,从节点之间不相互通信。CAN通信网采用网桥扩展方式增大网络中的节点。 报文帧格式 帧信息 IDE=1 RTR=0 X X DLC 扩展帧 远程帧 保留位 帧数据部分长度(不大于8) 帧标 识符 ID28 ID27 ID26 ID25 ID24 ID24 ID22 ID21 DestMACID(目标节点编码) ID20 ID19 ID18 ID17 ID16 ID15 ID14 ID13 xxxxxxx
[单片机]
基于<font color='red'>STM32</font>的CAN通信网-----一种ID配置方法
STM32如何高效接收串口数据?
硬件:stm32f103cbt6 软件:STM32F10x_StdPeriph_Lib_V3.5.0 DMA,直接内存存取,可以用它的双手释放CPU的灵魂,所以,本文通过USART3进行串口收发,接受使用DMA的方式,无需CPU进行干预,当接受完成之后,数据可以直接从内存的缓冲区读取,从而减少了CPU的压力。 具体的代码实现如下: usart_driver.h 封装了接口,数据接收回调函数类型,基本数据结构等; usart_driver.c 函数原型实现,中断服务函数实现等; 拷贝这两个文件即可,可以根据目录下的参考用例,进行初始化。 头文件usart_driver.h已经声明了外部函数可能用到的接口; USART3_DR的地
[单片机]
<font color='red'>STM32</font>如何高效接收串口数据?
STM32单个定时器四通道输入捕获
以前就纠结过能不能一个定时器进行多路的输入捕获,因为毕竟输出四路的PWM是轻松随意的,当时大概想了一下觉得可能会比较麻烦就一直没去尝试,最近组里的同学做方波测频和测占空比遇到了问题,又提到了这个,今天仔细想了一下有了思路就写程序然后上板子试了一下,解决了这个问题。 首先我们先看单路的输入捕获是怎么实现的 定时器的初始化函数: //定时器2通道1输入捕获配置 //arr:自动重装值 //psc:时钟预分频数 void TIM2_Cap_Init(u16 arr,u16 psc) { RCC- APB1ENR|=1 0; //TIM2 时钟使能 RCC- APB2ENR|=1 2; //使能PO
[单片机]
STM32定时器自学笔记
看STM32定时器一个多星期,真是乱啊。各种模式的说。这也主要是我们对定时器的各种模式的应用不是很了解。而我们对定时器的基础部分则是上手很快。就是定时器定时完成后的更新事件中断。捕获,比较这些还说得过去,再后来的从模式、触发、霍尔传感器和编码器等直接就乱了,更不用说高级定时器中的刹车、死区、互补等。 而我看定时器则是看了通用定时器,主要是刹车,编码器等这些对于我来说应用得少,即使哪天用到了也忘了。看了通用定时器不少于4次。总算能够理理清楚了。以下慢慢说。 通用定时器有以下一些模式: 计数模式(向上计数,向下计数,中央对齐计数) 捕获比较模式: (捕获)1、输入捕获模式 2、PWM输入模式 (比较)1、强制输出模式 2、比较输出模式
[单片机]
<font color='red'>STM32</font>定时器自学笔记
电源管理(STM32
一、低功耗模式 STM32F1xx 待机模式 电源控制寄存器——PWR_CR 位 1 PDDS:掉电深睡眠 与LPDS位协同操作 0:当CPU进入深睡眠时进入停机模式,调压器的状态由LPDS位控制。 1:CPU进入深睡眠时进入待机模式。 电源控制/状态寄存——PWR_CSR 位 0 WUF:唤醒标志 该位由硬件设置,并只能由POR/PDR(上电/掉电复位)或设置电源控制寄存器(PWR_CR)的 CWUF位清除。 0:没有发生唤醒事件 1:在WKUP引脚上发生唤醒事件或出现RTC闹钟事件。 注:当WKUP引脚已经是高电平时,在(通过设置EWUP位)使能WKUP引脚时,会检测到一个额外的 事件。 位 8
[单片机]
电源管理(<font color='red'>STM32</font>)
STM32编程小总结
1.在主函数的正式调用里,RCC的配置一定要在各外设的函数调用之前。 2.外设调试出现问题时,一定先考虑是不是没有打开外设的时钟。并且RCC配置和外设时钟的打开要在配置寄存器之前。 3.使用模块化编程可以使程序简单易读,可移植性高,下一次调用方便。但是可能会出现很多问题,必须一一克服。 在主函数里,把需要用得到的各模块配置函数调用写入,这一点很重要。 4.模块化编程时,一定要确保模块的.c文件添加进了工程目录,否则会出现:Undefined Symbol的错误提示,这一点要牢记。 5.中断服务函数必须要写进stm32f10x.it.c里面。否则会出问题。 6.有时添加的模块太多可能会调试不出来,这时考虑把GPI
[单片机]
小广播
添点儿料...
无论热点新闻、行业分析、技术干货……
设计资源 培训 开发板 精华推荐

最新单片机文章
何立民专栏 单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

换一换 更多 相关热搜器件
随便看看
电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved