目录

  • DS18B20数字温度计 (一) 电气特性, 寄生供电模式和远距离接线
  • DS18B20数字温度计 (二) 测温, ROM和CRC算法
  • DS18B20数字温度计 (三) 1-WIRE总线 ROM搜索算法和实际测试

DS18B20 搜索算法

以下说明当总线上存在多个 DS18B20 芯片时, 识别各个 DS18B20 的编号并进行通信的算法.

其实这是 1-Wire 总线的搜索算法, 当 1-Wire 总线上挂接了多个设备时, 总线控制端需要通过 ROM Search 命令来判断总线上存在的设备以及获取他们的8字节唯一ROM.

1-WIRE SEARCH ALGORITHM 算法规则和实现机制

ROM搜索算法的核心规则, 是在搜索中重复进行一个简单的三步操作

步骤1: 读一次: 得到一位的值

总控读取1个bit. 这时每个设备都会将ROM当前这一位的bit值放到总线上, 如果这位是0, 就会对总线写0(拉低总线), 如果这位是1, 则会对总线写1, 允许总线保持高电平. 如果两者都存在, 总控读取的是0(低电平).

步骤2: 再读一次: 得到这位的补码

总控继续读一个bit, 这时候每个设备会将ROM当前这一位的bit的补码放到总线上, 如果这位是0就会写1, 如果这位是1则会写0, 如果两者都存在, 总控会读到一个0, 这样总控就会知道存在多个设备, 并且它们的ROM在这一位上的值不同.

步骤3: 写一次: 指定这一位的目标值

总控写入一个bit, 比如写入0, 表示在后面的搜索中选择这一位为0的设备, 屏蔽掉这一位为1的设备

循环

总线控制端在8字节ROM的每一位上执行这个三步操作后, 就能知道一个 DS18B20 的 8字节 ROM 值, 如果总线上有多个 DS18B20, 则需要重复多次.

搜索示例

示例数据

下面的例子假设总线上有4个设备, 对应的ROM值分别为

  • ROM1 00110101…
  • ROM2 10101010…
  • ROM3 11110101…
  • ROM4 00010001…

示例搜索过程

搜索步骤如下

  1. 单线总线控制端(以下简称总控)执行 RESET, 所有的 DS18B20设备(以下简称设备)响应这个RESET
  2. 总控执行 Search ROM 命令
  3. 总控读取1个bit. 这时每个设备都会将自己的ROM的第一个bit放到总线上, ROM1 和 ROM4 会对总线写0(拉低总线), 而 ROM2 和 ROM3 则会对总线写1, 允许总线保持高电平. 这时候总控读取的是0(低电平).
  4. 总控继续读下一个bit, 每个设备会将第一个bit的补码放到总线上, 这时候 ROM1 和 ROM4 写1, 而 ROM2 和 ROM3 写0, 因此总控依然读到一个0, 这时候总控会知道存在多个设备, 并且它们的ROM在这一位上的值不同.
  5. (说明)从每次的两步读取中观察到的值分别有以下的含义
    • 00 有多个设备, 且在这一位上值不同
    • 01 所有设备的 ROM在这一位上的值是0
    • 10 所有设备的 ROM在这一位上的值是1
    • 11 总线上没有设备
  6. 总控写入一个bit, 比如写入0, 表示在后面的搜索中屏蔽 ROM2 和 ROM3, 仅留下 ROM1 和 ROM4
  7. 总控再执行两次读操作, 读到的值为0,1, 这表示总线上所有设备在这一位上的值都是0
  8. 总控写入一个bit, 因为值是确定的, 这次写入的是0
  9. 总控再执行两次读操作, 读到的值为0,0, 这表示总线上还有多个设备, 在这一位上的值不同
  10. 总控写入一个bit, 这次写入0, 这将屏蔽 ROM1, 仅留下 ROM4
  11. 总控重复进行三步操作, 读出 ROM4 剩余的位, 完成第一次搜索
  12. 总控再次重复之前的搜索直到第7位
  13. 总控写入一个bit, 这次写入1, 将屏蔽 ROM4, 仅保留 ROM1
  14. 总控通过重复三步操作, 读出 ROM1 剩余的位
  15. 总控再次重复之前的搜索直到第3位
  16. 总控写入一个bit, 这次写入1, 将屏蔽 ROM1 和 ROM4 仅保留 ROM2 和 ROM3
  17. 重复之前的逻辑, 当所有00读数都被处理, 说明设备的ROM已经全部被读取.

