找回密码
 立即注册
楼主: zhange

降龙棍外接ds18b20 记录

[复制链接]
  • 打卡等级:以坛为家I
  • 打卡总天数:243
  • 最近打卡:2025-05-11 07:59:01

61

主题

820

回帖

1544

积分

金牌会员

积分
1544
发表于 2024-5-18 16:15:59 | 显示全部楼层

读/写时序
DS18B20 的数据读写是通过时序处理位来确认信息交换的。
写时序
由两种写时序:写 1 时序和写 0 时序。总线控制器通过写 1 时序写逻辑 1 到DS18B20,写 0 时序写逻辑 0 到 DS18B20。所有写时序必须最少持续 60us,包括两个写周期之间至少 1us 的恢复时间。当总线控制器把数据线从逻辑高电平拉到
低电平的时候,写时序开始。
总线控制器要生产一个写时序,必须把数据线拉到低电平然后释放,在写时序开始后的 15us 释放总线。当总线被释放的时候,5K 的上拉电阻将拉高总线。总控制器要生成一个写 0 时序,必须把数据线拉到低电平并持续保持(至少 60us)。总线控制器初始化写时序后,DS18B20 在一个 15us 到 60us 的窗口内对 I/O 线采样。如果线上是高电平,就是写 1。如果线上是低电平,就是写 0。


截图202405181558376978.jpg


  1. void DS18b20_Write_0(void)                //写逻辑0码
  2. {
  3.         DQ = 0;                                //输出低电平
  4.         Delay60us();
  5.         DQ = 1;                                //输出高电平
  6.         Delay1us();               
  7.         Delay1us();       
  8. }
复制代码


截图202405181559465363.jpg


  1. void DS18b20_Write_1(void)                //写逻辑1码
  2. {
  3.         DQ = 0;                                //输出低电平
  4.         Delay1us();       
  5.         Delay1us();       
  6.         DQ = 1;                                //输出高电平
  7.         Delay60us();       
  8. }
复制代码


截图202405181610178755.jpg

  1. bit DS18b20_Read(void)                //读取电平
  2. {
  3.         bit state ;
  4.        
  5.         DQ = 0;                                //输出低电平
  6.         Delay1us();       
  7.         Delay1us();       
  8.         DQ = 1;                                //输出高电平
  9.         Delay1us();       
  10.         Delay1us();       
  11.         state = DQ;                        //读取当前电平
  12.         Delay60us();
  13.         return         state;
  14. }
复制代码



所有读时序必须最少 60us,包括两个读周期间至少 1us 的恢复时间。当总线控制器把数据线从高电平拉到低电平时,读时序开始,数据线必须至少保持 1us,然后总线被释放。在总线控制器发出读时序后,DS18B20 通过拉高或拉低总线上来传输 1 或 0。当传输逻辑 0 结束后,总线将被释放,通过上拉电阻回到上升沿状态。从 DS18B20 输出的数据在读时序的下降沿出现后 15us 内有效。因此,总线控制器在读时序开始后必须停止把 I/O 脚驱动为低电平 15us,以读取I/O 脚状态。


  1. void DS18b20_WriteByte(u8 dat)        //写一个字节
  2. {
  3.         u8 i;
  4.         for( i=0;i<8;i++ )                //循环八次
  5.         {
  6.                 if( dat & 0x01 )
  7.                         DS18b20_Write_1();
  8.                 else
  9.                         DS18b20_Write_0();
  10.                 dat >>=1;
  11.         }
  12. }
  13. // 1000 0000
  14. // x100 0000
  15. // xx10 0000
  16. u8 DS18b20_ReadByte(void)                //读取一个字节
  17. {
  18.         u8 i;
  19.         u8 dat=0;
  20.         for( i=0;i<8;i++ )                //循环八次
  21.         {
  22.                 dat >>=1;
  23.                
  24.                 if( DS18b20_Read() )        //如果读取到的是1,
  25.                         dat |= 0x80;
  26.         }
  27.         return dat;
  28. }
