作者:GWD 时间:2019.6.30
一、 学习要点: 1.问:为什么在移位操作之前要在阅读操作中赋值,而不是直接对准?DQ移位? 答:bit只有类型变量不能移位char,int这种可移位操作; 2.问:多点检测试验有18个b20的ROM如果序列号产生9个字节的地址序列怎么办? 答:生产设备bug,删除一个序列后测试(0x0d)正确; 3.问:手册中的精度分辨率为0.0625如何转化为现实中所需的温度? 答:精度分辨率为0.0625意味着传感器检测值每增加1,10进制时大0.0625所以检测值*0.0625是所需的值,乘以100后,百分位小数即使在整数和十位中,也方便打印数据; 4、问:18B20单点采集流程 答:第一步:发送起始信号: 第二步:发送rom指令 0xcc(跳过rom命令); 第三步:发送功能命令0x44(开始转换温度指令); 第四步:发送起始信号; 第五步:发送rom指令 0xcc(跳过rom命令); 第六步:发送功能指令0xbe (读取临存器指令); 第七步:两次阅读18B20值,然后转换; 注:起始信号 rom命令 无论何时操作18,功能指令都是一组B20就要这三组一起不拆开。 5、问:18B采集过程超过20点 答: 第一步:发送起始信号 第二步:发送rom指令 0x33(读取rom命令),读取8字节的值,把这8个char串口助手的变量hex在模式下打印后,存储char[8]数组可以通过这种方式线的18b20的rom值; 第三步:发送功能命令0x44(开始转换温度指令) 第四步:发送起始信号 第五步:发送rom指令 0x55(匹配rom命令),发送命令后跟随8字节rom地址,读哪个18b20就紧跟着哪个器件的地址码; 第六步:发送功能指令0xbe (读取暂存器指令) 第七步:两次阅读18B20值,然后转换。 6、问:hex适用于输出功能? 答:调时程序需要知道程序运行到某个地方时的值,hex打印出16进制值,如18B20查看rom地址时就应该用hex输出模式。 二、手册分析 传感器特性操作流程: 2.通信只需要一个管脚。每个设备的内部 ROM 上都烧写了一个独特的 64 温度可测范围为: -55℃至 125℃(-67℉至 257℉)。用户可以将内部温度采集精度定义为9-Bits 至 12-Bits; 3、引脚定义: 3.内部框图: 1)、内部64位ROM存储第一无二序号; 2)、在1—Wire在总线系统中,微控制器(主设备)通过每个设备 64 序列号用于识别总线上的设备。因为每个设备都有一个独特的序列号,理论上挂在总线上的设备可以是无限的; 4、DS18B20的另一个特点是无需外部电源即可供电。当数据线 DQ 高时由设备供电。 当总线拉高时,是内部电容 (Spp) 充电, 当总线下降时,电容器向设备供电。 这种由 1-Wire设备供电的总线称为寄生电源。 5、DS18B20的核心功能是直接温度 -数字测量。其温度转换可由用户自定义 9、 10、 11、 12 位精度分别为 0.5℃、 0.25℃、 0.125℃、 0.0625℃分辨率。值得注意的是,默认上电 12 位转换精度。 DS18B20 上电后,工作处于低功耗闲置状态。必须向主设备方向 DS18B20 发送温度转换命令 [44h]开始温度转换。 7. 一个温度数据 16 以扩展二进制补码数的形式存储在温度寄存器中(图2-3)。符号标志位(S)温度的正负极性:正数 S=0,负数则 S=1。如果 DS18B20 被定义为12 温度寄存器中的所有位置都将包含有效数据。若为 11 位转换精度,则 bit 0 未定义。若为 10 位转换精度,则 bit 1 和 bit 0 未定义。 若为 9 位转换精度,则 bit 2、 bit 1和 bit 0 未定义。 12.18B20常用操作: 1)、访问 DS18B20 如下所示: 第一步:初始化DS18B20 第二步: ROM 命令(跟随任何数据交换请求) 第三步: DS18B20 当执行这些功能命令(跟随任何数据交换请求)时 ROM 命令结束后,主设备必须回到上述步骤的第一步。 2)、ROM命令:读取 ROM[33h]:该命令只能在总线上从设备中使用。该命令使总线上的主要设备无需搜索 ROM从设备中读取命令过程 64 位 ROM 编码。 当总线上有超过一个设备时, 如果再次发送命令,当所有设备都会响应时,数据冲突就会发生。 3)、ROM命令: 匹配 ROM[55h]该匹配 ROM 随后发送命令 64 位的 ROM 编码使总线上的主设备与特定的从设备相匹配。只有完全匹配 64 位 ROM 只有从设备编码,才能响应总线上主设备发出的功能命令;总线上的其他从设备将等待下一个复位脉冲。 4)、ROM命令:跳过 ROM[CCh]:主要设备可以使用该命令同时将任何从设备发送到总线的所有设备 ROM 编码命令。例如,主设备通过总线上的所有设备 DS18B20 发送跳过 ROM 发送温度转换命令后,发送温度转换命令 [44h]命令, 所有设备将同时转动温度。 5)、DS18B20 功能命令:温度转换 [44h]该命令是初始化的单次温度转换。温度转换后,存储在临时存储寄存器中的温度转换数据 2 在个字节长度的温度寄存器中,之后 DS18B20 恢复到低功耗的闲置状态。当设备采用外部供电模式时,主设备可以在温度转换命令后执行读取数据时序, 6)、DS18B20 功能命令:读取临时存储器 [BEh]该命令允许主设备读取存储在临时存储器中的值。 7)、18B20时序:初始时序-复位和脉冲存在 8)、 18B20时序:写时序——图2-6)写时段有两种情况: “写 时段和写 0”时段。写主设备 1 时段来向 DS18B20 中写入逻辑 1 以及通过写 0 时段来向 DS18B20 中写入逻辑 0。每个写作时间必须是最小的 60us持续时间和独立写作时间至少有 1us恢复时间(添加小延迟)。主设备通过两个写作时间段 1-Wire 拉低总线进行初始化。 为了形成写 1 时段,在将 1-Wire 总线拉低后,主设备必须在 15us释放总线。 为了形成写 0 时段,在将 1-Wire 总线拉低后,主设备必须一直拉低总线(至少 60us)。 主设备初始化写时段后, DS18B20 将会在 15us至 60us总线在时间窗口采样。如果总线在采样窗口期间电平较高,则逻辑1写入 DS18B20;如果总线电平较低,则逻辑 0 被写入DS18B20。 8)、18B20时序:阅读时序-在读时序期间DS18B将数据传输到主设备。 因此, 主要设备执行暂存储存储器 [BEh]或读取供电模式 [B4h]之后,必须及时生成阅读时间,以便 DS18B20 才提供所需的数据。 此外,主设备可以在执行完转换温度 [44h] 或拷贝 EEPROM[B8h] 命令后生成读时段,以便获得操作信息。每个读时段最小必须有 60us的持续时间且独立的写时段间至少有 1us 的恢复时间。 读时序通过主设备将总线拉低超过 1us再释放总线来实现初始化。(这里注意下类似的时序图可能是某段时序图初始化的意思)当主设备初始化完读时段后,DS18B20 将会向总线发送 0 或者 1。 将总线拉高来发送逻辑 1,将总线拉至低来发77送逻辑 0。当发送完 0 后, DS18B20 将会释放总线,则通过上拉电阻该总线将会恢复到高电平的闲置状态。 从 DS18B20 中输出的数据在初始化读时序后仅有 15us的有效时间。因此,主设备在开始读时段后的 15us之内必须释放总线,并且对总线进行采样。系统的时序正确保证即是保持Tinit、Trc尽可能的短,同时主设备必须在读时段开始 15us时间内采样。 三:编程 1、一路采集温度 1)、代码功能:实现18B20的一路温度采集 2)、代码效果: 3)、代码:
#include <reg52.h>
#include "stdio.h"
#include "delay.h"
#include "intrins.h"
#include "18b20.h"
#include "LCD1602.h"
/*
作者:宫伟迪
时间:19.06.30
功能:实现18B20温度传感器的单路温度采集,在1602显示和串口打印
*/
typedef unsigned char uChar8;
typedef unsigned int uInt16;
void InitUART (void)
{
SCON = 0x50; // SCON: 模式 1, 8-bit UART, 使能接收
TMOD |= 0x25; // TMOD: timer 1, mode 2, 8-bit 重装 // timer 0,16位计数
TR0=0;
TL0 = 0;
TH0 = 0;
TH1 = 0xF4; // TH1: 重装值 9600 波特率 晶振 11.0592MHz
TR1 = 1; // TR1: timer 1 打开
EA = 1; //打开总中断
ES = 1; //打开串口中断
TI=1;
}
void main (void)
{
unsigned char tem_h,tem_l,bai,shi,ge,shifen,baifen;
int temp;
char *p = "temp1:";
float j=0;
InitUART( );
LCD1602_Init( );
while (1)
{
Delay200ms(); Delay200ms();Delay200ms();
DS18B20_Start();//18b20开始信号
DS18B20_Wr_Onebyte(0xCC);//发送跳过ROM的ROM命令
DS18B20_Wr_Onebyte(0x44);//发送开始转换温度的ROM命令
DS18B20_Start();
DS18B20_Wr_Onebyte(0xCC);
DS18B20_Wr_Onebyte(0xBE);
tem_l = DS18B20_Rd_Onebytr();
tem_h = DS18B20_Rd_Onebytr();
temp = tem_h;
temp <<= 8;
temp |= tem_l;
if( temp < 0 )
{
temp = temp - 1;
temp = ~temp;
}
j = temp;
temp = j * 0.0625 * 100 + 0.5;
bai = (temp / 10000) + '0';
shi = (temp % 10000/1000) + '0';
ge = (temp % 1000/100) + '0';
shifen = (temp % 100/10) + '0';
baifen = temp % 10 + '0';
printf("%c%c%c%c%c\n\r",shi,ge,'.',shifen,baifen);
Display_StrOnLcd1602(0,0,p);
Display_CharOnLcd(6,0,shi);
Display_CharOnLcd(7,0,ge);
Display_CharOnLcd(8,0,'.');
Display_CharOnLcd(9,0,shifen);
Display_CharOnLcd(10,0,baifen);
}
}
#include "18b20.h"
#include "intrins.h"
/*
作者:宫伟迪
时间:19.06.30
功能:实现18B20温度传感器的单路温度采集,在1602显示和串口打印
*/
void DS18B20_Start()
{
DQ = 1;
_nop_();
DQ = 0;
DelayXus(80);
DQ = 1;
DelayXus(7);
while(0 == DQ);
DQ = 1;
}
void DS18B20_Wr_Onebyte(unsigned char dat) //先写低位
{
unsigned char i = 0,j=0;
for(i=0;i < 8;i++)
{
DQ=0;
_nop_();
DQ = dat & 0x01;
DelayXus(10);//error1采样器件器件采集自己的就行,主机什么也不用干。
DQ = 1;
dat >>= 1;
}
}
unsigned char DS18B20_Rd_Onebytr(void) //先读低位
{
unsigned char i,j,dat;
for(i=0;i<8;i++)
{
DQ = 0;
_nop_();
DQ = 1;
j = DQ;
_nop_();
_nop_();;
dat = (dat>>1)|(j<<7);
DelayXus(5);
DQ = 1;
}
return dat;
}
2、多路采集温度 1)、代码功能:实现通过单总线访问rom地址的方法实现18b20的多点温度采集(实验中是3点,只买了3个18B20),使用时候要先检测新加入的18b20的rom地址,然后加入新的数组中就可以了。 2)、程序效果: 3)、代码
#include <reg52.h> //包含头文件,一般情况不需要改动,头文件包含特殊功能寄存器的定义
#include "stdio.h"
#include "delay.h"
#include "intrins.h"
#include "18b20.h"
#include "LCD1602.h"
/*
作者:宫伟迪
时间:19.06.30
功能:实现18B20温度传感器的单路温度采集,在1602显示和串口打印
*/
typedef unsigned char uChar8;
typedef unsigned int uInt16;
void InitUART (void)
{
SCON = 0x50; // SCON: 模式 1, 8-bit UART, 使能接收
TMOD |= 0x25; // TMOD: timer 1, mode 2, 8-bit 重装 // timer 0,16位计数
TR0=0;
TL0 = 0;
TH0 = 0;
TH1 = 0xF4; // TH1: 重装值 9600 波特率 晶振 11.0592MHz
TR1 = 1; // TR1: timer 1 打开
EA = 1; //打开总中断
ES = 1; //打开串口中断
TI=1;
}
void main (void)
{
unsigned char i,tem_h,tem_l,bai,shi,ge,shifen,baifen;
int temp;
char *p1 = "1:";
char *p2 = "2:";
char *p3 = "3:";
char rom_1[8]={0x28,0xFF,0x2D,0x86,0x67,0x18,0x01,0x97};//第三个18B20
char rom_2[8]={0X28,0X00,0X4E,0X45,0X92,0X17,0X02,0X6D};
char rom_3[8]={0x28,0x30,0x5F,0x45,0x92,/*0x0D,*/0x0A,0x02,0x54};
float j=0;
InitUART( );
LCD1602_Init( );
while (1)
{
DS18B20_Start();//18b20开始信号
DS18B20_Wr_Onebyte(0xcc);//发送跳过ROM的ROM命令
DS18B20_Wr_Onebyte(0x44);
DS18B20_Start();//18b20开始信号
DS18B20_Wr_Onebyte(0x55);//发送匹配ROM命令
for(i=0;i<8;i++)
{
DS18B20_Wr_Onebyte(rom_1[i]);
}
DS18B20_Wr_Onebyte(0xBE);
tem_l = DS18B20_Rd_Onebytr();
tem_h = DS18B20_Rd_Onebytr();
temp = tem_h;
temp <<= 8;
temp |= tem_l;
if( temp < 0 )
{
temp = temp - 1;
temp = ~temp;
}
j = temp;
temp = j * 0.0625 * 100 + 0.5;
bai = (temp / 10000) + '0';
shi = (temp % 10000/1000) + '0';
ge = (temp % 1000/100) + '0';
shifen = (temp % 100/10) + '0';
baifen = temp % 10 + '0';
Display_StrOnLcd1602(0,0,p1);
Display_CharOnLcd(2,0,shi);
Display_CharOnLcd(3,0,ge);
Display_CharOnLcd(4,0,'.');
Display_CharOnLcd(5,0,shifen);
Display_CharOnLcd(6,0,baifen);
DS18B20_Start();//18b20开始信号
DS18B20_Wr_Onebyte(0xcc);//发送跳过ROM的ROM命令
DS18B20_Wr_Onebyte(0x44);
DS18B20_Start();//18b20开始信号
DS18B20_Wr_Onebyte(0x55);//发送匹配ROM命令
for(i=0;i<8;i++)
{
DS18B20_Wr_Onebyte(rom_2[i]);
}
DS18B20_Wr_Onebyte(0xBE);
tem_l = DS18B20_Rd_Onebytr();
tem_h = DS18B20_Rd_Onebytr();
temp = tem_h;
temp <<= 8;
temp |= tem_l;
if( temp < 0 )
{
temp = temp - 1;
temp = ~temp;
}
j = temp;
temp = j * 0.0625 * 100 + 0.5;
bai = (temp / 10000) + '0';
shi = (temp % 10000/1000) + '0';
ge = (temp % 1000/100) + '0';
shifen = (temp % 100/10) + '0';
baifen = temp % 10 + '0';
Display_StrOnLcd1602(0,1,p2);
Display_CharOnLcd(2,1,shi);
Display_CharOnLcd(3,1,ge);
Display_CharOnLcd(4,1,'.');
Display_CharOnLcd(5,1,shifen);
Display_CharOnLcd(6,1,baifen);
DS18B20_Start();//18b20开始信号
DS18B20_Wr_Onebyte(0xcc);//发送跳过ROM的ROM命令
// for(i=0;i<8;i++)
// {
// rom_3[i] = DS18B20_Rd_Onebytr();
// }
// for(i=0;i<8;i++)
// {
// printf("%c",rom_3[i]);
// }
// while(1);
DS18B20_Wr_Onebyte(0x44);
DS18B20_Start();//18b20开始信号
DS18B20_Wr_Onebyte(0x55);//发送匹配ROM命令
for(i=0;i<8;i++)
{
DS18B20_Wr_Onebyte(rom_3[i]);
}
DS18B20_Wr_Onebyte(0xBE);
tem_l = DS18B20_Rd_Onebytr();
tem_h = DS18B20_Rd_Onebytr();
temp = tem_h;
temp <<= 8;
temp |= tem_l;
if( temp < 0 )
{
temp = temp - 1;
temp = ~temp;
}
j = temp;
temp = j * 0.0625 * 100 + 0.5;
bai = (temp / 10000) + '0';
shi = (temp % 10000/1000) + '0';
ge = (temp % 1000/100) + '0';
shifen = (temp % 100/10) + '0';
baifen = temp % 10 + '0';
Display_StrOnLcd1602(9,0,p3);
Display_CharOnLcd(11,0,shi);
Display_CharOnLcd(12,0,ge);
Display_CharOnLcd(13,0,'.');
Display_CharOnLcd(14,0,shifen);
Display_CharOnLcd(15,0,baifen);
}
}
代码下载地址: 链接:https://pan.baidu.com/s/1Knmk850_Sxmohf-Gkon2ow 提取码:wf1v