[PIC®/AVR®/dsPIC®产品] 【CuriosityNano测评报告】PIC18F16Q40+2路DS18B20测温

[复制链接]
 楼主| zhouminjie 发表于 2021-6-6 22:31 | 显示全部楼层 |阅读模式
本帖最后由 zhouminjie 于 2021-6-6 22:31 编辑

这次在开发板上实现单线挂载2个DS18B20测量温度,硬件如下:

①、新建工程,用MCC配置生成外设初始化代码

②、DS18B20初始化时序、写时序、读时序,参考AVR128DB48+DS18B20测温帖子,这里不再赘述
https://bbs.21ic.com/icview-3124376-1-1.html
③、单线上多路DS18B20的ROM搜索方法参考大神写的《1-Wire搜索算法详解(1)(2)(3)》,写的非常好,把算法的原理、过程步骤讲的很清楚
http://blog.sina.com.cn/s/blog_57ad1bd20102uxxu.html
http://blog.sina.com.cn/s/blog_57ad1bd20102uxxv.html
http://blog.sina.com.cn/s/blog_57ad1bd20102uxxw.html
算法代码如下:
  1. uint8_t OWSearch(void)
  2. {
  3.     uint8_t id_bit_number; //指示当前搜索ROM位(取值范围为1-64)
  4.     /*下面三个状态变量含义:last_zero:指针,记录一次搜索(ROM1-64位)最后一位往0走的混码点编号
  5.                           search_direction:搜索某一位时选择的搜索方向(0或1),也是“一写”的bit位值
  6.                           rom_byte_number:ROM字节序号,作为ROM_no[]数组的下标,取值为1—8
  7.     */
  8.     uint8_t last_zero, rom_byte_number, search_result;

  9.     uint8_t id_bit, cmp_id_bit,search_direction; //二读(正码、反码)、及一写(决定二叉搜索方向)
  10.     uint8_t rom_byte_mask ; //ROM字节掩码

  11.     //初始化本次搜索变量
  12.     id_bit_number = 1;
  13.     last_zero = 0;
  14.     rom_byte_number = 0;
  15.     rom_byte_mask = 1;
  16.     search_result = 0;
  17.     crc8 = 0;

  18.     /*
  19.     是否搜索完成(已到最后一个设备)?
  20.     */
  21.     if(!LastDeviceFlag) //LastDeviceFlag由上轮搜索确定是否为最后器件,当然首次进入前必须置FALSE
  22.     {
  23.         DS18B20_Rst();
  24.         //if(OWReset()) //复位总线
  25.         if(DS18B20_Check())
  26.         {
  27.             LastDiscrepancy = 0; //复位几个搜索变量
  28.             LastDeviceFlag = FALSE;
  29.             LastFamilyDiscrepancy = 0;
  30.             return FALSE; //如果无应答,返回FALSE,退出本轮搜索程序
  31.         }
  32.         DS18B20_Write_Byte(0xF0); //发送ROM搜索命令F0H
  33.         __delay_us(60);

  34.         /*
  35.         开始循环处理1-64位ROM,每位必须进行“二读”后进行判断,确定搜索路径
  36.         然后按选定的路径进行“一写”,直至完成全部位的搜索,这样一次循环
  37.         可以完成一轮搜索,找到其中一个ROM码
  38.         */
  39.         do //逐位读写搜索,1-64位循环
  40.         {
  41.             id_bit = DS18B20_Read_Bit(); //二读:先读正码、再读反码
  42.             cmp_id_bit = DS18B20_Read_Bit();

  43.             if(id_bit && cmp_id_bit) //二读11,则无器件退出程序
  44.                 break;
  45.             else //二读不为11,则需分二种情况
  46.             {
  47.             /*
  48.             第一种情况:01或10,直接可明确搜索方向
  49.             */
  50.                 if(id_bit != cmp_id_bit)
  51.                     search_direction = id_bit; //记下搜索方向search_direction的值待“一写”
  52.                 else
  53.                 {
  54.                 /*
  55.                 第二种情况:遇到了混码点,需分三种可能分析:
  56.                 1、当前位未到达上轮搜索的“最末走0混码点”(由LastDiscrepancy存储)
  57.                 说明当前经历的是一个老的混码点,判别特征为当前位在(小于)LastDiscrepancy前
  58.                 不管上次走的是0还是1,只需按上次走的路即可,该值需从ROM_NO中的当前位获取
  59.                 */
  60.                     if(id_bit_number < LastDiscrepancy)
  61.                         search_direction = ((ROM_NO[rom_byte_number] & rom_byte_mask) > 0);
  62.                     else
  63.                     /*
  64.                     2、当前位正好为上轮标记的最末的混码点,这个混码点也就是上次走0的点,那么这次就需要走1
  65.                     3、除去上二种可能,那就是第3种可能: 这是一个新的混码点,id_bit_number>LastDiscrepancy
  66.                     下一条语句巧妙地将上二种可能合在一起处理
  67.                     */
  68.                         search_direction = (id_bit_number == LastDiscrepancy);

  69.                     /*
  70.                     确定了混码点的路径方向还没完事,还需要更新一个指针:last_zero
  71.                     这个指针每搜索完一位后(注意是一bit不是一轮)总是指向新的混码点
  72.                     凡遇到新的混码点,我们按算法都是先走0,所以凡遇走0的混码点必须更新此指针
  73.                     */
  74.                     if(search_direction == 0)
  75.                     {
  76.                         last_zero = id_bit_number;

  77.                     /*
  78.                     下面二条是程序的高级功能了:64位ROM中的前8位是器件的家族代码,
  79.                     用LastFamilyDiscrepancy这个指针来记录前8位ROM中的最末一个混码点
  80.                     可用于在多类型器件的单线网络中对家族分组进行操作
  81.                     */
  82.                         if(last_zero < 9)
  83.                             LastFamilyDiscrepancy = last_zero;
  84.                     }
  85.                 }

  86.                 /*
  87.                 确定了要搜索的方向search_direction,该值即ROM中当前位的值,需要写入ROM
  88.                 然而64位ROM需分8个字节存入ROM_NO[],程序使用了一个掩码字节rom_byte_mask
  89.                 以最低位为例:该字节值为00000001,如记录1则二字节或,写0则与反掩码
  90.                 */
  91.                 if(search_direction == 1)
  92.                     ROM_NO[rom_byte_number] |= rom_byte_mask;
  93.                 else
  94.                     ROM_NO[rom_byte_number] &= ~rom_byte_mask;

  95.                 //关键的一步操作终于到来了:一写
  96.                 DS18B20_Write_Bit(search_direction);

  97.                 /*
  98.                 一个位的操作终于完成,但还需做些工作,以准备下一位的操作:
  99.                 包括:位变量id_bit_number指向下一位,字节掩码左移一位
  100.                 */
  101.                 id_bit_number++;
  102.                 rom_byte_mask <<= 1;

  103.                 //如果够8位一字节了,则对该字节计算CRC处理,更新字节号变量,重设掩码
  104.                 if(rom_byte_mask == 0)
  105.                 {
  106.                     GenerateCRC8(ROM_NO[rom_byte_number]); //CRC计算
  107.                     rom_byte_number++;
  108.                     rom_byte_mask = 1;
  109.                 }
  110.             }
  111.         }
  112.         while(rom_byte_number < 8); //ROM bytes编号为 0-7
  113.         //代码中是利用rom_byte_number<8来判断的,至此,完成8个字节共64位的循环处理

  114.         //一轮搜索成功,找到的一个ROM码也校验OK,则还要处理二个变量
  115.         if(!((id_bit_number < 65) || (crc8 != 0)))
  116.         {
  117.         /*
  118.         一轮搜索结束后,变量last_zero指向了本轮中最后一个走0的混码位
  119.         然后再把此变量保存在LastDiscrepancy中,用于下一轮的判断
  120.         last_zero在下轮初始为0,搜索是该变量是不断变动的
  121.         */
  122.             LastDiscrepancy = last_zero;

  123.             //如果这个指针为0,说明全部搜索结束,再也没有新ROM号器件了
  124.             if(LastDiscrepancy == 0)
  125.                 LastDeviceFlag = TRUE; //设置结束标志
  126.         
  127.                 search_result = TRUE; //返回搜索成功
  128.         }
  129.     }

  130.     /*
  131.     //搜索完成,如果搜索不成功包括搜索到了但CRC错误,复位状态变量到首次搜索的状态
  132.     */
  133.     if(!search_result || !ROM_NO[0])
  134.     {
  135.         LastDiscrepancy = 0;
  136.         LastDeviceFlag = FALSE;
  137.         LastFamilyDiscrepancy = 0;
  138.         search_result = FALSE;
  139.     }
  140.     return search_result;
  141. }
④、实现效果:

测试代码:

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?注册

×
dql2015 发表于 2021-6-7 19:02 | 显示全部楼层
guijial511 发表于 2021-6-7 20:57 来自手机 | 显示全部楼层
不错,支持一个。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

33

主题

140

帖子

3

粉丝
快速回复 在线客服 返回列表 返回顶部