使用寄生电源时,由于上拉电阻电阻较大,需要给这个电源高电压(强上拉)才能使DS18B02工作,本次案例不用使用。
OneWire.c
#include
#include
// 定义接口
sbit OneWire_IO = P3^7;
// 初始化单总线
unsigned char OneWire_Init(){
unsigned char i,ACK;
// 关闭中断,以免影响温度传感器读取数据(影响延时)
EA = 0;
OneWire_IO = 1;
OneWire_IO = 0; // 把总线拉低
_nop_();i = 227;while (--i); // 延时500us
OneWire_IO = 1; // 释放总线
_nop_();i = 29;while (--i); // 延时70us
ACK = OneWire_IO; // 返回从机的响应
_nop_();i = 227;while (--i); // 延时500us
EA = 1;
return ACK;
}
// 发送一位数据
void OneWire_SendBit(unsigned char Bit){
unsigned char i;
EA = 0;
OneWire_IO = 0;
i = 3;while (--i); // 延时10us
OneWire_IO = Bit;
i = 24;while (--i); // 延时50us
EA = 1;
OneWire_IO = 1; // 释放总线
}
// 接收一位数据
unsigned char OneWire_ReceiveBit(){
unsigned char i,Bit;
EA = 0;
OneWire_IO = 0;
i = 2;while (--i); // 延时5us
OneWire_IO = 1;
i = 2;while (--i); // 延时5us
Bit = OneWire_IO;
i = 24;while (--i); // 延时50us
EA = 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(){
unsigned char i,Byte = 0x00;
for(i=0;i<8;i++){
if(OneWire_ReceiveBit()){
Byte |= 0x01<<i;
}
}
return Byte;
}
DS18B20.c
#include
#include "OneWire.h"
#define SKIP_ROM 0xCC // 跳过ROM
#define CONVERT_T 0x44 // 温度交换
#define READ_SCRATCHPAD 0xBE // 读取RAM
// 温度变换
void DS18B20_CovertT(){
OneWire_Init();
OneWire_SendByte(SKIP_ROM);
OneWire_SendByte(CONVERT_T);
}
// 温度读取
float DS18B20_ReadT(){
unsigned char TLSB,TMSB;
int Temp;
float T;
OneWire_Init();
OneWire_SendByte(SKIP_ROM);
OneWire_SendByte(READ_SCRATCHPAD);
TLSB = OneWire_ReceiveByte(); // 高八位
TMSB = OneWire_ReceiveByte(); // 低八位
Temp = (TMSB<<8) | TLSB;
T = Temp/16.0; // 右移四位
return T;
}
main.c
#include
#include "LCD1602.h"
#include "DS18B20.h"
#include "Delay.h"
#include "AT24C02.h"
#include "Key.h"
#include "Time0Init.h"
float T,TShow;
char TL,TH;
unsigned char KeyNum;
void main()
{
DS18B20_CovertT(); //上电先转换一次温度,防止第一次读数据错误
Delayms(1000); //等待转换完成
TH=AT24C02_ReadByte(0); //读取温度阈值数据
TL=AT24C02_ReadByte(1);
if(TH>125 || TL<-55 || TH<=TL)
{
TH=20; //如果阈值非法,则设为默认值
TL=15;
}
LCD_Init();
LCD_ShowString(1,1,"T:");
LCD_ShowString(2,1,"TH:");
LCD_ShowString(2,9,"TL:");
LCD_ShowSignedNum(2,4,TH,3);
LCD_ShowSignedNum(2,12,TL,3);
Time0_Init();
while(1)
{
KeyNum=Key();
/*温度读取及显示*/
DS18B20_CovertT(); //转换温度
T=DS18B20_ReadT(); //读取温度
if(T<0)
{
LCD_ShowChar(1,3,'-');
TShow=-T;
}
else
{
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按键,TH自增
{
TH++;
if(TH>125){TH=125;}
}
if(KeyNum==2) //K2按键,TH自减
{
TH--;
if(TH<=TL){TH++;}
}
if(KeyNum==3) //K3按键,TL自增
{
TL++;
if(TL>=TH){TL--;}
}
if(KeyNum==4) //K4按键,TL自减
{
TL--;
if(TL<-55){TL=-55;}
}
//显示阈值数据
LCD_ShowSignedNum(2,4,TH,3);
LCD_ShowSignedNum(2,12,TL,3);
//写入到At24C02中保存
AT24C02_WriteByte(0,TH);
Delayms(5);
AT24C02_WriteByte(1,TL);
Delayms(5);
}
//越界判断
if(T>TH)
{
LCD_ShowString(1,13,"OV:H");
}
else if(T<TL)
{
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调用一次按键驱动函数
}
}