/** ****************************************************************************** * @file ds18b20_driver.c * @brief This file includes the HAL/LL driver for DS18B20 1-Wire Digital * Thermometer ****************************************************************************** */ #include "ds18b20_driver.h" DS18B20_Drv_t DS; OneWire_t OW; /** * @brief The function is used to check valid DS18B20 ROM * @retval Return in OK = 1, Failed = 0 * @param ROM Pointer to ROM number */ HAL_StatusTypeDef DS18B20_IsValidAddress(uint8_t *ROM) { if(ROM == NULL) return HAL_ERROR; uint8_t check_family = (*ROM == DS18B20_FAMILY_CODE); /* Calculate CRC */ uint8_t crc = OneWire_CRC8(ROM, 7); uint8_t check_crc = (crc == ROM[7]); /* Checks if first byte is equal to DS18B20's family code */ if(check_family && check_crc) return HAL_OK; else return HAL_ERROR; } /** * @brief The function is used to check valid DS18B20 ROM * @retval Return in OK = 1, Failed = 0 * @param ROM Pointer to ROM number */ HAL_StatusTypeDef DS18B20_IsValid(uint8_t *ROM) { if(ROM == NULL) return HAL_ERROR; if(*ROM == DS18B20_FAMILY_CODE) return HAL_OK; else return HAL_ERROR; } /** * @brief The function is used to get resolution * @retval Return value in 9 - 12 * @param OW OneWire HandleTypedef * @param ROM Pointer to ROM number */ uint8_t DS18B20_GetResolution(OneWire_t* OW, uint8_t *ROM) { uint8_t conf; if(OW == NULL) return HAL_ERROR; if(ROM == NULL) return HAL_ERROR; /* Check valid ROM */ if (DS18B20_IsValid(ROM) != HAL_OK) return 0; /* Reset line */ OneWire_Reset(OW); /* Select ROM number */ OneWire_MatchROM(OW, ROM); /* Read scratchpad command by onewire protocol */ OneWire_WriteByte(OW, DS18B20_CMD_READSCRATCHPAD); /* Ignore first 4 bytes */ OneWire_ReadByte(OW); OneWire_ReadByte(OW); OneWire_ReadByte(OW); OneWire_ReadByte(OW); /* 5th byte of scratchpad is configuration register */ conf = OneWire_ReadByte(OW); /* Return 9 - 12 value according to number of bits */ return ((conf & 0x60) >> 5) + 9; } /** * @brief The function is used as set resolution * @retval status in OK = 1, Failed = 0 * @param OW OneWire HandleTypedef * @param ROM Pointer to ROM number * @param Resolution Resolution in 9 - 12 */ HAL_StatusTypeDef DS18B20_SetResolution(OneWire_t* OW, uint8_t *ROM, DS18B20_Res_t Resolution) { if(OW == NULL) return HAL_ERROR; if(ROM == NULL) return HAL_ERROR; uint8_t th, tl, conf; /* Check valid ROM */ if (DS18B20_IsValid(ROM) != HAL_OK) return HAL_ERROR; /* Reset line */ OneWire_Reset(OW); /* Select ROM number */ OneWire_MatchROM(OW, ROM); /* Read scratchpad command by onewire protocol */ OneWire_WriteByte(OW, DS18B20_CMD_READSCRATCHPAD); /* Ignore first 2 bytes */ OneWire_ReadByte(OW); OneWire_ReadByte(OW); th = OneWire_ReadByte(OW); tl = OneWire_ReadByte(OW); conf = OneWire_ReadByte(OW); /* Set choosed resolution */ conf = Resolution; /* Reset line */ OneWire_Reset(OW); /* Select ROM number */ OneWire_MatchROM(OW, ROM); /* Write scratchpad command by onewire protocol, only th, tl and conf * register can be written */ OneWire_WriteByte(OW, DS18B20_CMD_WRITESCRATCHPAD); /* Write bytes */ OneWire_WriteByte(OW, th); OneWire_WriteByte(OW, tl); OneWire_WriteByte(OW, conf); /* Reset line */ OneWire_Reset(OW); /* Select ROM number */ OneWire_MatchROM(OW, ROM); /* Copy scratchpad to EEPROM of DS18B20 */ OneWire_WriteByte(OW, DS18B20_CMD_COPYSCRATCHPAD); return HAL_OK; } /** * @brief The function is used as start selected ROM device * @retval status in OK = 1, Failed = 0 * @param OW OneWire HandleTypedef * @param ROM Pointer to ROM number */ HAL_StatusTypeDef DS18B20_StartConvT(OneWire_t* OW, uint8_t *ROM) { if(OW == NULL) return HAL_ERROR; if(ROM == NULL) return HAL_ERROR; /* Check if device is DS18B20 */ if(DS18B20_IsValid(ROM) != HAL_OK) return HAL_ERROR; /* Reset line */ OneWire_Reset(OW); /* Select ROM number */ OneWire_MatchROM(OW, ROM); /* Start temperature conversion */ OneWire_WriteByte(OW, DS18B20_CMD_CONVERT); return HAL_OK; } /** * @brief The function is used as start all ROM device * @param OW OneWire HandleTypedef */ HAL_StatusTypeDef DS18B20_StartConvTAll(OneWire_t* OW) { if(OW == NULL) return HAL_ERROR; /* Reset pulse */ OneWire_Reset(OW); /* Skip rom */ OneWire_WriteByte(OW, ONEWIRE_CMD_SKIPROM); /* Start conversion on all connected devices */ OneWire_WriteByte(OW, DS18B20_CMD_CONVERT); return HAL_OK; } /** * @brief The function is used as read temreature from device and store in selected * destination * @retval status in OK = 1, Failed = 0 * @param OW OneWire HandleTypedef * @param ROM Pointer to ROM number * @param Destination Pointer to return value */ HAL_StatusTypeDef DS18B20_CalcTemperature(OneWire_t* OW, uint8_t *ROM, uint8_t *Scratchpad, float *Destination) { if(OW == NULL) return HAL_ERROR; if(ROM == NULL) return HAL_ERROR; if(Scratchpad == NULL) return HAL_ERROR; if(Destination == NULL) return HAL_ERROR; uint16_t temperature; uint8_t resolution; int8_t digit, minus = 0; float decimal; /* Check if device is DS18B20 */ if (DS18B20_IsValid(ROM) != HAL_OK) return HAL_ERROR; /* First two bytes of scratchpad are temperature values */ temperature = Scratchpad[0] | (Scratchpad[1] << 8); /* Reset line */ OneWire_Reset(OW); /* Check if temperature is negative */ if (temperature & 0x8000) { /* Two's complement, temperature is negative */ temperature = ~temperature + 1; minus = 1; } /* Get sensor resolution */ resolution = Scratchpad[4]; /* Store temperature integer digits and decimal digits */ digit = temperature >> 4; digit |= ((temperature >> 8) & 0x7) << 4; /* Store decimal digits */ switch (resolution) { case DS18B20_RESOLUTION_9BITS: { decimal = (temperature >> 3) & 0x01; decimal *= (float)DS18B20_DECIMAL_STEP_9BIT; } break; case DS18B20_RESOLUTION_10BITS: { decimal = (temperature >> 2) & 0x03; decimal *= (float)DS18B20_DECIMAL_STEP_10BIT; } break; case DS18B20_RESOLUTION_11BITS: { decimal = (temperature >> 1) & 0x07; decimal *= (float)DS18B20_DECIMAL_STEP_11BIT; } break; case DS18B20_RESOLUTION_12BITS: { decimal = temperature & 0x0F; decimal *= (float)DS18B20_DECIMAL_STEP_12BIT; } break; default: { *Destination = 0; return HAL_ERROR; } } /* Check for negative part */ decimal = digit + decimal; if (minus) { decimal = 0 - decimal; } /* Set to pointer */ *Destination = decimal; /* Return HAL_OK, temperature valid */ return HAL_OK; } /** * @brief The function is used as read scratchpad from device * @retval status in OK = 1, Failed = 0 * @param OW OneWire HandleTypedef * @param ROM Pointer to ROM number * @param Destination Pointer to Scratchpad array */ HAL_StatusTypeDef DS18B20_ReadScratchpad(OneWire_t* OW, uint8_t *ROM, uint8_t *Scratchpad) { if(OW == NULL) return HAL_ERROR; if(ROM == NULL) return HAL_ERROR; if(Scratchpad == NULL) return HAL_ERROR; /* Reset line */ OneWire_Reset(OW); /* Select ROM number */ OneWire_MatchROM(OW, ROM); /* Read scratchpad command by onewire protocol */ OneWire_WriteByte(OW, DS18B20_CMD_READSCRATCHPAD); /* Get data */ for (int i = 0; i < 9; i++) { /* Read byte by byte */ Scratchpad[i] = OneWire_ReadByte(OW); } /* Calculate CRC */ uint8_t crc = OneWire_CRC8(Scratchpad, 8); /* Check if CRC is ok */ if (crc != Scratchpad[8]) { /* CRC invalid */ return HAL_ERROR; } return HAL_OK; } /** * @brief The function is used to wait for end of convertion * @param OW OneWire HandleTypedef */ HAL_StatusTypeDef DS18B20_WaitForEndConvertion(OneWire_t* OW) { if(OW == NULL) return HAL_ERROR; uint32_t tickstart = HAL_GetTick(); /* Wait until line is released, then coversion is completed */ while(OneWire_ReadBit(OW) == 0) { if(HAL_GetTick() - tickstart > DS18B20_DELAY_MS_MAX) return HAL_TIMEOUT; // end of convertion has not come } return HAL_OK; // convertion done } /** * @brief The function is used to wait for end of convertion without blocking * @param OW OneWire HandleTypedef */ HAL_StatusTypeDef DS18B20_WaitForEndConvertion_NonBlocking(OneWire_t* OW) { if(OW == NULL) return HAL_ERROR; /* If line is pull down - conversion is ongoing */ if(OneWire_ReadBit(OW) == 0) return HAL_BUSY; else return HAL_OK; // convertion done } /** * @brief The function is used as set temperature alarm range on * selected device * @retval status in OK = 1, Failed = 0 * @param OW OneWire HandleTypedef * @param ROM Pointer to ROM number * @param Low Low temperature alarm, value > -55, 0 = reset * @param High High temperature alarm,, value < 125, 0 = reset */ HAL_StatusTypeDef DS18B20_SetTempAlarm(OneWire_t* OW, uint8_t *ROM, int8_t Low, int8_t High) { if(OW == NULL) return HAL_ERROR; if(ROM == NULL) return HAL_ERROR; uint8_t tl, th, conf; /* Check if device is DS18B20 */ if (DS18B20_IsValid(ROM) != HAL_OK) return HAL_ERROR; Low = ((Low < -55) || (Low == 0)) ? -55 : Low; High = ((High > 125) || (High == 0)) ? 125 : High; /* Reset line */ OneWire_Reset(OW); /* Select ROM number */ OneWire_MatchROM(OW, ROM); /* Read scratchpad command by onewire protocol */ OneWire_WriteByte(OW, DS18B20_CMD_READSCRATCHPAD); /* Ignore first 2 bytes */ OneWire_ReadByte(OW); OneWire_ReadByte(OW); th = OneWire_ReadByte(OW); tl = OneWire_ReadByte(OW); conf = OneWire_ReadByte(OW); th = (uint8_t)High; tl = (uint8_t)Low; /* Reset line */ OneWire_Reset(OW); /* Select ROM number */ OneWire_MatchROM(OW, ROM); /* Write scratchpad command by onewire protocol, only th, tl and conf * register can be written */ OneWire_WriteByte(OW, DS18B20_CMD_WRITESCRATCHPAD); /* Write bytes */ OneWire_WriteByte(OW, th); OneWire_WriteByte(OW, tl); OneWire_WriteByte(OW, conf); /* Reset line */ OneWire_Reset(OW); /* Select ROM number */ OneWire_MatchROM(OW, ROM); /* Copy scratchpad to EEPROM of DS18B20 */ OneWire_WriteByte(OW, DS18B20_CMD_COPYSCRATCHPAD); return HAL_OK; } /** * @brief The function is used as set user bytes with mask * @retval status in OK = 1, Failed = 0 * @param OW OneWire HandleTypedef * @param ROM Pointer to ROM number * @param UserBytes12 First 2 User Bytes (tHigh and tLow) * @param UserBytes34 Second 2 User Bytes * @param UserBytesMask Which User Bytes write, and which ignore */ HAL_StatusTypeDef DS18B20_WriteUserBytes(OneWire_t* OW, uint8_t *ROM, int16_t UserBytes12, int16_t UserBytes34, uint8_t UserBytesMask) { if(OW == NULL) return HAL_ERROR; if(ROM == NULL) return HAL_ERROR; uint8_t ub1, ub2, conf, ub3, ub4; uint8_t UserByte1 = UserBytes12 & 0xFF; uint8_t UserByte2 = UserBytes12 >> 8; uint8_t UserByte3 = UserBytes34 & 0xFF; uint8_t UserByte4 = UserBytes34 >> 8; /* Check if device is DS18B20 */ if (DS18B20_IsValid(ROM) != HAL_OK) return HAL_ERROR; /* Reset line */ OneWire_Reset(OW); /* Select ROM number */ OneWire_MatchROM(OW, ROM); /* Read scratchpad command by onewire protocol */ OneWire_WriteByte(OW, DS18B20_CMD_READSCRATCHPAD); /* Ignore first 2 bytes */ OneWire_ReadByte(OW); OneWire_ReadByte(OW); ub1 = OneWire_ReadByte(OW); ub2 = OneWire_ReadByte(OW); conf = OneWire_ReadByte(OW); OneWire_ReadByte(OW); ub3 = OneWire_ReadByte(OW); ub4 = OneWire_ReadByte(OW); /* If user bytes in mask */ if(UserBytesMask & (1<<0)) { ub1 = UserByte1; } if(UserBytesMask & (1<<1)) { ub2 = UserByte2; } if(UserBytesMask & (1<<2)) { ub3 = UserByte3; } if(UserBytesMask & (1<<3)) { ub4 = UserByte4; } /* Reset line */ OneWire_Reset(OW); /* Select ROM number */ OneWire_MatchROM(OW, ROM); /* Write scratchpad command by onewire protocol, only th, tl and conf * register can be written */ OneWire_WriteByte(OW, DS18B20_CMD_WRITESCRATCHPAD); /* Write bytes */ OneWire_WriteByte(OW, ub1); OneWire_WriteByte(OW, ub2); OneWire_WriteByte(OW, conf); OneWire_WriteByte(OW, ub3); OneWire_WriteByte(OW, ub4); /* Reset line */ OneWire_Reset(OW); /* Select ROM number */ OneWire_MatchROM(OW, ROM); /* Copy scratchpad to EEPROM of DS18B20 */ OneWire_WriteByte(OW, DS18B20_CMD_COPYSCRATCHPAD); return HAL_OK; } ///** // * @brief The function is used as search device that had temperature alarm // * triggered and store it in DS18B20 alarm data structure // * @retval status of search, OK = 1, Failed = 0 // * @param DS DS18B20 HandleTypedef // * @param OW OneWire HandleTypedef // */ //uint8_t DS18B20_AlarmSearch(DS18B20_Drv_t *DS, OneWire_t* OW) //{ // uint8_t t = 0; // /* Reset Alarm in DS */ // for(uint8_t i = 0; i < OW->RomCnt; i++) // { // for(uint8_t j = 0; j < 8; j++) // { // DS->AlmAddr[i][j] = 0; // } // } // /* Start alarm search */ // while (OneWire_Search(OW, DS18B20_CMD_ALARM_SEARCH)) // { // /* Store ROM of device which has alarm flag set */ // OneWire_GetDevRom(OW, DS->AlmAddr[t]); // t++; // } // return (t > 0) ? 1 : 0; //} /** * @brief The function is used to initialize the DS18B20 sensor, and search * for all ROM along the line. Store in DS18B20 data structure * @retval Rom detect status, OK = 1, No Rom detected = 0 * @param DS DS18B20 HandleTypedef * @param OW OneWire HandleTypedef */ HAL_StatusTypeDef DS18B20_Search(DS18B20_Drv_t *DS, OneWire_t *OW) { if(OW == NULL) return HAL_ERROR; OW->RomCnt = 0; /* Search all OneWire devices ROM */ while(1) { /* Start searching for OneWire devices along the line */ if(OneWire_Search(OW, ONEWIRE_CMD_SEARCHROM) != 1) break; /* Get device ROM */ OneWire_GetDevRom(OW, DS->DevAddr[OW->RomCnt]); OW->RomCnt++; } for(int i = OW->RomCnt; i < DS18B20_DEVICE_AMOUNT; i++) { for(int j = 0; j < 8; j++) DS->DevAddr[i][j] = 0; } if(OW->RomCnt > 0) return HAL_OK; else return HAL_BUSY; }