单片机论坛

 找回密码
 立即注册

QQ登录

只需一步,快速开始

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

8个ds18b20测温,不按规矩的搞法 附单片机源码+原理图

[复制链接]
跳转到指定楼层
楼主
brew9 发表于 2018-12-25 17:23 | 只看该作者 |只看大图 回帖奖励 |倒序浏览 |阅读模式
ds18b20单总线驱动,要挂接多个,就得扫描ROM提取序列号,还得匹配ROM取温度值,有点麻烦。分析其驱动原理,完全可以用P口的8个位同时驱动8个ds18b20,实现温度显示。

以下是proteus仿真效果:




以下是代码:
main.c
  1. #include "config.h"
  2. #include "timer.h"
  3. #include "lcd1604.h"
  4. #include "ds18b20.h"

  5. uchar temp_array[16], *p_array;
  6. //按位取值
  7. uchar code dbit[8] = {1, 2, 4, 8, 16, 32, 64, 128};
  8. uchar code pos[8] = {0,0,1,1,2,2,3,3};

  9. void dis_temps(void)
  10. {
  11.     uint16 temp;
  12.     uint8 i, j;
  13.     uchar str[6] = "";
  14.     bit temp_flag;
  15.    
  16.     for(i=0; i<8; i++)
  17.     {
  18.         for(j=0; j<16; j++)
  19.         {
  20.             temp >>= 1;
  21.             if((temp_array[j] & dbit[i]) == dbit[i])
  22.             {
  23.                 temp |=0x8000;
  24.             }
  25.         }
  26.         if((temp & 0xf800) == 0xf800)
  27.             {
  28.                     temp_flag = 1;                                
  29.                     temp = (~temp) + 1;
  30.             }else{                                                                                                   
  31.                     temp_flag = 0;                                
  32.             }
  33.         float2str(temp*0.0625, str, 1);
  34.         
  35.         if(temp_flag == 1)
  36.         {
  37.             if((i%2)==0)
  38.             {
  39.                 LCD1604_dis_str(0, pos[i], "-");
  40.             }else{
  41.                 LCD1604_dis_str(8, pos[i], "-");
  42.             }        
  43.         }else{
  44.             if((i%2)==0)
  45.             {
  46.                 LCD1604_dis_str(0, pos[i], " ");
  47.             }else{
  48.                 LCD1604_dis_str(8, pos[i], " ");
  49.             }        
  50.         }
  51.         if((i%2)==0)
  52.         {
  53.             LCD1604_dis_str(1, pos[i], str);
  54.         }else{
  55.             LCD1604_dis_str(9, pos[i], str);
  56.         }        
  57.     }
  58. }

  59. void main()
  60. {

  61.     LCD1604_init();
  62.     p_array = temp_array;

  63.     DS18B20_start();

  64.     while(1)
  65.     {
  66.         DS18B20_get_temp(p_array);
  67.         dis_temps();
  68.         DS18B20_start();
  69.         delay_ms(500);
  70.     }
  71. }
