解决方案

DS18B20温度传感器的特性、原理、驱动(华大半导体HC32L136、ESP32驱动)

seo靠我 2023-09-23 18:00:31

目录

1、模组简介

2、驱动原理

3、HC32L136驱动

4、ESP32驱动

新冠疫情、元器件涨价,同一家店铺之前买的DS18B20模组体积有大拇指这么大,最近买体积只有大拇指指甲盖这么大,以前无论买多少都有SEO靠我6元运费,今年哪怕买一块都是包邮,今年生意难做了,祈祷国泰民安、国强民富!

言归正传,说大事分割线~

1、模组简介

DS18B20的数字温度传感器,可以用来对环境温度进行定量的检测。DS18B20数字温度传SEO靠我感器是美国DALLAS公司生产的一总线数字温度传感器。其测温范围 -55℃~+125℃,固有测温分辨率0.5℃,支持多点组网功能,多个DS18B20可以并联在唯一的三线上,实现多点测温,测量结果以9~SEO靠我12位数字量方式串行传送。模组结构如下图所示:

模组特性如下所示: 

独特的1-Wire总线接口仅需要一个管脚来通信。每个设备的内部ROM上都烧写了一个独一无二的64位序列号。多路采集能力使得分布式温度采集SEO靠我应用更加简单。无需外围元件。能够采用数据线供电,供电范围为3.0V至5.5V。温度可测量范围为:-55℃至+125℃(-67℉至+257℉)。温度范围超过-10℃至85℃之外时测温分辨率0.5℃。内部SEO靠我温度采集精度可以由用户自定义为9-Bits至12-Bits。温度转换时间在转换精度为12-Bits时达到最大值750ms。用户自定义非易失性的的温度报警设置。定义了温度报警搜索命令和当温度超过用户自定SEO靠我义的设定值时。可选择的8-Pin SO (150 mils), 8-Pin μSOP,及3-Pin TO-92封装。与DS1822程序兼容。应用于温度控制系统,工业系统,民用产品,温度传感器,或者任何SEO靠我温度检测系统中。

DS18B20管脚定义如下图所示:

DS18B20采用Maxim公司专有的1-Wire总线协议,该总线协议仅需要一个控制信号进行通信。该控制信号线需要一个唤醒的上拉电阻以防止连接在该总线SEO靠我上的口是3态或者高阻态(DQ信号线是在DS18B20上)。在该总线系统中,微控制器(主设备)通过每个设备的64为序列号来识别该总线上的设备。因为每个设备都有一个独一无二的序列号,挂在一个总线上的设备理SEO靠我论上是可以无限个的。在下面的“1-Wire总线系统”章节中包含有1-Wire总线协议详细的命令和时序关系。

DS18B20的另外一个特性就是可以无需外部电源供电。当数据线DQ为高的时候由其为设备供电。总SEO靠我线拉高的时候为内部电容(Spp)充电,当总线拉低是由该电容向设备供电。这种由1-Wire总线为设备供电的方式称为“寄生电源”。此外,DS18B20也可以由外部电源通过VDD供电。DS18B20内部框图SEO靠我如下所示:

DS18B20的核心功能是直接温度—数字测量,上电后工作在低功耗闲置状态下,其温度转换可由用户自定义为9、10、11、12位精度分别为0.5℃、0.25℃、0.125℃、0.0625℃分辨率SEO靠我,上电默认为12位转换精度。温度数据以一个16位标志扩展二进制补码数的形式存储在温度寄存器中,符号标志位(S)温度的正负极性:正数则S=0,负数则S=1。如果DS18B20被定义为12位的转换精度,温SEO靠我度寄存器中的所有位都将包含有效数据。若为11位转换精度,则BIT 0为未定义的。若为10位转换精度,则BIT 1和BIT 0为未定义的。 若为9位转换精度,则BIT 2、BIT 1和BIT 0为未定义SEO靠我的。下表为在12位转换精度下温度输出数据与相对应温度之间的关系表。

DS18B20的温度输出数据时在摄氏度下校准的,若是在华氏度下应用的话,可以用查表法或者常规的数据换算,温度/数据对应关系如下表所示:SEO靠我

DS18B20可以通过VDD引脚由外部供电,或者可以由“寄生电源”供电,这使得DS18B20可以不采用当地的外部电源供电而实现其功能。

外部电源供电方式具有不需要上拉的MOSFET、该1-Wire总线在SEO靠我温度转换期间可执行其他动作的优点,外部电源供电方式如下图所示:

