用stm32操作DS18B20温度传感器学习思考

#include "stm32f10x.h"                  // Device header
#include "Delay.h"


#define DS_DQ_PORT    GPIOB        //数据线
#define DS_DQ_PIN      GPIO_Pin_0

#define ROM_READ         0x33        
#define ROM_MATCH        0x55       
#define ROM_SEARCH       0xF0        
#define ROM_SKIP         0xCC        
#define ALARM_SEARCH     0xEC        
#define TEMPER_CONVERT   0x44       
#define RAM_READ         0xBE        
#define RAM_WRITE        0x4E       
#define RAM_TO_EE        0x48        
#define EE_TO_RAM        0xB8       
#define POWER_READ       0xB4        
 

/*定义结构体用来存储温度*/

typedef struct
{
    u32 Temperature;      
    u8 Temper_plus_minus;    
}DS18B20_MEASURE;

/**
  * @brief DS18B20端口输入初始化
  * @param  无
  * @retval 无
  */
void DS18B20_In_Init(void)
{
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);//开启RCC时钟
    GPIO_InitTypeDef GPIO_InitStructure;
    GPIO_InitStructure.GPIO_Mode=GPIO_Mode_IPU;//这里设置的是上拉输入模式
    GPIO_InitStructure.GPIO_Pin=DS_DQ_PIN;
    GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;
    GPIO_Init(DS_DQ_PORT,&GPIO_InitStructure);
}

/**
  * @brief DS18B20端口输出初始化
  * @param  无
  * @retval 无
  */
void DS18B20_OUT_Init(void)
{
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);
    GPIO_InitTypeDef  GPIO_InitStructure;
    GPIO_InitStructure.GPIO_Pin = DS_DQ_PIN;                 
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_OD;         //这里选择的是开漏输出,推挽                                                                                                              输出也可以
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;        
    GPIO_Init(DS_DQ_PORT, &GPIO_InitStructure);                     
}
 

/**
  * @brief 写入数据0
  * @param  无
  * @retval 无
  */
void DS18B20_WR_0(void)
{
    GPIO_ResetBits(DS_DQ_PORT, DS_DQ_PIN);//端口数据清0    ,拉为低电平
    Delay_us(70);;         //延时最低60 60~120   
    GPIO_SetBits(DS_DQ_PORT, DS_DQ_PIN);  //端口数据拉高     ,拉位高电平 
    Delay_us(2);                          //延时2us,要大于1us
}

/**
  * @brief 写入数据1
  * @param  无
  * @retval 无
  */
void DS18B20_WR_1(void)
{
    GPIO_ResetBits(DS_DQ_PORT, DS_DQ_PIN);//端口数据清0    拉为低电平
    Delay_us(15);   //延时15秒,最低1us,发送数据起始位
    GPIO_SetBits(DS_DQ_PORT, DS_DQ_PIN);  //端口数据拉高 延时2us(大于1us)    拉为高电平
    Delay_us(30);     //延时30us,建议在15--60之间
}

/*这个要根据手册中写1或0的时序来写*/

用stm32操作DS18B20温度传感器学习思考_第1张图片

 /**
  * @brief 写入一个字节
  * @param  要写入的数据
  * @retval 无
  */

void DS18B20_Write_Byte(u8 data)
{
    u8 i,temp;
    
    DS18B20_OUT_Init();//数据线配置为输出模式
    for(i = 0; i < 8; i++)
    {
        temp = (data>>i)&0x01;//一共8位,从低位开始,然后向右移,每次取data的最后一位    
        if(temp)              
            DS18B20_WR_1();        //temp为真写1
        else                  
            DS18B20_WR_0();        //temp为假写0     
    }
}

/**
  * @brief 读取指定端口的一位数据(状态)
  * @param  无
  * @retval 返回端口状态,高电平返回1,低电平返回0
  */
u8 DS18B20_RD_Bit(void)
{
    u8 val;
    
    DS18B20_OUT_Init();//数据线配置为输出模式  ,为什么
    GPIO_ResetBits(DS_DQ_PORT, DS_DQ_PIN);//端口数据清0 ,把电平拉低
    Delay_us(2);          //延时2us,要求大于1us
    GPIO_SetBits(DS_DQ_PORT, DS_DQ_PIN);  //拉高,把电平拉高
    DS18B20_In_Init();             //数据配置为输入,为什么?
    Delay_us(15);            //延时10个us开始采样总线数据,根据读0和读1时序之间的不同来确定的
    val = 0;
    if(GPIO_ReadInputDataBit(DS_DQ_PORT, DS_DQ_PIN))//读取端口的一位数据,判断状态
        val = 1;                //如果高电平
    Delay_us(60);        //所有读时序必须间隔60us以上
    return val;
}

/*这个判断到底是读0还是读1时,根据读0和读1的时序图的区别来判断,并设置相应的标志量*/

/**
  * @brief 读取端口的字节
  * @param  无
  * @retval 返回该字节
  */
