我最近正在研究使用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 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 |
更多回帖