历史上的今天
返回首页

历史上的今天

今天是:2024年08月26日(星期一)

正在发生

2021年08月26日 | STM32 DS18B20 代码详解

2021-08-26 来源:eefocus

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);

推荐阅读

史海拾趣

Anvo-Systems公司的发展小趣事

Anvo-Systems在发展过程中始终注重企业文化建设和社会责任履行。公司倡导创新、协作、诚信的企业精神,为员工创造了一个积极向上的工作环境。同时,Anvo-Systems还积极参与社会公益活动,关注环保和可持续发展等问题。通过这些举措,Anvo-Systems不仅提升了企业的社会形象,也为社会的和谐发展做出了积极贡献。


请注意,以上故事纯属虚构,不代表现实中任何公司或行业的真实情况。在实际应用中,应根据具体公司的历史和发展情况进行调整和完善。

AEL [AEL Crystals Ltd]公司的发展小趣事

AEL Crystals非常重视与供应商和客户之间的合作关系。公司积极与供应商建立长期稳定的合作关系,确保原材料的稳定供应和质量可靠。同时,AEL Crystals也与众多客户建立了紧密的合作关系,深入了解客户需求并提供定制化的解决方案。这种长期合作关系的建立为公司的持续发展提供了有力保障。

Communications & Power Industries公司的发展小趣事

随着环保意识的日益增强,CPI积极响应国家号召,将绿色环保理念融入公司的经营发展中。公司加大了对环保技术的研发投入,推出了一系列低能耗、低排放的通信设备和电源产品。同时,CPI还加强了对生产过程的环保管理,通过引进先进的环保设备和技术,实现了生产废弃物的减量化、资源化和无害化处理。这些举措不仅提升了CPI的社会形象,也为公司的可持续发展注入了新的动力。

C&H Technology公司的发展小趣事

随着智能手机市场的快速发展,C&H Technology意识到单纯的芯片制造已经不能满足市场需求。于是,公司开始加大研发投入,致力于在5G通信、人工智能等前沿技术领域取得突破。经过多次试验和失败,C&H Technology的研发团队终于成功开发出了一款集成5G通信功能的手机芯片,并获得了多项专利。这一技术突破不仅提升了公司在行业内的地位,也为公司的未来发展奠定了坚实的基础。

B.B. Battery公司的发展小趣事

B.B. Battery公司成立之初,面临着资金短缺、市场竞争激烈等诸多挑战。然而,公司的创始人凭借对电池行业的深刻理解和敏锐的市场洞察力,带领团队不断探索和积累。他们深入调研市场需求,研发出适应市场需求的电池产品,并通过优化生产流程、降低成本等方式,逐步在市场上获得了一席之地。

Electric Imp Inc.公司的发展小趣事

面对日益激烈的市场竞争和不断变化的市场需求,Electric Imp Inc.公司始终保持着敏锐的市场洞察力和持续的创新精神。公司不断推出新产品、新技术,以满足不同客户的需求。同时,公司还加强了内部管理和团队建设,提高了员工的专业素质和工作效率。这些努力使得公司能够保持持续的发展态势,并在电子行业中保持领先地位。

问答坊 | AI 解惑

数控电源资料

数控电源精度在ad/da的选择上占很大因素欢迎回帖咨询…

查看全部问答>

FPGA/CPLD初学者应该如何入手?

作为一个有电子基本理论基础的新手,应该如何入手? 是应该先学习verilog&vhdl语言,还是其他什么? 我有听说过ilinx,altera和quartus,modelsim谁能帮忙具体解释下是什么?…

查看全部问答>

关于F28027功耗问题

刚用F28027,PCB做好以后,通上电发现电流就有60MA,很奇怪,烧入程序后发现电流有90MA,不知道为什么耗那么多电流,这个正常吗,根据芯片资料,我只给3.3V供电,那个VREGENZ我用电阻下拉到地了,在没烧程序前拿掉电阻,电流就没了,但是烧好程序后那个电阻有无 ...…

查看全部问答>

电子大赛试练 宽带放大器设计求助

最近在做一个宽带放大器 0-8M输入 要求放大1万倍 考虑三运放的仪表放大电路 找不到合适的放大器 买了ad846放大倍数不行啊 哪位高人能给推荐个合适的啊 或者换个电路用三极管场效应管也行  实在是在这方便没什么思路啊  给点指 ...…

查看全部问答>

华为硬件工程师手册..pdf免费!!!

.华为硬件工程师手册..pdf免费!!!…

查看全部问答>

【xilinx技术问答】FPGA能够实际工作的频率?

ISE软件中给出的综合报告和静态时序分析报告都有工作频率,请问哪一个是FPGA能够实际工作的频率? 答:经过映射和布线的频率值才是FPGA可以真正跑到的频率值看静态时序分析报告,基本上是这个数值。通过查看ISE9.103的 implement Design>Place ...…

查看全部问答>

SQLCE3.0问题

1、智能设备平台WINCE5.0、PC编程VS2005 C# 2、我想在WINCE5.0上操作数据库。运行我我自己的应用软件时提示:报错:无法加载 DLL“SQLCEME30.DLL”: 3、我重新编译内核,现在运行wince5.0时,WINGDOWS目录下已经有了所需的7个*。DLL文件,注册表 ...…

查看全部问答>

音频驱动某函数代码看不太懂,救助。

PBYTE OutputStreamContextM16::Render2(PBYTE pBuffer, PBYTE pBufferEnd, PBYTE pBufferLast) {     LONG CurrT = m_CurrT;     LONG DeltaT = m_DeltaT;     LONG CurrSamp0 = m_CurrSamp[0];     ...…

查看全部问答>

SQLServer CE 3.1

哪位大哥有SQLServer CE 3.1在WinCE6.0下应用的例子啊,以及如何详细部署的 资料,有的请指教,问题解决在送分.谢谢~…

查看全部问答>

CortexM0_IAP示例代码程序下载

CortexM0_IAP示例代码程序下载…

查看全部问答>