• 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
    ",t);
    }
    
    




  • 相关阅读:
    Go微服务框架gokratos学习01:quickstart 快速创建项目
    Go微服务框架gokratos学习02:proto 代码生成和项目代码编写步骤
    Go微服务框架gokratos学习04:服务注册和服务发现(etcd作为注册中心)
    竞态问题与RxJs
    深入探究MinimalApi是如何在Swagger中展示的
    springboot竟然有5种默认的加载路径,你未必都知道
    springboot多环境下如何进行动态配置
    springboot如何使用自定义配置文件
    做了这些年开发,今天第一次梳理了这三种常用的变量
    云开发中的战斗机 Laf,让你像写博客一样写代码
  • 原文地址:https://www.cnblogs.com/dengxiaojun/p/4279449.html
Copyright © 2020-2023  润新知