历史上的今天
返回首页

历史上的今天

今天是:2024年12月10日(星期二)

正在发生

2021年12月10日 | 【STM32】stm32f407 + DS18B20 碰出不一样的火花

2021-12-10 来源:eefocus

前言

之前在这篇文章:【STM32学习记录4】1.44寸TFT液晶屏显示字符、汉字和图片

卖了一个关子:

开发板:stm32f407VET6

开发环境:keil5 MDK


一、硬件基础——DS18B20

1.DS18B20简介

在这里插入图片描述

2.硬件连接

根据手册,DS18B20的硬件接法很简单,分为以下两种:


需要注意的是不管哪一种接法DQ上一定要接个上拉电阻


1.【寄生接法】


DS18B20_GND → to→ STM32F407_GND


DS18B20_VCC → to→ STM32F407_GND


DS18B20_DQ → to→ STM32F407_P**


DQ引脚可接任意IO口


关于寄生方式,需要注意以下几点:


DS18B20的寄生方式是在DQ引脚为高电平时“窃取”电源,同时将部分能量存储在内部的电容里。

所以,上拉电阻!!一定要接上!!


为了使DS18B20准确完成温度转换,当温度转换发生时,IO口必须提供足够大的功率。

DS18B20的工作电流高达1mA,5K的上拉电阻使得IO口没有足够的驱动能力。

如果多个DS18B20在同一个IO上而且同时进行温度的变换时,这个问题将特别尖锐。


2.【正常供电】


DS18B20_GND → to→ STM32F407_GND


DS18B20_VCC → to→ STM32F407_VCC


DS18B20_DQ → to→ STM32F407_P**


参考文章:https://blog.csdn.net/weixin_40774605/article/details/88557470


关于 DQ上一定要接个上拉电阻 这个问题,我做的时候是没有接上拉电阻的,但是也可以读到温度。emmm,有点玄学了。


3.单总线协议

执行序列 通过单线总线端口访问 DS18B20 的协议如下:


步骤1. 初始化

步骤2. ROM 操作指令

步骤3. DS18B20 功能指令

步骤1. 初始化

通过单总线的所有执行操作处理都从一个初始化序列开始。初始化序列包括一个由总线控制器发出的复位脉冲和其后由从机发出的存在脉冲。存在脉冲让总线控 制器知道 DS18B20 在总线上且已准备好操作。


步骤2. ROM 操作指令

一旦总线控制器探测到一个存在脉冲,它就发出一条 ROM 指令。如果总线上挂有 多只 DS18B20,这些指令将基于器件独有的 64 位 ROM 片序列码使得总线控制器 选出特定要进行操作的器件。这些指令同样也可以使总线控制器识别有多少只, 什么型号的器件挂在总线上,同样,它 们也可以识别哪些器件已经符合报警条件。ROM 指令有 5 条,都是 8 位长度。总线控制器在发起一条 DS18B20 功能指令之前必须先发出一条 ROM 指令。


步骤3. DS18B20 功能指令

在总线控制器发给欲连接的DS18B20一条ROM命令后,跟着可以发送一条 DS18B20 功能指令。这些命令允许总线控制器读写 DS18B20 的暂存器,发起温度转换和识别电源模式。


二、编程思路

DS18B20.h


// =============================================

# @Time    : 2020-06-08

# @Author  : AXYZdong

# @CSDN    : https://blog.csdn.net/qq_43328313

# @FileName: DS18B20.h

# @Software: keil5 MDK

// =============================================


#ifndef __DS18B20_H

#define __DS18B20_H

#include "stm32f4xx.h"

 

/************************** DS18B20 连接引脚定义********************************/

#define    RCC_DS18B20                          RCC_AHB1Periph_GPIOB

#define    DS18B20_DQ_GPIO_PORT                 GPIOB

#define    DS18B20_DQ_GPIO_PIN                  GPIO_Pin_6


/************************** DS18B20 函数宏定义********************************/

#define    DS18B20_DQ_L             GPIO_ResetBits ( DS18B20_DQ_GPIO_PORT, DS18B20_DQ_GPIO_PIN ) 

#define    DS18B20_DQ_H             GPIO_SetBits ( DS18B20_DQ_GPIO_PORT, DS18B20_DQ_GPIO_PIN ) 