复制代码




回复 支持 反对

使用道具 举报 送花

  • 打卡等级:以坛为家II
  • 打卡总天数:432
  • 最近打卡:2025-05-11 09:56:11
已绑定手机

19

主题

3197

回帖

4970

积分

论坛元老

积分
4970
发表于 2024-5-18 17:33:31 | 显示全部楼层
和dht11有点像都是单线的
回复 支持 反对

使用道具 举报 送花

  • 打卡等级:以坛为家I
  • 打卡总天数:342
  • 最近打卡:2025-05-11 00:57:00
已绑定手机

14

主题

600

回帖

2225

积分

荣誉版主

积分
2225
发表于 2024-5-19 01:51:05 | 显示全部楼层
晓*** 发表于 2024-5-18 11:08
别弄DS18B20了,来试试国产的单线温度传感器NST1001吧,精度更高,编程更简单。
https://www.stcaimcu.com/ ...

我买了几颗,还在路上.如果这个有塑封的就好了,我的项目就可以直接替换了,18b20国产的不够好,进口的价格太高.

点评

我刚买了200个,TO-92S封装的,含税价格1.1,可以直接直接替换18B20,不过超远距离传输的话,需要做好测试,摸清楚性能。  发表于 2024-5-19 11:38
回复 支持 反对

使用道具 举报 送花

  • 打卡等级:以坛为家I
  • 打卡总天数:243
  • 最近打卡:2025-05-11 07:59:01

61

主题

820

回帖

1544

积分

金牌会员

积分
1544
发表于 2024-5-19 07:32:19 | 显示全部楼层
接着搞开始写代码了


思路:循环扫描2个ds18b20的温度

1.需要首先获取每个ds18b20的唯一标识,获取标识的时候需要只接一个ds18b20  一个一个获取(网上找的别人的,我移植过来了)

  1. /**
  2.   * @brief  读取ROM码
  3.   * @param  存储DS18B20 ROM码的数组
  4.   * @retval None
  5.   */
  6. void ReadRomCode(unsigned char* romcode)
  7. {
  8.         bit ack;
  9.         unsigned char i;
  10.         ack = DS18b20_Reset1(); //复位
  11.         if(ack == 0)
  12.         {
  13.                 P20 = 0;
  14.                 DS18b20_WriteByte(0x33);   // 发送读取ROM命令
  15.                 Delay1ms();
  16.                 for(i = 0; i < 8; i++)
  17.                 {
  18.                         romcode[i] = DS18b20_ReadByte();    // 读取64位ROM码
  19.                 }
  20.                
  21.         }
  22. }
复制代码


2.将获取到的DS18B20器件的序列号通过数组保存起来


我代码里是直接把rom码发给串口,获取的


  1. unsigned char ROM_data0[8] = {0x28,0x8e,0xe2,0x83,0x00,0x00,0x00,0xef};    //存储dsrom码
  2. unsigned char ROM_data1[8] = {0x28,0x61,0x07,0x85,0x00,0x00,0x00,0xe3};    //存储dsrom码
复制代码


