feat(ds18b20): термометры DS18B20 поверх программной 1-Wire

Перенесён из репозитория ds18b20, который подключался сабмодулем в
KONOR_ds18b20. История библиотеки осталась там; сюда пришло состояние
на момент переезда.

Ядро на C99 без stm32f10x.h и динамической памяти. Порт — пять функций
(Init, DelayUs, Reset, WriteBit, ReadBit); реализация для STM32F1 идёт
в комплекте в ports/stm32f1. Хостовые тесты на модели шины с виртуальными
датчиками проходят: tests/test_ds18b20.c.
This commit is contained in:
2026-08-23 01:15:34 +03:00
parent 13f2c8fe64
commit 873ac438f3
11 changed files with 1701 additions and 0 deletions

125
c/ds18b20/include/ds18b20.h Normal file
View File

@@ -0,0 +1,125 @@
/**
* @file ds18b20.h
* @brief Драйвер термометров DS18B20 поверх шины 1-Wire.
*
* Модуль хранит перечень найденных датчиков и последние измерения, поэтому
* ответ на запрос GUI формируется без обращения к шине.
*/
#ifndef DS18B20_H
#define DS18B20_H
#include <stdint.h>
#include "onewire.h"
/** Максимум датчиков, помещающихся в один кадр SENSOR_DATA. */
#define DS18B20_MAX_SENSORS 8U
/** Код семейства DS18B20 в первом байте ROM. */
#define DS18B20_FAMILY_CODE 0x28U
/** Размер scratchpad вместе с байтом CRC8. */
#define DS18B20_SCRATCHPAD_SIZE 9U
#define DS18B20_STATUS_VALID 0x01U /**< Измерение достоверно. */
#define DS18B20_STATUS_CRC_ERROR 0x02U /**< Не сошёлся CRC8 scratchpad. */
#define DS18B20_STATUS_NO_PRESENCE 0x04U /**< Датчик не ответил на сброс. */
#define DS18B20_STATUS_PARASITE 0x08U /**< Датчик питается паразитно. */
#define DS18B20_WRITE_OK 0U /**< Запись подтверждена обратным чтением. */
#define DS18B20_WRITE_BUS_ERROR 1U /**< Нет presence или не сошёлся CRC8. */
#define DS18B20_WRITE_REJECTED 2U /**< Датчик ответил, но значение не изменил. */
/**
* @brief Состояние одного датчика на шине.
*/
typedef struct {
uint8_t rom[ONEWIRE_ROM_SIZE]; /**< Уникальный 64-битный идентификатор. */
int16_t raw; /**< Код температуры из scratchpad. */
uint8_t user_byte1; /**< Пользовательский байт 1 (регистр TH). */
uint8_t user_byte2; /**< Пользовательский байт 2 (регистр TL). */
uint8_t config; /**< Байт конфигурации с разрешением. */
uint8_t status; /**< Битовая маска DS18B20_STATUS_*. */
} DS18B20_Sensor;
/**
* @brief Перечень датчиков шины и общее состояние питания.
*/
typedef struct {
DS18B20_Sensor sensors[DS18B20_MAX_SENSORS]; /**< Найденные датчики. */
uint8_t count; /**< Число заполненных элементов массива. */
uint8_t parasite; /**< 1, если хотя бы один датчик питается паразитно. */
} DS18B20_Bus;
/**
* @brief Ищет датчики DS18B20 и запоминает их идентификаторы.
*
* Устройства других семейств пропускаются; ранее накопленные измерения
* сбрасываются.
*
* @param bus Перечень датчиков, принадлежащий приложению.
* @return Количество найденных датчиков.
*/
uint8_t DS18B20_Scan(DS18B20_Bus *bus);
/**
* @brief Запускает преобразование во всех датчиках командой SKIP ROM.
*
* @return 1 при наличии presence-импульса, иначе 0.
*/
uint8_t DS18B20_StartConversion(void);
/**
* @brief Читает scratchpad всех известных датчиков и обновляет измерения.
*
* Ошибка отдельного датчика не прерывает опрос остальных: она отражается в
* поле status соответствующего элемента.
*
* @param bus Перечень датчиков, заполненный DS18B20_Scan.
* @return Количество датчиков с достоверным измерением.
*/
uint8_t DS18B20_ReadAll(DS18B20_Bus *bus);
/**
* @brief Возвращает время преобразования для заданного разрешения.
*
* @param config Байт конфигурации scratchpad.
* @return Время преобразования в миллисекундах.
*/
uint16_t DS18B20_ConversionTimeMs(uint8_t config);
/**
* @brief Собирает байт конфигурации из разрешения в битах.
*
* @param bits Разрешение 9..12 бит.
* @return Байт конфигурации scratchpad.
*/
uint8_t DS18B20_ConfigFromResolution(uint8_t bits);
/**
* @brief Ищет датчик по идентификатору в накопленном перечне.
*
* @param bus Перечень датчиков.
* @param rom Искомый идентификатор.
* @return Указатель на элемент перечня либо 0, если ROM не найден.
*/
DS18B20_Sensor *DS18B20_Find(DS18B20_Bus *bus, const uint8_t *rom);
/**
* @brief Записывает три байта scratchpad выбранного датчика.
*
* @param sensor Датчик из перечня; кэш обновляется при успешной записи.
* @param user_byte1 Новое значение пользовательского байта 1 (TH).
* @param user_byte2 Новое значение пользовательского байта 2 (TL).
* @param config Байт конфигурации с требуемым разрешением.
* @param save_to_eeprom Признак копирования scratchpad в EEPROM датчика.
* @return DS18B20_WRITE_OK при подтверждённой записи, DS18B20_WRITE_BUS_ERROR
* при молчании датчика или сбое CRC8, DS18B20_WRITE_REJECTED если
* датчик ответил, но оставил прежние значения.
*/
uint8_t DS18B20_WriteScratchpad(DS18B20_Sensor *sensor, uint8_t user_byte1,
uint8_t user_byte2, uint8_t config,
uint8_t save_to_eeprom);
#endif /* DS18B20_H */