STM32 DS18B20 代码详解

发布者:灵感之翼最新更新时间:2021-10-19 来源: eefocus关键字:STM32  DS18B20  延时 手机看文章 扫描二维码
随时随地手机看文章

DS18B20是最常用来学习某一个新的开发工具的,程序都是大同小异,主要是要注意时序中的延时要准确,指令要正确,这里记录一下!


------------------第一部分是--------ds18b20.h----------------------


#ifndef __DS18B20_H

#define __DS18B20_H


#include "stm32f10x.h"

#include "bsp_SysTick.h"   //精确延时函数头文件----参考http://blog.csdn.net/xuxuechen/article/details/40783209这个看一下


#define HIGH  1 

#define LOW   0


#define DS18B20_CLK     RCC_APB2Periph_GPIOB

#define DS18B20_PIN      GPIO_Pin_10                  

#define DS18B20_PORT GPIOB                  //总体代表DS18B20的GPIO口为PB10



//带参宏,可以像内联函数一样使用,输出高电平或低电平

#define DS18B20_DATA_OUT(a)if (a)

GPIO_SetBits(GPIOB,GPIO_Pin_10);

else

GPIO_ResetBits(GPIOB,GPIO_Pin_10)

 //读取引脚的电平

#define  DS18B20_DATA_IN()  GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_10)


uint8_t DS18B20_Init(void);

float DS18B20_Get_Temp(uint8_t *a,uint8_t b);

void read_serial(uint8_t *serial);

#endif /* __DS18B20_H */


----------------第二部分是----------DS18B20.C源文件---------------------



#include "bsp_ds18b20.h"


uint8_t serial_1[8]={0x28,0x2d,0x9a,0xdd,0x02,0x00,0x00,0x3b}; 

uint8_t serial_2[8]={0x28,0x3b,0x2b,0xbc,0x02,0x00,0x00,0x4f};

uint8_t serial_3[8]={0x28,0x00,0x49,0x1b,0x03,0x00,0x00,0x4c};  //序列号,需要根据自己的DS18B20修改,具体读取方法,会有另一篇介绍。


static void DS18B20_GPIO_Config(void)

  GPIO_InitTypeDef GPIO_InitStructure;

  

  RCC_APB2PeriphClockCmd(DS18B20_CLK, ENABLE); 

  GPIO_InitStructure.GPIO_Pin = DS18B20_PIN; 

  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;   

  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; 

  GPIO_Init(DS18B20_PORT, &GPIO_InitStructure);


  GPIO_SetBits(DS18B20_PORT, DS18B20_PIN);  

}


static void DS18B20_Mode_IPU(void)  //使DS18B20-DATA引脚变为输入模式

{

  GPIO_InitTypeDef GPIO_InitStructure;

  

  GPIO_InitStructure.GPIO_Pin = DS18B20_PIN;

  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU; 

  GPIO_Init(DS18B20_PORT, &GPIO_InitStructure);

}


static void DS18B20_Mode_Out_PP(void)  //使DS18B20-DATA引脚变为输出模式

{

  GPIO_InitTypeDef GPIO_InitStructure;


  GPIO_InitStructure.GPIO_Pin = DS18B20_PIN; 

  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;   

  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;

  GPIO_Init(DS18B20_PORT, &GPIO_InitStructure);

}


static void DS18B20_Rst(void)  //主机给从机发送复位脉冲

{

  DS18B20_Mode_Out_PP();

  DS18B20_DATA_OUT(LOW);

  Delay_Us(750);  //主机至少产生480us的低电平复位信号

  DS18B20_DATA_OUT(HIGH);  //主机在产生复位信号后,需将总线拉高

  Delay_Us(15);   //从机接收到主机的复位信号后,会在15~60us后给主机发一个存在脉冲

}


static uint8_t DS18B20_Presence(void)  //检测从机给主机返回的存在脉冲

{

  uint8_t pulse_time = 0;


  DS18B20_Mode_IPU(); //主机设置为上拉输入


//等待存在脉冲的到来,存在脉冲为一个60~240us的低电平信号 

//如果存在脉冲没有来则做超时处理,从机接收到主机的复位信号后,会在15~60us后给主机发一个存在脉冲


  while( DS18B20_DATA_IN() && pulse_time<100 )

  {

    pulse_time++;

    Delay_Us(1);

  } 

  if( pulse_time >=100 )   //经过100us后,存在脉冲都还没有到来

        return 1;

  else

        pulse_time = 0;

  while( !DS18B20_DATA_IN() && pulse_time<240 )  //存在脉冲到来,且存在的时间不能超过240us 

  {

    pulse_time++;

    Delay_Us(1);

  } 

  if( pulse_time >=240 )

    return 1;

  else

    return 0;

}