3.main函数如下:  基础就是冲哥课程里的代码

  1. #include "COMM/stc.h"                //调用头文件
  2. #include "COMM/stc32_stc8_usb.h"
  3. #include "stdio.h"
  4. #include "stc32g.h"
  5. #include "18b20.h"
  6. #define MAIN_Fosc 22118400L        //定义主时钟
  7. unsigned char ROM_data[8];    //存储dsrom码
  8. unsigned char ccc = 0xee;
  9. char *USER_DEVICEDESC = NULL;
  10. char *USER_PRODUCTDESC = NULL;
  11. char *USER_STCISPCMD = "@STCISP#";
  12. bit  TIM_10MS_Flag;                        //10ms的标志位
  13. void sys_init();        //函数声明
  14. void delay_ms(u16 ms);        //unsigned int
  15. void Delay3000ms(void)        //@22.1184MHz
  16. {
  17.         unsigned long edata i;
  18.         _nop_();
  19.         _nop_();
  20.         i = 16588798UL;
  21.         while (i) i--;
  22. }
  23. void main()                                        //程序开始运行的入口
  24. {
  25.         int dat = 0;                        //初始数值
  26.         unsigned int wendu;
  27.         unsigned int wendu1;
  28.         sys_init();                                //USB功能+IO口初始化
  29.         usb_init();                                //usb库初始化
  30.         EUSB = 1;          //中断允许位
  31.         EA = 1;                                        //CPU开放中断,打开总中断。
  32.         while( DeviceState != DEVSTATE_CONFIGURED );
  33.         while(1)                //死循环
  34.         {
  35.                 delay_ms(2);
  36.                
  37.                 if( bUsbOutReady )                                                               
  38.                 {
  39. //                        USB_SendData(UsbOutBuffer,OutNumber);
  40.                         usb_OUT_done();
  41.                 }
  42.           Delay3000ms();
  43.                
  44. //读取当前ds18的标识码               
  45. //    ReadRomCode(ROM_data);
  46. //                printf( "当前rom1:%x-", ROM_data[0]);
  47. //                printf( "当前rom2:%x-", ROM_data[1]);
  48. //                printf( "当前rom3:%x-", ROM_data[2]);
  49. //                printf( "当前rom4:%x-", ROM_data[3]);
  50. //                printf( "当前rom5:%x-", ROM_data[4]);
  51. //                printf( "当前rom6:%x-", ROM_data[5]);
  52. //                printf( "当前rom7:%x-", ROM_data[6]);
  53. //                printf( "当前rom8:%x\r\n", ROM_data[7]);
  54.                
  55.                 P01 = !P01;
  56.                 wendu = DS18b20_ReadTemp2(0);                                                                //300ms到达,读取一次温度
  57.                 if( MinusFlag==1 )
  58.                 {
  59.                         printf( "当前温度0:-%.01f\r\n",(float)((float)wendu/10) );
  60.                 }
  61.                 else
  62.                 {
  63.                         printf( "当前温度0:%.01f\r\n",(float)((float)wendu/10) );
  64.                 }
  65.                
  66.                 Delay3000ms();
  67.                 wendu1 = DS18b20_ReadTemp2(1);                                                                //300ms到达,读取一次温度
  68.                 if( MinusFlag==1 )
  69.                 {
  70.                         printf( "当前温度1:-%.01f\r\n",(float)((float)wendu1/10) );
  71.                 }
  72.                 else
  73.                 {
  74.                         printf( "当前温度1:%.01f\r\n",(float)((float)wendu1/10) );
  75.                 }
  76.                
  77.                
  78.                        
  79.         }
  80. }
  81. void sys_init()                //函数定义
  82. {
  83.     WTST = 0;  //设置程序指令延时参数,赋值为0可将CPU执行指令的速度设置为最快
  84.     EAXFR = 1; //扩展寄存器(XFR)访问使能
  85.     CKCON = 0; //提高访问XRAM速度
  86.         P0M1 = 0x00;   P0M0 = 0x00;   //设置为准双向口
  87.     P1M1 = 0x00;   P1M0 = 0x00;   //设置为准双向口
  88.     P2M1 = 0x00;   P2M0 = 0x00;   //设置为准双向口
  89.     P3M1 = 0x00;   P3M0 = 0x00;   //设置为准双向口
  90.     P4M1 = 0x00;   P4M0 = 0x00;   //设置为准双向口
  91.     P5M1 = 0x00;   P5M0 = 0x00;   //设置为准双向口
  92.     P6M1 = 0x00;   P6M0 = 0x00;   //设置为准双向口
  93.     P7M1 = 0x00;   P7M0 = 0x00;   //设置为准双向口
  94.        
  95.     P3M0 = 0x00;
  96.     P3M1 = 0x00;
  97.     P3M0 &= ~0x03;
  98.     P3M1 |= 0x03;
  99.         USBCON = 0X00;                                        //usb初始化
  100.         USBCLK = 0X00;
  101.         IRC48MCR = 0X00;
  102.         delay_ms(10);
  103.     //设置USB使用的时钟源
  104.     IRC48MCR = 0x80;    //使能内部48M高速IRC
  105.     while (!(IRC48MCR & 0x01));  //等待时钟稳定
  106.     USBCLK = 0x00;        //使用CDC功能需要使用这两行,HID功能禁用这两行。
  107.     USBCON = 0x90;
  108. }
  109. void delay_ms(u16 ms)        //unsigned int
  110. {
  111.         u16 i;
  112.         do
  113.         {
  114.                 i = MAIN_Fosc/6000;
  115.                 while(--i);
  116.         }while(--ms);
  117. }