复制代码
ds18b20.c
  1. #include "config.h"
  2. #include "ds18b20.h"
  3. #include "timer.h"

  4. /*==========================================================================
  5.   函数名称:DS18B20_reset
  6.   函数功能:初始化DS18B20并检测存在脉冲
  7.   返    回:dat(各引脚DS18B20存在数据,如果不为0x00,则表示有元件故障)
  8.   说    明:DS18B20拉低总线以示存在,然后在480us内主动释放总线。
  9. --------------------------------------------------------------------------*/
  10. uchar DS18B20_reset(void)
  11. {
  12.     uchar dat;
  13.     DS18B20_IO = 0xff;
  14.     _nop_();
  15.     DS18B20_IO = 0x00;
  16.     delay500us();
  17.    
  18.     DS18B20_IO = 0xff;
  19.     delay80us();
  20.     dat = DS18B20_IO;       //读取P2口各引脚数据
  21.    
  22.     delay500us();
  23.    
  24.     return dat;             //如果不检测,则可用 "return 0x00;"
  25. }
  26. /*==========================================================================
  27.   函数名称:DS18B20_PWB
  28.   函数功能:P口同时写一个字节。
  29.   备    注:PWB(P1 write byte)
  30. --------------------------------------------------------------------------*/
  31. void DS18B20_PWB(uchar dat)
  32. {
  33.     uint8 i;

  34.     for(i=0; i<8; i++)
  35.     {
  36.         DS18B20_IO = 0x00;
  37.         _nop_();
  38.         DS18B20_IO = ((dat&0x01)==0)?0x00:0xff;
  39.         delay80us();
  40.         DS18B20_IO = 0xff;
  41.         _nop_();
  42.         dat >>= 1;
  43.     }
  44. }
  45. /*==========================================================================
  46.   函数名称:DS18B20_PR_16bit
  47.   函数功能:并口读16个字节。
  48.   说    明:P1口同时读数据,算法上须调整,引入长度16的数组来保存数据。
  49.             温度的输出需要采用遍历取值方式。
  50. --------------------------------------------------------------------------*/
  51. void DS18B20_PR_16bit(uchar *p_array)
  52. {
  53.     uint8 i;
  54.     uint16 dat = 0;

  55.     for (i=0; i<16; i++)
  56.     {
  57.         DS18B20_IO = 0x00;
  58.         _nop_();
  59.         DS18B20_IO = 0xff;
  60.         _nop_();
  61.         *(p_array+i) = DS18B20_IO;      //把各端口的值保存到数组中
  62.         delay80us();
  63.     }
  64. }
  65. /*==========================================================================
  66.   函数名称:DS18B20_start
  67.   函数功能:启动一次18B20温度转换
  68. --------------------------------------------------------------------------*/
  69. void DS18B20_start(void)
  70. {
  71.     uchar dat;

  72.     EA = 0;                                   //禁止总中断
  73.    
  74.     dat = DS18B20_reset();                    //执行总线复位,并获取18B20应答
  75.     if (dat == 0x00)                          //如18B20正确应答,则启动一次转换
  76.     {
  77.         DS18B20_PWB(0xCC);                    //跳过ROM操作
  78.         DS18B20_PWB(0x44);                    //启动一次温度转换
  79.     }

  80.     EA = 1;                                   //使能总中断
  81. }
  82. /*==========================================================================
  83.   函数名称:DS18B20_get_temp
  84.   函数功能:读取DS18B20转换的温度值
  85. --------------------------------------------------------------------------*/
  86. void DS18B20_get_temp(uchar *p_array)
  87. {
  88.     uchar dat;

  89.     EA = 0;                                   //禁止总中断
  90.    
  91.     dat = DS18B20_reset();                    //执行总线复位,并获取18B20应答
  92.     if (dat == 0x00)                          //如18B20正确应答,则读取温度值
  93.     {
  94.         DS18B20_PWB(0xCC);                    //跳过ROM操作
  95.         DS18B20_PWB(0xBE);                    //发送读命令
  96.         DS18B20_PR_16bit(p_array);
  97.     }

  98.     EA = 1;                                   //使能总中断
  99. }
  100. //========================================================================//
复制代码





评分

参与人数 2黑币 +65 收起 理由
perfect123 + 15 赞一个!
admin + 50 共享资料的黑币奖励!

查看全部评分

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

使用道具 举报

沙发
yjj996 发表于 2019-1-4 22:50 | 只看该作者
请问阁下的头文件,能不能给一下
回复

使用道具 举报

板凳
perfect123 发表于 2019-1-5 09:59 | 只看该作者
这个很容易搞的呀,调用一个18b20如果需要400毫秒,如果用8个端口几乎同时调用8个,那么时间大概是401毫秒。修改一下代码而已。其实各有利弊,用一根线搞8个,好处是省端口,省线,坏处是读取一次太慢,而且维护困难
回复

使用道具 举报

地板
 楼主| brew9 发表于 2019-1-8 13:04 | 只看该作者
perfect123 发表于 2019-1-5 09:59
这个很容易搞的呀,调用一个18b20如果需要400毫秒,如果用8个端口几乎同时调用8个,那么时间大概是401毫秒 ...

谢谢评分!
写数据和读数据是完全同步的。
一根网线,接6个18b20,也许可以满足很多场合需求了。
回复

使用道具 举报

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

本版积分规则

QQ|手机版|小黑屋|单片机论坛 |51hei电子论坛2群 联系QQ:125739409;技术交流QQ群219535678

Powered by 单片机教程网

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