• (十二)51单片机----用DS18B20浅测一下工(江)西的室外温度


    目录

    DS18B20

    DS18B20介绍

    引脚及应用电路

    内部结构框图

    储存器结构

    单总线

    单总线介绍

    电路规范

    电源供电​

    寄生供电

    时序结构

    操作流程

    数据帧

    温度存储格式

    代码

    运行效果


            今天我们要做的是一个温度计,因为江西这几天的温度太高了,所以就产生了去测一下室外温度的想法,所以我就在下午5点左右带着单片机去了室外,开始了测温。不过呆了一分钟不到就溜了,哈哈哈!

    DS18B20

    DS18B20介绍

    • DS18B20是一种常见的数字温度传感器,其控制命令和数据都是以数字信号的方式输入输出,相比较于模拟温度传感器,具有功能强大、硬件简单、易扩展、抗干扰性强等特点
    • 测温范围:-55°C 到 +125°C
    • 通信接口:1-Wire(单总线)
    • 其它特征:可形成总线结构、内置温度报警功能、可寄生供电

    引脚及应用电路

            这是 DS18B20 的原理图,本身难度不大,主要就是关于单总线的知识,我们后面会详细介绍。

    内部结构框图

    • 64-BIT ROM:作为器件地址,用于总线通信的寻址
    • SCRATCHPAD(暂存器):用于总线的数据交互
    • EEPROM:用于保存温度触发阈值和配置参数

            左边是上拉电阻,下方是有电源时走的线路,上方是DQ单总线走的线路。先通过一个ROM寻址,相当于大门的功能,然后是内存控制,相当于管家,再到RAM关联的设备,这大概就是内部的结构,在图中都有说明。 

    储存器结构

    单总线

    单总线介绍

    • 单总线(1-Wire BUS)是由Dallas公司开发的一种通用数据总线
    • 一根通信线:DQ
    • 异步、半双工
    • 单总线只需要一根通信线即可实现数据的双向传输,当采用寄生供电时,还可以省去设备的VDD线路,此时,供电加通信只需要DQ和GND两根线

    电路规范

    • 设备的DQ均要配置成开漏输出模式
    • DQ添加一个上拉电阻,阻值一般为4.7KΩ左右
    • 若此总线的从机采取寄生供电,则主机还应配一个强上拉输出电路

    电源供电

    寄生供电

    时序结构

            初始化:主机将总线拉低至少480us,然后释放总线,等待15~60us后,存在的从机会拉低总线60~240us以响应主机,之后从机将释放总线

            发送一位:主机将总线拉低60~120us,然后释放总线,表示发送0;主机将总线拉低1~15us,然后释放总线,表示发送1。从机将在总线拉低30us后(典型值)读取电平,整个时间片应大于60us

            接收一位:主机将总线拉低1~15us,然后释放总线,并在拉低后15us内读取总线电平(尽量贴近15us的末尾),读取为低电平则为接收0,读取为高电平则为接收1 ,整个时间片应大于60us

            发送一个字节:连续调用8次发送一位的时序,依次发送一个字节的8位(低位在前)

            :有些同学可能觉得读和写如此相似,单片机怎么去区分是读还是写呢?其实单片机默认为写入,相当于课堂上默认老师先说话一样,然后给出相应的指令,才能读取,相当于老师让我们回答问题之后,学生才能说话一样。

            接收一个字节:连续调用8次接收一位的时序,依次接收一个字节的8位(低位在前)

    操作流程

    • 初始化:从机复位,主机判断从机是否响应
    • ROM操作:ROM指令+本指令需要的读写操作
    • 功能操作:功能指令+本指令需要的读写操作

    数据帧

    温度存储格式

            以补码的形式存储,便于计算机进行计算,有不了解的同学可以去看我的数电笔记。计算转换的过程如下所示:

    代码

            介绍完了硬件部分,我们接下来就来编写代码实现其功能吧!


    首先是单总线的代码部分,如下所示:

    1. // OneWire.c
    2. #include
    3. //DQ引脚定义
    4. sbit OneWire_DQ=P3^7;
    5. /**
    6. * @brief 单总线初始化
    7. * @param 无
    8. * @retval 从机响应位,0为响应,1为未响应
    9. */
    10. unsigned char OneWire_Init(void)
    11. {
    12. unsigned char i;
    13. unsigned char AckBit;
    14. OneWire_DQ=1;
    15. OneWire_DQ=0;
    16. i = 227;while (--i); //@11.0592MHz Delay 500us
    17. OneWire_DQ=1; //释放
    18. i = 34;while (--i); //Delay 80us
    19. AckBit=OneWire_DQ; // 应答
    20. i = 227;while (--i); //Delay 500us
    21. return AckBit;
    22. }
    23. /**
    24. * @brief 单总线发送一位
    25. * @param Bit 要发送的位
    26. * @retval 无
    27. */
    28. void OneWire_SendBit(unsigned char Bit)
    29. {
    30. unsigned char i;
    31. OneWire_DQ=0;
    32. i = 3;while (--i); //Delay 10us
    33. OneWire_DQ=Bit;
    34. i = 22;while (--i); //Delay 50us
    35. OneWire_DQ=1;
    36. }
    37. /**
    38. * @brief 单总线接收一位
    39. * @param 无
    40. * @retval 读取的位
    41. */
    42. unsigned char OneWire_ReceiveBit(void)
    43. {
    44. unsigned char i;
    45. unsigned char Bit;
    46. OneWire_DQ=0;
    47. i = 2;while (--i); //Delay 6us
    48. OneWire_DQ=1;
    49. i = 2;while (--i); //Delay 6us
    50. Bit=OneWire_DQ;
    51. i = 22;while (--i); //Delay 50us
    52. return Bit;
    53. }
    54. /**
    55. * @brief 单总线发送一个字节
    56. * @param Byte 要发送的字节
    57. * @retval 无
    58. */
    59. void OneWire_SendByte(unsigned char Byte)
    60. {
    61. unsigned char i;
    62. for(i=0;i<8;i++)
    63. {
    64. OneWire_SendBit(Byte&(0x01<
    65. }
    66. }
    67. /**
    68. * @brief 单总线接收一个字节
    69. * @param 无
    70. * @retval 接收的一个字节
    71. */
    72. unsigned char OneWire_ReceiveByte(void)
    73. {
    74. unsigned char i;
    75. unsigned char Byte=0x00;
    76. for(i=0;i<8;i++)
    77. {
    78. if(OneWire_ReceiveBit()){Byte|=(0x01<
    79. }
    80. return Byte;
    81. }

    然后是DS18B20的代码,如下所示:

    1. // DS18B20.c
    2. #include
    3. #include "OneWire.h"
    4. //DS18B20指令
    5. #define DS18B20_SKIP_ROM 0xCC
    6. #define DS18B20_CONVERT_T 0x44
    7. #define DS18B20_READ_SCRATCHPAD 0xBE
    8. /**
    9. * @brief DS18B20开始温度变换
    10. * @param 无
    11. * @retval 无
    12. */
    13. void DS18B20_ConvertT(void)
    14. {
    15. OneWire_Init();
    16. OneWire_SendByte(DS18B20_SKIP_ROM);
    17. OneWire_SendByte(DS18B20_CONVERT_T);
    18. }
    19. /**
    20. * @brief DS18B20读取温度
    21. * @param 无
    22. * @retval 温度数值
    23. */
    24. float DS18B20_ReadT(void)
    25. {
    26. unsigned char TLSB,TMSB;
    27. int Temp;
    28. float T;
    29. OneWire_Init();
    30. OneWire_SendByte(DS18B20_SKIP_ROM);
    31. OneWire_SendByte(DS18B20_READ_SCRATCHPAD);
    32. TLSB=OneWire_ReceiveByte();
    33. TMSB=OneWire_ReceiveByte();
    34. Temp=(TMSB<<8)|TLSB;
    35. T=Temp/16.0; // 右移4位,取小数
    36. return T;
    37. }

    最后就是我们代码的主函数了,代码如下所示:

    1. // main.c
    2. #include
    3. #include "LCD1602.h"
    4. #include "DS18B20.h"
    5. #include "Delay.h"
    6. float T;
    7. void main()
    8. {
    9. DS18B20_ConvertT(); //上电先转换一次温度,防止第一次读数据错误
    10. Delay(1000); //等待转换完成
    11. LCD_Init();
    12. LCD_ShowString(1,1,"Temperature:");
    13. while(1)
    14. {
    15. DS18B20_ConvertT(); //转换温度
    16. T=DS18B20_ReadT(); //读取温度
    17. if(T<0)
    18. {
    19. LCD_ShowChar(2,1,'-'); //显示负号
    20. T=-T; //将温度变为正数
    21. }
    22. else
    23. {
    24. LCD_ShowChar(2,1,'+'); //显示正号
    25. }
    26. LCD_ShowNum(2,2,T,3); //显示温度整数部分
    27. LCD_ShowChar(2,5,'.');
    28. LCD_ShowNum(2,6,(unsigned long)(T*10000)%10000,4);//显示温度小数部分
    29. }
    30. }

    运行效果

            感觉温度应该还可以升,但是等不了了,30秒左右温度就到了44度,(刚出去的时候就有40多度)然后就先回去了,这还是下午5点,中午两点都不敢去尝试。(其实是还没睡醒,哈哈哈!)

    测温

  • 相关阅读:
    企业电子招标采购系统源码Spring Boot + Mybatis + Redis + Layui + 前后端分离 构建企业电子招采平台之立项流程图
    循环中的闭包
    SASE , sdp等
    自动驾驶算法———车道检测(一)
    JavaWeb核心(2)
    Mocha Pro 2024 v11.0.1 Mac版摄像机反求跟踪插件更新:优化AE/PR/OFX/达芬奇工作流程
    java面试强基(8)
    C++初阶(命名空间+缺省参数+const总结+引用总结+内联函数+auto关键字)
    pytorch单机多卡及常见问题
    安装sklearn包错误解决以及 scikit-learn简介
  • 原文地址:https://blog.csdn.net/weixin_66578482/article/details/126011904