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:
125
c/ds18b20/include/ds18b20.h
Normal file
125
c/ds18b20/include/ds18b20.h
Normal 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 */
|
||||
149
c/ds18b20/include/onewire.h
Normal file
149
c/ds18b20/include/onewire.h
Normal file
@@ -0,0 +1,149 @@
|
||||
/**
|
||||
* @file onewire.h
|
||||
* @brief Программная шина 1-Wire на выводе с открытым стоком.
|
||||
*
|
||||
* Драйвер не зависит от типа датчика: он выдаёт тайминги, ищет ROM и считает
|
||||
* CRC8. Работа с DS18B20 вынесена в ds18b20.c.
|
||||
*
|
||||
* Реализация разделена надвое:
|
||||
* src/onewire.c переносимая часть - побайтовый обмен, CRC8, поиск ROM,
|
||||
* MATCH ROM и SKIP ROM; ни регистров, ни задержек;
|
||||
* ports/<платформа> пять функций, зависящих от железа: OneWire_Init,
|
||||
* OneWire_DelayUs, OneWire_Reset, OneWire_WriteBit
|
||||
* и OneWire_ReadBit.
|
||||
*
|
||||
* Чтобы перенести библиотеку на другой микроконтроллер, достаточно написать
|
||||
* эти пять функций - остальное собирается как есть.
|
||||
*/
|
||||
|
||||
#ifndef ONEWIRE_H
|
||||
#define ONEWIRE_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
/** Размер идентификатора устройства 1-Wire в байтах. */
|
||||
#define ONEWIRE_ROM_SIZE 8U
|
||||
|
||||
/**
|
||||
* @brief Состояние обхода шины алгоритмом SEARCH ROM.
|
||||
*
|
||||
* Структура принадлежит вызывающему коду; параллельные обходы должны
|
||||
* использовать разные экземпляры.
|
||||
*/
|
||||
typedef struct {
|
||||
uint8_t rom[ONEWIRE_ROM_SIZE]; /**< Текущий найденный идентификатор. */
|
||||
uint8_t last_discrepancy; /**< Позиция последней развилки, 1..64. */
|
||||
uint8_t last_family_discrepancy; /**< Развилка внутри кода семейства. */
|
||||
uint8_t last_device; /**< Признак завершённого обхода. */
|
||||
} OneWire_Search;
|
||||
|
||||
/**
|
||||
* @brief Настраивает вывод шины и счётчик циклов для микросекундных задержек.
|
||||
*
|
||||
* Вызывается один раз после инициализации тактирования системы.
|
||||
*/
|
||||
void OneWire_Init(void);
|
||||
|
||||
/**
|
||||
* @brief Формирует импульс сброса и проверяет ответ устройств.
|
||||
*
|
||||
* @note На время выборки presence прерывания запрещаются примерно на 75 мкс;
|
||||
* длительность самого импульса сброса на точность не влияет.
|
||||
*
|
||||
* @return 1, если хотя бы одно устройство выдало presence-импульс, иначе 0.
|
||||
*/
|
||||
uint8_t OneWire_Reset(void);
|
||||
|
||||
/**
|
||||
* @brief Передаёт один бит в тайм-слоте записи.
|
||||
*
|
||||
* @param bit Передаваемое значение, отличное от нуля означает единицу.
|
||||
*/
|
||||
void OneWire_WriteBit(uint8_t bit);
|
||||
|
||||
/**
|
||||
* @brief Считывает один бит в тайм-слоте чтения.
|
||||
*
|
||||
* @return Принятое значение бита: 0 или 1.
|
||||
*/
|
||||
uint8_t OneWire_ReadBit(void);
|
||||
|
||||
/**
|
||||
* @brief Передаёт байт младшим битом вперёд.
|
||||
*
|
||||
* @param value Передаваемый байт.
|
||||
*/
|
||||
void OneWire_WriteByte(uint8_t value);
|
||||
|
||||
/**
|
||||
* @brief Принимает байт младшим битом вперёд.
|
||||
*
|
||||
* @return Принятый байт.
|
||||
*/
|
||||
uint8_t OneWire_ReadByte(void);
|
||||
|
||||
/**
|
||||
* @brief Передаёт блок байтов подряд без промежуточных сбросов.
|
||||
*
|
||||
* @param data Указатель на передаваемые байты.
|
||||
* @param size Количество байтов.
|
||||
*/
|
||||
void OneWire_WriteBytes(const uint8_t *data, uint32_t size);
|
||||
|
||||
/**
|
||||
* @brief Принимает блок байтов подряд.
|
||||
*
|
||||
* @param data Буфер приёмника.
|
||||
* @param size Количество байтов.
|
||||
*/
|
||||
void OneWire_ReadBytes(uint8_t *data, uint32_t size);
|
||||
|
||||
/**
|
||||
* @brief Считает CRC8 Dallas/Maxim с полиномом 0x8C.
|
||||
*
|
||||
* @param data Проверяемые байты.
|
||||
* @param size Количество байтов.
|
||||
* @return Значение CRC8; для блока вместе с контрольным байтом равно нулю.
|
||||
*/
|
||||
uint8_t OneWire_Crc8(const uint8_t *data, uint32_t size);
|
||||
|
||||
/**
|
||||
* @brief Подготавливает состояние к новому полному обходу шины.
|
||||
*
|
||||
* @param search Состояние обхода, принадлежащее вызывающему коду.
|
||||
*/
|
||||
void OneWire_SearchInit(OneWire_Search *search);
|
||||
|
||||
/**
|
||||
* @brief Находит следующий идентификатор на шине.
|
||||
*
|
||||
* @param search Состояние обхода, ранее подготовленное OneWire_SearchInit.
|
||||
* @return 1, если поле rom содержит новый проверенный ROM, иначе 0.
|
||||
*/
|
||||
uint8_t OneWire_SearchNext(OneWire_Search *search);
|
||||
|
||||
/**
|
||||
* @brief Адресует конкретное устройство командой MATCH ROM.
|
||||
*
|
||||
* @param rom Восьмибайтовый идентификатор устройства.
|
||||
* @return 1 при наличии presence-импульса, иначе 0.
|
||||
*/
|
||||
uint8_t OneWire_SelectRom(const uint8_t *rom);
|
||||
|
||||
/**
|
||||
* @brief Адресует все устройства шины командой SKIP ROM.
|
||||
*
|
||||
* @return 1 при наличии presence-импульса, иначе 0.
|
||||
*/
|
||||
uint8_t OneWire_SkipRom(void);
|
||||
|
||||
/**
|
||||
* @brief Задерживает выполнение на заданное число микросекунд.
|
||||
*
|
||||
* Используется драйверами шины и модулем DS18B20 при ожидании EEPROM.
|
||||
*
|
||||
* @param microseconds Длительность задержки.
|
||||
*/
|
||||
void OneWire_DelayUs(uint32_t microseconds);
|
||||
|
||||
#endif /* ONEWIRE_H */
|
||||
Reference in New Issue
Block a user