总控通过单线总线读取所有设备, 每个设备需要的时间为960 µs + (8 + 3 x 64) 61 µs = 13.16 ms, 识别速度为每秒钟75个设备.

代码逻辑

使用代码实现时, 整体的逻辑是按一个固定的方向(先0后1)深度优先遍历一个二叉树.

数据结构

  • 预设一个8字节数组 Buff 用于记录路径(即ROM的读数)
  • 预设一个8字节数组 Stack, 用于记录每一位的值是否确定, 如果确定就是1, 未确定就是0.
  • 预设一个整数变量 Split_Point 用于记录每一轮搜索中得到的最深分叉点的位置, 下一次到这一位就用1进行分叉.

遍历逻辑

在每一轮遍历中

  1. 从低位开始, 每一位进行两次读, 得到这一位的值和补码
  2. 对前面的结果进行判断
    1. 如果为11, 说明没有设备, 直接退出
    2. 如果为01, 说明这一位都是0, 写入 Buff, 同时将 Stack 这一位设成 1, 表示这一位已确认
    3. 如果为10, 说明这一位都是1, 写入 Buff, 同时将 Stack 这一位设成 1, 表示这一位已确认
    4. 如果为00, 说明这一位产生了分叉, 需要继续判断
  3. 对分叉的判断, 与 Split_Point 记录的值进行比较
    1. 如果当前位置比已知的分叉点更浅, 说明还没到该分叉的位置, 继续设置成 Buff 中上一次使用的值, Stack不变
    2. 如果当前位置等于分叉点, 说明已经到了上次定好的分叉位置, 上次已经用0分叉过了, 这次就用1进行分叉, 这一位就确认了, 将 Stack 这一位设成 1, 表示已确认
    3. 如果当前位置比已知的分叉点位置还要深, 说明发现了新的分叉点(例如用1分叉后, 进入了新的子树, 发现下面还有分叉), 更新 Split_Point 记录分叉点位置, 将 Stack 这一位设成 0 (未确认), 用默认的0继续往下走
  4. 在这轮遍历结束后, Buff 就得到了一个新的地址
  5. 检查 Split_Point 是否需要往上挪: 在 Stack 上找到 Split_Point 标识的位置, 如果值为1, 则将 Split_Point 设置到最浅的一个0的位置. (例如这次正好在分叉点使用1分叉, 当前点确认了, 而之后又全是确认的情况, 需要将分叉点往上移)
  6. 结束条件: 和深度遍历一样, 每一轮遍历后分叉点可能会上下变化, 当分叉点的位置为0时, 说明遍历结束

代码实现

搜索逻辑的C语言代码实现

/*** buff, stack 和 split_point 都是全局变量, 由外部传入* */
uint8_t DS18B20_Search(uint8_t *buff, uint8_t *stack, uint8_t split_point)
{uint8_t len = 64, pos = 0;/* 分叉点的初始值应该用0xFF, 如果输入参数为0, 将其设为0xFF */split_point = (split_point == 0x00)? 0xFF : split_point;/* Reset line */DS18B20_Reset();/* Start searching */DS18B20_WriteByte(ONEWIRE_CMD_SEARCHROM);// len 初始值为64, 对 8 字节 ROM 做一个遍历while (len--){// 两次读, 读取这一位bit值和补码__BIT pb = DS18B20_ReadBit();__BIT cb = DS18B20_ReadBit();if (pb && cb) // 都是1, 表示没有设备{return 0;}else if (pb) // pb=1, cb=0, 说明这一位为1{// 在buff上记录这一位*(buff + pos / 8) |= 0x01 << (pos % 8);DS18B20_WriteBit(SET);// 在stack上将这一位记录为1, 表示已确认*(stack + pos / 8) |= 0x01 << (pos % 8);}else if (cb) // pb=0, cb=1, 说明这一位为0{// 在buff上记录这一位*(buff + pos / 8) &= ~(0x01 << (pos % 8));DS18B20_WriteBit(RESET);// 在stack上将这一位记录为1, 表示已确认*(stack + pos / 8) |= 0x01 << (pos % 8);}else // 出现分叉点{if (split_point == 0xFF || pos > split_point){// 比上次记录的点更深, 出现了新的分叉点*(buff + pos / 8) &= ~(0x01 << (pos % 8));DS18B20_WriteBit(RESET);// 在stack上将这一位记录为0, 表示未确认*(stack + pos / 8) &= ~(0x01 << (pos % 8));// 记录新的分叉点位置split_point = pos;}else if (pos == split_point){// 到达了上次记录的分叉点位置, 这次使用1继续往下走*(buff + pos / 8) |= 0x01 << (pos % 8);DS18B20_WriteBit(SET);// 在stack上将这一位记录为1, 表示已确认*(stack + pos / 8) |= 0x01 << (pos % 8);}else{// 这个分叉点处于中间位置, 还没到处理时间, 继续使用上次记录的值DS18B20_WriteBit(*(buff + pos / 8) >> (pos % 8) & 0x01);}}pos++;}// 重新定位分叉点, 将其指向到stack上最后一个未确认的位置while (split_point > 0 && *(stack + split_point / 8) >> (split_point % 8) & 0x01 == 0x01) split_point--;return split_point;
}

