DS18B20中文资料手册及程序代码下载链接:

链接:https://pan.baidu.com/s/1c_POj04yqatXVwzM_zarGw             提取码:2q3a

DS18B20单总线上多路采集的关键在于读取ROM指令,通过ROM指令读取指定的DS18B20温度。

64 位(激)光刻只读存储器

每只DS18B20 都有一个唯一存储在ROM 中的64 位编码。最前面8 位是单线系列编码:28h。接着的48 位是一个唯一的序列号。最后8 位是以上56 位的CRC 编码。CRC的详细解释见CRC 发生器节。64位ROM和ROM操作控制区允许DS18B20作为单总线器件并按照详述于单总线系统节的单总线协议工作。

ROM 指令

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

Search ROM [F0h] (搜索ROM 指令)

当系统上电初始化的时候,总线控制器必须通过识别总线上所有ROM片序列码去得到从机的数目和型号。总线控制器通过搜索ROM指令多次循环搜索ROM编码,以确认所有从机器件。如果总线上只有一只从机,那么可以用较为简单的读取ROM 指令(见下文)代替搜索ROM 指令。

READ ROM [33h] (读取ROM 指令)
只有在总线上存在单只DS18B20的时候才能使用这条命令。该命令允许总线控制器在不使用搜索ROM 指令的情况下读取从机的64 位片序列码。如果总线上有不止一只从机,当所有从机试图同时传送信号时就会发生数据冲突。

MATH ROM [55h] (匹配ROM 指令)
匹配ROM 指令,后跟64 位ROM 编码序列,让总线控制器在多点总线上定位一只特定的DS18B20。只有和64 位ROM 片序列码完全匹配的DS18B20 才能响应随后的存储器操作指令;所有和64位ROM片序列码不匹配的从机都将等待复位脉冲。

以下是STM32的DS18B20多路采集,时序代码和普通读单个的代码一致,添加了读取ID和读取多个DS18B20的程序。

核心代码如下:

  DS18B20.c文件代码:

