关于网站建设的问卷调查,个人简历范文,闽侯做网站,随州最新消息内容
通过DS18B20温度传感器#xff0c;在数码管显示检测到的温度值#xff1b;
DS18B20介绍
简介
DS18B20是由DALLAS半导体公司推出的一种的“一线总线#xff08;单总线#xff09;”接口的温度传感器#xff1b;
与传统的热敏电阻等测温元件相比#xff0c;它是一…内容
通过DS18B20温度传感器在数码管显示检测到的温度值
DS18B20介绍
简介
DS18B20是由DALLAS半导体公司推出的一种的“一线总线单总线”接口的温度传感器
与传统的热敏电阻等测温元件相比它是一种新型的体积小、适用电压宽、与微处理器接口简单的数字化温度传感器
特点
DS18B20温度传感器具有如下特点
适应电压范围更宽电压范围3.05.5V在寄生电源方式下可由数据线供电温范围-55℃125℃在-1085℃时精度为±0.5℃可编程的分辨率为912位对应的可分辨温度分别为0.5℃、0.25℃、0.125℃和 0.0625℃可实现高精度测温在9位分辨率时最多在93.75ms内把温度转换为数字12位分辨率时最多在750ms内把温度值转换为数字速度更慢测量结果直接输出数字温度信号以一根总线串行传送给CPU同时可传送CRC校验码具有极强的抗干扰纠错能力负压特性电源极性接反时芯片不会因发热而烧毁但不能正常工作
结构
DS18B20一共有三个管脚当我们正对传感器切面传感器型号字符那一面时传感器的管脚顺序是从左到右排列
管脚1为GND管脚2为数据DQ管脚3为VDD
如果把传感器插反那么电源将短路传感器就会发烫很容易损坏所以一定要注意传感器方向
通常在开发板上都会标出传感器的凸起出所以只需要把传感器凸起的方向对着开发板凸起方向插入即可
DS18B20温度传感器的内部存储器包括一个高速的暂存器RAM和一个非易失性的可电擦除的EEPROM后者存放高温度和低温度触发器TH、TL和配置寄存器
配置寄存器是配置不同的位数来确定温度和数字的转化配置寄存器结构如下
TMR1R011111
低五位一直都是1TM是测试模式位用于设置DS18B20在工作模式还是在测试模式在DS18B20出厂时该位被设置为0用户不需要去改动
R1和R0用来设置DS18B20的精度分辨率可设置为91011或12位对应的分辨率温度是0.5℃0.25℃0.125℃和0.0625℃
R0和R1配置如下图 在初始状态下默认的精度是12位即R01、R11
高速暂存存储器由9个字节组成其分配如下 当温度转换命令44H发布后经转换所得的温度值以二字节补码形式存放在高速暂存存储器的第0和第1个字节
存储由两个字节组成高字节的前5位是符号位S单片机可通过单线接口读到该数据读取时低位在前高位在后数据格式如下 如果测得的温度大于0这5位为‘0’只要将测到的数值乘以0.0625默认精度是12位即可得到实际温度 如果温度小于0这5位为‘1’测到的数值需要取反加1再乘以0.0625即可得到实际温度
温度计算
温度与数据对应关系如下 比如我们要计算85度数据输出十六进制是0X0550因为高字节的高5位为0表明检测的温度是正温度0X0550对应的十进制为1360将这个值乘以12位精度0.0625所以可以得到85度
DS18B20使用
知道了怎么计算温度接下来我们就来看看如何读取温度数据
由于DS18B20是单总线器件所有的单总线器件都要求采用严格的信号时序以保证数据的完整性
DS18B20时序包括如下几种初始化时序、写0和1时序、 读0和1时序
DS18B20发送所有的命令和数据都是字节的低位在前
这里我们简单介绍这几个信号的时序
初始化时序
初始化时序图如下
单总线上的所有通信都是以初始化序列开始
主机输出低电平保持低电平时间至少480us该时间的时间范围可以从480到960us以产生复位脉冲
接着主机释放总线外部的上拉电阻将单总线拉高延时1560us并进入接收模式
接着DS18B20拉低总线60~240us以产生低电平应答脉冲若为低电平还要做延时其延时的时间从外部上拉电阻将单总线拉高算起最少要480us
写时序
写时序图如下 写时序包括写0时序和写1时序
所有写时序至少需要60us且在2次独立的写时序之间至少需要1us的恢复时间两种写时序均起始于主机拉低总线
写1时序主机输出低电平延时2us然后释放总线延时60us
写0时序主机输出低电平延时60us然后释放总线延时2us
读时序
读时序图如下 单总线器件仅在主机发出读时序时才向主机传输数据所以在主机发出读数据命令后必须马上产生读时序以便从机能够传输数据
所有读时序至少需要60us且在2次独立的读时序之间至少需要1us的恢复时间
每个读时序都由主机发起至少拉低总线1us
主机在读时序期间必须释放总线并且在时序起始后的15us之内采样总线状态
一般的读时序过程为主机输出低电平延时2us然后主机转入输入模式延时12us然后读取单总线当前的电平然后延时50us
完整过程
了解了单总线时序之后我们来看看DS18B20的温度读取过程 DS18B20的温度读取过程为复位→发SKIP ROM命令0XCC→发开始转换命令0X44→延时→复位→发送SKIP ROM命令0XCC→发读存储器命令0XBE→连续读出两个字节数据(即温度)→结束
原理图 由图可知总线连接p37口所以我们通过控制该io口的电位变化即可实现初始化以及读写时序
思路
根据时序图编写初始化、读、写程序初始化包括复位和检测DS18B20是否存在
编写检测DS18B20是否存在的程序如果信号口一直为低电位即判定为不存在
按使用步骤读取温度值转换为十进制后使其在数码管上显示
编码
User
main.c
/** Description: 通过DS18B20温度传感器在数码管显示检测到的温度值*/
#include public.h
#include smg.h
#include ds18b20.hvoid main()
{u8 i 0;int temp_value;u8 temp_buf[5];ds18b20_init(); // 初始化DS18B20while (1){i;if (i % 50 0) // 间隔一段时间读取温度值间隔时间要大于温度传感器转换温度时间12位分辨率时转换时间为750mstemp_value ds18b20_read_temperture() * 10; // 保留温度值小数后一位if (temp_value 0) // 负温度{temp_value -temp_value;temp_buf[0] 0x40; // 显示负号}elsetemp_buf[0] 0x00; // 不显示temp_buf[1] gsmg_code[temp_value / 1000]; // 百位temp_buf[2] gsmg_code[temp_value % 1000 / 100]; // 十位temp_buf[3] gsmg_code[temp_value % 1000 % 100 / 10] | 0x80; // 个位小数点temp_buf[4] gsmg_code[temp_value % 1000 % 100 % 10]; // 小数点后一位smg_display(temp_buf, 4);}
}Public
public.h
#ifndef _public_H
#define _public_H#include reg52.htypedef unsigned int u16; // 对系统默认数据类型进行重定义
typedef unsigned char u8;void delay_10us(u16 ten_us);
void delay_ms(u16 ms);#endifpublic.c
#include public.h/*** description: 延时函数ten_us1时大约延时10us* param {u16} ten_us 延时倍数* return {*}*/
void delay_10us(u16 ten_us)
{while (ten_us--);
}/**ms延时函数ms1时大约延时1ms**** param {u16} ms 延时倍数* return {*}*/
void delay_ms(u16 ms)
{u16 i, j;for (i ms; i 0; i--)for (j 110; j 0; j--);
}App/ds18b20
ds18b20.h
#ifndef _ds18b20_H
#define _ds18b20_H#include public.h// 管脚定义
sbit DS18B20_PORT P3 ^ 7; // DS18B20数据口定义// 函数声明
u8 ds18b20_init(void);
float ds18b20_read_temperture(void);#endifds18b20.c
#include ds18b20.h
#include intrins.h/*** description: 复位DS18B20* return {*}*/
void ds18b20_reset(void)
{DS18B20_PORT 0; // 拉低DQdelay_10us(75); // 拉低750usDS18B20_PORT 1; // DQ1delay_10us(2); // 20US
}/*** description: 检测DS18B20是否存在* return {u8} 1:未检测到DS18B20的存在0:存在*/
u8 ds18b20_check(void)
{u8 time_temp 0;while (DS18B20_PORT time_temp 20) // 等待DQ为低电平{time_temp;delay_10us(1);}if (time_temp 20)return 1; // 如果超时则强制返回1elsetime_temp 0;while ((!DS18B20_PORT) time_temp 20) // 等待DQ为高电平{time_temp;delay_10us(1);}if (time_temp 20)return 1; // 如果超时则强制返回1return 0;
}/*** description: 从DS18B20读取一个位* return {u8} 1/0*/
u8 ds18b20_read_bit(void)
{u8 dat 0;DS18B20_PORT 0;_nop_();_nop_();DS18B20_PORT 1;_nop_();_nop_(); // 该段时间不能过长必须在15us内读取数据if (DS18B20_PORT)dat 1; // 如果总线上为1则数据dat为1否则为0elsedat 0;delay_10us(5);return dat;
}/*** description: 从DS18B20读取一个字节* return {u8} 一个字节数据*/
u8 ds18b20_read_byte(void)
{u8 i 0;u8 dat 0;u8 temp 0;for (i 0; i 8; i) // 循环8次每次读取一位且先读低位再读高位{temp ds18b20_read_bit();dat (temp 7) | (dat 1);}return dat;
}/*** description: 写一个字节到DS18B20* param {u8} dat 要写入的字节* return {*}*/
void ds18b20_write_byte(u8 dat)
{u8 i 0;u8 temp 0;for (i 0; i 8; i) // 循环8次每次写一位且先写低位再写高位{temp dat 0x01; // 选择低位准备写入dat 1; // 将次高位移到低位if (temp){DS18B20_PORT 0;_nop_();_nop_();DS18B20_PORT 1;delay_10us(6);}else{DS18B20_PORT 0;delay_10us(6);DS18B20_PORT 1;_nop_();_nop_();}}
}/*** description: 开始温度转换* return {*}*/
void ds18b20_start(void)
{ds18b20_reset(); // 复位ds18b20_check(); // 检查DS18B20ds18b20_write_byte(0xcc); // SKIP ROMds18b20_write_byte(0x44); // 转换命令
}/*** description: 初始化DS18B20的IO口DQ同时检测DS的存在* return {u8} 1:不存在0:存在*/
u8 ds18b20_init(void)
{ds18b20_reset();return ds18b20_check();
}/*** description: 从ds18b20得到温度值* return {float} 温度数据*/
float ds18b20_read_temperture(void)
{float temp;u8 dath 0;u8 datl 0;u16 value 0;ds18b20_start(); // 开始转换ds18b20_reset(); // 复位ds18b20_check();ds18b20_write_byte(0xcc); // SKIP ROMds18b20_write_byte(0xbe); // 读存储器datl ds18b20_read_byte(); // 低字节dath ds18b20_read_byte(); // 高字节value (dath 8) datl; // 合并为16位数据if ((value 0xf800) 0xf800) // 判断符号位负温度{value (~value) 1; // 数据取反再加1temp value * (-0.0625); // 乘以精度}else // 正温度{temp value * 0.0625;}return temp;
}App/smg
smg.h
#ifndef _smg_H
#define _smg_H#include public.h#define SMG_A_DP_PORT P0 // 使用宏定义数码管段码口// 定义数码管位选信号控制脚
sbit LSA P2 ^ 2;
sbit LSB P2 ^ 3;
sbit LSC P2 ^ 4;extern u8 gsmg_code[17]; // 使“共阴极数码管显示0~F的段码数据”这个变量定义为外部可用void smg_display(u8 dat[], u8 pos);#endifsmg.c
#include smg.h// 共阴极数码管显示0~F的段码数据
u8 gsmg_code[17] {0x3f, 0x06, 0x5b, 0x4f, 0x66, 0x6d, 0x7d, 0x07, 0x7f, 0x6f, 0x77, 0x7c, 0x39, 0x5e, 0x79, 0x71};/*** description: 动态数码管显示函数* param {u8} dat 要显示的数据* param {u8} pos 从左开始第几个位置开始显示范围1-8* return {*}*/
void smg_display(u8 dat[], u8 pos)
{u8 i 0;u8 pos_temp pos - 1;for (i pos_temp; i 8; i){switch (i) // 位选{case 0:LSC 1;LSB 1;LSA 1;break;case 1:LSC 1;LSB 1;LSA 0;break;case 2:LSC 1;LSB 0;LSA 1;break;case 3:LSC 1;LSB 0;LSA 0;break;case 4:LSC 0;LSB 1;LSA 1;break;case 5:LSC 0;LSB 1;LSA 0;break;case 6:LSC 0;LSB 0;LSA 1;break;case 7:LSC 0;LSB 0;LSA 0;break;}SMG_A_DP_PORT dat[i - pos_temp]; // 传送段选数据delay_10us(100); // 延时一段时间等待显示稳定SMG_A_DP_PORT 0x00; // 消影}
}编译和结果
按F7编译无错误生成.hex文件使用pz-isp将hex文件下载到单片机
结果显示检测到的温度