一、实验的基本功能:
1.实现温度报警功能系统,通过DS18B20温度传感芯片
2.实现功能:随时监控传感周边的温度,并且设置最高温度,当达到阈值蜂鸣器报警
二、实现大概内容如下:
1.熟悉DS18B20芯片工作状态,如:DS18B20d的储存器
2.熟悉DS18B20与单片机的单总线通信(one-wire),比如:one-wire通信时序,ROM、功能指
3.熟悉蜂鸣器的工作状态
4.主要过程:由DS18B20实时监控温度变换,得到的Float传给单片机,单片机通过LCD1602显示数值。
通过单片机给DS18B20传达设置最高温度,达到阈值蜂鸣器报警
三、DS18B20芯片的知识
1.DS18B20内部结构

·BIT ROM: 作为器件储存地址,用于总线通信的寻址(与暂存器对接),当有很多暂存器,就要寻址
·SCRATCHPD:暂存器,用于总线数据交
·EEPROM:用于保存温度触发阈值和配置参数
2.DS18B20储存器件

·Byte0 ~ Byte1:读取有效值,与总线进行交流(掉电丢失)
·Byte2 ~ Byte3:保存温读触发的阈值和配置参数
·Byte4 ~ Byte7:保留位
·Byte8:检验位
3.DS18B20通信的时序定义
初始化信号

·主机总线拉低至480us,释放总线,等待60us,从机会拉低240us以响应主机,之后从机将释放总线
发送信号

·主机总线拉低至60u ~ 120us,释放总线,表示发送0。
·主机总线拉低至1u ~ 15us,释放总线,表示发送1。
·从机将在总线拉低30us后,读取1电平,整个时间大于60us
·需要注意的是:不是最后单元的低或高电平代表0/1,而是一个过程代表0/1
接收信号

