我最近正在研究使用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:\inc\status.h"
#include "c:\inc\crc8.c"
#include "c:\inc\delay.c"
#include "c:\inc\format.h"
#include <stdio.h>
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 sbuf[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<wide;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<wide;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<sizeof(id);i++)
if(id)
return 1;
return 0;
}
public:
char convert()// 本程序調用周期至少2ms或以上
{
static unsigned char sbuf[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:
sbuf=Read_DS(8);
if(i>=9)
{
Reset_DS();
if(GetCRC8(sbuf,8)==sbuf[8])// 校驗CRC
{
int i;
i=sbuf[1]*0x100+sbuf[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,sbuf[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++)
sbuf=Read_DS(8);
if(GetCRC8(sbuf,8)==sbuf[8])// 校驗CRC
{
if(sbuf[2]==TH&&sbuf[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 sbuf[8];
if(Reset_DS())
{
Write_DS(DS_ReadROM,8);
for(i=0;i<8;i++)
{
sbuf=Read_DS(8);
}
Reset_DS();
if(GetCRC8(sbuf,7)==sbuf[7])// 校驗CRC
{
for(i=0;i<8;i++)
id=sbuf;// 拷貝數據到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(sbuf,"%2d.%d",i,j);
break;
case 3:
sprintf(sbuf,"%3d.%d",i,j);
break;
default:
sprintf(sbuf,"%d.%d",i,j);
break;
}
return sbuf;
}
DS18B20()
{
format(id,sizeof(id),0);
mode=DS_12BIT;
TH=100;
TL=0;
power=0;
rel=0;
status=0;
setup=0;
seDDS();
seDS();
}
};
#endif
|