调用方法

sp = 0;
do
{// ROM search and store ROM bytes to addrsp = DS18B20_Detect(addr, Search_Stack, sp);// Print the new split point and addressUART1_TxHex(sp);UART1_TxChar(' ');PrintArray(addr, 0, 8);UART1_TxString("\r\n");
} while (sp);

运行实测

对一个挂载了19个 DS18B20 的 1-Wire 总线进行实际测试, 用1uF电容和1N4148模拟寄生供电电路, 与上位机只连了两根线.

实际的测试输出如下, 第一列输出的是Split_Point的值, 表示当前的分叉深度, 后半部分是这个DS18B20采样的温度值和CRC

0F 2854FD96F0013C1A........B20155057FA5A5669A CRC:9A ␍␊
0D 28D44496F0013C4C........BD0155057FA5A56660 CRC:60 ␍␊
0B 28744196F0013CC2........B50155057FA5A5664A CRC:4A ␍␊
09 280CCB96F0013C8D........B20155057FA5A5669A CRC:9A ␍␊
0B 28D2A396F0013C75........B50155057FA5A5664A CRC:4A ␍␊
0D 288AFB48F6973CFD.......BE0155057FA581665F CRC:5F ␍␊
0C 28AA8196F0013C37........B40155057FA5A56609 CRC:09 ␍␊
0A 283A9096F0013C37........B80155057FA5A56636 CRC:36 ␍␊
08 283E5996F0013C3A........B80155057FA5A56636 CRC:36 ␍␊
0B 2811E896F0013C2A........B70155057FA5816636 CRC:36 ␍␊
0C 28C90196F0013C66........B40155057FA5A56609 CRC:09 ␍␊
0D 28597196F0013CBA........B80155057FA5A56636 CRC:36 ␍␊
0A 28794648F65D3C26........B60155057FA5A5668F CRC:8F ␍␊
0B 2865BB96F0013CB5........BD0155057FA5A56660 CRC:60 ␍␊
0C 28ADCB96F0013CE6........BA0155057FA581664A CRC:4A ␍␊
09 281D1648F64B3CEA.......BD0155057FA5A56660 CRC:60 ␍␊
0B 2843E896F0013C6A........BB0155057FA5A566F3 CRC:F3 ␍␊
0A 289B0896F0013CD5........B70155057FA5816636 CRC:36 ␍␊
00 28EF5C96F0013C1B........BE0155057FA5A566A5 CRC:A5 ␍␊

参考

  • 单线总线搜索算法 1-WIRE SEARCH ALGORITHM https://www.maximintegrated.com/en/design/technical-documents/app-notes/1/187.html