“寄生电源”供电方式在远程温度检测或空间比较有限制的地方有很大的应用,其由DQ口拉高时向其供电。总线拉高的时候为内部电容(Cpp)充电,当SEO靠我总线拉低是由该电容向设备供电。当DS18B20为“寄生电源”供电模式时,该VDD引脚必须连接到地。“寄生电源”供电方式在温度超过+100℃时不推荐使用,因为在超过该温度下时将会有很大的漏电流导致不能进SEO靠我行正常的通信。实际应用中,在类似的温度状态下强烈推荐该DS18B20由外部电源供电,“寄生电源”供电方式如下图所示。

DS18B20存储器包含了SRAM暂存寄存器、过温和低温(TH和TL)温度报警寄存器SEO靠我、配置寄存器的非易失性EEPROM。当温度报警功能没有用到的时候,过温和低温(TH和TL)温度报警寄存器可以当做通用功能的存储单元。

SRAM暂存寄存器中的Byte 0和Byte 1分别作为温度寄存器的SEO靠我低字节和高字节,同时这两个字节是只读的;Byte 2和Byte 3作为过温和低温(TH和TL)温度报警寄存器;Byte 4保存着配置寄存器的数据;Byte 5、6、7作为内部使用的字节而保留使用,不可SEO靠我被写入;Byte 8存储着该暂存寄存器中Byte 0至Byte 7的循环冗余校验(CRC)值,并且只读不可写入,存储器组织结构如下图所示:

2、驱动原理

DS18B20的驱动过程主要依托于1-Wire总线SEO靠我系统,该总线系统可以一个总线主设备控制一个或多个从设备,我们的MCU作为主设备,DS18B20永远为从设备,1-Wire总线系统上所有的命令或者数据的发送送都是遵循低位先发送的原则。

1-Wire总线系SEO靠我统仅有一根数据线,且需要一个5kΩ左右的外部上拉电阻,因此闲置情况下数据线是高电平。每个设备(主设备或从设备)通过一个漏极开路或3态门引脚连接至数据线上。这就允许每个设备“释放”数据线,当设备没有传递SEO靠我数据的时其他设备可以有效地使用数据线。DS18B20的1-Wire总线接口(DQ引脚)是其内部电路组成的漏极开路,硬件配置如下图所示:

实现DS18B20的驱动主要有三步:

第一步:初始化DS18B20;SEO靠我

第二步:ROM命令(紧跟任何数据交换请求);

第三步:DS18B20功能命令(紧跟任何数据交换请求);

每次对DS18B20的访问都必须遵循这样的步骤来进行,如果这些步骤中的任何一个丢失或者没有执行,则DSEO靠我S18B20将不会响应。这只说明驱动的思路,具体参见DS18B20数据手册。

3、HC32L136驱动

第1步:配置GPIO,这里配置HC32L136的PB03引脚,PB03引脚连接DS18B20数据线,SEO靠我所以IO口的方向(输入、输出)在读、写过程中是不断变化的,代码如下所示:

