【驱动】DS18B20

前言

DS18B20,单总线,它已经有定义好的初始化、写数据、读数据的时序图和一些需要使用的指令。驱动的关键,是writebit和readbit两个函数的时序。

1、初始化

说明:在初始化单片机的IO的输入输出、时钟等,把DQ引脚拉低480us后,DS18B20就会自动完成复位,之后单片机拉高DQ引脚15~60us后,检测DQ引脚,如果存在60~240us的低电平,则表示DS18B20在线并能正常工作。

2、读、写数据

说明: 读取的数据,低位在前,例如12345678,按位读出来的顺序8,7,6,5,4,3,2,1

写入的数据,也是低位在前,例如12345678,写入的顺序8,7,6,5,4,3,2,1

3、功能指令

每次进行功能指令操作前,都必须重新对DS18B20进行复位操作。

转换温度      44h

忽略ROM    CCh

读取寄存器   BEh 

4、驱动代码

#include "ds18b20.h"
#include "stm32f10x_gpio.h"
#include "delay.h"    
#include "lcd.h"

#define GPIO_x         GPIOA
#define GPIO_Pin_x     GPIO_Pin_0
#define DS18B20_IO_IN()  {GPIOA->CRL&=0XFFFFFFF0;GPIOA->CRL|=8<<0;} 
#define DS18B20_IO_OUT() {GPIOA->CRL&=0XFFFFFFF0;GPIOA->CRL|=3<<0;}
static void Init_DQ(void);
static void ds18b20_Rst(void);
int ds12820_init(void);  
static int ds18b20_Readbit(void);
static unsigned char ds18b20_Readbyte(void);
static void ds18b20_Writebyte(unsigned char cmd);
short ds18b20_GetTemp(void);
static int ds18b20_Check(void);     
/*
ds18b20 has  3 configs :10bits/11bits/12bits,user can ingnor the high 2 bits because they has no use except impacting its thransmission speed.
Every time when you want use function command you must follow the steps below:
step1: Initialization
step2: ROM Command(if only 1 18b20,can skip this step)
step3: ds18b20 Function Command
每一次操作均需要满足以上步骤。
例如:进行温度转换的function command后,需要再次复位,再进行读取温度的function command
*/
 
/*
@brief  init IO_DQ and init its value 
 */
static void Init_DQ(void){
    GPIO_InitTypeDef  GPIO_InitStructure;
    
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);    //使能PORTA口时钟  
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;               //PORTA0 推挽输出
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;          
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_Init(GPIOA, &GPIO_InitStructure);

    GPIO_SetBits(GPIOA,GPIO_Pin_0);    //输出1
}
/*
step1: 拉低DQ 1us
step2: 等待30us
step3: 采样
*/
static int ds18b20_Readbit(void){ 
    unsigned char data=0;
        DS18B20_IO_OUT();
        GPIO_ResetBits(GPIO_x,GPIO_Pin_x); 
      delay_us(2);
        GPIO_SetBits(GPIO_x,GPIO_Pin_x); 
        DS18B20_IO_IN();
        delay_us(20);
        if(GPIO_ReadInputDataBit(GPIO_x,GPIO_Pin_x))
            data=1;
        else
            data=0;
        delay_us(50);//must be
        return data;
     
}
/*
step1:拉低1us
step2:延时15us
step3:读取BitVal
从低位到高位读出
*/  
static unsigned char ds18b20_Readbyte(void){
    unsigned char i=0;
    unsigned char BitVal=0;
    unsigned char data=0;  
    for (i=0;i<8;i++) {
      BitVal=ds18b20_Readbit();
            data |= (BitVal<<i); 
    }                           
    return data;
}
/*
@brief: step1:拉低1us
                step2:写BitVal
                step3:持续60us
从低位到高位写入
*/

static void ds18b20_Writebyte(unsigned char cmd){
    unsigned char i=0;
    unsigned char BitVal=0;
        DS18B20_IO_OUT();
    for (i=0;i<8;i++){ 
        BitVal=cmd&0x01;
              cmd =cmd>>1;
                if(BitVal){
                    GPIO_ResetBits(GPIO_x,GPIO_Pin_x); 
                    delay_us(2);
                    GPIO_SetBits(GPIO_x,GPIO_Pin_x); 
                    delay_us(60);      
                }
                else{
                    GPIO_ResetBits(GPIO_x,GPIO_Pin_x); 
                    delay_us(60);
                    GPIO_SetBits(GPIO_x,GPIO_Pin_x); 
                    delay_us(2);      
                } 
    }
} 
/*
step1: 高电平750us
step2: 低电平15us
*/
static void ds18b20_Rst(void){  
        DS18B20_IO_OUT(); 
        GPIO_ResetBits(GPIO_x,GPIO_Pin_x); 
      delay_us(750);
        GPIO_SetBits(GPIO_x,GPIO_Pin_x); 
        delay_us(15);
}
//@brief 低电平480us~960us,等待15~60us,DQ会变成低电平60~240us
static int ds18b20_Check(void){
    int i=0;
    int cnt=0;
    //检查应答  
    while(GPIO_ReadInputDataBit(GPIO_x,GPIO_Pin_x)!=0){ 
        delay_us(1);
    }
    for(i=0;i<150;i++){//多次读取,防止时序抖动
        if(GPIO_ReadInputDataBit(GPIO_x,GPIO_Pin_x)) 
            cnt++;
        delay_us(1);
    }
    if(cnt > 60)
        return 1;
    else
        return 0;  
}
//@brief  init  ds18b20  before  get its tempreture
int ds12820_init(void){ 
    ds18b20_Rst();
    if(ds18b20_Check() == 1) 
        return 1; 
    else
        return -1;    
}
/*
step1:init
step2:ROM Command(skip)
step3:ds18b20 Function Command
 */
short ds18b20_GetTemp(void){
    unsigned char TL=0;
    unsigned char TH=0; 
    short temp=0; 
    Init_DQ();
    ds12820_init();  
    ds18b20_Writebyte(0xCC);// skip rom
    ds18b20_Writebyte(0x44);// convert     
    delay_ms(800);
    ds12820_init();  
    ds18b20_Writebyte(0xCC);// skip ROM
    ds18b20_Writebyte(0xBE);//read RAM
    TL=ds18b20_Readbyte(); // LSB   
    TH=ds18b20_Readbyte(); // MSB 
   
    if(TH>7){ 
      TH=~TH;
      TL=~TL; 
            temp=-(float)((TH<<8)+TL+1)*0.625;  
    }
    else 
            temp=(float)((TH<<8)+TL)*0.625;  
        return temp; 
}
//end
/*生命如此美好。认真工作之余,不要忘了认真对待生活,认真对待身边人!*/
原文地址:https://www.cnblogs.com/isha2088/p/6870292.html