·主机总线拉低至1u ~ 15us,然后释放总线,并在拉低电平15us内读取总线电平,读取低电平就是0,高电平就是1
四、OneWire通信功能实现的功能函数
unsigned char OneWire_Init(void); //OneWire通信开始信号
void OneWire_sendBit(unsigned char Bit); //OneWire发送一个bit的传输
unsigned char OneWire_ReceiveBit(void); //OneWire接收一个bit的传输
void OneWire_SendByte(unsigned char Byte); //OneWire发送一个字节通信
unsigned char OneWire_ReceiveByte(void); //OneWire接收一个字节通信
void DS18B20_Convert(void); //改变改变温度转换命令
float DS18B20_ReadT(void); //读取DS18B20的温度命令
五、配置单总线通信(one-wire)的代码演示及解释
1.端口的调用和地址的重置命名
sbit OneWire_DQ = P3^7;
#define DS18B20_SKIP_ROM 0xCC
#define DS18B20_CONVERT_T 0x44
#define DS18B20_READ_SCRATCHPAD 0xBE
·命令指令:
DS18B20_SKIP_ROM 跳过寻址指令
DS18B20_CONVERT_T 改变变寄存器的温度指令
DS18B20_READ_SCRATCHPAD 读取寄存器的温度
2.OneWire通信开始信号
unsigned char OneWire_Init(void)
{
unsigned char i;
unsigned char AckBit;
OneWire_DQ = 1; //释放总线
OneWire_DQ = 0; //总线拉低至480us
i = 218;while (--i); //@11.0592 500us
OneWire_DQ = 1; //释放总线,等待60us,从机会拉低240us以响应主机(无需关心,是硬件拉低)
i = 29;while (--i); //@11.0592 70us
AckBit = OneWire_DQ; //获取响应的低电平
i = 218;while (--i); //@11.0592 500us
return AckBit;
}
·整根据通信时序拉低时序即可,需要注意的是硬件会发高电平信号,进行接收
3.OneWire发送一个bit的传输
void OneWire_sendBit(unsigned char Bit)
{
unsigned char i;
OneWire_DQ = 0; //将总线拉低
i = 3;while (--i); //@11.0592 10us
OneWire_DQ = Bit; //对总线赋值0/1
i = 22;while (--i); //当发送0时,10+50us,才释放总线,发送为0,当发送1是,总线被拉低10us,释放总线
OneWire_DQ = 1; //@11.0592 50us
}
·该函数不同if语句,1为15s以内,0为60s以内,所以在10s后,将传值bit赋给OneWire。
如果是0就是继续拉低,如果是1就是已经在15以内拉低,表示1。
4.OneWire接收一个bit的传输
unsigned char OneWire_ReceiveBit(void)
{
unsigned char i;
unsigned char Bit;
OneWire_DQ = 0; //拉低5us
i = 1;while (--i); //@11.0592 5us
OneWire_DQ = 1; //释放总线
i = 1;while (--i); //@11.0592 5us
Bit = OneWire_DQ; //读取总线电平,硬件怎么发送信号的无需关心
i = 22;while (--i); //拉低
return Bit;
}
·主机总线拉低至1u ~ 15us,然后释放总线,并在拉低电平15us内读取总线电平。
·硬件是怎么发送电平的无需关心,只发送一位bit0/1
5.OneWire发送一个字节通信
void OneWire_SendByte(unsigned char Byte)
{
unsigned char i;
for(i=0;i<8;i++)
{
OneWire_sendBit(Byte&(0x01<<i));
}
}
·将Byte一位一位取出,先考虑的是先取高位还是低位
·“&”bit&1是1就是1,是0就是0
·取每一位<<,>>将0x01进行移位
6.OneWire接收一个字节通信
unsigned char OneWire_ReceiveByte(void)
{
unsigned char i;
unsigned char Byte = 0x00;
for(i=0;i<8;i++)
{
if(OneWire_ReceiveBit())
{
Byte |= (0x01<<i);
}
}
return Byte;
}
·接收0/1组成Byte,通过if的布尔类型,0/1而进入下一步
·“|”的功能byte|=(0x01<<i),或运算,也就是说进入if就为对应位赋值1
7.改变改变温度转换命令
void DS18B20_Convert(void)
{
OneWire_Init(); //通信初始化
OneWire_SendByte(DS18B20_SKIP_ROM);//发送跳过ROM寻址指令
OneWire_SendByte(DS18B20_CONVERT_T);//发送功能指令,改变温度转换
}
8.读取DS18B20的温度命令
float DS18B20_ReadT(void)
{
unsigned char TLSB,TMSB;
int Temp;
float T;
OneWire_Init(); //通信初始化
OneWire_SendByte(DS18B20_SKIP_ROM); //发送跳过ROM寻址指令
OneWire_SendByte(DS18B20_READ_SCRATCHPAD ); //发送功能指令,读取温度
TLSB = OneWire_ReceiveByte(); //接收前一个字节
TMSB = OneWire_ReceiveByte(); //接收第二个字节
Temp = (TMSB<<8)|TLSB; //整合温度数据
T = Temp/16.0;
return T;
}
七、mian函数运行
#include "Onewire.h"
#include "LCD1602.h"
#include <REGX52.H>
#include "Delay.h"
#include "Buzzer.h"
#include "I2C.H"
float T,TShow;
char TLow,THigh;
unsigned char KeyNum;
void main()
{
DS18B20_Convert();
Delay(1000);
LCD_Init();
THigh=AT24C02_ReadByte(0); //读取温度阈值数据
TLow=AT24C02_ReadByte(1);
if(THigh>125 || TLow<-55 || THigh<=TLow)
{
THigh=20; //如果阈值非法,则设为默认值
TLow=15;
}
LCD_ShowString(1,1,"T:");
LCD_ShowString(2,1,"TH:");
LCD_ShowString(2,9,"TL:");
LCD_ShowSignedNum(2,4,THigh,3);
LCD_ShowSignedNum(2,12,TLow,3);
while(1)
{
DS18B20_Convert();
T = DS18B20_ReadT();
//显示数据格式
if(T<0) //如果温度小于0
{
LCD_ShowChar(1,3,'-'); //显示负号
TShow=-T; //将温度变为正数
}
else //如果温度大于等于0
{
LCD_ShowChar(1,3,'+'); //显示正号
TShow=T;
}
LCD_ShowNum(1,4,TShow,3); //显示温度整数部分
LCD_ShowChar(1,7,'.'); //显示小数点
LCD_ShowNum(1,8,(unsigned long)(TShow*100)%100,2);//显示温度小数部分
if(T>THigh) //越界判断
{
LCD_ShowString(1,13,"OV:H");
Buzzer_Time(100);
}
else if(T<TLow)
{
LCD_ShowString(1,13,"OV:L");
Buzzer_Time(100);
}
else
{
LCD_ShowString(1,13," ");
}
}
}