文章目录
- 前言
- 一、单总线
- 二、DS18B20温度读取
- 三、主函数
前言
上节中对 “DS18B20” 进行初步的介绍,,本节则是对其的基本应用之一。
在实例应用之前需要先了解一下“单总线”
一、单总线
简介
- 单总线(1-Wire BUS)是由Dallas公司开发的一种通用数据总线
- —根通信线︰DQ
- 异步、半双工
- 单总线只需要一根通信线即可实现数据的双向传输,当采用寄生供电时,还可以省去设备的VDD线路,此时,供电加通信只需要DQ和GND两根线
电路规范
- 设备的DQ均要配置成开漏输出模式
- DQ添加一个上拉电阻,阻值一般为4.7KQ左右
- 若此总线的从机采取寄生供电,则主机还应配一个强上拉输出电路
时序结构
初始化︰ 主机将总线拉低至少480us,然后释放总线,等待15~ 60us后,存在的从机会拉低总线60~240us以响应主机,之后从机将释放总线
unsigned char OneWire_Init(void)
{unsigned char i;unsigned char AckBit;EA=0;OneWire_DQ=1;OneWire_DQ=0;i = 247;while (--i); //Delay 500usOneWire_DQ=1;i = 32;while (--i); //Delay 70usAckBit=OneWire_DQ;i = 247;while (--i); //Delay 500usEA=1;return AckBit;
}
发送一位︰ 主机将总线拉低60~ 120us,然后释放总线,表示发送0;主机将总线拉低1~15us,然后释放总线,表示发送1。从机将在总线拉低30us后(典型值)读取电平,整个时间片应大于60us
void OneWire_SendBit(unsigned char Bit)
{unsigned char i;EA=0;OneWire_DQ=0;i = 4;while (--i); //Delay 10usOneWire_DQ=Bit;i = 24;while (--i); //Delay 50usOneWire_DQ=1;EA=1;
}
接收一位︰ 主机将总线拉低1~15us,然后释放总线,并在拉低后15us内读取总线电平((尽量贴近15us的末尾),读取为低电平则为接收0,读取为高电平则为接收1,整个时间片应大于60us
unsigned char OneWire_ReceiveBit(void)
{unsigned char i;unsigned char Bit;EA=0;OneWire_DQ=0;i = 2;while (--i); //Delay 5usOneWire_DQ=1;i = 2;while (--i); //Delay 5usBit=OneWire_DQ;i = 24;while (--i); //Delay 50usEA=1;return Bit;
}
发送一个字节
void OneWire_SendByte(unsigned char Byte)
{unsigned char i;for(i=0;i<8;i++){OneWire_SendBit(Byte&(0x01<<i));}
}
接收一个字节
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;
}
二、DS18B20温度读取
//DS18B20指令
#define DS18B20_SKIP_ROM 0xCC
#define DS18B20_CONVERT_T 0x44
#define DS18B20_READ_SCRATCHPAD 0xBE/*** @brief DS18B20开始温度变换* @param 无* @retval 无*/
void DS18B20_ConvertT(void)
{OneWire_Init();OneWire_SendByte(DS18B20_SKIP_ROM);OneWire_SendByte(DS18B20_CONVERT_T);
}/*** @brief DS18B20读取温度* @param 无* @retval 温度数值*/
float DS18B20_ReadT(void)
{unsigned char TLSB,TMSB;int Temp;float T;OneWire_Init();OneWire_SendByte(DS18B20_SKIP_ROM); OneWire_SendByte(DS18B20_READ_SCRATCHPAD); TLSB=OneWire_ReceiveByte();TMSB=OneWire_ReceiveByte();Temp=(TMSB<<8)|TLSB;T=Temp/16.0;return T;
}
三、主函数
以下涉及到的AT24C02在前几节介绍IIC时 已有提交,了解详情请移步 “IIC 协议”
void main()
{DS18B20_ConvertT(); //上电先转换一次温度,防止第一次读数据错误Delay(1000); //等待转换完成THigh=AT24C02_ReadByte(0); //读取温度阈值数据TLow=AT24C02_ReadByte(1);if(THigh>125 || TLow<-55 || THigh<=TLow){THigh=20; //如果阈值非法,则设为默认值TLow=15;}LCD_Init();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);Timer0_Init();while(1){KeyNum=Key();/*温度读取及显示*/DS18B20_ConvertT(); //转换温度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(KeyNum){if(KeyNum==1) //K1按键,THigh自增{THigh++;if(THigh>125){THigh=125;}}if(KeyNum==2) //K2按键,THigh自减{THigh--;if(THigh<=TLow){THigh++;}}if(KeyNum==3) //K3按键,TLow自增{TLow++;if(TLow>=THigh){TLow--;}}if(KeyNum==4) //K4按键,TLow自减{TLow--;if(TLow<-55){TLow=-55;}}LCD_ShowSignedNum(2,4,THigh,3); //显示阈值数据LCD_ShowSignedNum(2,12,TLow,3);AT24C02_WriteByte(0,THigh); //写入到At24C02中保存Delay(5);AT24C02_WriteByte(1,TLow);Delay(5);}if(T>THigh) //越界判断{LCD_ShowString(1,13,"OV:H");}else if(T<TLow){LCD_ShowString(1,13,"OV:L");}else{LCD_ShowString(1,13," ");}}
}void Timer0_Routine() interrupt 1
{static unsigned int T0Count;TL0 = 0x18; //设置定时初值TH0 = 0xFC; //设置定时初值T0Count++;if(T0Count>=20){T0Count=0;Key_Loop(); //每20ms调用一次按键驱动函数}
}