写在最前面:纯自用笔记,综合了很多资料,搞一个最精简最应试的,加油我只能说
【常用传感器】DS18B20温度传感器原理详解及例程代码_ds18b20温度传感器工作原理-CSDN博客
上面这个链接比本篇更具有可读性
引用功能介绍
传感器参数
- 测温范围为-55℃到+125℃,在-10℃到+85℃范围内误差为±0.4°。
- 返回16位二进制温度数值
- 主机和从机通信使用单总线,即使用单线进行数据的发送和接收
- 在使用中不需要任何外围元件,独立芯片即可完成工作。
- 掉电保护功能 DS18B20 内部含有 EEPROM ,通过配置寄存器可以设定数字转换精度和报警温度,在系统掉电以后,它仍可保存分辨率及报警温度的设定值。
- 每个DS18B20都有独立唯一的64位-ID,此特性决定了它可以将任意多的DS18b20挂载到一根总线上,通过ROM搜索读取相应DS18B20的温度值
- 宽电压供电,电压2.5V~5.5V
- DS18B20返回的16位二进制数代表此刻探测的温度值,其高五位代表正负。如果高五位全部为1,则代表返回的温度值为负值。如果高五位全部为0,则代表返回的温度值为正值。后面的11位数据代表温度的绝对值,将其转换为十进制数值之后,再乘以0.0625即可获得此时的温度值。
(原文链接:https://blog.csdn.net/as480133937/article/details/112604303)
底层
代码指令
芯片包资料(底层读写函数)
//芯片包自带底层
#include "onewire.h"
#include "reg52.h"
sbit DQ = P1^4;
//单总线内部延时函数
void Delay_OneWire(unsigned int t)
{
t *= 12; //存疑(12T时需要,1T时不需要)
while(t--);
}
//单总线写操作
void Write_DS18B20(unsigned char dat)
{
unsigned char i;
for(i=0;i<8;i++)
{
DQ = 0;
DQ = dat&0x01; //与1按位与运算,dat最低位为1时DQ总线为1,dat最低位为0时DQ总线为0
Delay_OneWire(5);
DQ = 1;
dat >>= 1;
}
Delay_OneWire(5);
}
//单总线读操作
unsigned char Read_DS18B20(void)
{
unsigned char i;
unsigned char dat;
for(i=0;i<8;i++)
{
DQ = 0;
dat >>= 1;
DQ = 1;
if(DQ)
{
dat |= 0x80;
}
Delay_OneWire(5);
}
return dat;
}
//DS18B20初始化
bit init_ds18b20(void)
{
bit initflag = 0;
DQ = 1;
Delay_OneWire(12);
DQ = 0;
Delay_OneWire(80);
DQ = 1;
Delay_OneWire(10);
initflag = DQ;
Delay_OneWire(5);
return initflag;
}
调用函数
需要自己写的部分,(和底层代码都放在1-Wire.c里,背住)
读时序时是先读低字节,在读高字节,也就是先读取高速暂存器的第0个字节(温度的低8位),再读取高速暂存器的第1个字节(温度的高8位) 我们正常使用DS18B20读取温度读取两个温度字节即可
/**
* @brief介绍 读取温度函数,完成温度转换,并返回转换后的温度数据
* @param参数 无
* @retval返回值 温度高低两个字节 浮点数
*/
float read_t()
{
unsigned int low,high; //返回的温度数据的高低八位
float temprature;
//温度变换
init_ds18b20(); //初始化
Write_DS18B20(0xcc); //跳过ROM
Write_DS18B20(0x44); //进行温度转换
//温度读取
init_ds18b20(); //初始化
Write_DS18B20(0xcc); //跳过ROM
Write_DS18B20(0xbe); //读取温度
low = Read_DS18B20(); //读取低位
high = Read_DS18B20(); //读取高位
temprature = ((high << 8) | low) / 16.0; //代码bug,没考虑负数补码,所以负数温度读取不准确,需要另加标志位
return temprature; //存疑
}
//转载其他博主对于补码的处理
unsigned int Templ,Temp2,Temperature; //Templ低八位,Temp2高八位
unsigned char Minus Flag=0; //负温度标志位
if(Tenp2&0xFC)//判断符号位是否为1
{
Minus Flag=l; //负温度标志位置1
Temperature=((Temp2<<8)|Temp1); //高八位第八位进行整合
Temperature=((Temperature)+1); //讲补码转换为原码,求反,补1
Temperature*=0.0625;//求出十进制
}
else //温度为正值
{
Minus Flag=0; //负温度标志位置0
Temperature =((Temp2<<8) |Temp1)*0.0625;
原文链接:https://blog.csdn.net/as480133937/article/details/112604303
main.c
/* 头文件声明区 */
#include <STC15F2K60S2.H>//单片机寄存器专用头文件
#include <Init.h>//初始化底层驱动专用头文件
#include <Led.h>//Led底层驱动专用头文件
#include <Key.h>//按键底层驱动专用头文件
#include <Seg.h>//数码管底层驱动专用头文件
#include "onewire.h" //√
/* 变量声明区 */
unsigned char Key_Val,Key_Down,Key_Old,Key_Up;//按键专用变量
unsigned char Key_Slow_Down;//按键减速专用变量
unsigned char Seg_Buf[8] = {10,10,10,10,10,10,10,10};//数码管显示数据存放数组
unsigned char Seg_Point[8] = {0,0,0,0,0,0,0,0};//数码管小数点数据存放数组
unsigned char Seg_Pos;//数码管扫描专用变量
unsigned int Seg_Slow_Down;//数码管减速专用变量
unsigned char ucLed[8] = {0,0,0,0,0,0,0,0};//Led显示数据存放数组
float t; //√
/* 键盘处理函数 */
void Key_Proc()
{
if(Key_Slow_Down) return;
Key_Slow_Down = 1;//键盘减速程序
Key_Val = Key_Read();//实时读取键码值
Key_Down = Key_Val & (Key_Old ^ Key_Val);//捕捉按键下降沿
Key_Up = ~Key_Val & (Key_Old ^ Key_Val);//捕捉按键上降沿
Key_Old = Key_Val;//辅助扫描变量
}
/* 信息处理函数 */
void Seg_Proc()
{
if(Seg_Slow_Down) return;
Seg_Slow_Down = 1;//数码管减速程序
t = read_t(); //√
Seg_Buf[0] = (unsigned char)t / 10 % 10; //23.7 在第一格数码管显示第十位(t为浮点数,需要强制类型转换之后再把变量赋值给Seg_Buf[])
Seg_Buf[1] = (unsigned char)t % 10; //23.7 个位
Seg_Buf[2] = (unsigned int)(t * 10) % 10; //23.7 小数部分第一位
}
/* 其他显示函数 */
void Led_Proc()
{
}
/* 定时器0中断初始化函数 */
void Timer0Init(void) //1毫秒@12.000MHz
{
AUXR &= 0x7F; //定时器时钟12T模式
TMOD &= 0xF0; //设置定时器模式
TL0 = 0x18; //设置定时初始值
TH0 = 0xFC; //设置定时初始值
TF0 = 0; //清除TF0标志
TR0 = 1; //定时器0开始计时
ET0 = 1; //定时器中断0打开
EA = 1; //总中断打开
}
/* 定时器0中断服务函数 */
void Timer0Server() interrupt 1
{
if(++Key_Slow_Down == 10) Key_Slow_Down = 0;//键盘减速专用
if(++Seg_Slow_Down == 500) Seg_Slow_Down = 0;//数码管减速专用
if(++Seg_Pos == 8) Seg_Pos = 0;//数码管显示专用
Seg_Disp(Seg_Pos,Seg_Buf[Seg_Pos],Seg_Point[Seg_Pos]);
Led_Disp(Seg_Pos,ucLed[Seg_Pos]);
}
void Delay750ms() //@12.000MHz
{
unsigned char i, j, k;
i = 35;
j = 51;
k = 182;
do
{
do
{
while (--k);
} while (--j);
} while (--i);
}
/* Main */
void main()
{
read_t(); //避免上电温度显示85 //√
Delay750ms(); //延时750ms,因为第一次运行转换的周期就是750ms //√
System_Init();
Timer0Init();
while (1)
{
Key_Proc();
Seg_Proc();
Led_Proc();
}
}