DS18B20的代码有很多,这篇的代码主要参考自美信公司的应用笔记。proteus仿真时对时不对的,实在搞不懂为嘛。程序中除了基本的读取温度外还有搜索1-wire器件算法,读取1-wire器件EEPROM/高速缓存的算法。这些算法中有一点需要注意,由于温度转换需要较长时间至少750MS,因此启动温度转换到实际读取温度值需要延时,否则将无法正确读到温度值。这是我痛苦的经历,因为美信公司的应用手册上没有调用延时函数,因此一直获取不到温度值。此处加以记录希望下次不要重蹈覆辙。
#include
#define uchar unsigned char
#define uint unsigned int
sbit DS=P2^2; //define interface
void delay(int us)
{
int i;
for(i=0;i>i;
tmp &= 0x01;
writeBit(tmp);
}
delay(5);
}
//读高速缓存
unsigned int temp_c;
void Read_Temperature(void)
{
char get[10];
char temp_lsb,temp_msb;
int k;
char temp_f;
resetSingleBus();
writeByte(0xCC); //Skip ROM
writeByte(0x44); // Start Conversion
delayMs(800); //750ms 转换时间
resetSingleBus();
writeByte(0xCC); // Skip ROM
writeByte(0xBE); // Read Scratch Pad
delayMs(800); //750ms 转换时间
for (k=0;k<9;k++)
{
get[k]=readByte();
}
//printf("\n ScratchPAD DATA = %X%X%X%X%X\n",get[8],get[7],get[6],get[5],get[4],get[3],get[2],get[1],get[0]);
temp_msb = get[1]; // Sign byte + lsbit
temp_lsb = get[0]; // Temp data plus lsb
if (temp_msb <= 0x80){temp_lsb = (temp_lsb/2);} // shift to get whole degree
temp_msb = temp_msb & 0x80; // mask all but the sign bit
if (temp_msb >= 0x80) {temp_lsb = (~temp_lsb)+1;} // twos complement
if (temp_msb >= 0x80) {temp_lsb = (temp_lsb/2);}// shift to get whole degree
if (temp_msb >= 0x80) {temp_lsb = ((-1)*temp_lsb);} // add sign bit
//printf( "\nTempC= %d degrees C\n", (int)temp_lsb ); // print temp. C
temp_c = temp_lsb; // ready for conversion to Fahrenheit
temp_f = (((int)temp_c)* 9)/5 + 32;
// printf( "\nTempF= %d degrees F\n", (int)temp_f );
}
//rom
void ReadROMCode(void)
{
int n;
char romCode[9]={0};
resetSingleBus() ;
writeByte(0x33) ;
for (n=0; n<8; n++)
{
romCode[n] = (char)readByte();
}
romCode[8]=0x00;
}
void ReadScratchPad(void)
{
int j ;
char padCode[10]={0};
writeByte(0xBE);
delayMs(800);
for(j =0; j <8; j ++)
{
padCode[j] = readByte();
}
}
unsigned char ROM[8];
unsigned char FoundROM[5][8];
unsigned char lastDiscrep=0;
unsigned char doneFlag=0;
unsigned char numROMs;
unsigned char dowcrc;
unsigned char code dscrc_table[] = {
0, 94, 188, 226, 97, 63, 221, 131, 194, 156, 126, 32, 163, 253, 31, 65,
157, 195, 33, 127, 252, 162, 64, 30, 95, 1, 227, 189, 62, 96, 130, 220,
35, 125, 159, 193, 66, 28, 254, 160, 225, 191, 93, 3, 128, 222, 60, 98,
190, 224, 2, 92, 223, 129, 99, 61, 124, 34, 192, 158, 29, 67, 161, 255,
70, 24, 250, 164, 39, 121, 155, 197, 132, 218, 56, 102, 229, 187, 89, 7,
219, 133, 103, 57, 186, 228, 6, 88, 25, 71, 165, 251, 120, 38, 196, 154,
101, 59, 217, 135, 4, 90, 184, 230, 167, 249, 27, 69, 198, 152, 122, 36,
248, 166, 68, 26, 153, 199, 37, 123, 58, 100, 134, 216, 91, 5, 231, 185,
140, 210, 48, 110, 237, 179, 81, 15, 78, 16, 242, 172, 47, 113, 147, 205,
17, 79, 173, 243, 112, 46, 204, 146, 211, 141, 111, 49, 178, 236, 14, 80,
175, 241, 19, 77, 206, 144, 114, 44, 109, 51, 209, 143, 12, 82, 176, 238,
50, 108, 142, 208, 83, 13, 239, 177, 240, 174, 76, 18, 145, 207, 45, 115,
202, 148, 118, 40, 171, 245, 23, 73, 8, 86, 180, 234, 105, 55, 213, 139,
87, 9, 235, 181, 54, 104, 138, 212, 149, 203, 41, 119, 244, 170, 72, 22,
233, 183, 85, 11, 136, 214, 52, 106, 43, 117, 151, 201, 74, 20, 246, 168,
116, 42, 200, 150, 21, 75, 169, 247, 182, 232, 10, 84, 215, 137, 107, 53};
unsigned char ow_crc( unsigned char x)
{
dowcrc = dscrc_table[ dowcrc^x] ;
return dowcrc;
}
// NEXT
// The Next function searches for the next device on the 1-Wire bus. If
// there are no more devices on the 1-Wire then 0 is returned.
//
unsigned char Next(void)
{
unsigned char m = 1; // ROM Bit index
unsigned char n = 0; // ROM Byte index
unsigned char k = 1; // bit mask
unsigned char x = 0;
unsigned char discrepMarker = 0; // discrepancy marker
unsigned char g; // Output bit
unsigned char nxt; // return value
int flag;
char dowcrc = 0; // reset the dowcrc
nxt = 0; // set the next flag to 0
flag = resetSingleBus() ; // reset the 1-Wire
if(flag||doneFlag) // no parts -> return 0
{
lastDiscrep = 0; // reset the search
return 0;
}
writeByte(0xF0) ; // send SearchROM command
delayMs(10);
do
// for all eight bytes
{
x= 0;
if(readBit() ==1)
x = 2;
if(readBit() ==1)
x |= 1; // and its complement
if(x ==3) // there are no devices on the 1-Wire
break;
else
{
if(x>0) // all devices coupled have 0 or 1
g = x>>1; // bit write value for search
else
{
// if this discrepancy is before the last
// discrepancy on a previous Next then pick
// the same as last time
if(m0) ;
else // if equal to last pick 1
g = (m==lastDiscrep) ; // if not then pick 0
// if 0 was picked then record
// position with mask k
if (g==0)
discrepMarker = m;
}
if(g==1) // isolate bit in ROM[ n] with mask k
ROM[n] |= k;
else
ROM[ n] &= ~k;
writeBit(g) ; // ROM search write
m++; // increment bit counter m
k = k<<1; // and shift the bit mask k
if(k==0) // if the mask is 0 then go to new ROM
{ // byte n and reset mask
ow_crc(ROM[n] ) ; // accumulate the CRC
n++; k++;
}
}
}while(n<8) ; //loop until through all ROM bytes 0-7
if(m<65||dowcrc) // if search was unsuccessful then
lastDiscrep=0; // reset the last discrepancy to 0
else
{// search was successful, so set lastDiscrep,
// lastOne, nxt
lastDiscrep = discrepMarker;
doneFlag = (lastDiscrep==0) ;
nxt = 1; // indicates search is not complete yet, more
// parts remain
}
return nxt;
}
unsigned char First(void)
{
lastDiscrep = 0; // reset the rom search last discrepancy global
doneFlag = 0;
return Next() ; // call Next and return its return value
}
void FindDevices(void)
{
unsigned char m;
if(!resetSingleBus() ) //Begins when a presence is detected
{
if(First() ) //Begins when at least one part is found
{
numROMs=0;
do
{
numROMs++;
for(m=0; m<8; m++)
{
FoundROM[ numROMs] [ m] =ROM[ m] ; //Identifies ROM
//number on found device
}
}while(Next()&&(numROMs<2)); //Continues until no additional devices are found
}
}
}
unsigned char Send_MatchRom(void)
{
unsigned char i;
if(resetSingleBus())
return 0;
writeByte(0x55) ; // match ROM
for(i=0; i<8; i++)
{
writeByte(FoundROM[0][i] ) ; //send ROM code
}
return 1;
}
void main()
{
do
{
resetSingleBus();
First();
FindDevices();
ReadROMCode();
Read_Temperature();
ReadScratchPad();
}while(1);
}
resetSingleBus/First/FindDevices/ReadRomCode/ReadScratchPad依次是复位/搜索第一个1wire器件/搜索EEPROM/搜索告诉缓存
下图为我的仿真图
下图为设置DS18B20传感器的EEPROM/高速缓存,MCU运行时即可设置:
DS18B20的64BROM在MCU尚未仿真时设置:
参考文档:Interfacing the DS18X20_DS1822 1-Wire® Temperature Sensor in a Microcontroller Environment - Application Note - Maxim.pdf