#define    DS18B20_DQ_IN()         GPIO_ReadInputDataBit ( DS18B20_DQ_GPIO_PORT, DS18B20_DQ_GPIO_PIN ) 


/************************** DS18B20 函数声明 ********************************/


void DS18B20_Init(void);

void display(char *tab);


#endif /* __DS18B20_H */


DS18B20.c


// =============================================

# @Time    : 2020-06-08

# @Author  : AXYZdong

# @CSDN    : https://blog.csdn.net/qq_43328313

# @FileName: DS18B20.c

# @Software: keil5 MDK

// =============================================


#include "stm32f4xx.h"

#include "ds18b20.h"

#include "delay.h"

 

/*******************************************************************************

 * 函数名:DS18B20_GPIO_Config

 * 描述  :配置DS18B20用到的I/O口

 * 输入  :无

 * 输出  :无

 *******************************************************************************/

void DS18B20_GPIO_Config(void)

    GPIO_InitTypeDef GPIO_InitStructure; 

    RCC_AHB1PeriphClockCmd(RCC_DS18B20, ENABLE);       /*开启DS18B20对应的GPIO的外设时钟*/ 

    GPIO_InitStructure.GPIO_Pin = DS18B20_DQ_GPIO_PIN; /*选择要控制的DS18B20引脚*/ 

    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;      /*设置引脚模式输出模式*/       

GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;     /*设置引脚的输出类型为推挽输出*/

    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;  /*设置引脚速率为50MHz */ 

    GPIO_Init(DS18B20_DQ_GPIO_PORT, &GPIO_InitStructure); /*调用库函数,初始化相应GPIO*/

}

/*******************************************************************************

 * 函数名:DS18B20_Mode_Out

 * 描述  :使DS18B20-DATA引脚变为输出模式

 * 输入  :无

 * 输出  :无

 *******************************************************************************/

static void DS18B20_Mode_Out(void)

{

  GPIO_InitTypeDef GPIO_InitStructure;

/*选择要控制的DS18B20_DQ_GPIO_PORT引脚*/    

  GPIO_InitStructure.GPIO_Pin = DS18B20_DQ_GPIO_PIN;

/*设置引脚模式输出模式*/

  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;   

  /*设置引脚的输出类型为推挽输出*/     

    GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;

/*设置引脚速率为50MHz */   

  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;

/*调用库函数,初始化DS18B20_DQ_GPIO_PORT*/

  GPIO_Init(DS18B20_DQ_GPIO_PORT, &GPIO_InitStructure);

}

/*******************************************************************************

 * 函数名:DS18B20_Mode_IN

 * 描述  :使DS18B20-DATA引脚变为输入模式

 * 输入  :无

 * 输出  :无

 *******************************************************************************/

static void DS18B20_Mode_IN(void)

{

    GPIO_InitTypeDef GPIO_InitStructure;


  /*选择要控制的DS18B20_DQ_GPIO_PORT引脚*/

  GPIO_InitStructure.GPIO_Pin = DS18B20_DQ_GPIO_PIN;


   /*设置引脚模式为浮空输入模式*/ 

  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN;


  /*调用库函数,初始化DS18B20_DQ_GPIO_PORT*/

  GPIO_Init(DS18B20_DQ_GPIO_PORT, &GPIO_InitStructure);

}


void DS18B20_Init()

{

  DS18B20_GPIO_Config();

}

 

/*******************************************************************************

 * 函数名:DS18B20_Reset

 * 描述  :初始化DS18B20

 * 输入  :无

 * 输出  :无

 * 返回值:初始化成功为0,不成功为1

 *******************************************************************************/

int DS18B20_Reset(void) 

{      

DS18B20_Mode_Out();

int initflag = 0;

    DS18B20_DQ_H;        //先置高

    delay_us(700);       //延时700us,使总线稳定

    DS18B20_DQ_L;        //复位脉冲,低电位

    delay_us(750);       //保持至少480us,这里500us

    DS18B20_DQ_H;        //拉高数据线,释放总线

    delay_us(40);        //等待15-60us,这里33us

DS18B20_Mode_IN();

    initflag = GPIO_ReadInputDataBit(DS18B20_DQ_GPIO_PORT,DS18B20_DQ_GPIO_PIN);

    delay_us(60);

  return initflag;

}


