第十四节 DS18B20温度传感器读取温度的学习 本节主要讲了GPIO的操作和DS18B20温度传感器的使用
学习笔记的pdf版:
14科星F107开发板学习笔记—DS18B20温度传感器的学习.pdf
(439.34 KB)
源码工程文件
14科星F107开发板学习笔记源码—DS18B20温度传感器的学习.rar
(3.01 MB)
笔记的部分内容如下:
首先我们看一下科星F107开发板关于DS18B20的硬件原理图: 如上图所示,MCU通过PD7引脚连接DS18B20的DQ(数字信号输入/输出端)进行指令和数据的交互,所以我们需要配置PD7这个GPIO口。 下面我们讲一下DS18B20的使用(更加详细的资料,请查阅DS18B20的芯片手册) DS18B20测温系统具有测温系统简单、测温精度高、连接方便、占用口线少等优点。DS18B20默认为单总线12位(二进制)温度读数。内部有64位唯一的ID编码。工作电压从3.0~5.5V。测量温度范围从-55℃~125℃。最高±0.0625℃分辩率。 有两种实现读取温度的方式: 1、DS18B20寄生电源供电方式电路 在寄生电源供电方式下,DS18B20从单线信号线上汲取能量:在信号线DQ处于高电平期间把能量储存在内部电容里,在信号线处于低电平期间消耗电容上的电能工作,直到高电平到来再给寄生电源(电容)充电。
独特的寄生电源方式有三个好处:
1)进行远距离测温时,无需本地电源
2)可以在没有常规电源的条件下读取ROM
3)电路更加简洁,仅用一根I/O口实现测温 这种方式对供电电压要求比较高 必须在5v 不然会造成很大的误差,DS18B20的VDD 引脚必须接地,只适合简单的单点采集。可靠性难以保证,不能用电池供电。一般不建议采用。 2、DS18B20的外部电源供电方式 在外部电源供电方式下,DS18B20工作电源由VDD引脚接入,此时I/O线不需要强上拉,不存在电源电流不足的问题,可以保证转换精度,同时在总线上理论可以挂接任意多个DS18B20传感器,组成多点测温系统。注意:在外部供电的方式下,DS18B20的GND引脚不能悬空,否则不能转换温度,读取的温度总是85℃。 外部电源供电方式是DS18B20最佳的工作方式,工作稳定可靠,抗干扰能力强,而且电路也比较简单,可以开发出稳定可靠的多点温度监控系统。 DS18B20使用中注意事项 DS18B20虽然具有测温系统简单、测温精度高、连接方便、占用口线少等优点,但在实际应用中也应注意以下几方面的问题: 较小的硬件开销需要相对复杂的软件进行补偿,由于DS18B20与微处理器间采用串行数据传送,因此,在对DS18B20进行读写编程时,必须严格的保证读写时序,否则将无法读取测温结果。在使用PL/M、C等高级语言进行系统程序设计时,对DS18B20操作部分最好采用汇编语言实现。 在DS18B20的有关资料中均未提及单总线上所挂DS18B20数量问题,容易使人误认为可以挂任意多个DS18B20,在实际应用中并非如此。当单总线上所挂DS18B20超过8个时,就需要解决微处理器的总线驱动问题,这一点在进行多点测温系统设计时要加以注意。 连接DS18B20的总线电缆是有长度限制的。试验中,当采用普通信号电缆传输长度超过50m时,读取的测温数据将发生错误。当将总线电缆改为双绞线带屏蔽电缆时,正常通讯距离可达150m,当采用每米绞合次数更多的双绞线带屏蔽电缆时,正常通讯距离进一步加长。这种情况主要是由总线分布电容使信号波形产生畸变造成的。因此,在用DS18B20进行长距离测温系统设计时要充分考虑总线分布电容和阻抗匹配问题。 在DS18B20测温程序设计中,向DS18B20发出温度转换命令后,程序总要等待DS18B20的返回信号,一旦某个DS18B20接触不好或断线,当程序读该DS18B20时,将没有返回信号,程序进入死循环。这一点在进行DS18B20硬件连接和软件设计时也要给予一定的重视。 测温电缆线建议采用屏蔽4芯双绞线,其中一对线接地线与信号线,另一组接VCC和地线,屏蔽层在源端单点接地 DS18B20内部寄存器映射如下图所示: 下面开始代码的编写,我们这里直接分析main()函数,功能就是获取温度值,然后每秒钟通过串口打印1次温度值。实现代码如下: int main(void) { RCC_Configuration(); //配置时钟 GPIO_Configuration();//配置GPIO口,也配置了串口所用的GPIO口 USART_Configuration();//配置串口通讯的参数 if(SysTick_Config(720000)) //配置 点滴时钟的频率 { while (1); } while (1) { delay(100); //延时1秒钟 temp_18B20data=get18B20data();//获取温度值 if(tempS==0) //判断温度值的正负 temper[0]='-'; else temper[0]='+'; temper[1]=temp_18B20data/100+0x30; temper[2]=(temp_18B20data%100)/10+0x30; temper[3]='.'; temper[4]=temp_18B20data%10+0x30; printf("\n\r 当前温度:"); printf(temper); //打印温度值 printf("\n\r"); } } 这里我们主要讲温度获取函数get18B20data(),代码如下: //从ds18b20得到温度值 //精度:0.1C //返回值:温度值 (-550~1250) short get18B20data(void) { u8 TL,TH; short tem; start18B20 (); // ds18B20 startconvert res18B20 (); //复位18B20 check18B20 ();//检测18B20的存在 write18B20byte (0xcc);// 忽略 64 位ROM 地址,直接向 DS18B20 发温度变换命令 write18B20byte (0xbe);// 读内部RAM 中9 字节的内容 的指令 TL=read18B20byte(); // LSB 连续读,先读去地位再读取高位数据 TH=read18B20byte(); // MSB if(TH>7) //高5位为 符号位,只有高5位全为0时才为正号 { TH=~TH; TL=~TL; tempS=0;//温度为负 } else tempS=1;//温度为正 tem=TH; //获得高八位 tem<<=8; tem+=TL;//获得低八位 tem=(float)tem*0.625;//转换 return tem; //返回温度值 } 第一步,开始温度转换,这里用到了DS18B20的指令0xcc和0x44。这些指令在DS18B20的芯片手册中都有,如下图(更多详细资料请查阅手册): 开始温度转换的函数如下: //开始温度转换 void start18B20(void)// ds18B20 start convert { res18B20(); check18B20 (); write18B20byte (0xcc);// 忽略 64 位 ROM 地址,直接向 DS18B20 发温度变换命令 write18B20byte (0x44);// 启动DS18B20 进行温度转换,12 位转换时最长为750ms(9 位为93.75ms)。结果存入内部9 字节RAM 中。 } 第二步 进行温度数据的读取。先发送读取命令,然后进行温度数据的读取 res18B20 (); //复位18B20 check18B20 ();//检测18B20的存在 write18B20byte (0xcc);// 忽略 64 位 ROM 地址,直接向 DS18B20 发温度变换命令 write18B20byte (0xbe);// 读内部RAM 中9 字节的内容 的指令 TL=read18B20byte(); // LSB 连续读,先读去地位再读取高位数据 TH=read18B20byte(); // MSB 第三步 温度数据的处理,提取符号位和数据位 数据的格式如下图,读取的两个字节中,高字节的二进制中的前面5 位是符号位,如果测得的温度大于0,这5 位为0,只要将测到的数值乘于0.0625 即可得到实际温度;如果温度小于0,这5 位为1,测到的数值需要取反加1 再乘于0.0625 即可得到实际温度。所以程序中当高字节大于7(0000 0111)时,符号位为负,否则为正。最后返回算出的温度值。 if(TH>7) //高5位为 符号位,只有高5位全为0时才为正号 { TH=~TH; TL=~TL; tempS=0;//温度为负 } else tempS=1;//温度为正 tem=TH; //获得高八位 tem<<=8; tem+=TL;//获得低八位 tem=(float)tem*0.625;//转换 return tem; //返回温度值 这里的1s计时使用的是SysTick中断,中断处理函数为TimingDelay_Decrement(); 下面把程序烧录到开发板,每秒钟会通过串口打印实时温度值,现象如下:
|