| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249 |
- #include "OneWireSensor.h"
- #include <furi.h>
- #include <furi_hal.h>
- #include <one_wire/one_wire_host.h>
- const SensorType DS18x2x = {
- .typename = "DS18x2x",
- .interface = &ONE_WIRE,
- .pollingInterval = 250,
- .allocator = unitemp_OneWire_alloc,
- .mem_releaser = unitemp_OneWire_free,
- .initializer = unitemp_OneWire_init,
- .deinitializer = unitemp_OneWire_deinit,
- .updater = unitemp_OneWire_update};
- /**
- * @brief Запуск общения с датчиком
- *
- * @param sensor Указатель на датчик
- * @return Истина если датчик отозвался
- */
- static bool oneWire_start(OneWireSensor* instance) {
- furi_hal_gpio_write(instance->gpio->pin, false);
- furi_delay_us(500);
- furi_hal_gpio_write(instance->gpio->pin, true);
- //Ожидание подъёма шины
- uint32_t t = furi_get_tick();
- while(!furi_hal_gpio_read(instance->gpio->pin)) {
- //Выход если шина не поднялась
- if(furi_get_tick() - t > 100) return false;
- }
- furi_delay_us(100);
- bool status = !furi_hal_gpio_read(instance->gpio->pin);
- furi_delay_us(400);
- return status;
- }
- /**
- * @brief Запись байта на шину One Wire
- *
- * @param instance Указатель на инстанс датчика
- * @param data Записываемый байт
- */
- static void oneWire_write(OneWireSensor* instance, uint8_t data) {
- for(int i = 0; i < 8; i++) {
- if((data & (1 << i)) != 0) {
- // write 1
- furi_hal_gpio_write(instance->gpio->pin, false);
- furi_delay_us(1);
- furi_hal_gpio_write(instance->gpio->pin, true);
- furi_delay_us(90);
- } else {
- furi_hal_gpio_write(instance->gpio->pin, false);
- furi_delay_us(90);
- furi_hal_gpio_write(instance->gpio->pin, true);
- //Ожидание подъёма шины
- uint32_t t = furi_get_tick();
- while(!furi_hal_gpio_read(instance->gpio->pin)) {
- //Выход если шина не поднялась
- if(furi_get_tick() - t > 100) return;
- }
- }
- }
- }
- /**
- * @brief Чтение бита на шине One Wire
- *
- * @param instance Указатель на инстанс датчика
- * @return Логический уровень бита
- */
- static bool oneWire_read_bit(OneWireSensor* instance) {
- furi_hal_gpio_write(instance->gpio->pin, false);
- furi_delay_us(2); // Длительность низкого уровня, минимум 1 мкс
- furi_hal_gpio_write(instance->gpio->pin, true);
- furi_delay_us(8); // Пауза до момента сэмплирования, всего не более 15 мкс
- bool r = furi_hal_gpio_read(instance->gpio->pin);
- furi_delay_us(80); // Ожидание до следующего тайм-слота, минимум 60 мкс с начала низкого уровня
- return r;
- }
- /**
- * @brief Чтение байта с шины One Wire
- *
- * @param instance Указатель на инстанс датчика
- * @return Байт информации
- */
- static uint8_t oneWire_read(OneWireSensor* instance) {
- uint8_t r = 0;
- for(uint8_t p = 8; p; p--) {
- r >>= 1;
- if(oneWire_read_bit(instance)) r |= 0x80;
- }
- return r;
- }
- /**
- * @brief Чтение массива байт с шины One Wire
- *
- * @param instance Указатель на инстанс датчика
- * @param data Указатель на массив, куда будут записаны данные
- * @param len Количество байт
- */
- static void oneWire_readBytes(OneWireSensor* instance, uint8_t* data, size_t len) {
- for(size_t i = 0; i < len; i++) {
- data[i] = oneWire_read(instance);
- }
- }
- /**
- * @brief Запись массива байт на шину One Wire
- *
- * @param instance Указатель на инстанс датчика
- * @param data Указатель на массив, откуда будут записаны данные
- * @param len Количество байт
- */
- static void oneWire_writeBytes(OneWireSensor* instance, uint8_t* data, size_t len) {
- for(size_t i = 0; i < len; i++) {
- oneWire_write(instance, data[i]);
- }
- }
- bool unitemp_OneWire_alloc(void* s, uint16_t* anotherValues) {
- Sensor* sensor = (Sensor*)s;
- OneWireSensor* instance = malloc(sizeof(OneWireSensor));
- if(instance == NULL) {
- FURI_LOG_E(APP_NAME, "Sensor %s instance allocation error", sensor->name);
- return false;
- }
- sensor->instance = instance;
- instance->gpio = unitemp_GPIO_getFromInt(anotherValues[0]);
- if(instance->gpio != NULL) {
- return true;
- }
- FURI_LOG_E(APP_NAME, "Sensor %s GPIO setting error", sensor->name);
- free(instance);
- return false;
- }
- static uint8_t onewire_CRC_update(uint8_t crc, uint8_t b) {
- for(uint8_t p = 8; p; p--) {
- crc = ((crc ^ b) & 1) ? (crc >> 1) ^ 0b10001100 : (crc >> 1);
- b >>= 1;
- }
- return crc;
- }
- static bool onewire_CRC_check(uint8_t* data, size_t len) {
- uint8_t crc = 0;
- for(size_t i = 0; i < len; i++) {
- crc = onewire_CRC_update(crc, data[i]);
- }
- return !crc;
- }
- bool unitemp_OneWire_free(void* s) {
- Sensor* sensor = (Sensor*)s;
- free(sensor->instance);
- return true;
- }
- bool unitemp_OneWire_init(void* s) {
- OneWireSensor* instance = ((Sensor*)s)->instance;
- if(instance == NULL || instance->gpio == NULL) {
- FURI_LOG_E(APP_NAME, "Sensor pointer is null!");
- return false;
- }
- //Высокий уровень по умолчанию
- furi_hal_gpio_write(instance->gpio->pin, true);
- //Режим работы - OpenDrain, подтяжка включается на всякий случай
- furi_hal_gpio_init(
- instance->gpio->pin, //Порт FZ
- GpioModeOutputOpenDrain, //Режим работы - открытый сток
- GpioPullUp, //Принудительная подтяжка линии данных к питанию
- GpioSpeedVeryHigh); //Скорость работы - максимальная
- if(!oneWire_start(instance)) return false;
- oneWire_write(instance, 0x33); // Чтение ПЗУ
- uint8_t buff[8];
- oneWire_readBytes(instance, buff, 8);
- if(!onewire_CRC_check(buff, 8)) {
- return false;
- }
- FURI_LOG_D(APP_NAME, "%s family code: 0x%02X", ((Sensor*)s)->name, buff[0]);
- instance->familyCode = buff[0];
- if(instance->familyCode == FC_DS18B20 || instance->familyCode == FC_DS1822) {
- //Установка разрядности в 10 бит
- if(!oneWire_start(instance)) return false;
- oneWire_write(instance, 0xCC); // skip ROM
- oneWire_write(instance, 0x4E); // Запись в память
- buff[0] = 0x4B; //Значение нижнего предела
- buff[1] = 0x46; //Значение высшего предела
- buff[2] = 0x3F; //10 бит разрядность преобразования
- oneWire_writeBytes(instance, buff, 3);
- //Сохранение значений в EEPROM для автоматического восстановления после сбоев питания
- if(!oneWire_start(instance)) return false;
- oneWire_write(instance, 0xCC); // skip ROM
- oneWire_write(instance, 0x48); // Запись в EEPROM
- }
- return true;
- }
- bool unitemp_OneWire_deinit(void* s) {
- OneWireSensor* instance = ((Sensor*)s)->instance;
- if(instance == NULL || instance->gpio == NULL) return false;
- //Низкий уровень по умолчанию
- furi_hal_gpio_write(instance->gpio->pin, false);
- //Режим работы - аналог, подтяжка выключена
- furi_hal_gpio_init(
- instance->gpio->pin, //Порт FZ
- GpioModeAnalog, //Режим работы - аналог
- GpioPullNo, //Подтяжка выключена
- GpioSpeedLow); //Скорость работы - минимальная
- return true;
- }
- UnitempStatus unitemp_OneWire_update(void* s) {
- Sensor* sensor = (Sensor*)s;
- OneWireSensor* instance = ((Sensor*)s)->instance;
- if(sensor->status != UT_POLLING) {
- if(!oneWire_start(instance)) return UT_TIMEOUT;
- oneWire_write(instance, 0xCC); // skip ROM
- oneWire_write(instance, 0x44); // convert t
- return UT_POLLING;
- } else {
- if(!oneWire_start(instance)) return UT_TIMEOUT;
- oneWire_write(instance, 0xCC); // skip ROM
- oneWire_write(instance, 0xBE); // Read Scratch-pad
- uint8_t buff[9];
- oneWire_readBytes(instance, buff, 9);
- if(!onewire_CRC_check(buff, 9)) {
- return UT_BADCRC;
- }
- int16_t raw = buff[0] | ((int16_t)buff[1] << 8);
- if(instance->familyCode == FC_DS18S20) {
- sensor->temp = (float)raw / 2.0f;
- } else {
- sensor->temp = (float)raw / 16.0f;
- }
- }
- return UT_OK;
- }
|