#define ONEWIRE_PIN_LAT LATBbits.LATB0 #define ONEWIRE_PIN_TRIS TRISBbits.TRISB0 #define ONEWIRE_PIN_PORT PORTBbits.RB0 // 1wire command set #define ONEWIRE_CMD_SEARCHROM 0xF0 #define ONEWIRE_CMD_READROM 0x33 #define ONEWIRE_CMD_MATCHROM 0x55 #define ONEWIRE_CMD_SKIPROM 0xCC #define ONEWIRE_CMD_ALARMSEARCH 0xEC // basic delay function #define delay480us() {DelayUs(480)} #define delay280us() {DelayUs(280)} #define delay100us() {DelayUs(100)} #define delay120us() {DelayUs(120)} #define delay70us() {DelayUs(70)} #define delay15us() {DelayUs(15)} /** PROTOTYPES *****************************************************/ // onewire pin functions void ow_low(void); void ow_high(void); void ow_input(void); void ow_output(void); unsigned int ow_state(void); // onwire protocol functions unsigned int owReset(void); unsigned int owReadBit(void); void owWriteBit(unsigned int bitvalue); unsigned int owReadByte(void); void owWriteByte(unsigned int data); /** DECLARATIONS ***************************************************/ // ds18b20 scratchpad registers #define DS18B20_SP_TLSB 0 #define DS18B20_SP_TMSB 1 #define DS18B20_SP_HLIM 2 #define DS18B20_SP_LLIM 3 #define DS18B20_SP_CFG 4 #define DS18B20_SP_RES0 5 #define DS18B20_SP_RES1 6 #define DS18B20_SP_RES2 7 #define DS18B20_SP_CRC 8 // ds18b20 rom registers #define DS18B20_ROM_DEVTYPE 0 #define DS18B20_ROM_SERIAL1 1 #define DS18B20_ROM_SERIAL2 2 #define DS18B20_ROM_SERIAL3 3 #define DS18B20_ROM_SERIAL4 4 #define DS18B20_ROM_SERIAL5 5 #define DS18B20_ROM_SERIAL6 6 #define DS18B20_ROM_CRC 7 // DS18B20 command set #define DS18B20_CMD_CONVERTTEMP 0x44 #define DS18B20_CMD_WRITESCRATCHPAD 0x4E #define DS18B20_CMD_READSCRATCHPAD 0xBE #define DS18B20_CMD_COPYSCRATCHPAD 0x48 #define DS18B20_CMD_RECALLEE 0xB8 #define DS18B20_CMD_READPOWERSUPPLY 0xB4 // DS18B20 structures sizes #define DS18B20_SCRATCHPAD_SIZE 9 #define DS18B20_ROM_SIZE 8 // Specific delay routine #define delay100ms() {DelayMs(100)} void ow_low(void) { ONEWIRE_PIN_TRIS=0; ONEWIRE_PIN_LAT=0; } void ow_high(void) { ONEWIRE_PIN_TRIS=0; ONEWIRE_PIN_LAT=1; } void ow_input(void) { ONEWIRE_PIN_TRIS=1; } void ow_output(void) { ONEWIRE_PIN_TRIS=0; } unsigned int ow_state(void) { unsigned int state=0x00; ow_input(); state=ONEWIRE_PIN_PORT; ow_output(); ow_high(); return(state); } unsigned int owReset(void) { unsigned int presence=0x00; ow_low(); delay480us(); // reset window slot ow_high(); delay70us(); // allow pin to stabilize presence=ow_state(); // 0 = device present, 1 = no device on bus delay280us(); // wait-out remaining initialisation window. return(~presence); // device(s) present and initialised. Invert because I don't like inverse loic } // Read one bit from OneWire Bus. unsigned int owReadBit(void) { unsigned int i=0x00; ow_low(); // pull OneWire Bus down ow_high(); // pull OneWire Bus up (init of "read" timeslot) delay15us(); i=ow_state(); // wait 15us return(i); // return bit } // Write one bit to OneWire Bus. void owWriteBit(unsigned int bitvalue) { ow_low(); // pull OneWire Bus down if(bitvalue) // In the next 20us < timeslot < 120us { // you can write 1 or 0. ow_high(); // If "1", it's do the job } delay100us(); // wait end of write timeslot ow_high(); // return the Bus to high } unsigned int owReadByte(void) { unsigned int i; unsigned int data=0x00; for(i=0; i<8; i++) { ow_low(); if(owReadBit()) { data|=0x01<>i; temp&=0x01; owWriteBit(temp); } delay100us(); } /** PROTOTYPES *****************************************************/ int ftoa(float x, char *str, char prec, char format); unsigned int ds18b20SetResolution(unsigned int resolution); void ds18b20ReadScratchpad(unsigned int data[DS18B20_SCRATCHPAD_SIZE]); void ds18b20ReadROM(unsigned int data[DS18B20_ROM_SIZE]); void ds18b20ReadTemp(float temp_c_float, char *temp_c_str); void ds18b20ReadScratchpad(unsigned int data[DS18B20_SCRATCHPAD_SIZE]) { unsigned int i; owReset(); // Only one device at 1wire bus owWriteByte(ONEWIRE_CMD_SKIPROM); // 0xCC Only one device at 1wire bus owWriteByte(DS18B20_CMD_READSCRATCHPAD);// 0xBE for(i=0; i12)) resolution=9; resolution_cfgfield=((resolution-9)<<5); // see DS18B20 datasheet page 7 if(~owReset()) { return(0); } owWriteByte(ONEWIRE_CMD_SKIPROM); // 0xCC owWriteByte(DS18B20_CMD_WRITESCRATCHPAD);// 0x4E owWriteByte(0b01111101); // set max TH threshold (125'C) 0x7D owWriteByte(0b11001001); // set min TL threshold (-55'C) 0xC9 owWriteByte(resolution_cfgfield); // Temp resolution, set to nbit owReset(); // reset owWriteByte(ONEWIRE_CMD_SKIPROM); // 0xCC owWriteByte(DS18B20_CMD_COPYSCRATCHPAD); // 0x48 delay280us(); // allow time for flash memory write. ds18b20ReadScratchpad(scratchpad); // scratchpad contains all information return((scratchpad[DS18B20_SP_CFG] & 0b01100000)>>5); } /********************************************************************* * Function: ftoa(float x, char *str, char prec, char format) * Overview: Transforms a float number into a char string * Input: float x - float number input * char *str - pointer to a char array string that store the output * char prec - precision * char format - output format * Output: none *********************************************************************/ int ftoa(float x, char *str, char prec, char format) { int ie, i, k, ndig, fstyle; double y; char *start; start=str; //based on precision set number digits ndig=prec+1; if(prec<0) { ndig=7; } if(prec>22) { ndig=23; } fstyle = 0; //exponent 'e' if((format == 'f') || (format == 'F')) { fstyle=1; //normal 'f' } if((format=='g') || (format=='G')) { fstyle=2; } ie = 0; /* if x negative, write minus and reverse */ if(x<0) { *str++ = '-'; x = -x; } //if (x<0.0) then increment by 10 till between 1.0 and 10.0 if(x!=0.0) { while(x<1.0) { x=x* 10.0; ie--; } } //if x>10 then let's shift it down while(x>=10.0) { x=x*(1.0/10.0); ie++; } /* in f format, number of digits is related to size */ if(fstyle) { ndig=ndig + ie; } if((prec==0) && (ie>ndig) && (fstyle)) { ndig=ie; } /* round. x is between 1 and 10 and ndig will be printed to right of decimal point so rounding is ... */ y=1; for(i=1; i=10.0) { x = 1.0; ie++; ndig++; } //check and see if the number is less than 1.0 if((fstyle) && (ie<0)) { *str++ = '0'; if(prec!=0) { *str++ = '.'; } if(ndig<0) { ie = ie-ndig; // limit zeros if underflow } for(i=-1; i>ie; i--) { *str++ = '0'; } } //for each digit for(i=0; iie; k=k/10); //find the decade of exponent for (; k > 0; k=k/10) { char t; // t=DIV(ie,k); *str++ = t + '0'; ie = ie -(t*k); } } *str++ = '\0'; return(str-start); //return string length } /********************************************************************* * Function: ds18b20ReadTemp(float temp_c_float, char *temp_c_str) * Overview: Read temperature and store the value in two formats: a float * variable and a string with value for easy character output * functions (serial, LCD, etc). * Input: float temp_c_float - float temperature variable * char *temp_c_str - pointer to char array string that store the output * Output: none *********************************************************************/ void ds18b20ReadTemp(float temp_c_float, char *temp_c_str) { unsigned int scratchpad[9]; unsigned int temp_lsb,temp_msb,temp_full,temp_frac; unsigned int resolution,scale; unsigned int delaymult; // Determine resolution - find delay multiply // res = 0x00 - 9bits - 93.75ms - 100ms // = 0x01 - 10bits - 186.5ms - 200ms // = 0x10 - 11bits - 375ms - 400ms // = 0x11 - 12bits - 750ms - 800ms ds18b20ReadScratchpad(scratchpad); resolution=((scratchpad[DS18B20_SP_CFG] & 0b01100000)>>5); delaymult=1<>3; break; case 1: scale=4; temp_frac=(temp_lsb&0b00001111)>>2; break; case 2: scale=8; temp_frac=(temp_lsb&0b00001111)>>1; break; case 3: scale=16; temp_frac=(temp_lsb&0b00001111); break; default: break; } temp_lsb = ((temp_lsb & 0b11110000)>>4); // LSB temperature bits temp_msb = ((temp_msb & 0b00001111)<<4); // MSB temperature bits temp_full= (temp_msb + temp_lsb); // Two Complement temperature byte // A signed integer value is obtained from a two complement unsigned integer // using the folowing equation // // n-2 // -----| // \ // x = -x[n-1]2^(n-1) + > x_i * 2^i // / // -----| // i=0 // // where n is the number of bits used. // // This give us the integer part of the temperature. The fractional part must // be added to this value. This FRACtional part is given by the folowing // equation: // // (resolution - n) // -----| // \ // FRAC = > x_-i * 2^-i // / // -----| // i=1 // // where n is the number of bits used. // // Or (simplyfing) // for 12 bits resolution, FRACtional part is 4 bits, then // FRAC = FRACtional/(2^4) = FRACtional/16 // // for 11 bits resolution, FRACtional part is 3 bits, then // FRAC = FRACtional/(2^3) = FRACtional/8 // // ... // if(temp_full & 0b10000000) { // negative value temp_c_float = (float)(temp_full&0b01111111) + ((float)temp_frac/scale) - 128; ftoa(temp_c_float, temp_c_str, resolution+1, 'F'); } else { // positive value temp_c_float = (float)(temp_full&0b01111111) + ((float)temp_frac/scale); ftoa(temp_c_float, temp_c_str, resolution+1, 'F'); } }