static uint8_t DS18B20_Read_Bit(void)  //从DS18B20读取一个bit

{

  uint8_t dat;


  DS18B20_Mode_Out_PP();  //读0和读1的时间至少要大于60us

  DS18B20_DATA_OUT(LOW);  //读时间的起始:必须由主机产生 >1us <15us 的低电平信号

  Delay_Us(10);

  DS18B20_Mode_IPU(); //设置成输入,释放总线,由外部上拉电阻将总线拉高

  if( DS18B20_DATA_IN() == SET )

      dat = 1;

  else

     dat = 0;

  Delay_Us(45);   //这个延时参数请参考时序图


  return dat;

}


uint8_t DS18B20_Read_Byte(void)  //从DS18B20读一个字节,低位先行

{

  uint8_t i, j, dat = 0; 


  for(i=0; i<8; i++) 

  {

      j = DS18B20_Read_Bit(); 

  dat = (dat) | (j<  }


  return dat;

}


void DS18B20_Write_Byte(uint8_t dat)  //写一个字节到DS18B20,低位先行

{

  uint8_t i, testb;


  DS18B20_Mode_Out_PP();

  for( i=0; i<8; i++ )

  {

    testb = dat&0x01;

    dat = dat>>1; 

    if (testb) //写0和写1的时间至少要大于60us

    { 

        DS18B20_DATA_OUT(LOW);

        Delay_Us(8);

        DS18B20_DATA_OUT(HIGH);

        Delay_Us(58);

    } 

  else

    { 

        DS18B20_DATA_OUT(LOW);

        Delay_Us(70);

        DS18B20_DATA_OUT(HIGH);

        Delay_Us(2);

      }

  }

}


void DS18B20_Start(void)

{

  DS18B20_Rst();   

  DS18B20_Presence();  

  DS18B20_Write_Byte(0XCC); //跳过 ROM  

  DS18B20_Write_Byte(0X44); //开始转换 

}


uint8_t DS18B20_Init(void)

{

  DS18B20_GPIO_Config();

  DS18B20_Rst();


  return DS18B20_Presence();

}


void DS18B20_Match_Serial(uint8_t a)    //匹配序列号

{

  uint8_t i;

  DS18B20_Rst();

  DS18B20_Presence();

  DS18B20_Write_Byte(0X55); //匹配序列号指令

  if(a==1)

  {

    for(i=0;i<8;i++) 

       DS18B20_Write_Byte(serial_1[i]);

  }

  else if(a==2)

  {

    for(i=0;i<8;i++) 

       DS18B20_Write_Byte(serial_2[i]);

  } 

  else if(a==3)

  {

    for(i=0;i<8;i++) 

       DS18B20_Write_Byte(serial_3[i]);

  }       

}



//存储的温度是16 位的带符号扩展的二进制补码形式

//当工作在12位分辨率时,其中5个符号位,7个整数位,4个小数位


//         |---------整数----------|-----小数 分辨率 1/(2^4)=0.0625----|

//低字节  | 2^3 | 2^2 | 2^1 | 2^0 | 2^(-1) | 2^(-2) | 2^(-3) | 2^(-4) |


//        |-----符号位:0->正  1->负-------|-----------整数-----------|

//高字节  |  s  |  s  |  s  |  s  |    s   |   2^6  |   2^5  |   2^4  |

//温度 = 符号位 + 整数 + 小数*0.0625



float DS18B20_Get_Temp(uint8_t *a,uint16_t go_temp,uint8_t b)

{

  uint8_t tpmsb, tplsb;

  short s_tem;

  float f_tem;

  int temp_num;


  DS18B20_Rst();   

  DS18B20_Presence();  

  DS18B20_Write_Byte(0XCC); // 跳过 ROM 

  DS18B20_Match_Serial(b); //匹配序列号

  DS18B20_Write_Byte(0X44); // 开始转换 


  DS18B20_Rst();

  DS18B20_Presence();

  DS18B20_Write_Byte(0XCC); //跳过 ROM  

  DS18B20_Match_Serial(b); //匹配序列号

  DS18B20_Write_Byte(0XBE); //读温度值 


  tplsb = DS18B20_Read_Byte();  

  tpmsb = DS18B20_Read_Byte(); 


  s_tem = tpmsb<<8;

  s_tem = s_tem | tplsb;


  if( s_tem < 0 ) //负温度

  {

    f_tem = (~s_tem+1) * 0.0625;

    temp_num = (~s_tem+1) * 0.0625*10;

    go_temp= temp_num;

    if(temp_num>=1000)

    {

       a[0]='-';

       a[1]= temp_num/1000+'0';

       a[2]= temp_num%1000/100+'0';

       a[3]= temp_num%100/10+'0';

       a[4]='.';

       a[5]= temp_num%10+'0';

       a[6]= '';

    }

    else

    {

       a[0]='-';

       a[1]= temp_num/100+'0';

       a[2]= temp_num%100/10+'0';

       a[3]='.'; 

       a[4]=temp_num%10+'0';

       a[5]= '';

    }

  } 

  else

  {

    f_tem = s_tem * 0.0625;

    temp_num = s_tem * 0.0625*10;

    go_temp= temp_num;

    if(temp_num>=1000)

    {

       a[0]='+';

       a[1]= temp_num/1000+'0';

       a[2]= temp_num%1000/100+'0';

       a[3]= temp_num%100/10+'0';

       a[4]='.';

       a[5]= temp_num%10+'0';

       a[6]= '';

    }

   else

   {

       a[0]='+';

       a[1]= temp_num/100+'0';

       a[2]= temp_num%100/10+'0';

       a[3]='.'; 

       a[4]=temp_num%10+'0';

       a[5]= '';

    }

  } 

  return f_tem;

}


void read_serial(uint8_t *serial)  //读取序列号

{

  uint8_t i;

  DS18B20_Rst();

  DS18B20_Presence();

  DS18B20_Write_Byte(0X33); //读取序列号指令

  for(i=0;i<8;i++) 

     serial[i] = DS18B20_Read_Byte(); 

}


----------------第三部分是-------------main.c--------------


int main(void)

        int go_num;


        uint8_t *temp_ds18b20;




        USART1_Config();

        printf("多个DS18B20温度读取实验!rn");

        while(1)  

        {


                DS18B20_Get_Temp(temp_ds18b20,go_num,3);


                     printf("%drn",go_num);


                Delay_Ms(200);


                DS18B20_Get_Temp(temp_ds18b20,go_num,2);

                printf("%drn",go_num);

[1] [2]
关键字:STM32  DS18B20  延时 引用地址:STM32 DS18B20 代码详解

上一篇:STM32 I2C总线 自我总结学习
下一篇:STM32 MDK 工程创建 图解步骤

推荐阅读最新更新时间:2024-11-10 13:50

基于STM32的温度采集报警系统
单片机源程序如下: #include stm32f10x.h #include delay.h #include usart.h #include LCD1602.h #include led.h #include ds18b20.h //Buzzer--------------- PB8 //LED1----------------- PB15 //LED2----------------- PA8 //Relay2--------------- PA9 //Relay1--------------- PA10 float Set_H = 35.0; //高温报警温度 float Set_L = 10
[单片机]
基于<font color='red'>STM32</font>的温度采集报警系统
STM32 ADC的规则通道和注入通道的区别
STM32的每个ADC模块通过内部的模拟多路开关,可以切换到不同的输入通道并进行转换。STM32特别地加入了多种成组转换的模式,可以由程序设置好之后,对多个模拟通道自动地进行逐个地采样转换。 有2种划分转换组的方式:规则通道组和注入通道组。通常规则通道组中可以安排最多16个通道,而注入通道组可以安排最多4个通道。 在执行规则通道组扫描转换时,如有例外处理则可启用注入通道组的转换。 一个不太恰当的比喻是:规则通道组的转换好比是程序的正常执行,而注入通道组的转换则好比是程序正常执行之外的一个中断处理程序。 再举一个不一定使用的例子: 假如你在家里的院子内放了5个温度探头,室内放了3个温度探头;你需要时刻监视室外温
[单片机]
单片机 软件延时时间控制
一、简述 记--通过代码方式实现软件延时(不精确延时)。 二、指令周期 单片机需要一个时钟信号送给内部各个电路,才能使它们有节拍地协同工作。时钟信号的频率是由外部震荡电路的晶振频率决定的。 外接晶振的频率 = 时钟信号的频率 = 工作频率。(如24MHz,12MHz,11.0592MHz) 震荡周期:为单片机提供时钟脉冲的振荡源的周期。 震荡周期 = 1/晶振频率 (如晶振频率是12MHz时,振荡周期 = 1/12MHz = (1/12)us) 机器周期:51系列单片机的一个机器周期由12个震荡周期组成。 机器周期 = 12 * 振荡周期 (如晶振频率是24MHz时,振荡周期 = 1/
[单片机]
STM32应用简章之PWM输出
① 使能定时器3和相关IO口时钟。 使能定时器3时钟:RCC_APB1PeriphClockCmd(); 使能GPIOB时钟:RCC_APB2PeriphClockCmd(); ② 初始化IO口为复用功能输出。函数:GPIO_Init(); GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; ③这里我们是要把PB5用作定时器的PWM输出引脚,所以要重映射配置, 所以需要开启AFIO时钟。同时设置重映射。 RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE);
[单片机]
STM32:I2C接口读写EEPROM(AT24C02)试验例程
硬件平台:stm32f10xZET6 开发环境:keil MDK uVisionv4.10 开发语言:C、ST_lib_3.5固件库 EEPROM:电可擦可编程只读存储器。 【stm32f10xZET6开发板的I2C外设物理层特点】 (1)两条串行总线:一条双向数据线(SDA),一条时钟线(SCL); (2)从设备地址唯一; (3)支持总线仲裁; (4)三种速率传输模式: 标准模式100kbit/s 快速模式400kbit/s 高速模式3.4Mbit/s (目前大多I2C设备尚不支持高速模式) (5)片上的滤波器可以滤去总线数据线上的毛刺波保证数据完整; (6)连接到相同总线的IC数量受到总线的最大电容400p
[单片机]
STM32 IAP 设计实例 (二)
上一篇介绍了IAP的实现。这里开始介绍主机的一个设计实例。 目标功能:STM32做主机,硬件接口主要包括SD card, USB,CAN, LCD,按键。 主要功能: 1,通过USB链接到PC,将用于更新的APP程序的BIN文件,放入SD中。 2,STM32通过FATFS读写SD卡中的文件。 3,通过CAN接口发送数据给从机。 4,LCD和按键用于人机交互。 PC通过STM32 USB读取SD卡的部分功能直接使用使用了神州三号开发板中的例程。移植FATFS参考了网上的一些例子,比较乱。 view plain copy int main(void) { uint16_t Status
[单片机]
<font color='red'>STM32</font> IAP 设计实例 (二)
stm32液晶、RTC时间显示问题
最近调液晶屏日期和时间显示,修改RTC.c中的程序中if(HAL_RTCEx_BKUPRead(RTCHandle,RTC_BKP_DR0)!= 0xABCD) { sTime- Hours=14; sTime- Minutes=37; sTime- Seconds=20; sTime- SubSeconds=0; sTime- TimeFormat=RTC_HOURFORMAT12_AM; sTime- DayLightSaving=RTC_DAYLIGHTSAVING_NONE; sTime- StoreOperation=RTC_STOREOPERATION_RESET; HAL
[单片机]
单片机延时方法总结
实现延时通常有两种方法:一种是硬件延时,要用到定时器/计数器,这种方法可以提高CPU的工作效率,也能做到精确延时;另一种是软件延时,这种方法主要采用循环体进行。 1 使用定时器/计数器实现精确延时 单片机系统一般常选用11.059 2 MHz、12 MHz或6 MHz晶振。第一种更容易产生各种标准的波特率,后两种的一个机器周期分别为1 μs和2 μs,便于精确延时。本程序中假设使用频率为12 MHz的晶振。最长的延时时间可达216=65 536 μs。若定时器工作在方式2,则可实现极短时间的精确延时;如使用其他定时方式,则要考虑重装定时初值的时间(重装定时器初值占用2个机器周期)。 在实际应用中,定时常采用中断方式,如进行适
[单片机]
小广播
设计资源 培训 开发板 精华推荐

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

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

换一换 更多 相关热搜器件

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved