营销网站推荐,网站建设高端设计,html企业整站模板网站,wordpress必用插件一、DS18B20介绍 DS18B20数字温度传感器是DALLAS公司生产的单总线器件#xff0c;用它来组成一个测温系统具有线路简单#xff0c;体积小#xff0c;在一根通信线上可以挂很多这样的数字温度传感器#xff0c;十分方便。 温度传感器种类众多#xff0c;应用在高精度、高可…一、DS18B20介绍 DS18B20数字温度传感器是DALLAS公司生产的单总线器件用它来组成一个测温系统具有线路简单体积小在一根通信线上可以挂很多这样的数字温度传感器十分方便。 温度传感器种类众多应用在高精度、高可靠性的场合时DALLAS公司生产的DS18B20温度传感器当仁不让。超小的体积超低的硬件开销抗干扰能力强精度高附加功能强使得DS18B20更受欢迎。DS18B20的优势更是我们学习单片机技术和开发温度相关小产品的不二选择。了解工作原理和应用可以拓宽您对单片机开发的思路。
二、DS18B20特点 1、通信采用1-Wire接口 2、每个DS18B20都有唯一的64位序列码储存在板载ROM中 3、无需外部元件 4、可从数据线供电电源范围为3.0V ~ 5.5V。 5、可测量的温度范围在-55℃ ~ 125℃ 6、在1085℃范围内精确度为±0.5℃ 7、温度计分辨率可设置为9~12位12位时分辨率对应为0.0625℃ 三、DS18B20在实际应用中的典型接法
1、工作在寄生电源下的典型接法 2、 外部供电下的典型接法 四、单总线时序 DS18B20采用1-wire Bus所有数据都在一条线上传输因此单总线协议对时序要求非常严格以确保数据的完整性。 单总线信号类型:复位脉冲、存在脉冲、写0、写1、读0、读1。所有这些信号除存在脉冲由DS18B20发出的以外其他信号都由总线控制器发出。 数据传输总是从最低有效位开始。
1、初始化时序
初始化时序里面包含了复位DS18B20和接收DS18B20返回的存在信号。
主机和DS18B20做任何通讯前都需要对其初始化。初始化期间总线控制器拉低总线并保持480us以上挂在总线上的器件将被复位然后释放总线等到15-60us此时18B20将返回一个60-240us之间的低电平存在信号。
复位脉冲和存在脉冲时序图 2、写时序
写时序分为写0时序和写1时序。
总线控制器通过控制单总线高低电平持续时间从而把逻辑1或0写DS18B20中。
总线控制器要产生一个写时序必须将总线拉低最少1us产生写0时序时总线必须保持低电平60~120us之间然后释放总线产生写1时序时在总线产生写时序后的15us内允许把总线拉高。注意2次写周期之间至少间隔1us 3、读时序
读时序分为读0时序和读1时序。
总线控制器通过读取由DS18B20控制的总线高低电平接收DS18B20数据,总线控制器要产生一个读时序必须将总线拉低至少1us然后释放总线在读信号开始后15us内总线控制器采样总线数据读一位数据至少保持在60us以上。注意2次读周期之间至少间隔1us
读时序图: 读1详细时序图: 五、DS18B20暂存器 温度寄存器图表 配置寄存器图表 部分ROM指令及功能指令 执行序列 通过单线总线端口访问DS18B20的协议如下 步骤1. 初始化 步骤2. ROM操作指令 步骤3. DS18B20功能指令
忽略ROM指令CCh
这条指令允许总线控制器不用提供64 位ROM 编码就使用功能指令。例如总线控制器可以先发出一条忽略ROM 指令然后发出温度转换指令[44h]从而完成温度转换操作。在单点总线情况下使用该命令器件无需发回64 位ROM 编码从而节省了时间。如果总线上有不止一只从机若发出忽略ROM指令由于多只从机同时传送信号总线上就会发生数据冲突。
六、DS18B20功能指令
1、温度转换指令44h
这条命令用以启动一次温度转换。温度转换指令被执行产生的温度转换结果数据以2个字节的形式被存储在高速暂存器中而后DS18B20保持等待状态。
2、读暂存器指令BEh
这条命令读取暂存器的内容。读取将从字节0 开始一直进行下去直到读完暂存器所有字节如果不想读完所有字节控制器可以在任何时间发出复位命令来中止读取。
3、写暂存器指令4Eh
这条命令向DS18B20 的暂存器写入数据开始位置在TH 寄存器暂存器的第2个字节接下来写入TL 寄存器暂存器的第3 个字节最后写入配置寄存器暂存器的第4 个字节
4、拷贝暂存器指令48h
这条命令把TH,TL 和配置寄存器第2、3、4 字节的内容拷贝到EEPROM 中。 七、执行序列
通过单线总线端口访问DS18B20的协议如下
步骤1. 初始化
步骤2. ROM操作指令
步骤3. DS18B20功能指令 温度转换命令 读取暂存器命令
八、DS18B20驱动代码
1、51单片机数码管显示
#include reg52.h
#include intrins.h
#define MAIN_Fosc 11059200UL //宏定义主时钟HZ
/*自定义类型名
*/
typedef unsigned char INT8U;
typedef unsigned char uchar;typedef unsigned int INT16U;
typedef unsigned int uint;/*硬件接口位声明
*/
sbit DS P2^2; //DS18B20单总线
sbit DU P2^6; //数码管段选
sbit WE P2^7; //数码管位选
/*
共阴极数码管段选码
*/
uchar code table[]{
//0 1 2 3 4 5 6 7 8
0x3F, 0x06, 0x5B, 0x4F, 0x66, 0x6D, 0x7D, 0x07, 0x7F,
//9 A B C D E F - . 关显示
0x6F, 0x77, 0x7C, 0x39, 0x5E, 0x79, 0x71, 0x40, 0x80, 0x00};/*
数码管位选码
*///第1位 2位 3位 4位 5位 6位 7位 8位
uchar code T_COM[] {0xfe, 0xfd, 0xfb, 0xf7, 0xef, 0xdf, 0xbf, 0x7f};//数码管位码/*
函数void Delay_Ms(INT16U ms)
参数ms毫秒延时形参
描述12T 51单片机自适应主时钟毫秒级延时函数
*/
void Delay_Ms(INT16U ms)
{INT16U i;do{i MAIN_Fosc / 96000; while(--i); //96T per loop}while(--ms);
}
/*us延时函数执行一次US--所需6.5us进入一次函数需要11.95us*/
void Delay_us(uchar us)
{while(us--);
}
/*
函数void Display(INT16U Value)
参数Value,显示值 取值0-65535
描述共阴极数码管显示函数可显示一个字节的数
*/
void Display(INT16U Value) //注意由于需要显示的数大于一个字节所有形参需为int型
{
//------------------------------DU 0; //关闭段选P0 table[Value/100]; //数码管显示百位DU 1; //打开段选DU 0; //关闭段选WE 0; //关闭位选P0 T_COM[0]; //第一位数码管WE 1; //打开位选WE 0; //关闭位选Delay_Ms(3);
//-------------------------------DU 0;P0 table[Value%100/10]|0x80; //显示十位DU 1;DU 0;WE 0;P0 T_COM[1]; //第二位数码管WE 1;WE 0;Delay_Ms(3);
//-------------------------------DU 0;P0 table[Value%10]; //显示个位DU 1;DU 0;WE 0;P0 T_COM[2]; //第三位数码管WE 1;WE 0;Delay_Ms(3);
}
/*单总线初始化时序*/
bit ds_init()
{bit i;DS 1;_nop_();DS 0;Delay_us(75); //拉低总线499.45us 挂接在总线上的18B20将会全部被复位DS 1; //释放总线Delay_us(4); //延时37.95us 等待18B20发回存在信号i DS;Delay_us(20); //141.95usDS 1;_nop_();return (i);
}
/*写一个字节*/
void write_byte(uchar dat)
{uchar i;for(i0;i8;i){DS 0;_nop_();//产生些时序DS dat 0x01;Delay_us(10);//76.95usDS 1; //释放总线准备下一次数据写入_nop_();dat 1;}
}uchar read_byte()
{uchar i, j, dat;for(i0;i8;i){DS 0;_nop_();//产生读时序DS 1;_nop_();//释放总线j DS;Delay_us(10);//76.95usDS 1;_nop_();dat (j7)|(dat1); }return (dat);
}
void main()
{uint i;uchar L, M;
/* ds_init();//初始化DS18B20write_byte(0xcc);//发送跳跃ROM指令write_byte(0x4e);//写暂存器指令write_byte(0x7f);write_byte(0xf7);write_byte(0x1f);//配置工作在9位模式下ds_init();//初始化DS18B20write_byte(0xcc);//发送跳跃ROM指令 write_byte(0x48);*/while(1){ds_init();//初始化DS18B20write_byte(0xcc);//发送跳跃ROM指令write_byte(0x44);//发送温度转换指令ds_init();//初始化DS18B20write_byte(0xcc);//发送跳跃ROM指令write_byte(0xbe);//读取DS18B20暂存器值L read_byte();M read_byte();i M;i 8;i | L; i i * 0.0625 * 10 0.5;Display(i);}
}
2、51单片机LCD1602液晶显示
#include reg52.H
#include intrins.H
#include math.H#define uchar unsigned char#define uint unsigned intsbit dula P2^6;sbit wela P2^7;sbit rw P3^6; sbit RS P3^5; sbit LCDEN P3^4; void delayUs()
{_nop_();
}void delayMs(uint a)
{uint i, j;for(i a; i 0; i--)for(j 100; j 0; j--);}void writeComm(uchar comm)
{RS 0; P0 comm;LCDEN 1;delayUs();LCDEN 0;delayMs(1);
}//写数据:RS1, RW0;
void writeData(uchar dat)
{RS 1;P0 dat;LCDEN 1;delayUs();LCDEN 0;delayMs(1);}void init(){rw 0; dula wela 0;writeComm(0x38);writeComm(0x0c); writeComm(0x06);writeComm(0x01);
}void writeString(uchar * str, uchar length)
{uchar i;for(i 0; i length; i){writeData(str[i]);}}/**//*****************************DS18B20*******************************/sbit ds P2^2;
void dsInit(){unsigned int i; ds 0;i 100; while(i0) i--;ds 1; i 4;while(i0) i--;}void dsWait(){unsigned int i;while(ds); while(~ds);i 4;while(i 0) i--;
}bit readBit()
{unsigned int i;bit b;ds 0;i; ds 1; i; i; b ds;i 8; while(i0) i--;return b;
}unsigned char readByte()
{unsigned int i;unsigned char j, dat;dat 0;for(i0; i8; i){j readBit();dat (j 7) | (dat 1);}return dat;
}void writeByte(unsigned char dat)
{unsigned int i;unsigned char j;bit b;for(j 0; j 8; j){b dat 0x01;dat 1;if(b) {ds 0; i; i; ds 1; i 8; while(i0) i--; }else {ds 0;i 8; while(i0) i--; ds 1;i; i;}}
}void sendChangeCmd()
{dsInit(); dsWait(); delayMs(1); writeByte(0xcc);writeByte(0x44);
}void sendReadCmd()
{dsInit();dsWait();delayMs(1);writeByte(0xcc); writeByte(0xbe);
}int getTmpValue()
{unsigned int tmpvalue;int value; float t;unsigned char low, high;sendReadCmd();low readByte(); high readByte();tmpvalue high;tmpvalue 8;tmpvalue | low;value tmpvalue;\t value * 0.0625;\value t * 100 (value 0 ? 0.5 : -0.5); //大于0加0.5, 小于0减0.5return value;
}void display(int v)
{unsigned char count;unsigned char datas[] {0, 0, 0, 0, 0};unsigned int tmp abs(v);datas[0] tmp / 10000;datas[1] tmp % 10000 / 1000;datas[2] tmp % 1000 / 100;datas[3] tmp % 100 / 10;datas[4] tmp % 10;writeComm(0xc03);if(v 0){writeString(- , 2);}else{writeString( , 2);}if(datas[0] ! 0){writeData(0datas[0]);}for(count 1; count ! 5; count){writeData(0datas[count]);if(count 2){writeData(.);}}
}
/**//*****************************DS18B20*******************************/void main()
{uchar table[] xianzaiwendu: ;sendChangeCmd();init();writeComm(0x80);writeString(table, 16);while(1){delayMs(1000); //温度转换时间需要750ms以上writeComm(0xc0);display(getTmpValue());sendChangeCmd();}
}3、STM32
#include stm32f4xx_hal.h// DS18B20引脚定义
#define DS18B20_GPIO_PORT GPIOA
#define DS18B20_GPIO_PIN GPIO_PIN_0// 定义DS18B20相关命令
#define DS18B20_CMD_SKIP_ROM 0xCC
#define DS18B20_CMD_CONVERT_T 0x44
#define DS18B20_CMD_READ_SCRATCHPAD 0xBE// 函数声明
void DS18B20_DelayUs(uint32_t us);
void DS18B20_Init(void);
uint8_t DS18B20_Reset(void);
void DS18B20_WriteByte(uint8_t byte);
uint8_t DS18B20_ReadByte(void);
float DS18B20_GetTemperature(void);int main(void)
{// 初始化HAL库HAL_Init();// 初始化GPIO引脚__HAL_RCC_GPIOA_CLK_ENABLE();GPIO_InitTypeDef GPIO_InitStruct;GPIO_InitStruct.Pin DS18B20_GPIO_PIN;GPIO_InitStruct.Mode GPIO_MODE_OUTPUT_OD;GPIO_InitStruct.Pull GPIO_PULLUP;GPIO_InitStruct.Speed GPIO_SPEED_FREQ_LOW;HAL_GPIO_Init(DS18B20_GPIO_PORT, GPIO_InitStruct);while (1){// 测量温度并输出结果float temperature DS18B20_GetTemperature();printf(Temperature: %.2f°C\r\n, temperature);// 延时一段时间HAL_Delay(1000);}
}// 微秒级延时函数
void DS18B20_DelayUs(uint32_t us)
{uint32_t ticks us * (SystemCoreClock / 1000000) / 3;while (ticks--){__NOP();}
}// 初始化DS18B20
void DS18B20_Init(void)
{// 复位DS18B20DS18B20_Reset();// 发送跳过ROM命令DS18B20_WriteByte(DS18B20_CMD_SKIP_ROM);
}// 复位DS18B20并检测设备存在
uint8_t DS18B20_Reset(void)
{uint8_t presence 0;// 拉低总线HAL_GPIO_WritePin(DS18B20_GPIO_PORT, DS18B20_GPIO_PIN, GPIO_PIN_RESET);DS18B20_DelayUs(480);// 释放总线HAL_GPIO_WritePin(DS18B20_GPIO_PORT, DS18B20_GPIO_PIN, GPIO_PIN_SET);DS18B20_DelayUs(60);// 检测DS18B20响应presence HAL_GPIO_ReadPin(DS18B20_GPIO_PORT, DS18B20_GPIO_PIN);DS18B20_DelayUs(420);return presence;
}// 发送一个字节给DS18B20
void DS18B20_WriteByte(uint8_t byte)
{for (uint8_t i 0; i 8; i){// 发送低位HAL_GPIO_WritePin(DS18B20_GPIO_PORT, DS18B20_GPIO_PIN, GPIO_PIN_RESET);DS18B20_DelayUs(2);// 发送高位根据byte的第i位来决定if (byte (1 i)){HAL_GPIO_WritePin(DS18B20_GPIO_PORT, DS18B20_GPIO_PIN, GPIO_PIN_SET);}DS18B20_DelayUs(60);// 释放总线HAL_GPIO_WritePin(DS18B20_GPIO_PORT, DS18B20_GPIO_PIN, GPIO_PIN_SET);}
}// 从DS18B20读取一个字节
uint8_t DS18B20_ReadByte(void)
{uint8_t byte 0;for (uint8_t i 0; i 8; i){// 发送低位HAL_GPIO_WritePin(DS18B20_GPIO_PORT, DS18B20_GPIO_PIN, GPIO_PIN_RESET);DS18B20_DelayUs(2);// 释放总线HAL_GPIO_WritePin(DS18B20_GPIO_PORT, DS18B20_GPIO_PIN, GPIO_PIN_SET);DS18B20_DelayUs(8);// 读取高位数据if (HAL_GPIO_ReadPin(DS18B20_GPIO_PORT, DS18B20_GPIO_PIN)){byte | (1 i);}DS18B20_DelayUs(50);}return byte;
}// 读取DS18B20温度
float DS18B20_GetTemperature(void)
{DS18B20_Init();// 发送温度转换命令DS18B20_WriteByte(DS18B20_CMD_CONVERT_T);// 等待转换完成HAL_Delay(800);// 复位DS18B20并跳过ROMDS18B20_Init();// 发送读取寄存器命令DS18B20_WriteByte(DS18B20_CMD_READ_SCRATCHPAD);// 读取温度数据uint8_t tempLow DS18B20_ReadByte();uint8_t tempHigh DS18B20_ReadByte();// 计算温度值int16_t temp (tempHigh 8) | tempLow;float temperature (float)temp / 16.0f;return temperature;
}