/** ****************************************************************************** * @file dallas_tools.c * @brief Драйвер для работы с датчиками температуры DS18B20 * @author MicroTechnics (microtechnics.ru) ****************************************************************************** @details Этот файл содержит реализацию функций для работы с датчиком DALLAS_HandleTypeDef через интерфейс 1-Wire. Он предоставляет функции для чтения и записи конфигурации, выполнения измерений и обработки полученных данных. *****************************************************************************/ /* Includes ----------------------------------------------------------------*/ #include "dallas_tools.h" /* Declarations and definitions --------------------------------------------*/ struct { DALLAS_HandleTypeDef outdoor; DALLAS_HandleTypeDef indoor; DALLAS_HandleTypeDef bathroom; DALLAS_HandleTypeDef kitchen; DALLAS_HandleTypeDef big_room; DALLAS_HandleTypeDef small_room; DALLAS_HandleTypeDef living_room; DALLAS_HandleTypeDef basement; }AllSens; /* Functions ---------------------------------------------------------------*/ void Dallas_ReadAll(void) { HAL_StatusTypeDef result; result = Dallas_StartConvertTAll(&OW, DALLAS_WAIT_BUS, 0); result = Dallas_ReadTemperature(&AllSens.outdoor); result = Dallas_ReadTemperature(&AllSens.indoor); result = Dallas_ReadTemperature(&AllSens.bathroom); result = Dallas_ReadTemperature(&AllSens.kitchen); result = Dallas_ReadTemperature(&AllSens.big_room); result = Dallas_ReadTemperature(&AllSens.small_room); result = Dallas_ReadTemperature(&AllSens.living_room); result = Dallas_ReadTemperature(&AllSens.basement); } void Dallas_FirstInit(void) { uint8_t mask = DALLAS_USER_BYTE_ALL; OneWire_Init(&OW); DS18B20_Search(&DS, &OW); Dallas_SensorInitByInd(&OW, &AllSens.outdoor, 0); Dallas_WriteUserBytes(&AllSens.outdoor, 1, NULL, mask); Dallas_SensorInitByInd(&OW, &AllSens.indoor, 1); Dallas_WriteUserBytes(&AllSens.indoor, 2, NULL, mask); Dallas_SensorInitByInd(&OW, &AllSens.bathroom, 2); Dallas_WriteUserBytes(&AllSens.bathroom, 3, NULL, mask); Dallas_SensorInitByInd(&OW, &AllSens.kitchen, 3); Dallas_WriteUserBytes(&AllSens.kitchen, 4, NULL, mask); Dallas_SensorInitByInd(&OW, &AllSens.big_room, 4); Dallas_WriteUserBytes(&AllSens.big_room, 5, NULL, mask); Dallas_SensorInitByInd(&OW, &AllSens.small_room, 5); Dallas_WriteUserBytes(&AllSens.small_room, 6, NULL, mask); Dallas_SensorInitByInd(&OW, &AllSens.living_room, 6); Dallas_WriteUserBytes(&AllSens.living_room, 7, NULL, mask); Dallas_SensorInitByInd(&OW, &AllSens.basement, 7); Dallas_WriteUserBytes(&AllSens.basement, 8, NULL, mask); } /** * @brief Инициализирует структуру датчика по индеку * @param onewire Указатель на структуру OneWire * @param sensor Указатель на структуру датчика * @param UserBytes34 Пользовательские байты 3 и 4, NULL для игнора * @param UserBytes12 Пользовательские байты 1 и 2, NULL для игнора * @retval HAL Status * @details старший байт - UserByte4/UserByte2, младший - UserByte3/UserByte1. */ HAL_StatusTypeDef Dallas_SensorInitByUserBytes(OneWire_t *onewire, DALLAS_HandleTypeDef *sensor, uint16_t UserBytes34, uint16_t UserBytes12) { HAL_StatusTypeDef result; uint8_t UserByte1 = UserBytes12 & 0xFF; uint8_t UserByte2 = UserBytes12 >> 8; uint8_t UserByte3 = UserBytes34 & 0xFF; uint8_t UserByte4 = UserBytes34 >> 8; uint8_t UserByte12Cmp = 0; uint8_t UserByte34Cmp = 0; if(onewire == NULL) return HAL_ERROR; if(sensor == NULL) return HAL_ERROR; for(int i = 0; i < DS18B20_DEVICE_AMOUNT; i++) { UserByte12Cmp = 0; UserByte34Cmp = 0; sensor->sensROM = &DS.DevAddr[i]; sensor->onewire = onewire; /* Проверка присутствует ли выбранный датчик на линии */ result = Dallas_IsConnected(sensor); if (result != HAL_OK) return result; /* Сравнение UserByte1 и UserByte2, если выбрано */ if(UserBytes12 != NULL) { if( (sensor->scratchpad.tHighRegister == UserByte1) && (sensor->scratchpad.tLowRegister == UserByte2)) { UserByte12Cmp = 1; } }/* Если равнение UserByte1 и UserByte2 не выбрано, то считаем что они одинаковые */ else { UserByte12Cmp = 1; } /* Сравнение UserByte3 и UserByte4, если выбрано */ if(UserBytes34 != NULL) { if( (sensor->scratchpad.UserByte3 == UserByte3) && (sensor->scratchpad.UserByte4 == UserByte4)) { UserByte34Cmp = 1; } }/* Если равнение UserByte3 и UserByte4 не выбрано, то считаем что они одинаковые */ else { UserByte34Cmp = 1; } /* Если нашли нужный датчик - завершаем поиск */ if(UserByte12Cmp && UserByte34Cmp) { return HAL_OK; } } /* Возвращаем ошибку если не нашли */ return HAL_ERROR; } /** * @brief Инициализирует структуру датчика по индеку * @param onewire Указатель на структуру OneWire * @param sensor Указатель на структуру датчика * @param sens_ind Порядковый номер датчика в структуре * @retval HAL Status * @details Индекс - это порядковый номер датчика в списке найденных. * Т.е. каким по счету этот датчик был найден */ HAL_StatusTypeDef Dallas_SensorInitByInd(OneWire_t *onewire, DALLAS_HandleTypeDef *sensor, uint8_t sens_ind) { HAL_StatusTypeDef result; if(onewire == NULL) return HAL_ERROR; if(sensor == NULL) return HAL_ERROR; sensor->sensROM = &DS.DevAddr[sens_ind]; sensor->onewire = onewire; /* Проверка присутствует ли выбранный датчик на линии */ result = Dallas_IsConnected(sensor); if (result != HAL_OK) return result; return HAL_OK; } /** * @brief Запускает измерение температуры на всех датчиках * @param waitCondition Условие ожидания завершения преобразования * @retval HAL Status */ HAL_StatusTypeDef Dallas_StartConvertTAll(OneWire_t *onewire, DALLAS_WaitCondition waitCondition, uint8_t dallas_delay_ms) { HAL_StatusTypeDef result; uint8_t rxDummyData; // Отправка команды начала преобразования температуры result = DS18B20_StartConvTAll(onewire); if(result != HAL_OK) { return result; } // Ожидание завершения преобразования, путем проверки шины if (waitCondition == DALLAS_WAIT_BUS) { result = DS18B20_WaitForEndConvertion(onewire); return result; } // Ожидание завершения преобразования, путем задержки if (waitCondition == DALLAS_WAIT_DELAY) { uint32_t delayValueMs = 0; switch (dallas_delay_ms) { case DALLAS_CONFIG_9_BITS: delayValueMs = DALLAS_DELAY_MS_9_BITS; break; case DALLAS_CONFIG_10_BITS: delayValueMs = DALLAS_DELAY_MS_10_BITS; break; case DALLAS_CONFIG_11_BITS: delayValueMs = DALLAS_DELAY_MS_11_BITS; break; case DALLAS_CONFIG_12_BITS: delayValueMs = DALLAS_DELAY_MS_12_BITS; break; default: break; } HAL_Delay(delayValueMs); } return result; } /** * @brief Измеряет температуру на датчике * @param sensor Указатель на структуру датчика * @param waitCondition Условие ожидания завершения преобразования * @retval HAL Status */ HAL_StatusTypeDef Dallas_ConvertT(DALLAS_HandleTypeDef *sensor, DALLAS_WaitCondition waitCondition) { HAL_StatusTypeDef result; uint8_t rxDummyData; /* Проверка присутствует ли выбранный датчик на линии */ result = Dallas_IsConnected(sensor); if (result != HAL_OK) return result; // Отправка команды начала преобразования температуры result = DS18B20_StartConvT(sensor->onewire, (uint8_t *)sensor->sensROM); if(result != HAL_OK) { return result; } // Ожидание завершения преобразования, путем проверки шины if (waitCondition == DALLAS_WAIT_BUS) { result = DS18B20_WaitForEndConvertion(sensor->onewire); if(result == HAL_TIMEOUT) { sensor->f.timeout_convertion_cnt++; } return result; } // Ожидание завершения преобразования, путем задержки if (waitCondition == DALLAS_WAIT_DELAY) { uint32_t delayValueMs = 0; switch (sensor->scratchpad.ConfigRegister) { case DALLAS_CONFIG_9_BITS: delayValueMs = DALLAS_DELAY_MS_9_BITS; break; case DALLAS_CONFIG_10_BITS: delayValueMs = DALLAS_DELAY_MS_10_BITS; break; case DALLAS_CONFIG_11_BITS: delayValueMs = DALLAS_DELAY_MS_11_BITS; break; case DALLAS_CONFIG_12_BITS: delayValueMs = DALLAS_DELAY_MS_12_BITS; break; default: break; } HAL_Delay(delayValueMs); } /* Не считываем температуру, если не выбрано ожидание окончания преобразования */ if(waitCondition != DALLAS_WAIT_NONE) { result = Dallas_ReadTemperature(sensor); } return result; } /** * @brief Читает содержимое памяти (scratchpad) датчика DALLAS_HandleTypeDef * @param sensor Указатель на структуру датчика * @retval HAL Status */ HAL_StatusTypeDef Dallas_ReadTemperature(DALLAS_HandleTypeDef *sensor) { HAL_StatusTypeDef result; /* Проверка присутствует ли выбранный датчик на линии */ result = Dallas_IsConnected(sensor); if (result != HAL_OK) return result; result = DS18B20_CalcTemperature(sensor->onewire, (uint8_t *)sensor->sensROM, (uint8_t *)&sensor->scratchpad, &sensor->temperature); if (result != HAL_OK) { sensor->f.read_temperature_err_cnt++; return result; } return HAL_OK; } /** * @brief Выполняет команду инициализации DALLAS_HandleTypeDef * @param sensor Указатель на структуру датчика * @retval HAL Status */ HAL_StatusTypeDef Dallas_IsConnected(DALLAS_HandleTypeDef *sensor) { HAL_StatusTypeDef result; result = DS18B20_ReadScratchpad(sensor->onewire, (uint8_t *)sensor->sensROM, (uint8_t *)&sensor->scratchpad); if (result == HAL_OK) { sensor->isConnected = 1; return HAL_OK; } else { if(sensor->isConnected == 1) { sensor->f.disconnect_cnt++; } sensor->isConnected = 0; return HAL_BUSY; // использую busy, чтобы отличать ситуацию от HAL_ERROR } } /** * @brief Записывает пользовательские байты * @param sensor Указатель на структуру датчика * @param UserBytes12 Пользовательские байты 1 и 2 * @param UserBytes34 Пользовательские байты 3 и 4 * @param UserBytesMask Маска, какие байты записывать, а какие нет * @retval HAL Status * @details старший байт - UserByte4/UserByte2, младший - UserByte3/UserByte1. */ HAL_StatusTypeDef Dallas_WriteUserBytes(DALLAS_HandleTypeDef *sensor, uint16_t UserBytes12, uint16_t UserBytes34, uint8_t UserBytesMask) { HAL_StatusTypeDef result = DS18B20_WriteUserBytes(sensor->onewire, (uint8_t *)sensor->sensROM, UserBytes12, UserBytes34, UserBytesMask); if (result != HAL_OK) { sensor->f.read_temperature_err_cnt++; return result; } result = DS18B20_ReadScratchpad(sensor->onewire, (uint8_t *)sensor->sensROM, (uint8_t *)&sensor->scratchpad); if (result != HAL_OK) { sensor->f.read_temperature_err_cnt++; return result; } return result; } ///** // * @brief Читает уникальный ROM-код датчика DALLAS_HandleTypeDef // * @param sensor Указатель на структуру датчика // * @retval HAL Status // */ //HAL_StatusTypeDef Dallas_ReadRom(DALLAS_HandleTypeDef *sensor) //{ // HAL_StatusTypeDef result = HAL_OK; // uint8_t rxData[DALLAS_READ_ROM_RX_BYTES_NUM]; // // DS18B20_ReadScratchpad(sensor->onewire, sensor->sensROM, (uint8_t *)&sensor->scratchpad); // // // if (result == HAL_OK) // { // for (uint8_t i = 0; i < DALLAS_SERIAL_NUMBER_LEN_BYTES; i++) // { // sensor->sensROM[i] = rxData[DALLAS_SERIAL_NUMBER_OFFSET_BYTES + i]; // } // } // return result; //}