找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 532|回复: 6
打印 上一主题 下一主题
收起左侧

51单片机读取18B20传感器的ROM序列码是8个FF

[复制链接]
回帖奖励 1 黑币 回复本帖可获得 1 黑币奖励! 每人限 1 次
跳转到指定楼层
楼主
      最近搞51单片机4个18b20传感器并联,通过读取ROM序列码查询温度并显示在1602液晶上,现在已经能显示,并且使用了几天。4个18b20的ROM序列码是一个单独的工程代读出来,写到另一个工程的数组里。现在想把两个工程功能合并,我用之前的代码一个一个读取ROM序列码时,发现有两个能读出来并且正确,有两个读出来的是8个FF,   如果把这4个并联在又能读出各自的温度。 一时间不知道是传感器问题还是时序问题。请大师指点指点这是读取rom序列码的代码:
  1. #include "STC89C5xRC.H"
  2. #include "timer_drv.h"
  3. #include "key_drv.h"
  4. #include "Delay.h"
  5. #include "Display.h"
  6. #include "stdio.h"
  7. #include "Ds18b20.h"
  8. #include "intrins.h"
  9. #include "one_bus.h"


  10. // -------------------------- 5. 测试示例 --------------------------
  11. void main(void)
  12. {

  13.         unsigned char romcode[8];
  14.         unsigned char key_val;
  15.         unsigned char i;
  16.         
  17.     KeyDrvInit();  // 初始化按键驱动
  18.     Timer0Init();
  19.         Timer1Init();   //000818
  20.     DelayMs(1000);
  21.         Start_18B20();
  22.     ReadRomCode(romcode);
  23.     printf("The Init is ok\n");
  24.         DelayMs(1000);
  25.         for(i = 0; i < 8; i ++)
  26.         {
  27.             
  28.                 printf("0X%bX \n", romcode[i]);
  29.         }
  30.         
  31.     while(1)
  32.         {

  33.                

  34.                 key_val = GetKeyVal();
  35.          if(key_val != 0)  // 有按键操作时进入分支
  36.         {
  37. ///           printf("the key_val num is %u\n", key_val);
  38.                         
  39.                         switch(key_val)
  40.             {
  41.                 // KEY1操作
  42.                 case 1:    P10 = ~P10; break;  //短按                    
  43.                
  44.                     
  45.                                 
  46.                 // KEY2操作
  47.                 case 2:    P11 = ~P11; break;  // 短按                                      
  48.                
  49.                     
  50.                   
  51.                 // KEY3操作
  52.                 case 3:    P12 = ~P12; break;  // 短按                  
  53.                
  54.                                 // KEY4操作
  55.                 case 4:    P13 = ~P13; break;  // 短按   

  56.                 default:       // 无效值,可忽略
  57.                     break;
  58.             }
  59.         // 主循环可执行其他任务(无阻塞)
  60.         // ...
  61.         }
  62.     }
  63. }











  64. #include "STC89C5xRC.H"
  65. #include "one_bus.h"
  66. #include "Delay.h"
  67. #include "intrins.h"
  68. #include "Ds18b20.h"


  69. /**
  70. ***********************************************************
  71. * @brief 单总线复位
  72. * @param  
  73. * @param  
  74. * @return ack
  75. ***********************************************************
  76. */
  77. bit OneWireRst()
  78. {
  79.         bit ack;
  80.    
  81.         DS18B20 = 1;
  82.         _nop_();        //00102105   1.09us
  83.         
  84.         DS18B20 = 0;  //拉低总线,发复位脉冲
  85.         DelayUs(250);   //00279514   580.51us   (480us-960us)
  86.     DS18B20 = 1;  
  87.     DelayUs(25);    //00153103   59.68us
  88.     ack = DS18B20;//读取IO口,DS18B20的ack
  89.     while(!DS18B20);//等待18B20释放总线,等待存在脉冲结束

  90.     return ack;
  91. }



  92. /**
  93. ***********************************************************
  94. * @brief 单总线写一个字节
  95. * @param  
  96. * @param  
  97. * @return
  98. ***********************************************************
  99. */
  100. void WriteOneWire(unsigned char dat)
  101. {
  102.         u8 i;
  103.         bit dstemp;
  104.         for(i = 0; i < 8; i++)
  105.         {
  106.                 dat = dat >> 1;
  107.                 dstemp = CY;
  108.                 if(dstemp)
  109.                 {
  110.                         DS18B20 = 1;
  111.                         _nop_();        //00102105   1.09us
  112.                         
  113.                         DS18B20 = 0;
  114.                         _nop_();        //00102105   1.09us
  115.                         _nop_();        //00102105   1.09us
  116.                         DS18B20 = 1;
  117.                         DelayUs(40);    //00166124   92.23us  (60-120us)
  118.                 }
  119.                 else
  120.                 {
  121.                         DS18B20 = 1;
  122.                         _nop_();        //00102105   1.09us
  123.                         
  124.                         DS18B20 = 0;
  125.                         DelayUs(40);    //00166124   92.23us  (60-120us)
  126.                 }
  127.                
  128.                
  129.         }


  130. }


  131. /**
  132. ***********************************************************
  133. * @brief 单总线读一个字节
  134. * @param  
  135. * @param  
  136. * @return   dat
  137. ***********************************************************
  138. */
  139. unsigned char ReadOneWire()
  140. {
  141.         unsigned char dat;
  142.         unsigned char tmp;
  143.         

  144.         for(tmp = 0x01; tmp != 0; tmp <<= 1)
  145.      {
  146.             DS18B20 = 1;
  147.             _nop_();        //00102105   1.09us
  148.             DS18B20 = 0;
  149.                 _nop_();        //00102105   1.09us
  150.                 _nop_();        //00102105   1.09us
  151.                 DS18B20 = 1;
  152.                 _nop_();        //00102105   1.09us
  153.                 if(!DS18B20)
  154.                 {
  155.                    dat &= ~tmp;
  156.                 }                        
  157.             
  158.                 else
  159.                 {
  160.                    dat |= tmp;
  161.                 }
  162.                 DelayUs(50);    //此语句若延时时间太短会出现读取数值不对
  163.          }

  164.      return dat;

  165. }













  166. #include "STC89C5xRC.h"
  167. #include "Ds18b20.h"
  168. #include "Display.h"
  169. #include "Delay.h"
  170. #include "stdio.h"
  171. #include "one_bus.h"

  172.   int temper;


  173. bit Start_18B20()
  174. {
  175.         bit ack;
  176.         ack = OneWireRst(); //1.初始化
  177.     if(ack == 0)
  178.         {
  179.                 WriteOneWire(SKIP_ROM);//2.ROM指令
  180.                 WriteOneWire(CONVERT_T);//3.功能指令 启动温度转换
  181.                
  182.         }
  183.         
  184.         return ~ack;

  185. }        



  186. /**
  187. ***********************************************************
  188. * @brief DS18B20读一个字节
  189. * @param  
  190. * @param  
  191. * @return 读回来的数值
  192. ***********************************************************
  193. */

  194. int DsGetTem()
  195. {
  196.         u8 tem1,tem2;
  197.         
  198.         EA = 0;
  199.         Start_18B20();
  200.         WriteOneWire(0xcc);
  201.         WriteOneWire(0x44);
  202.         OneWireRst();
  203.         WriteOneWire(0xcc);
  204.         WriteOneWire(0xbe);
  205.         tem1 = ReadOneWire();
  206.         tem2 = ReadOneWire();
  207.         EA = 1;
  208.         temper = tem2;
  209.         temper = (temper << 8) | tem1;
  210.         temper = temper * 0.0625 * 10;

  211.         return temper;
  212. }


  213. /**
  214. ***********************************************************
  215. * @brief 读取DS18B20 ROM
  216. * @param  
  217. * @param  
  218. * @return
  219. ***********************************************************
  220. */
  221. void ReadRomCode(unsigned char *romcode)
  222. {
  223.         bit ack;
  224.         unsigned char i;
  225.         ack = OneWireRst();//获取复位脉冲
  226.         if(ack == 0)
  227.         {
  228.                 WriteOneWire(0x33);//读取ROM指令
  229.                 for(i = 0; i < 8; i ++)
  230.                 {
  231.                         romcode[i] = ReadOneWire();//读64位ROM码 下面一句和这句意思一样
  232. //                    *(romcode+i) = ReadOneWire();//读64位ROM码
  233.                 }
  234.         
  235.         }



  236. }


