uint8_t OWI_SearchRom(myOneWire *ow) { uint8_t bitIndex = 0; uint8_t byteIndex = 0; uint8_t newDeviation = 0; uint8_t bitMask = 0x01; uint8_t bitA; uint8_t bitB; OWI_SendByte(ow, OWI_SEARCH_ROM); while (bitIndex < 64) { bitA = OWI_ReadBit(ow); bitB = OWI_ReadBit(ow); if(bitA && bitB) { newDeviation = -1; return newDeviation; } else if(bitA ^ bitB) { if(bitA) ow->address[byteIndex] |= bitMask; else ow->address[byteIndex] &= ~bitMask; } else { if(bitIndex == ow->lastDeviation) { ow->address[byteIndex] |= bitMask; } else if(bitIndex > ow->lastDeviation) { ow->address[byteIndex] &= ~bitMask; newDeviation = bitIndex; } else if(!(ow->address[byteIndex] & bitMask)) { newDeviation = bitIndex; } } OWI_WriteBit(ow, ow->address[byteIndex] & bitMask); bitIndex++; bitMask <<= 1; if(!bitMask) { bitMask = 0x01; byteIndex++; } } return newDeviation; }
uint8_t OWI_ReceiveByte(myOneWire* ow) { uint8_t data = 0; uint8_t bitsReceived; for(bitsReceived = 0; bitsReceived < 8; bitsReceived++) { data >>= 1; if(OWI_ReadBit(ow)) { data |= 0x80; } } return data; }
/***************************************************************************** * Function name : DS18B20_SetDeviceAccuracy * Parameters : bus - вывод микроконтроллера, который выполн¤ет роль 1WIRE шины * *id - им¤ массива из 8-ми элементов, в котором хранитс¤ * адрес датчика DS18B20 * accuracy - значение точность необходимой дл¤ установлени¤ * 0 - 9bit * 1 - 10bit * 2 - 11bit * 3 - 12bit * * Purpose : јдресует датчик DS18B20, записывает в пам¤ть (scratchpad), * копирует scratchpad в EEPROM. * —ледует вызывать только один раз дл¤ настройки устройства *****************************************************************************/ void DS18B20_SetDeviceAccuracy(unsigned char bus, unsigned char* id, unsigned char accuracy){ OWI_DetectPresence(bus); OWI_MatchRom(id, bus); OWI_SendByte(DS18B20_WRITE_SCRATCHPAD, bus); OWI_SendByte(0x00, bus); //Th OWI_SendByte(0x00, bus); //Tl OWI_SendByte(0x1F | ((accuracy & 0x03)<<5), bus); //Config OWI_DetectPresence(bus); OWI_MatchRom(id, bus); OWI_SendByte(DS18B20_COPY_SCRATCHPAD, bus); while (!OWI_ReadBit(bus)); }
/*! \brief Receives one byte of data from the 1-Wire(R) bus. * * This function automates the task of receiving a complete byte * of data from the 1-Wire bus. * * \param pin A bitmask of the bus to read from. * * \return The byte read from the bus. */ unsigned char OWI_ReceiveByte( unsigned char pin ) { unsigned char data; unsigned char i; // Clear the temporary input variable. data = 0x00; // Do once for each bit for ( i = 0; i < 8 ; i++ ) { // Shift temporary input variable right. data >>= 1; // Set the msb if a '1' value is read from the bus. // Leave as it is ('0') else. if ( OWI_ReadBit(pin) ) { // Set msb data |= 0x80; } } return data; }
/***************************************************************************** * Function name : DS18B20_ReadTemperature * Returns : коды - READ_CRC_ERROR, если считанные данные не прошли проверку * READ_SUCCESSFUL, если данные прошли проверку * Parameters : bus - вывод микроконтроллера, который выполняет роль 1WIRE шины * *id - имя массива из 8-ми элементов, в котором хранится * адрес датчика DS18B20 * *ds18b20_temperature - указатель на шестнадцати разрядную переменную * в которой будет сохранено считанного зн. температуры * Purpose : Адресует датчик DS18B20, дает команду на преобразование температуры * ждет, считывает его память - scratchpad, проверяет CRC, * сохраняет значение температуры в переменной, возвращает код ошибки *****************************************************************************/ BYTE DS18B20_ReadTemperature(BYTE bus, BYTE * id, WORD* ds18b20_temperature) { unsigned char scratchpad[9]; unsigned char i; /*подаем сигнал сброса команду для адресации устройства на шине подаем команду - запук преобразования */ OWI_DetectPresence(bus); OWI_MatchRom(id, bus); OWI_SendByte(DS18B20_CONVERT_T ,bus); /*ждем, когда датчик завершит преобразование*/ while (!OWI_ReadBit(bus)); /*подаем сигнал сброса команду для адресации устройства на шине команду - чтение внутренней памяти затем считываем внутреннюю память датчика в массив */ OWI_DetectPresence(bus); OWI_MatchRom(id, bus); OWI_SendByte(DS18B20_READ_SCRATCHPAD, bus); for (i = 0; i<=8; i++){ scratchpad[i] = OWI_ReceiveByte(bus); } if(OWI_CheckScratchPadCRC(scratchpad) != OWI_CRC_OK){ return READ_CRC_ERROR; } *ds18b20_temperature = MAKEWORD(scratchpad[0], scratchpad[1]); return READ_SUCCESSFUL; }
unsigned char OWI_SearchAlarm( unsigned char * bitPattern, unsigned char lastDeviation, unsigned char pin ) { unsigned char currentBit = 1; unsigned char newDeviation = 0; unsigned char bitMask = 0x01; unsigned char bitA; unsigned char bitB; // Send SEARCH ROM command on the bus. OWI_SendByte(OWI_ROM_ALARM, pin); // Walk through all 64 bits. while ( currentBit <= 64 ) { // Read bit from bus twice. bitA = OWI_ReadBit(pin); bitB = OWI_ReadBit(pin); if ( bitA && bitB ) { // Both bits 1 (Error). newDeviation = OWI_ROM_SEARCH_FAILED; return newDeviation; } else if ( bitA ^ bitB ) { // Bits A and B are different. All devices have the same bit here. // Set the bit in bitPattern to this value. if ( bitA ) { ( *bitPattern ) |= bitMask; } else { ( *bitPattern ) &= ~bitMask; } } else // Both bits 0 { // If this is where a choice was made the last time, // a '1' bit is selected this time. if ( currentBit == lastDeviation ) { ( *bitPattern ) |= bitMask; } // For the rest of the id, '0' bits are selected when // discrepancies occur. else if ( currentBit > lastDeviation ) { ( *bitPattern ) &= ~bitMask; newDeviation = currentBit; } // If current bit in bit pattern = 0, then this is // out new deviation. else if ( !( *bitPattern & bitMask ) ) { newDeviation = currentBit; } // IF the bit is already 1, do nothing. else { } } // Send the selected bit to the bus. if ( ( *bitPattern ) & bitMask ) { OWI_WriteBit1(pin); } else { OWI_WriteBit0(pin); } // Increment current bit. currentBit++; // Adjust bitMask and bitPattern pointer. bitMask <<= 1; if ( !bitMask ) { bitMask = 0x01; bitPattern++; } } return newDeviation; }
/* * owiADCConvert(unsigned char bus_pattern, unsigned char * id) * * * this function implements the convert function * using the 0x3C command * * CRC checks are not performed * * input: * bus_pattern: * pattern of bus lines to send command to * id : * 1-wire device id 8 byte char array * - if set, i.e. not NULL, only device with this id is addressed (MATCH_ROM) * - else every device is used (ROM_SKIP) * * return: * 0: ok * 1: failed * */ uint8_t owiADCConvert(unsigned char currentPins, unsigned char * id) { printDebug_p(debugLevelEventDebug, debugSystemOWIADC, __LINE__, filename, PSTR("bus_pattern: %#x starting conversion sequence"), currentPins ); static uint16_t maxConversionTime = OWI_ADC_MAX_CONVERSION_TIME_MILLISECONDS; static uint32_t count; static uint32_t maxcount; static unsigned char timeout_flag; uint8_t trialsCounter = 0; uint8_t result = RESULT_OK; uint16_t receive_CRC; maxcount = ( OWI_ADC_CONVERSION_DELAY_MILLISECONDS > 0 ) ? maxConversionTime / OWI_ADC_CONVERSION_DELAY_MILLISECONDS : 1; count = maxcount; timeout_flag = FALSE; /* * CONVERT [3CH] * * The Convert command is used to initiate the analog to digital conversion for one or more channels at the * resolution specified in memory page 1, control/status data. The conversion takes between 60 and 80 μs * per bit plus an offset time of maximum 160 μs every time the convert command is issued. For four * channels with 12-bit resolution each, as an example, the convert command will not take more than * 4x12x80 μs plus 160 μs offset, which totals 4 ms. If the DS2450 gets its power through the VCC pin, the * bus master may communicate with other devices on the 1-Wire bus while the DS2450 is busy with A/D * conversions. If the device is powered entirely from the 1-Wire bus, the bus master must instead provide a * strong pullup to 5V for the estimated duration of the conversion in order to provide sufficient energy. * * The conversion is controlled by the input select mask (Figure 7a) and the read-out control byte (Figure * 7b). In the input select mask the bus master specifies which channels participate in the conversion. A * channel is selected if the bit associated to the channel is set to 1. If more than one channel is selected, the * conversion takes place one channel after another in the sequence A, B, C, D, skipping those channels that * are not selected. The bus master can read the result of a channel’s conversion before the conversion of all * the remaining selected channels is completed. In order to distinguish between the previous result and the * new value the bus master uses the read-out control byte. This byte allows presetting the conversion readout * registers for each selected channel to all 1’s or all 0’s. If the expected result is close to 0 then one * should preset to all 1’s or to all 0’s if the conversion result will likely be a high number. In applications * where the bus master can wait until all selected channels are converted before reading, a preset of the * read-out registers is not necessary. Note that for a channel not selected in the input select mask, the * channel’s read-out control setting has no effect. If a channel constantly yields conversion results close to * 0 the channel’s output transistor may be conducting. See section Device Registers for details. * * INPUT SELECT MASK (CONVERSION COMMAND) Figure 7a * bit 7 bit 6 bit 5 bit 4 bit 3 bit 2 bit 1 bit 0 * “don’t care” D C B A * * READ-OUT CONTROL (CONVERSION COMMAND) Figure 7b * bit 7 bit 6 bit 5 bit 4 bit 3 bit 2 bit 1 bit 0 * Set D Clear D Set C Clear C Set B Clear B Set A Clear A * * Set Clear Explanation * 0 0 no preset, leave as is * 0 1 preset to all 0’s * 1 0 preset to all 1’s * 1 1 (illegal code) * * Following the Convert command byte the bus master transmits the input select mask and the read-out * control byte. Now the bus master reads the CRC16 of the command byte, select mask and control byte. * The conversion will start no earlier than 10 μs after the most significant bit of the CRC is received by the * bus master. * * With a parasitic power supply the bus master must activate the strong pullup within this 10 μs window for * a duration that is estimated as explained above. After that, the data line returns to an idle high state and * communication on the bus can resume. The bus master would normally send a reset pulse to exit the * Convert command. Read data time slots generated after the strong pullup has ended but before issuing a * reset pulse should result in all 1’s if the conversion time was calculated correctly. * * With VCC power supply the bus master may either send a reset pulse to exit the Convert command or * continuously generate read data time slots. As long as the DS2450 is busy with conversions the bus * master will read 0’s. After the conversion is completed the bus master will receive 1’s instead. Since in a * open-drain environment a single 0 overwrites multiple 1’s the bus master can monitor multiple devices * converting simultaneously and immediately knows when the last one is ready. As in the parasite * powered scenario the bus master finally has to exit the Convert command by issuing a rest pulse. * * from data sheet: http://datasheets.maximintegrated.com/en/ds/DS2450.pdf */ while( trialsCounter < OWI_SEND_BYTE_MAX_TRIALS ) { trialsCounter++; receive_CRC = 0; result = RESULT_OK; printDebug_p(debugLevelEventDebug, debugSystemOWIADC, __LINE__, filename, PSTR("bus_pattern: %#x sending command, mask, readout byte"),currentPins ); /* select one or all, depending if id is given */ if ( NULL == id) { /* * SKIP ROM [CCH] * * This command can save time in a single drop bus system by allowing the bus master to access the * memory/convert functions without providing the 64-bit ROM code. If more than one slave is present on * the bus and a read command is issued following the Skip ROM command, data collision will occur on the * bus as multiple slaves transmit simultaneously (open drain pulldowns will produce a wired-AND result). */ OWI_SkipRom(currentPins); result = owiSendBytesAndCheckCRC16(currentPins, 3, DS2450_CONVERT, DS2450_CONVERSION_CHANNEL_SELECT_MASK, DS2450_CONVERSION_READOUT_CONTROL); result = RESULT_OK; /*disable CRC check for skip rom*/ } else { /* * MATCH ROM [55H] * * The match ROM command, followed by a 64-bit ROM sequence, allows the bus master to address a * specific DS2450 on a multidrop bus. Only the DS2450 that exactly matches the 64-bit ROM sequence * will respond to the following memory/convert function command. All slaves that do not match the 64-bit * ROM sequence will wait for a reset pulse. This command can be used with a single or multiple devices * on the bus. */ OWI_MatchRom(id, currentPins); // Match id found earlier result = owiSendBytesAndCheckCRC16(currentPins, 3, DS2450_CONVERT, DS2450_CONVERSION_CHANNEL_SELECT_MASK, DS2450_CONVERSION_READOUT_CONTROL); result = RESULT_OK; /*disable CRC check for skip rom*/ } // printDebug_p(debugLevelEventDebug, debugSystemOWIADC, __LINE__, filename, PSTR("crc16 checksum 3 bytes %#x ?"), owiComputeCRC16(0x0000, 3, DS2450_CONVERT, DS2450_CONVERSION_CHANNEL_SELECT_MASK, DS2450_CONVERSION_READOUT_CONTROL) ); // printDebug_p(debugLevelEventDebug, debugSystemOWIADC, __LINE__, filename, PSTR("crc16 checksum 4 bytes %#x ?"), owiComputeCRC16(0x0000, 4, OWI_ROM_SKIP, DS2450_CONVERT, DS2450_CONVERSION_CHANNEL_SELECT_MASK, DS2450_CONVERSION_READOUT_CONTROL) ); // printDebug_p(debugLevelEventDebug, debugSystemOWIADC, __LINE__, filename, PSTR("crc16 checksum 3 bytes %#x ?"), owiComputeCRC16(0xFFFF, 3, DS2450_CONVERT, DS2450_CONVERSION_CHANNEL_SELECT_MASK, DS2450_CONVERSION_READOUT_CONTROL) ); // printDebug_p(debugLevelEventDebug, debugSystemOWIADC, __LINE__, filename, PSTR("crc16 checksum 4 bytes %#x ?"), owiComputeCRC16(0xFFFF, 4, OWI_ROM_SKIP, DS2450_CONVERT, DS2450_CONVERSION_CHANNEL_SELECT_MASK, DS2450_CONVERSION_READOUT_CONTROL) ); if ( RESULT_OK == result ) { break; } else { if (OWI_SEND_BYTE_MAX_TRIALS != trialsCounter) { printDebug_p(debugLevelEventDebug, debugSystemOWIADC, __LINE__, filename, PSTR("CRC16 check send byte failed - trial no. %i, computed %#x != received %#x"), trialsCounter); /* ending the Convert command sequence in any case by issuing a Reset Pulse*/ OWI_DetectPresence(currentPins); /*the "DetectPresence" function includes sending a Reset Pulse*/ continue; } else { CommunicationError_p(ERRG, dynamicMessage_ErrorIndex, TRUE, PSTR("CRC16 check reached max trials (%i) on send byte"), OWI_SEND_BYTE_MAX_TRIALS); result = RESULT_FAILURE; break; } } } //loop that waits for the conversion to be done if ( RESULT_OK == result ) { result = RESULT_OK; while ( OWI_ReadBit(currentPins) == 0 ) { _delay_ms(OWI_ADC_CONVERSION_DELAY_MILLISECONDS); /* timeout check */ if ( 0 == --count) { timeout_flag = TRUE; result = RESULT_FAILURE; break; } } printDebug_p(debugLevelEventDebug, debugSystemOWIADC, __LINE__, filename, PSTR("waited %i times a delay of %i ms"), maxcount - count, OWI_ADC_CONVERSION_DELAY_MILLISECONDS); /* ending the Convert command sequence in any case by issuing a Reset Pulse*/ OWI_DetectPresence(currentPins); /*the "DetectPresence" function includes sending a Reset Pulse*/ } /* post conversion status analysis*/ if (RESULT_OK == result) { owiAdcTimeoutAndFailureBusMask &= ~(currentPins); result = RESULT_OK; printDebug_p(debugLevelEventDebug, debugSystemOWIADC, __LINE__, filename, PSTR("OWI ADC Conversion failed (bus_pattern: %#x)"), currentPins); } else { result = RESULT_FAILURE; if ( NULL == id ) { owiAdcTimeoutAndFailureBusMask |= currentPins; if ( FALSE != timeout_flag ) { CommunicationError_p(ERRG, dynamicMessage_ErrorIndex, TRUE, PSTR("OWI ADC Conversion timeout (bus_pattern: %#x"), currentPins); printDebug_p(debugLevelEventDebug, debugSystemOWIADC, __LINE__, filename, PSTR("OWI Adc Conversion timeout (>%i ms) on bus_mask (%#x)"), maxConversionTime, currentPins); } CommunicationError_p(ERRG, dynamicMessage_ErrorIndex, TRUE, PSTR("OWI ADC Conversion failed (bus_pattern: %#x)"), currentPins); } else { owiCreateIdString(owi_id_string, id); if ( FALSE != timeout_flag ) { CommunicationError_p(ERRG, dynamicMessage_ErrorIndex, TRUE, PSTR("OWI ADC Conversion timeout (id: %s"), owi_id_string); printDebug_p(debugLevelEventDebug, debugSystemOWIADC, __LINE__, filename, PSTR("OWI Adc Conversion timeout (>%i ms) (id: %s)"), maxConversionTime, owi_id_string); } CommunicationError_p(ERRG, dynamicMessage_ErrorIndex, TRUE, PSTR("OWI ADC Conversion failed (id: %s)"), owi_id_string); } } return result; }