u8 DS18B20_RD_Byte(void)    
{
  u8 i,dat; //
    
    dat = 0;
  for(i = 0; i < 8; i++)
  {
        dat |= DS18B20_RD_Bit() << i;        //先读低位,并把每位赋值给dat
    }
    return dat;
}
/*这个要根据读时序来配置*/

用stm32操作DS18B20温度传感器学习思考_第2张图片


/**
  * @brief 复位并初始化函数
  * @param  
  * @retval 为0电表成功,非0代表失败
  */ uint8_t DS18B20_Reset(void)
{
    uint8_t timeout;
    
    DS18B20_OUT_Init();//设置为端口输出模式  ?
    
    GPIO_ResetBits(DS_DQ_PORT, DS_DQ_PIN);//端口数据清0 设为低电平
    Delay_us(600);//时间在480--960之间
    
    GPIO_SetBits(DS_DQ_PORT, DS_DQ_PIN);//端口设置1    设为高电平
    Delay_us(50);                 //最低延时15us 15us-60us
    DS18B20_In_Init();   //端口输入初始化?
    
    //等待DS18B20应答
    while(GPIO_ReadInputDataBit(DS_DQ_PORT, DS_DQ_PIN)) //如果端口状态为高电平         //等待拉低
    {
        Delay_us(1);
        if(++timeout > 240)     //时间超时
         goto Exit;
    }
    timeout = 0;
    while(!GPIO_ReadInputDataBit(DS_DQ_PORT, DS_DQ_PIN))    //如果端口状态为低电平 //等待拉高
    {
        Delay_us(1);
        if(++timeout > 240)  //超时
         goto Exit;
    }
    
    return 0;              //成功
    
Exit:
    return 0xFF; //超时
}

用stm32操作DS18B20温度传感器学习思考_第3张图片

 1.单片机拉低总线至少480us,产生复位脉冲,然后释放总线(拉高电平)。 2.这时DS8B20检测到请求之后,会拉低信号,大约60~240us表示应答。 3.DS8B20拉低电平的60~240us之间,单片机读取总线的电平,如果是低电平,那么表示初始化成功 4.DS18B20拉低电平60~240us之后,会释放总线。

/**
  * @brief 读取DS18B20的转换温度
  * @param  无
  * @retval 无
  */

 void DS18B20_ReadTemper(void)
{
    u8 TH,TL;            //温度高8位 低8位
    u16 temper;        //温度
    
    DS18B20_Reset();                                    //复位DS18B20总线
    DS18B20_Write_Byte(ROM_SKIP);                //写一个字节,先写低位(跳过ROM(只读存储器)(0xcc)),只有一个温度传感器时,可以跳过
    DS18B20_Write_Byte(TEMPER_CONVERT);    //读一个字节,(启动温度转换(0x44))
    DS18B20_Reset();                                    //复位DS18B20
    DS18B20_Write_Byte(ROM_SKIP);                //跳过ROM  0xcc
    DS18B20_Write_Byte(RAM_READ);                //读RAM中9字节数据(0xbe)
    TL = DS18B20_RD_Byte();                      //先读低字节
    TH = DS18B20_RD_Byte();                     //读高字节
    
    temper = (TH << 8) + TL;//把单独的高低位整合到一起
    if(TH > 7)    //负温度,前八位表示正负,0表式正
    {
        DS18B20_Measure.Temper_plus_minus = 1;       //标记负温度
        temper = (~temper) + 1;                                      //求补码
    }
    else                     //正温度
    {
        DS18B20_Measure.Temper_plus_minus = 0;    //标记正温度
    }
    
    DS18B20_Measure.Temperature = temper * 6250 / 10000;        //温度计算 精度为0.625;
}

*************上述为DS18B20.C文件*******************

/*以下为DS18B20.H文件*/

#ifndef __DS18B20_H__
#define __DS18B20_H__

void DS18B20_In_Init(void);
void DS18B20_OUT_Init(void);
u8 DS18B20_Reset(void);
void DS18B20_ReadTemper(void);

typedef struct
{
    u32 Temperature;      
    u8 Temper_plus_minus;    
}DS18B20_MEASURE;


 DS18B20_MEASURE DS18B20_Measure;


#endif

/*main.c*/

#include "Delay.h"
#include "OLED.H"
#include "DS18B20.H"

extern DS18B20_MEASURE DS18B20_Measure;

int main(void)
{
    OLED_Init();
    OLED_ShowString(1,1,"Zqz");
    
    while(1)
    {
        DS18B20_ReadTemper();//读取温度
        OLED_ShowChar(2,4,'.');
        if(DS18B20_Measure.Temper_plus_minus==1) OLED_ShowChar(2,1,'-');//负的显示负号
        else OLED_ShowChar(2,1,'+');
        OLED_ShowNum(2,2,DS18B20_Measure.Temperature/10,2);//显示前两位
        OLED_ShowNum(2,5,DS18B20_Measure.Temperature%10,1);//显示小数部分
        
    }
}

你可能感兴趣的:(stm32,学习,嵌入式硬件)