复制代码





0c9eafe5a4759376f6bb4f8554403bf8.png (13.43 KB, 下载次数: 0)

0c9eafe5a4759376f6bb4f8554403bf8.png
分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏1 分享淘帖 顶 踩
回复

使用道具 举报

沙发
ID:1133081 发表于 2025-11-23 08:22 | 只看该作者
单线多点18b20的测温需要先读出各分支器件的序列号并保存,通常采用“二读法”,再根据序列号匹配各分支器件,才能正确获取各分支器件的温度值。
回复

使用道具 举报

板凳
ID:1151496 发表于 2025-11-23 19:12 | 只看该作者
WL0123 发表于 2025-11-23 08:22
单线多点18b20的测温需要先读出各分支器件的序列号并保存,通常采用“二读法”,再根据序列号匹配各分支器 ...

这4个18b20我是知道序列号的,是之前读出来做好记录的,如果现在将这4个序列号写到数组里能读出并显示温度,我现在想加一个功能是插一个传感器,按下按键,读出ROM码再保存到eep。这个功能是为了方便更换传感器不用重新烧录。现在遇到的问题是我单独只能读出2个正确的rom码,另外两个读出来都是8个FF。你要说传感器坏了吧,把这个传感器之前读出来的ROM码写进去又能读出温度。
回复