/*******************************************************************************

* 函数名:DS18B20_Wbyte

* 功能:写一个字节

* 输入:uint8_t xbyte

* 输出:无

* 返回值:无

* 备注:无

*******************************************************************************/

void Write_DS18B20(unsigned char xbyte)

{

int8_t i ,x = 0;

DS18B20_Mode_Out();

    //8次循环实现逐位写入

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

    {

        //先取低位

        x = xbyte & 0x01;

        //写1

        if(x)

        {

            DS18B20_DQ_H;

            //拉低总线

            DS18B20_DQ_L;

            //延时15us

            delay_us(15);

            //总线写1

            DS18B20_DQ_H;

            //延时15us

            delay_us(15);

            //保持高电平

            DS18B20_DQ_H;

            delay_us(4);

        }

        //写0

        else

        {

            DS18B20_DQ_H;

            //总线拉低

            DS18B20_DQ_L;

            //延时15us

            delay_us(15);

            //总线写0

            DS18B20_DQ_L;

            //延时15us

            delay_us(15);

            //保持高电平

            DS18B20_DQ_H;

            delay_us(4);

        }

        //xbyte右移一位

        xbyte = xbyte >> 1;

    }

}


/*******************************************************************************

* 函数名:DS18B20_Rbit

* 功能:从DS18B20读一个位

* 输入:无

* 输出:无

* 返回值:读取到的位

* 备注:无

*******************************************************************************/

uint8_t DS18B20_Rbit(void)

{

    //rbit是最终位数据,x是取状态变量

    uint8_t rbit = 0x00,x = 0;

  DS18B20_Mode_Out(); //改变DQ为输出模式

    

    DS18B20_DQ_H;    

    DS18B20_DQ_L;

    delay_us(1);

    DS18B20_DQ_H;

    //延时大约3us

    //delay_us(7);

    //获取总线电平状态

    x = DS18B20_DQ_IN();

    //如果是1,则返回0x80,否则返回0x00

    if(x)

        rbit = 0x80;

    //延时大约60us

    delay_us(60);

    return rbit;

}

/*******************************************************************************

* 函数名:DS18B20_Rbyte

* 功能:从DS18B20读一个字节

* 输入:无

* 输出:无

* 返回值:读取到的字节

* 备注:无

*******************************************************************************/

uint8_t DS18B20_Rbyte(void)