uint8_t DS18B20_Init(void) {stc_gpio_cfg_t stcGpioCfg;DDSEO靠我L_ZERO_STRUCT(stcGpioCfg);Sysctrl_SetPeripheralGate(SysctrlPeripheralGpio,TRUE); //开启GPIO时钟门控 stcGpiSEO靠我oCfg.enDir = GpioDirOut; ///< 端口方向配置->输出 stcGpioCfg.enOD = GpioOdDisable; ///< 推挽输出stcGpioCfg.enPu =SEO靠我 GpioPuDisable; ///< 端口上拉配置->禁止stcGpioCfg.enPd = GpioPdDisable; ///< 端口下拉配置->禁止stcGpioCfg.enDrv=GpioSEO靠我DrvH; ///< 强驱动Gpio_Init(GpioPortB,GpioPin8,&stcGpioCfg); ///< 端口初始化Gpio_SetIO(GpioPortB,GpioPin8); /SEO靠我//< 默认置高电平 }

第2步:配置延时,本案例基于HC32L136 24MHz时钟频率下工作的,一个机器周期约为2us(num参数,不是倍数关系,HC32L136延时相当不精准,需要SEO靠我用示波器验证),代码如下所示:

void delay_us(uint32_t num) {while(num--){__NOP();} }

第3步:初始化以及检测DS18BSEO靠我20是否存在,当DS18B20响应复位信号的存在脉冲后,则其向主设备表明其在该总线上,并且已经做好操作命令。

在初始化序列期间,总线上的主设备通过拉低1-Wire总线超过480us来发送(TX)复位脉冲SEO靠我。之后主设备释放总线而进入接收模式(RX)。当总线释放后,5kΩ左右的上拉电阻将1-Wire总线拉至高电平。当DS18B20检测到该上升边沿信号后,其等待15us至60us后通过将1-Wire总线拉低SEO靠我60us至240us来实现发送一个存在脉冲。初始化时序如下图所示:

初始化时序代码如下所示:

//复位DS18B20 void DS18B20_Rst(void) { DSSEO靠我18B20_IO_OUT(); ///< 配置端口输出Gpio_ClrIO(GpioPortB,GpioPin8); ///< 拉低DQdelay100us(7); ///< 拉低700usGpio_SEO靠我SetIO(GpioPortB,GpioPin8); ///< 拉高DQdelay10us(1); ///< 拉高15us }//等待DS18B20的回应 //返回1:SEO靠我未检测到DS18B20的存在 //返回0:存在 uint8_t DS18B20_Check(void) { uint8_t retry=0;DS18B2SEO靠我0_IO_IN(); ///< 配置端口输入while ((Gpio_GetInputIO(GpioPortB,GpioPin8)==1) && (retry<100)) ///< 最多200us{rSEO靠我etry++; delay_us(1); ///< 每次等待2us} if(retry>=200) {return 1;}else {retry=0;}while ((Gpio_GetInputIO(SEO靠我GpioPortB,GpioPin8)==0 )&& (retry<120)) ///< 最多240us{retry++;delay_us(1); ///< 每次等待2us}if(retry>=120SEO靠我) {return 1; }return 0; }

运行程序,时序效果如下所示:

第4步:开始转换DS18B20,写入ROM命令:0XCC和0X44。写时段有两种情况:“写1”时段和“写0SEO靠我”时段,主设备通过写1时段来向DS18B20中写入逻辑1以及通过写0时段来向DS18B20中写入逻辑0。每个写时段最小必须有60us的持续时间且独立的写时段间至少有1us的恢复时间。

为了形成写1时段,SEO靠我在将1-Wire总线拉低后,主设备必须在15us之内释放总线。当总线释放后,5kΩ的上拉电阻将总线拉至高。为了形成写0时段,在将1-Wire总线拉低后,在整个时段期间主设备必须一直拉低总线(至少60uSEO靠我s)。

在主设备初始化写时段后,DS18B20将会在15us至60us的时间窗口内对总线进行采样。如果总线在采样窗口期间是高电平,则逻辑1被写入DS18B20;若总线是低电平,则逻辑0被写入DS18B2SEO靠我0。读/写时段时序如下所示:

 转换DS18B20代码如下所示:

//写一个字节到DS18B20 //dat:要写入的字节 void DS18B20_Write_Byte(uSEO靠我int8_t dat) { uint8_t j;uint8_t testb;DS18B20_IO_OUT(); ///< 配置端口输出for (j=1;j<=8;j++) {testb=dat&0x0SEO靠我1;dat=dat>>1;if (testb) ///< 写入1{Gpio_ClrIO(GpioPortB,GpioPin8); delay_us(1); ///< 拉低2us Gpio_SetIO(SEO靠我GpioPortB,GpioPin8); delay10us(5); ///< 拉高64us}else ///< 写入0{Gpio_ClrIO(GpioPortB,GpioPin8); delay10SEO靠我us(5); ///< 拉低64usGpio_SetIO(GpioPortB,GpioPin8); delay_us(1); ///< 拉高2us }} }//开始温度转换 SEO靠我 void DS18B20_Start(void) { DS18B20_Rst(); DS18B20_Check(); DS18B20_Write_Byte(0xCC); ///<SEO靠我 skip romDS18B20_Write_Byte(0x44); ///< convert }

运行程序,写入0XCC(二进制:‭1100 1100‬)时序效果如下所示:

写入0X44SEO靠我(二进制:0100 0100‬)时序效果如下所示:

第5步: 写入读取DS18B20暂存器功能命令:0XCC和0XBE,代码如下所示:

DS18B20_Write_Byte(0xCC); ///< skiSEO靠我p romDS18B20_Write_Byte(0xBE); ///< convert

运行程序,写入0XBE(二进制:‭1011 1110‬)时序效果如下所示:

第6步:  读取温度寄存器数据,这里只需SEO靠我要读取两个字节(16位)即可。每个读时段最小必须有60us的持续时间且独立的写时段间至少有1us的恢复时间。读时段通过主设备将总线拉低超过1us再释放总线来实现初始化,当主设备初始化完读时段后,DS1SEO靠我8B20将会向总线发送0或者1。DS18B20通过将总线拉至高来发送逻辑1,将总线拉至低来发送逻辑0。当发送完0后,DS18B20将会释放总线,则通过上拉电阻该总线将会恢复到高电平的闲置状态。从DS1SEO靠我8B20中输出的数据在初始化读时序后仅有15us的有效时间,因此,主设备在开始改读时段后的15us之内必须释放总线,并且对总线进行采样。读时段时序图如下所示:

读时段代码如下所示:

//从DS18B20读SEO靠我取一个位 //返回值:1/0 uint8_t DS18B20_Read_Bit(void) {uint8_t data;DS18B20_IO_OUT()SEO靠我; ///< 配置端口输出Gpio_ClrIO(GpioPortB,GpioPin8); delay_us(1); ///< 等待2usGpio_SetIO(GpioPortB,GpioPin8);DSEO靠我S18B20_IO_IN(); ///< 配置端口输入delay_us(40); ///< 等待12usif(Gpio_GetInputIO(GpioPortB,GpioPin8)==1){data=SEO靠我1;}else {data=0; }delay10us(4); ///< 等待52usreturn data; }//从DS18B20读取一个字节 //返回值:读到的数SEO靠我据 uint8_t DS18B20_Read_Byte(void) { uint8_t i=0,j=0,dat=0;uint8_t num1,num2;for (i=1SEO靠我;i<=8;i++) ///< 一次读取一个字节,8位{j=DS18B20_Read_Bit();num1=j<<7;num2=dat>>1;dat=num1|num2;} return dat; SEO靠我 }TL=DS18B20_Read_Byte(); ///< 读取LSB,低八位数据 TH=DS18B20_Read_Byte(); ///< 读取MSB,高八位数据

运行程SEO靠我序,读取低八位数据时序效果如下所示:

 读取高八位数据时序效果如下所示:

所以读到的数据为,二进制:101101010。

第7步:将十六进制数据转换为十进制形式,代码如下所示:

if(TH>7) ///< 温度SEO靠我为负 {TH=~TH;TL=~TL; temp_flag=0; } else ///< 温度为正 {temp_flag=1; SEO靠我 } tem=TH; tem<<=8; tem+=TL; temp=(float)tem/16.0; ///< 转换数据 if(temp_flag)SEO靠我 {return temp; } return -temp;

二进制:101101010按照数据手册转换为十进制362,362除以16为22.625‬,与此时程序串口打印SEO靠我效果完全一致,说明转换无误。

4、ESP32驱动

闲来无事为了验证温度检测的精准性(HC32L136精度较差),特使用ESP32又写了一版驱动程序,完整示例代码如下所示(可直接复制使用):

#includeSEO靠我 <OneWire.h>int DS18B20_Pin = D3; //DS18B20信号引脚在D3上//温度芯片I/O OneWire ds(DS18B20_Pin); //配置数字SEO靠我引脚D3void setup(void) {Serial.begin(9600);Serial.println("Start!\n"); }void loop(void) {floatSEO靠我 temperature = getTemp();Serial.println(temperature);delay(1000); }float getTemp(){//获取DS18BSEO靠我20温度数据byte data[12];byte addr[8];if ( !ds.search(addr)) {//若无传感器继续搜索ds.reset_search();return -1000;}SEO靠我if ( OneWire::crc8( addr, 7) != addr[7]) {Serial.println("CRC is not valid!");return -1000;}if ( addSEO靠我r[0] != 0x10 && addr[0] != 0x28) {Serial.print("Device is not recognized");return -1000;}ds.reset();SEO靠我ds.select(addr);ds.write(0x44,1); //开始转换byte present = ds.reset();ds.select(addr); ds.write(0xBE); /SEO靠我/读暂存存储器for (int i = 0; i < 9; i++) { //读取9个字节data[i] = ds.read();}ds.reset_search();byte MSB = data[SEO靠我1];byte LSB = data[0];float tempRead = ((MSB << 8) | LSB); float TemperatureSum = tempRead / 16;retuSEO靠我rn TemperatureSum;}

同时运行程序,HC32L136和ESP32同时获取DS18B20温度数据基本一致,时序效果如下所示:

串口输出数据效果如下所示:

“SEO靠我”的新闻页面文章、图片、音频、视频等稿件均为自媒体人、第三方机构发布或转载。如稿件涉及版权等问题,请与 我们联系删除或处理,客服邮箱:html5sh@163.com,稿件内容仅为传递更多信息之目的,不代表本网观点,亦不代表本网站赞同 其观点或证实其内容的真实性。

网站备案号:浙ICP备17034767号-2