DS18B20数字温度计 (三) 1-WIRE总线 ROM搜索算法和实际测试相关推荐

  1. 单片机小白学习之路(三十二)---DS18B20数字温度计(三)

    目标:目标: DS18B20数字温度计(三) 18b20开始转换温度 DS18B20 的典型温度读取过程为:复位→发 SKIP ROM 命令(0XCC)→发开始转换命令( 0X44)→延时→复位→发送 ...

  2. DS18B20数字温度计 (一) 电气特性, 寄生供电模式和远距离接线

    目录 DS18B20数字温度计 (一) 电气特性, 寄生供电模式和远距离接线 DS18B20数字温度计 (二) 测温, ROM和CRC算法 DS18B20数字温度计 (三) 1-WIRE总线ROM搜索 ...

  3. 数字温度计的c语言编程,基于DS18B20数字温度计的设计(全文完整版)

    <基于DS18B20数字温度计的设计.doc>由会员分享,可免费在线阅读全文,更多与<基于DS18B20数字温度计的设计>相关文档资源请在帮帮文库(www.woc88.com) ...

  4. DS18B20数字温度计使用(转)

    DS18B20数字温度计使用 发布人:来自网络   发布时间:2010-6-16 1.DS18B20基本知识 DS18B20数字温度计是DALLAS公司生产的1-Wire,即单总线器件,具有线路简单, ...

  5. 单片机实例35——DS18B20数字温度计使用(硬件电路图+C语言程序)

    35. DS18B20数字温度计使用 1.DS18B20基本知识 DS18B20数字温度计是DALLAS公司生产的1-Wire,即单总线器件,具有线路简单,体积小的特点.因此用它来组成一个测温系统,具 ...

  6. 数字温度计的c语言编程,DS18B20数字温度计C程序(能显示负温)

    DS18B20数字温度计C程序(能显示负温) //***********DS18B20数字温度计C程序****************// //*MCU: AT892051 // //*MCU-cry ...

  7. DS18B20数字温度计使用

    1.DS18B20基本知识 DS18B20数字温度计是DALLAS公司生产的1-Wire,即单总线器件,具有线路简单,体积小的特点.因此用它来组成一个测温系统,具有线路简单,在一根通信线,可以挂很多这 ...

  8. DS18B20数字温度计系统设计

    STC89C52单片机 STC89C52单片机接口介绍 这个单片机一共有40个引脚. ①P0口(P0.0~P0.7) 8位漏极开关型双向I/O端口.可以作为通用I/O口使用,但必须加上拉电阻. ②P1 ...

  9. DS18B20数字温度计设计

    一.单片机简介. 1 二.设计任务和要求. 1 三.设计方案的总体设计框图. 1 3.1硬件电路框图. 1 3.2硬件电路概述. 2 3.3主控电路. 2 3.4显示电路. 2 3.5报警温度调节电路 ...

最新文章

  1. 关于JS中switch语句的判断条件!
  2. Activity中与ListActivity中使用listview区别
  3. java 索引排序_Java培训MySQL之排序分组优化索引的选择
  4. redis.conf 常见配置介绍
  5. 最新ui设计趋势_10个最新且有希望的UI设计趋势
  6. Vue项目中遇到了大文件分片上传的问题
  7. 不带缓存的I/O和标准(带缓存的)I/O
  8. 阿里云python服务器_Python服务器
  9. 计算机技术要求单科成绩吗,软考考试合格标准怎样确定?单科成绩是否保留?
  10. 职高计算机word教学视频,职高计算机专业Word范例教学三例.doc
  11. Linux学习技巧分享
  12. python数据库操作批量sql执行_python 批量远程执行SQL SERVER 脚本
  13. 黑莓手机BlackBerry Servicebook(简称SB)应用详解指南
  14. spdy_buffer
  15. 动听百年:音乐播放器发展沉浮史
  16. 弘辽科技:如何写出自带流量的标题
  17. DFS搜索和输出所有路径
  18. 论文录用后不想发了,撤稿会有什么影响吗?
  19. less面试_想获得理想工作?面试时千万不要说这七句话
  20. 利用转写软件进行高效记录

热门文章

  1. 偷天换日合约易主,地址变脸移花接木——底层函数误用漏洞 | 漏洞分析连载之四...
  2. 树莓派通过java获取麦克风声音并播放
  3. ubc 文学院 计算机,英属哥伦比亚大学UBC专业
  4. 《逻辑学》の思维导图(小区域总结,望高人能补充)
  5. 用户体验是个什么东西?用户体验如何评价好坏?怎样用一句话描述用户体验评价方法的核心?
  6. 材料设计Materials Studio教程(简易课程)
  7. Cisco AP 配置
  8. 知乎高赞!11个短小精悍的Python代码!
  9. 阿根廷华人网:华人超市整体改观 树立华商新形象
  10. 免费无限次的API 接口