#include "DS18B20.h"
#include "Delay.h"
#include "stdio.h" // printf用#define DS18B20_GPIO_NUM              GPIO_Pin_5
#define DS18B20_GPIO_X                  GPIOC
#define RCC_APB2Periph_DS18B20_GPIO_X   RCC_APB2Periph_GPIOC#define DS18B20_DQ_OUT_Low          GPIO_ResetBits(DS18B20_GPIO_X,DS18B20_GPIO_NUM)
#define DS18B20_DQ_OUT_High         GPIO_SetBits(DS18B20_GPIO_X,DS18B20_GPIO_NUM)
#define DS18B20_DQ_IN               GPIO_ReadInputDataBit(DS18B20_GPIO_X,DS18B20_GPIO_NUM) #define MaxSensorNum 8
unsigned char DS18B20_ID[MaxSensorNum][8];  // 存检测到的传感器DS18B20_ID的数组,前面的维数代表单根线传感器数量上限
unsigned char DS18B20_SensorNum;            // 检测到的传感器数量(从1开始,例如显示1代表1个,8代表8个)// 配置DS18B20用到的I/O口
void DS18B20_GPIO_Config(void)
{GPIO_InitTypeDef GPIO_InitStructure;RCC_APB2PeriphClockCmd(RCC_APB2Periph_DS18B20_GPIO_X, ENABLE);GPIO_InitStructure.GPIO_Pin = DS18B20_GPIO_NUM;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;GPIO_Init(DS18B20_GPIO_X, &GPIO_InitStructure);GPIO_SetBits(DS18B20_GPIO_X, DS18B20_GPIO_NUM);
}// 引脚输入
void DS18B20_Mode_IPU(void)
{GPIO_InitTypeDef GPIO_InitStructure;GPIO_InitStructure.GPIO_Pin = DS18B20_GPIO_NUM;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;GPIO_Init(DS18B20_GPIO_X, &GPIO_InitStructure);
}// 引脚输出
void DS18B20_Mode_Out(void)
{GPIO_InitTypeDef GPIO_InitStructure;GPIO_InitStructure.GPIO_Pin = DS18B20_GPIO_NUM;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;GPIO_Init(DS18B20_GPIO_X, &GPIO_InitStructure);}// 复位,主机给从机发送复位脉冲
void DS18B20_Rst(void)
{DS18B20_Mode_Out();DS18B20_DQ_OUT_Low;     // 产生至少480us的低电平复位信号Delay_us(480);DS18B20_DQ_OUT_High;  // 在产生复位信号后,需将总线拉高Delay_us(15);
}// 检测从机给主机返回的应答脉冲。从机接收到主机的复位信号后,会在15~60us后给主机发一个应答脉冲
u8 DS18B20_Answer_Check(void)
{u8 delay = 0;DS18B20_Mode_IPU(); // 主机设置为上拉输入// 等待应答脉冲(一个60~240us的低电平信号 )的到来// 如果100us内,没有应答脉冲,退出函数,注意:从机接收到主机的复位信号后,会在15~60us后给主机发一个存在脉冲while (DS18B20_DQ_IN&&delay < 100){delay++;Delay_us(1);}// 经过100us后,如果没有应答脉冲,退出函数if (delay >= 100)//Hu200return 1;elsedelay = 0;// 有应答脉冲,且存在时间不超过240uswhile (!DS18B20_DQ_IN&&delay < 240){delay++;Delay_us(1);}if (delay >= 240)return 1;return 0;
}// 从DS18B20读取1个位
u8 DS18B20_Read_Bit(void)
{u8 data;DS18B20_Mode_Out();DS18B20_DQ_OUT_Low; // 读时间的起始:必须由主机产生 >1us <15us 的低电平信号Delay_us(2);DS18B20_DQ_OUT_High;Delay_us(12);DS18B20_Mode_IPU();// 设置成输入,释放总线,由外部上拉电阻将总线拉高if (DS18B20_DQ_IN)data = 1;elsedata = 0;Delay_us(50);return data;
}// 从DS18B20读取2个位
u8 DS18B20_Read_2Bit(void)//读二位 子程序
{u8 i;u8 dat = 0;for (i = 2; i > 0; i--){dat = dat << 1;DS18B20_Mode_Out();DS18B20_DQ_OUT_Low;Delay_us(2);DS18B20_DQ_OUT_High;DS18B20_Mode_IPU();Delay_us(12);if (DS18B20_DQ_IN)    dat |= 0x01;Delay_us(50);}return dat;
}// 从DS18B20读取1个字节
u8 DS18B20_Read_Byte(void)  // read one byte
{u8 i, j, dat;dat = 0;for (i = 0; i < 8; i++){j = DS18B20_Read_Bit();dat = (dat) | (j << i);}return dat;
}// 写1位到DS18B20
void DS18B20_Write_Bit(u8 dat)
{DS18B20_Mode_Out();if (dat){DS18B20_DQ_OUT_Low;// Write 1Delay_us(2);DS18B20_DQ_OUT_High;Delay_us(60);}else{DS18B20_DQ_OUT_Low;// Write 0Delay_us(60);DS18B20_DQ_OUT_High;Delay_us(2);}
}// 写1字节到DS18B20
void DS18B20_Write_Byte(u8 dat)
{u8 j;u8 testb;DS18B20_Mode_Out();for (j = 1; j <= 8; j++){testb = dat & 0x01;dat = dat >> 1;if (testb){DS18B20_DQ_OUT_Low;// 写1Delay_us(10);DS18B20_DQ_OUT_High;Delay_us(50);}else{DS18B20_DQ_OUT_Low;// 写0Delay_us(60);DS18B20_DQ_OUT_High;// 释放总线Delay_us(2);}}
}//初始化DS18B20的IO口,同时检测DS的存在
u8 DS18B20_Init(void)
{DS18B20_GPIO_Config();DS18B20_Rst();return DS18B20_Answer_Check();
}// 从ds18b20得到温度值,精度:0.1C,返回温度值(-550~1250),Temperature1返回浮点实际温度
float DS18B20_Get_Temp(u8 i)
{//u8 flag;u8 j;//匹配的字节u8 TL, TH;short Temperature;float Temperature1;DS18B20_Rst();DS18B20_Answer_Check();DS18B20_Write_Byte(0xcc);// skip romDS18B20_Write_Byte(0x44);// convertDS18B20_Rst();DS18B20_Answer_Check();// DS18B20_Write_Byte(0xcc);// skip rom//匹配ID,i为形参DS18B20_Write_Byte(0x55);for (j = 0; j < 8; j++){DS18B20_Write_Byte(DS18B20_ID[i][j]);}DS18B20_Write_Byte(0xbe);// convertTL = DS18B20_Read_Byte(); // LSB   TH = DS18B20_Read_Byte(); // MSB  if (TH & 0xfc){//flag=1;Temperature = (TH << 8) | TL;Temperature1 = (~Temperature) + 1;Temperature1 *= 0.0625;}else{//flag=0;Temperature1 = ((TH << 8) | TL)*0.0625;}return Temperature1;
}// 自动搜索ROM
void DS18B20_Search_Rom(void)
{u8 k, l, chongtuwei, m, n, num;u8 zhan[5];u8 ss[64];u8 tempp;l = 0;num = 0;do{DS18B20_Rst(); //注意:复位的延时不够Delay_us(480); //480、720DS18B20_Write_Byte(0xf0);for (m = 0; m < 8; m++){u8 s = 0;for (n = 0; n < 8; n++){k = DS18B20_Read_2Bit();//读两位数据k = k & 0x03;s >>= 1;if (k == 0x01)//01读到的数据为0 写0 此位为0的器件响应{DS18B20_Write_Bit(0);ss[(m * 8 + n)] = 0;}else if (k == 0x02)//读到的数据为1 写1 此位为1的器件响应{s = s | 0x80;DS18B20_Write_Bit(1);ss[(m * 8 + n)] = 1;}else if (k == 0x00)//读到的数据为00 有冲突位 判断冲突位{//如果冲突位大于栈顶写0 小于栈顶写以前数据 等于栈顶写1chongtuwei = m * 8 + n + 1;if (chongtuwei > zhan[l]){DS18B20_Write_Bit(0);ss[(m * 8 + n)] = 0;zhan[++l] = chongtuwei;}else if (chongtuwei < zhan[l]){s = s | ((ss[(m * 8 + n)] & 0x01) << 7);DS18B20_Write_Bit(ss[(m * 8 + n)]);}else if (chongtuwei == zhan[l]){s = s | 0x80;DS18B20_Write_Bit(1);ss[(m * 8 + n)] = 1;l = l - 1;}}else{//没有搜索到}}tempp = s;DS18B20_ID[num][m] = tempp; // 保存搜索到的ID}num = num + 1;// 保存搜索到的个数} while (zhan[l] != 0 && (num < MaxSensorNum));DS18B20_SensorNum = num;//printf("DS18B20_SensorNum=%d\r\n",DS18B20_SensorNum);
}

DS18B20.h文件代码:

#ifndef __DS18B20_H
#define __DS18B20_H #include "stm32f10x.h"u8 DS18B20_Init(void);
u8 DS18B20_Read_Byte(void);
u8 DS18B20_Read_Bit(void);
u8 DS18B20_Answer_Check(void);
void  DS18B20_GPIO_Config(void);
void  DS18B20_Mode_IPU(void);
void  DS18B20_Mode_Out(void);
void  DS18B20_Rst(void);
void  DS18B20_Search_Rom(void);
void  DS18B20_Write_Byte(u8 dat);
float DS18B20_Get_Temp(u8 i);#endif

main.c文件代码:

#include "stm32f10x.h"
#include "stdio.h"
#include "string.h"//strlen、memset用到
#include "USART.h"
#include "Delay.h"
#include "DS18B20.h"extern unsigned char DS18B20_ID[8][8];//检测到的传感器ID存数组
extern unsigned char DS18B20_SensorNum;int main(void)
{u8 num=0;USART1_init(9600);while(DS18B20_Init())//初始化DS18B20,兼检测18B20{printf("DS18B20 Check Failed!\r\n");  }printf("DS18B20 Ready!\r\n");while(1){     DS18B20_Search_Rom();printf("DS18B20_SensorNum:%d\r\n",DS18B20_SensorNum);for(num=0;num<DS18B20_SensorNum;num++){printf("ID:%02x%02x%02x%02x%02x%02x%02x%02x TM:%.2f\r\n",DS18B20_ID[num][0],DS18B20_ID[num][1],DS18B20_ID[num][2],DS18B20_ID[num][3],DS18B20_ID[num][4],DS18B20_ID[num][5],DS18B20_ID[num][6],DS18B20_ID[num][7],DS18B20_Get_Temp(num));}printf("\r\n");Delay_s(2);}
}

运行结果如图:

STM32学习笔记二、DS18B20单总线上挂载多路采集相关推荐

  1. STM32学习笔记二:命令行工具安装

    一目了然 1 简述 2 Windows Terminal 安装 3 PowerShell7 安装 4 Cmake安装 5 ninja安装 1 简述 熟悉 Linux 系统的小伙伴都清楚 Termina ...

  2. 学习笔记二:OSS上传视频截帧

    简介 这章主要是上传视频截帧,公司需求对动态上传需求是OSS上传和截帧(最开始时没有需求,自己用的是FFmpeg 多媒体处理工具截取的),最后因为服务器上没有FFmpeg 工具,导致上传docker报 ...

  3. wxpython应用程序对象与顶级窗口_wxPython学习笔记(二)

    如何创建和使用一个应用程序对象? 任何wxPython应用程序都需要一个应用程序对象.这个应用程序对象必须是类wx.App或其定制的子类的一个实例.应用程序对象的主要目的是管理幕后的主事件循环. 父类 ...

  4. STM32学习笔记:FLASH读写之二

    因为关于STM32的Flash相关的知识点比较多,所以该内容的学习我们分为以下4个部分 1.RAM和ROM的一些基本概念 -- STM32学习笔记:FLASH读写之一 2.STM32的Flash寄存器 ...

  5. 《STM32学习笔记》3——核心功能电路与编程(上)

    接上文,文中的图片,大多数来自视频的截图(来自洋桃电子). 欢迎大家批评指正! STM32学习笔记-专栏 文章目录 一.核心板电路分析 二.点灯 LED 1.LED电路 2.LED功能相关初始化配置 ...

  6. STM32学习笔记(15)——SPI协议

    STM32学习笔记(15)--SPI协议 一.SPI协议简介 1. 物理层 2. 协议层 (1) 通讯的开始与停止 (2)时钟极性CPOL.时钟相位CPHA 二.STM32的SPI外设 1. 通讯引脚 ...

  7. STM32学习笔记 | 引起电源和系统异常复位的原因

    关注+星标公众号,不错过精彩内容 每一块处理器都有复位的功能,不同处理器复位的类型可能有差异,引起复位的原因也可能有多种. STM32的复位功能非常强大,可通过软件.硬件和一些事件触发系统复位,而且通 ...

  8. 《STM32学习笔记》4——核心功能电路与编程(下)

    接上文,文中的图片,大多数来自视频的截图(来自洋桃电子). 欢迎大家批评指正! STM32学习笔记-专栏 文章目录 一.蜂鸣器驱动 1.蜂鸣器介绍 2.蜂鸣器电路 3.蜂鸣器程序 二. MIDI 音乐 ...

  9. 【STM32学习笔记-点亮LED灯】

    STM32学习笔记-点亮LED灯 文章目录 STM32学习笔记-点亮LED灯 一.原理图分析 二.代码分析 1.mian函数 2.led.c函数 3.led.h函数 4.函数文件整理 5.LED_In ...

  10. STM32学习笔记(四)丨TIM定时器及其应用(定时中断、内外时钟源选择)

    本篇文章包含的内容 一.TIM 定时器 1.1 TIM 定时器简介 1.2 TIM 定时器类型及其工作原理简介 1.2.1 基本定时器工作原理及其结构 1.2.2 通用定时器工作原理及其结构 1.2. ...

最新文章

  1. Dlib简介及在windows7 vs2013编译过程
  2. Git 技术篇 - git remote修改、移除仓库源的使用方法,git添加仓库源提示fatal: remote origin already exists.问题解决
  3. jquery validate验证方法
  4. [Leetcode] Majority Element 众数
  5. DIV Scroll属性
  6. redis 8种淘汰策略
  7. jieba库初识与运用
  8. php怎么判断文件在下载,php文件下载显示找不到文件怎么办
  9. 软件测试(三)——软件测试用例篇
  10. 数字调制解调—扩频通信和伪码同步
  11. CSP-2022 游寄
  12. fastlane实现Android自动化打包
  13. Linux 管道通信
  14. Spring Boot 分布式事物管理
  15. VMware虚拟机安装Linux教程
  16. CTime 的一般常用方法
  17. 大数据系列sql基础知识(史上最全,收藏起来)
  18. Chrome浏览器扩展学习之 - 添加书签
  19. android oreo自带壁纸,OREO 8图标包
  20. 谁在说谎--Python实现

热门文章

  1. CTF 关于linux 7z解压的一点trick
  2. 推进交通安全文化建设,首先要建立科学的理念
  3. 在VB中如何使IE窗口最大化
  4. Java SHA哈希示例
  5. uniform,attribute和varying
  6. 终于搞清楚了:happen-before原则是干什么的
  7. 表格OCR相关资源整理【ICDAR】【表格识别】【持续更新...】
  8. CryEngine 动态添加模型
  9. 24道互联网大厂最爱问智商题汇总|你能答对几道?(附带答案、详解)
  10. 【BLE】蓝牙数据速率