我最近正在研究使用AVR来驱动MAXIN的DS18B20,琢磨了几天,终于把它的驱动程序写好了.
使用IAR C++编译器
#ifndef DS18B20_H
#define DS18B20_H
/****************************************只需在源程序里定义以下宏
#define seDDS() (seDB0())
#define clDDS() (clDB0())
#define seDS() (sePB0())
#define clDS() (clPB0())
#define GetDS() (GetPB0())
*********************************************/
/*********************************** 函数说明 *********************
void DS18B20::DS18B20(void) 构造函数
void DS18B20::init()初始化DS18B20
char DS18B20::GetiD()读取器件ID,成功返回1,并且器件的64位id号保存到DS18B20.id[4],里,失败返回0
char DS18B20::convter()读取温度,成功返回1,并且温度值保存到DS18B20.temp里,未就绪返回0。此程序需要调用数次才能正确转换
调用周期不得低于2ms
char DS18B20::GetPower()读取总线供电模式,正常返回1,寄生返回0
char DS18B20::SearchAlARM()读取报警,有报警返回1,没有返回0
****************************************************/
#define DS_ReadROM 0x33
#define DS_CopyROM 0x48
#define DS_MatchROM 0x55
#define DS_SkipROM 0xCC
#define DS_SearchROM 0xF0
#define DS_AlarmSearch 0xEC
#define DS_Convert 0x44
#define DS_ReadRAM 0xBE
#define DS_WriteRAM 0x4E
#define DS_ReadPower 0xB4
#define DS_9BIT 0
#define DS_10BIT 1
#define DS_11BIT 2
#define DS_12BIT 3
#include "c:incstatus.h"
#include "c:inccrc8.c"
#include "c:incdelay.c"
#include "c:incformat.h"
#include
class DS18B20
{
public:
float temp;// 温度
int rel;// 温度偏移量
char id[8];// 器件ID号
char mode;// 转换模式9-12bit
unsigned char TH;// 预警温度上限
unsigned char TL;// 预警温度下限
char power;// 0:寄生供电 1:电源供电
char status;// 单线总线状态0: 无连接 1:已连接
char ***uf[10];
private:
char setup;
/****************************************复位总线***********************/
char Reset_DS()
{
unsigned int x;
seDS();
seDDS();
DELAY_80us();
if(GetDS())
{
clDS();
DELAY_600us();
seDS();
clDDS();
for(x=0;x<30;)
{
if(GetDS())x++;
else
{
for(x=0;x<30;)
{
if(GetDS())
{
seDDS();
DELAY_600us();//
return 1;
}
else
x++;
DELAY_10us();
}
clDDS();
return 0;
}
DELAY_10us();//
}
}
clDDS();
return 0;
}
/**************************************************写总线*******************/
void Write_DS(unsigned dat,unsigned char wide)// dat:数据 wide:数据宽度(位数)
{
unsigned char i,sreg;
seDDS();
for(i=0;i
{
sreg=SREG;
SREG&=0x7F;// 关中断
if(dat&0x01)
{
clDS();
DELAY_10us();
seDS();
DELAY_80us();
}
else
{
clDS();
DELAY_80us();
seDS();
DELAY_10us();
}
SREG=sreg;// 恢复中断 发生的中断将依次执行
dat>>=1;
}
}
/***************************************************读总线*******************/
unsigned char Read_DS(unsigned char wide)
{
unsigned char dat,i,sreg;
for(i=dat=0;i
{
if(GetDS())
{
sreg=SREG;
SREG&=0x7F;
clDS();
seDDS();
DELAY_10us();
seDS();
clDDS();
dat>>=1;
DELAY_10us();
if(GetDS())dat|=0x80;
seDDS();
SREG=sreg;
DELAY_80us();
}
else
{
setup=0;
}
}
return dat;
}
char getid()
{
char i;
for(i=0;i
if(id)
return 1;
return 0;
}
public:
char convert()// 本程序调用周期至少2ms或以上
{
static unsigned char ***uf[9];
static unsigned int i;
switch(setup)
{
case 0:
if(Reset_DS())// 开始
{
status=1;
setup++;
}
else
status=0;
break;
case 1:
if(getid())
{
Write_DS(DS_MatchROM,8);// 匹配ROM
for(i=0;i<8;i++)
Write_DS(id,8);
}
else
{
Write_DS(DS_SkipROM,8);// 跳过匹配
}
Write_DS(DS_Convert,8);// 启动转换
i=power?0:500;// 选择电源方式,以达到最快速度
setup++;
break;
case 2:
if(i)// 延时
{
i--;
}
else if(Read_DS(8)==0xFF)// 等待转换结束
{
Reset_DS();
if(getid())
{
Write_DS(DS_MatchROM,8);// 匹配ROM
for(i=0;i<8;i++)
Write_DS(id,8);
}
else
Write_DS(DS_SkipROM,8);
Write_DS(DS_ReadRAM,8);
i=0;
setup++;
}
break;
case 3:
***uf=Read_DS(8);
if(i>=9)
{
Reset_DS();
if(GetCRC8(***uf,8)==***uf[8])// 校验CRC
{
int i;
i=***uf[1]*0x100+***uf[0];
i+=rel;
temp=i/16+(i%16)*0.125;
setup=0;
status=1;
return 1;
}
setup=0;
}
break;
}
return 0;
}
char GetPower()
{
unsigned char x;
if(Reset_DS())
{
Write_DS(DS_SkipROM,8);
Write_DS(DS_ReadPower,8);
x=Read_DS(8);
Reset_DS();
if(x)
return 1;
}
return 0;
}
/*************************************预警搜索****************************/
char SearchAlarm()
{
if(Reset_DS())
{
Write_DS(DS_AlarmSearch,8);
if(Read_DS(2)==0x80)// 读两个位
{
Reset_DS();
return 1;
}
}
Reset_DS();
return 0;
}
//TH:高温限制 TL:低温限制
//mode:转换模式 0:9bit(93.75ms) 1:10bit(187.5ms) 2:11bit(375ms) 3:12bit(750ms)
//power:总线的电源模式
//ID:器件ID号
char init()
{
unsigned char i,***uf[9];
if(Reset_DS())
{
if(getid())
{
Write_DS(DS_MatchROM,8);
for(i=0;i<8;i++)
Write_DS(id,8);
}
else
Write_DS(DS_SkipROM,8);
Write_DS(DS_WriteRAM,8);
Write_DS(TH,8);
Write_DS(TL,8);
Write_DS(((mode&0x03)<<5)|0x1F,8);
Reset_DS();
if(getid())
{
Write_DS(DS_MatchROM,8);
for(i=0;i<8;i++)
Write_DS(id,8);
}
else
Write_DS(DS_SkipROM,8);
Write_DS(DS_ReadRAM,8);
for(i=0;i<9;i++)
***uf=Read_DS(8);
if(GetCRC8(***uf,8)==***uf[8])// 校验CRC
{
if(***uf[2]==TH&&***uf[3]==TL)
{
Reset_DS();
if(getid())
{
Write_DS(DS_MatchROM,8);
for(i=0;i<8;i++)
Write_DS(id,8);
}
else
Write_DS(DS_SkipROM,8);
Write_DS(DS_CopyROM,8);
DELAY_200ms();
Reset_DS();
power=GetPower();
Reset_DS();
return 1;// 完成
}
}
}
return 0;
}
/*********************************************读取DS18B20的64位ROM******************/
char GetID()
{
unsigned char i;
unsigned char ***uf[8];
if(Reset_DS())
{
Write_DS(DS_ReadROM,8);
for(i=0;i<8;i++)
{
***uf=Read_DS(8);
}
Reset_DS();
if(GetCRC8(***uf,7)==***uf[7])// 校验CRC
{
for(i=0;i<8;i++)
id=***uf;// 拷贝数据到ROM
return 1;
}
}
return 0;
}
char* disp(char width=0)
{
int i=(int)temp;
int j=(int)(temp*10);
j%=10;
if(temp<0)
j=0-j;
switch(width)
{
case 2:
sprintf(***uf,"%2d.%d",i,j);
break;
case 3:
sprintf(***uf,"%3d.%d",i,j);
break;
default:
sprintf(***uf,"%d.%d",i,j);
break;
}
return ***uf;
}
DS18B20()
{
format(id,sizeof(id),0);
mode=DS_12BIT;
TH=100;
TL=0;
power=0;
rel=0;
status=0;
setup=0;
seDDS();
seDS();
}
};
#endif
|