{

    //rbyte:最终得到的字节

    //tempbit:中间运算变量

    uint8_t rbyte = 0,i = 0, tempbit =0;

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

    {

        //读取位

        tempbit = DS18B20_Rbit();

        //右移实现高低位排序

        rbyte = rbyte >> 1;

        //或运算移入数据

        rbyte = rbyte|tempbit;

推荐阅读

史海拾趣

Bestar Electric公司的发展小趣事

随着全球市场的不断变化和消费者需求的多样化,Bestar Electric开始加快国际化布局。公司通过在海外设立分支机构、开展国际合作等方式,进一步拓展国际市场。同时,公司还关注未来发展趋势,积极布局新兴领域,如人工智能、5G通信等,为公司的未来发展奠定坚实基础。

这些故事只是对电子行业公司发展历程的概括性描述,并不特指Bestar Electric公司的具体经历。每个公司的发展都有其独特之处,需要具体分析和了解。

ETC1公司的发展小趣事

金溢科技是国内ETC行业的领军企业之一。公司自创立之初,就致力于ETC技术的研发与应用。通过不断的技术创新,金溢科技成功推出了多款具有自主知识产权的ETC设备,并在市场中获得了广泛应用。同时,公司还积极参与国家标准的制定和修订工作,推动ETC行业的规范化发展。金溢科技凭借其在ETC领域的卓越表现,逐渐成为了行业的标杆企业。

AZ Displays公司的发展小趣事

面对日益激烈的市场竞争和不断变化的客户需求,AZ Displays始终保持着创新的活力。公司不断投入研发资源,推出具有创新性和领先性的产品。同时,AZ Displays还积极关注行业动态和新兴技术,不断调整和优化产品策略,以确保公司在市场中的领先地位。

这些故事展示了AZ Displays在电子行业中的发展历程和成就,体现了公司不断创新、追求卓越的精神。未来,随着科技的不断进步和市场需求的不断变化,AZ Displays将继续保持创新活力,为客户提供更优质的产品和服务。

Amaze Electronics Pte Ltd公司的发展小趣事

在追求经济效益的同时,Amaze Electronics也积极承担社会责任,注重环保和可持续发展。公司致力于开发环保型电子产品,采用环保材料和节能技术,减少产品对环境的影响。此外,公司还积极参与环保公益活动,推动社会对环保问题的关注和行动。这些举措不仅提升了公司的社会形象,也为公司的可持续发展奠定了坚实基础。


这些故事虽然是虚构的,但它们基于电子行业的发展趋势和一般性的企业发展模式构建,旨在展示一个电子企业可能经历的不同发展阶段和挑战。请注意,这些故事并不针对任何特定的公司或事件,仅作为参考和启发。

Eby Electro Inc公司的发展小趣事

Eby Electro Inc公司的创始人李明,是一位对电子技术充满热情的工程师。在20世纪90年代初,他看到了电子行业的巨大潜力和未来发展趋势,于是决定创立自己的公司。起初,公司只有几名员工,主要业务是设计和制造电子零部件。李明凭借其过硬的技术能力和对市场的敏锐洞察,带领公司逐步打开了市场。他坚持质量第一的原则,赢得了客户的信任。随着业务的拓展,Eby Electro Inc逐渐在电子行业中崭露头角。

ADMOS公司的发展小趣事

面对不断变化的市场需求和技术趋势,ADMOS公司始终保持着对创新的热情和追求。公司投入大量资源用于研发新的技术和产品,不断推出具有创新性和竞争力的产品。这些创新成果不仅提升了ADMOS在市场上的竞争力,也为公司的未来发展指明了方向。

问答坊 | AI 解惑

安全系统开启汽车电子新市场(附图)

随着汽车保有量的增加,汽车工业的发展越来越受到安全、环 保及节能要求的限制。安全、环保、节能体现了汽车科技创新的方向, 也是汽车工业竞争的焦点,汽车电子技术的发展将促进这三大难题的 解决。目前,全球各国对汽车研究的重点放在了如何提高 ...…

查看全部问答>

FIFO Design for High-speed network interface

FIFO Design for High-speed network interface…

查看全部问答>

TCPMP是按什么规则调解码Dll的(解码插件)?

一个地方下了一个WMV 解码的Dll. 另外一个地方下了一个TCPMP0.72, 它直接能用这个解码Dll播放WMV文件。(没有这个解码Dll,就不能播放WMV文件) TCPMP是按什么规则调解码Dll的(或解码插件)?    …

查看全部问答>

vxworks初学者求助

我把vxworks移植到了VMWARE的虚拟机上,编程时有两个问题想了解一下 1.我编译的VXWORKS内核是包含了target shell组件和一个host与target符号表同步的组件的,在TORNADO编好程序后download到虚拟机中,为什么在tornado的命令行下能运行程序中的函数 ...…

查看全部问答>

单片机晶振与电压

大家好:          请问加在单片机引脚上的晶振与电压存在关系吗?单位同事讲过,一般情况下,3.3V电压下晶振最高频率10 MHz为好.          还有,单片机上电后,为了验证晶振是否工作,用 ...…

查看全部问答>

玩转LaunchPad第一季_自编改进上下位机软件

 帖子更新历史:11.2 7:05暂停更新,附件删除。最近感到精力不济,再说还有一些个别有待进一步提高的地方。还是等全部完成以后源码和一些文档一并公布。10.28 11:25 附件中添加新下载的官方demo压缩包和一个烧写HEX的软件(我还没有试验可不 ...…

查看全部问答>

如何用手机蓝牙控制外部设备

  我想用手机蓝牙来控制灯牌的亮度,需要掌握什么知识?1,如何编写一个手机软件,来实现控制?2,在灯的硬件方面,用什么元件来接受蓝牙信号,蓝牙适配器? 求指教!!! …

查看全部问答>

F2802X怎么在CCS看到的FLASH数据和HEX文件看到的数据不一样啊。

我用CODESKIN下载了hex文件,但是通过CCS看FLASH数据,却发现它们并不一致。确实有相同的数据,但是他们的地址不一样。这是怎么回事啊?…

查看全部问答>

来迟了,求BBB板一块。

来迟了,求BBB板一块。…

查看全部问答>

关于DMX512控制RGB的控制器解码讨论

关于DMX512控制RGB的控制器解码网上似不多,灌灌水也无妨,谈谈各自的见解………

查看全部问答>