/* Dallas 1-Wire bus routines */ #if defined(__XC) #include /* XC8 General Include File */ #elif defined(HI_TECH_C) #include /* HiTech General Include File */ #endif #include /* For uint8_t definition */ #include /* For true/false definition */ #include "system.h" #include "user.h" #include "onewire.h" // fast way, macros #define OWLOW { PORTAbits.RA5 = 0; TRISAbits.TRISA5 = 0; } #define OWHIGH { PORTAbits.RA5 = 1; TRISAbits.TRISA5 = 0; } #define OWTRI { TRISAbits.TRISA5 = 1; } #define OWREAD (PORTAbits.RA5) // slow way, causes a function call inline void drive_OW_low(void) { PORTAbits.RA5 = 0; TRISAbits.TRISA5 = 0; } inline void drive_OW_high(void) { PORTAbits.RA5 = 1; TRISAbits.TRISA5 = 0; } inline void float_OW(void) { TRISAbits.TRISA5 = 1; } inline bool read_OW(void) { TRISAbits.TRISA5 = 1; return PORTAbits.RA5; } /* start the 1-Wire bus * */ void OW_start(void) { //drive_OW_high(); float_OW(); } /* reset the bus, test for presence signal */ bool OW_reset(void) { bool presence = 0; OWLOW; //drive_OW_low(); DelayUs(250); DelayUs(250); OWTRI; //float_OW(); // let it float high DelayUs(70); presence = OWREAD; //read_OW(); // now sample DelayUs(215); DelayUs(215); return ! presence; } void OW_write_bit(bool val) { #if 0 // Maxim dev note 2420 drive_OW_low(); DelayUs(3); if (val) float_OW(); DelayUs(60); float_OW(); DelayUs(2); #else OWLOW; NOP(); NOP(); // NOP(); // doc one for other delays if (val) OWTRI; DelayUs(60); OWTRI; NOP(); NOP(); #endif } bool OW_read_bit() { bool val; #if 0 /* Maxim dev note 2420 */ drive_OW_low(); DelayUs(6); float_OW(); DelayUs(4); val = read_OW(); DelayUs(50); #else OWLOW; // NOP(); NOP(); NOP(); NOP(); NOP(); NOP(); OWTRI; // NOP(); NOP(); NOP(); NOP(); val = read_OW(); DelayUs(50); #endif return val; } void OW_write_byte(unsigned char byte) { for (char i=8; i!=0; i--) { OW_write_bit( byte & 0x01 ); byte >>= 1; } } unsigned char OW_read_byte(void) { unsigned char byte = 0; for (char i=8; i!=0; i--) { byte >>= 1; if (OW_read_bit()) byte |= 0x80; } return byte; } static const unsigned char 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 romid[8]; char LastDiscrepancy = 0; char LastFamilyDiscrepancy = 0; char LastDeviceFlag = false; unsigned char crc8; static unsigned char docrc8(unsigned char value) { crc8 = dscrc_table[crc8 ^ value]; return crc8; } /* enumerate the devices */ bool OW_search() { char id_bit_number = 1; char last_zero = 0; char rom_byte_number = 0; char search_result = 0; unsigned char rom_byte_mask = 1; unsigned char search_direction; crc8 = 0; // do not interrupt us int_disable(); // if the last call was not the last one if (!LastDeviceFlag) { if (!OW_reset()) { msg_write("Reset said nothing there.\r\n"); // reset the search LastDiscrepancy = 0; LastDeviceFlag = 0; LastFamilyDiscrepancy = 0; int_enable(); return 0; } // issue the search command OW_write_byte(0xF0); // loop to do the search do { // read a bit and its complement bool id_bit = OW_read_bit(); DelayUs(6); bool cmp_id_bit = OW_read_bit(); // check for no devices on bus if (id_bit && cmp_id_bit) { break; } if (id_bit != cmp_id_bit) { // all devices have a 0 here, or they all have a 1 search_direction = id_bit; } else { // both bits zero, so both 0 and 1 exist // if this discrepancy is before the Last Discrepancy // on a previous next then pick the same as last time if (id_bit_number < LastDiscrepancy) { search_direction = ((romid[rom_byte_number] & rom_byte_mask) > 0); } else { // if equal to last pick 1, if not then pick 0 search_direction = (id_bit_number == LastDiscrepancy); } // if 0 was picked then record its position in LastZero if (search_direction == 0) { last_zero = id_bit_number; // check for last discrepancy in family if (last_zero < 9) LastFamilyDiscrepancy = last_zero; } } // set or clear the bit in the ROM byte rom_byte_number // with mask rom_byte_mask if (search_direction == 1) romid[rom_byte_number] |= rom_byte_mask; else romid[rom_byte_number] &= ~rom_byte_mask; // serial number search direction write bit OW_write_bit(search_direction); // increment the byte counter id_bit_number // and shift the mask rom_byte_mask id_bit_number++; rom_byte_mask <<= 1; // if the mask is 0 then go to new SerialNum byte rom_byte_number and reset mask if (rom_byte_mask == 0) { docrc8(romid[rom_byte_number]); // accumulate the CRC rom_byte_number++; rom_byte_mask = 1; } } while (rom_byte_number < 8); // loop until all rom bytes 0-7 } // end of not-last-device // if the search was succesful then if (!(id_bit_number < 65 || crc8 != 0)) { // search successful LastDiscrepancy = last_zero; // check for last device if (LastDiscrepancy == 0) LastDeviceFlag = true; search_result = true; } if (!search_result || !romid[0]) { LastDiscrepancy = 0; LastDeviceFlag = false; LastFamilyDiscrepancy = 0; search_result = false; } int_enable(); return search_result; } void OW_search_init() { LastDiscrepancy = 0; LastDeviceFlag = false; LastFamilyDiscrepancy = 0; for (int j=0; j<8; j++) romid[j]=0; } /* ask the (lone) device for its Serial number */ void OW_identify() { int_disable(); OW_reset(); // read ROM command OW_write_byte(0x33); for (int j=0; j<8; j++) romid[j] = OW_read_byte(); int_enable(); } /* is anyone parasite powered ? */ bool OW_parasite(void) { int_disable(); OW_reset(); OW_write_byte(0xCC); // skip the rom command OW_write_byte(0xB4); // are you parasite powered ? bool no = OW_read_bit(); int_enable(); return !no; } /* select a specific device, * if family==0 select all devices (skip rom) */ static void OW_select_id(void) { if (romid[0] == 0) { OW_write_byte(0xCC); // all devices for now } else { OW_write_byte(0x55); // match rom for (int8_t j=0; j<8; j++) { OW_write_byte(romid[j]); } } } /* read a memory block eg scratchpad 0xBE */ void OW_read_block(uint8_t code, uint8_t * data, uint8_t len) { int_disable(); OW_reset(); OW_select_id(); OW_write_byte(code); for (int8_t j=0; j eeprom * 4Eh - write scratchpad (send 3 bytes ) * BEh - read scratchpad ( 8 bytes + crc) * B8h - recall EEPROM -> scratchpad * B4h - read power supply (read 1 bit) */