使用道具 举报

地板
ID:888875 发表于 2025-11-23 21:04 | 只看该作者
问题太多,还有启动温度转换之后要等一定时间才能读取到准确数据
回复

使用道具 举报

5#
ID:1133081 发表于 2025-11-24 08:34 | 只看该作者
小桥流水不 发表于 2025-11-23 19:12
这4个18b20我是知道序列号的,是之前读出来做好记录的,如果现在将这4个序列号写到数组里能读出并显示温 ...

在已知多器件的序列号的条件下,需要发匹配命令0x55,匹配成功才能正确读取指定器件返回的温度值。例如:
  1. //匹配多通道DS18B20序列号
  2. void SeriesNumber(u8 ch)
  3. {
  4.         u8 i;
  5.         DS18B20_WriteByte(0x55); //发送匹配 ROM 命令
  6.         for(i=0;i<8;i++)
  7.                 DS18B20_WriteByte(table[ch][i]);
  8. }
  9. //读取多通道DS18B20温度函数
  10. u16 ReadTemperature(u8 ch)
  11. {
  12.         u16 TempH, TempL, Temperature;
  13.         DS18B20_Reset();                //设备复位
  14.         DS18B20_WriteByte(0xCC);        //跳过ROM匹配
  15.         DS18B20_WriteByte(0x44);        //启动转换
  16.         while (!DQ);                    //等待转换完成
  17.         DS18B20_Reset();                //设备复位
  18.         SeriesNumber(ch);               //匹配 ROM
  19.         DS18B20_WriteByte(0xBE);        //读暂存存储器命令
  20.         TempL = DS18B20_ReadByte();     //读温度低字节
  21.         TempH = DS18B20_ReadByte();     //读温度高字节       
  22.         if(TempH & 0xf8)                //判断是否位负数
  23.         {
  24.                 MinusFlag = 1;              //设置负数标志
  25.                 Temperature = (TempH<<8) | TempL;
  26.                 Temperature = ~Temperature + 1;
  27.                 Temperature *= 0.625;       //0.0625 * 10,保留1位小数点
  28.         }
  29.         else
  30.         {
  31.                 MinusFlag = 0;              //清除负数标志
  32.                 Temperature = (((TempH<<8) | TempL) * 0.625); //0.0625 * 10,保留1位小数点
  33.         }       
  34.         return Temperature;
  35. }
复制代码




回复

使用道具 举报

6#
ID:71233 发表于 2025-11-24 09:17 | 只看该作者
我觉得多半是时序不对
回复

使用道具 举报

7#
ID:382454 发表于 2025-12-1 15:45 | 只看该作者
这个数据表格里肯定有说,单总线多个并联。也可以分开多个IO口。
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

快速回复 返回顶部 返回列表