一、前言
????????使用LCD1602实时显示DS18B20传感器捕抓的环境温度。
二、概述
(一)传感器说明
????????DS18B20数字温度计提供9位温度读数。信息经过单线接口送入或送出DS18B20传感器,因此从中央处理器到DS18B20仅需要提供电源以及一根数据线,就可以工作。
(二)DS18B20的ROM指令表
ROM 指令表
指令 | 约定代码 | 功能 |
---|
读ROM | 33H | 读取DS18B20温度传感器ROM中的编码(即64位地址) | 符合ROM | 55H | 发送此命令之后,接着发出64位ROM编码,访问单总线上与该编码相对应的DS18B20使用之作出响应,为下一步对该DS18B20的读写作准备 | 搜索ROM | F0H | 用于确定挂接在同一总线上DS18B20的个数和识别64位ROM地址,为操作各器件作好准备 | 跳过ROM | C0H | 忽略64位ROM地址,直接向DS18B20发温度变换命令,适用于单片工作。 | 告警搜索 | ECH | 执行后只有温度超过设定值上限或下限才能做出响应 |
(三)DS18B20的RAM指令表
RAM 指令表
指令 | 约定代码 | 功能 |
---|
温度变换 | 44H | 启动DS18B20进行温度转换 | 读暂存器 | BEH | 读内部RAM中9字节的内容 | 写暂存器 | 4EH | 发出向内部RAM的3、4字节写上、下限温度数据命令,紧跟该命令后,是传送两字节的数据 | 复制暂存器 | 48H | 将RAM中的第3、4字节的内容复制到EEPROM中 | 重调EEPROM | E8H | 将EEPROM中内容恢复到RAM中的第3、4字节 | 读供电方式 | B4H | 读DS18B20供电模式,寄生供电时为‘0’,外接电源供电时为’1‘ |
三、DS18B20单总线协议
1、DS18B20初始化
(1) 数据线拉到低电平“0”。
(2) 延时480微妙(该时间的时间范围可以从480到960微妙)。
(3)?数据线拉到高电平“1”。
(4) 延时等待80微妙。如果初始化成功则在15到60微妙时间内产生一个由DS18B20所返回的低电平“0”.根据该状态可以来确定它的存在,但是应注意不能无限的进行等待,不然会使程序进入死循环,所以要进行超时判断。
(5) 若CPU读到了数据线上的低电平“0”后,还要做延时,其延时的时间从发出的高电平算起(第3步的时间算起)最少要480微妙。
2、读时序
(1) 将数据线拉低“0”。
(2) 延时1微妙。
(3) 将数据线拉高“1”,释放总线准备读数据。
(4) 延时10微妙。 //等待数据稳定
(5) 读数据线的状态得到1个状态位,并进行数据处理。
(6) 延时45微妙。
(7) 重复1~7步骤,直到读完一个字节。
3、写时序
(1) 数据线先置低电平“0”
(2) 延时15微妙。
(3) 按从低位到高位的顺序发送数据(一次只发送一位)。
(4) 延时60微妙。
(5) 将数据线拉到高电平。
(6) 重复1~5步骤,直到发送完整的字节。
(7) 最后将数据线拉高。
四、硬件连接
?
五、程序例程
1、DS18B20.c文件
#include "ds18b20.h"
/*******************************************************************************
* 函 数 名 : DS18B20_IO_IN
* 函数功能 : DS18B20_IO输入配置
* 输 入 : 无
* 输 出 : 无
*******************************************************************************/
void DS18B20_IO_IN(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Pin=DS18B20_PIN;
GPIO_InitStructure.GPIO_Mode=GPIO_Mode_IPU;
GPIO_Init(DS18B20_PORT,&GPIO_InitStructure);
}
/*******************************************************************************
* 函 数 名 : DS18B20_IO_OUT
* 函数功能 : DS18B20_IO输出配置
* 输 入 : 无
* 输 出 : 无
*******************************************************************************/
void DS18B20_IO_OUT(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Pin=DS18B20_PIN;
GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode=GPIO_Mode_Out_PP;
GPIO_Init(DS18B20_PORT,&GPIO_InitStructure);
}
/*******************************************************************************
* 函 数 名 : DS18B20_Reset
* 函数功能 : 复位DS18B20
* 输 入 : 无
* 输 出 : 无
*******************************************************************************/
void DS18B20_Reset(void)
{
DS18B20_IO_OUT(); //SET PG11 OUTPUT
DS18B20_DQ_OUT=0; //拉低DQ
delay_us(750); //拉低750us
DS18B20_DQ_OUT=1; //DQ=1
delay_us(15); //15US
}
/*******************************************************************************
* 函 数 名 : DS18B20_Check
* 函数功能 : 检测DS18B20是否存在
* 输 入 : 无
* 输 出 : 1:未检测到DS18B20的存在,0:存在
*******************************************************************************/
u8 DS18B20_Check(void)
{
u8 retry=0;
DS18B20_IO_IN();//SET PG11 INPUT
while (DS18B20_DQ_IN&&retry<200)
{
retry++;
delay_us(1);
};
if(retry>=200)
return 1;
else
retry=0;
while (!DS18B20_DQ_IN&&retry<240)
{
retry++;
delay_us(1);
};
if(retry>=240)
return 1;
return 0;
}
/*******************************************************************************
* 函 数 名 : DS18B20_Read_Bit
* 函数功能 : 从DS18B20读取一个位
* 输 入 : 无
* 输 出 : 1/0
*******************************************************************************/
u8 DS18B20_Read_Bit(void) // read one bit
{
u8 data;
DS18B20_IO_OUT();//SET PG11 OUTPUT
DS18B20_DQ_OUT=0;
delay_us(2);
DS18B20_DQ_OUT=1;
DS18B20_IO_IN();//SET PG11 INPUT
delay_us(12);
if(DS18B20_DQ_IN)
data=1;
else
data=0;
delay_us(50);
return data;
}
/*******************************************************************************
* 函 数 名 : DS18B20_Read_Byte
* 函数功能 : 从DS18B20读取一个字节
* 输 入 : 无
* 输 出 : 一个字节数据
*******************************************************************************/
u8 DS18B20_Read_Byte(void) // read one byte
{
u8 i,j,dat;
dat=0;
for (i=1;i<=8;i++)
{
j=DS18B20_Read_Bit();
dat=(j<<7)|(dat>>1);
}
return dat;
}
/*******************************************************************************
* 函 数 名 : DS18B20_Write_Byte
* 函数功能 : 写一个字节到DS18B20
* 输 入 : dat:要写入的字节
* 输 出 : 无
*******************************************************************************/
void DS18B20_Write_Byte(u8 dat)
{
u8 j;
u8 testb;
DS18B20_IO_OUT();//SET PG11 OUTPUT;
for (j=1;j<=8;j++)
{
testb=dat&0x01;
dat=dat>>1;
if (testb)
{
DS18B20_DQ_OUT=0;// Write 1
delay_us(2);
DS18B20_DQ_OUT=1;
delay_us(60);
}
else
{
DS18B20_DQ_OUT=0;// Write 0
delay_us(60);
DS18B20_DQ_OUT=1;
delay_us(2);
}
}
}
/*******************************************************************************
* 函 数 名 : DS18B20_Start
* 函数功能 : 开始温度转换
* 输 入 : 无
* 输 出 : 无
*******************************************************************************/
void DS18B20_Start(void)// ds1820 start convert
{
DS18B20_Reset();
DS18B20_Check();
DS18B20_Write_Byte(0xcc);// skip rom
DS18B20_Write_Byte(0x44);// convert
}
/*******************************************************************************
* 函 数 名 : DS18B20_Init
* 函数功能 : 初始化DS18B20的IO口 DQ 同时检测DS的存在
* 输 入 : 无
* 输 出 : 1:不存在,0:存在
*******************************************************************************/
u8 DS18B20_Init(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd(DS18B20_PORT_RCC,ENABLE);
GPIO_PinRemapConfig(GPIO_Remap_SWJ_Disable,ENABLE);
GPIO_InitStructure.GPIO_Pin=DS18B20_PIN;
GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode=GPIO_Mode_Out_PP;
GPIO_Init(DS18B20_PORT,&GPIO_InitStructure);
DS18B20_Reset();
return DS18B20_Check();
}
/*******************************************************************************
* 函 数 名 : DS18B20_GetTemperture
* 函数功能 : 从ds18b20得到温度值
* 输 入 : 无
* 输 出 : 温度数据
*******************************************************************************/
float DS18B20_GetTemperture(void)
{
u16 temp;
u8 a,b;
float value;
DS18B20_Start(); // ds1820 start convert
DS18B20_Reset();
DS18B20_Check();
DS18B20_Write_Byte(0xcc);// skip rom
DS18B20_Write_Byte(0xbe);// convert
a=DS18B20_Read_Byte(); // LSB
b=DS18B20_Read_Byte(); // MSB
temp=b;
temp=(temp<<8)+a;
if((temp&0xf800)==0xf800)
{
temp=(~temp)+1;
value=temp*(-0.0625);
}
else
{
value=temp*0.0625;
}
return value;
}
2、主函数
int main(void)
{
float temper = 0.0;
char display_temp[20] = {0};
Usart1_Pin_Init(115200);
printf("初始化成功\r\n");
Sys_Delay_Init();
Lcd1602_Init();
DS18B20_Init();
delay_ms(50);
while(1)
{
temper=DS18B20_GetTemperture();
if(temper<0)
{
printf("检测的温度为:-");
}
else
{
printf("检测的温度为: ");
}
printf("%.2f°C\r\n",temper);
sprintf(display_temp,"TEMP:%.3f",temper);
Lcd1602_DisplayString(1,1,(u8 *)display_temp); //显示温度值
}
}
六、实验结果
?
相关程序和资料,有需要者自行下载
网盘链接:
? ??????链接:https://pan.baidu.com/s/1kW9866jJ9AQYM4YLc1kEUw? ????????提取码:o3m4
?如有什么问题欢迎指出来,有什么模块可以联系博主,博主会查询资料分享出来。
|