复制代码





回复 支持 反对

使用道具 举报 送花

  • 打卡等级:初来乍到
  • 打卡总天数:8
  • 最近打卡:2024-11-20 08:30:47

0

主题

14

回帖

64

积分

注册会员

积分
64
发表于 2024-11-20 08:37:55 | 显示全部楼层
大神,请教一下,如果同时使用10个DS18B20,分开10个IO接DS18B20,去控制10个继电器工作?怎么写??代码?能不能实现?
回复 支持 反对

使用道具 举报 送花

  • 打卡等级:以坛为家I
  • 打卡总天数:355
  • 最近打卡:2025-05-09 08:02:45

2

主题

31

回帖

1359

积分

金牌会员

积分
1359
发表于 2024-11-20 08:55:42 | 显示全部楼层
22.1184MHz,楼主改下吧!22.1184Hz,啥也干不了
回复 支持 反对

使用道具 举报 送花

  • 打卡等级:以坛为家II
  • 打卡总天数:531
  • 最近打卡:2025-05-11 00:14:24

10

主题

1163

回帖

5215

积分

论坛元老

积分
5215
发表于 2024-11-20 16:28:31 | 显示全部楼层
love*** 发表于 2024-11-20 08:37
大神,请教一下,如果同时使用10个DS18B20,分开10个IO接DS18B20,去控制10个继电器工作?怎么写??代码? ...

如果同时使用10个DS18B20,1个IO接DS18B20就可以了。
单线总线可以支持,127个DS18B20理论上。实际上也可以20~30个。
回复 支持 反对

使用道具 举报 送花

  • 打卡等级:以坛为家II
  • 打卡总天数:531
  • 最近打卡:2025-05-11 00:14:24

10

主题

1163

回帖

5215

积分

论坛元老

积分
5215
发表于 2024-11-20 16:43:19 | 显示全部楼层
网上的18b20程序,很多是用Delay延时直接去写的,目的更多是让你了解这个芯片的工作原理
但这种程序在现实的量产产品中肯定是不行的,因为单片机可能还要做其它的事
可以用定时器来进行非阻塞式的通讯
回复 支持 反对

使用道具 举报 送花

  • 打卡等级:以坛为家I
  • 打卡总天数:243
  • 最近打卡:2025-05-11 07:59:01

61

主题

820

回帖

1544

积分

金牌会员

积分
1544
发表于 2024-11-21 09:09:49 | 显示全部楼层
D_Wo*** 发表于 2024-11-20 08:55
22.1184MHz,楼主改下吧!22.1184Hz,啥也干不了

标记下   。。
回复 支持 反对

使用道具 举报 送花

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

本版积分规则

QQ|手机版|小黑屋|深圳国芯人工智能有限公司 ( 粤ICP备2022108929号-2 )

GMT+8, 2025-5-11 20:16 , Processed in 0.163887 second(s), 112 queries .

Powered by Discuz! X3.5

© 2001-2025 Discuz! Team.

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