Интерфейс 1-Wire
1-Wire — шина, в которой ведущему и ведомым хватает одной линии данных с подтягивающим резистором и общего провода, а ведомые могут питаться прямо от линии. Ниже — сброс и тайм-слоты по даташиту DS18B20 и AN126, поиск устройств по AN187, CRC, подключение DS18B20 и правила для длинных линий из AN148.
Обновлено Редакция GAW
Содержание
- Как устроена шина 1-Wire
- Временные слоты 1-Wire
- ROM-команды 1-Wire
- Термодатчик DS18B20
- Подключение DS18B20
- Длинные линии и топология сети (AN148)
- Аппаратные ведущие: DS2482 и DS2480B
- CRC8 в 1-Wire
- Программная реализация на AVR
- 1-Wire через UART (AN214)
- Arduino: библиотеки OneWire и DallasTemperature
- iButton и другие устройства 1-Wire
- Типичные ошибки и отладка
1-Wire — последовательная шина, придуманная в Dallas Semiconductor (позже компания вошла в Maxim Integrated, а Maxim — в Analog Devices). Для обмена хватает одной сигнальной линии и общего провода. Ведущий, обычно микроконтроллер, начинает каждый бит, ведомые отвечают в отведённое им время, а адресом служит 64-битный номер, который производитель записывает в каждую микросхему. Многие ведомые не имеют вывода питания и берут энергию с той же линии. Так устроены термометры DS18B20, «таблетки» iButton, микросхемы серийного номера DS2401, память DS2431, двухканальные коммутаторы DS2413.
Все числа в статье — из документации производителя: даташита DS18B20 (ревизия 6, июль 2019 года), application notes Maxim 126 (программный ведущий), 187 (поиск устройств), 148 (длинные линии), 214 (ведущий на UART) и 27 (CRC), а также сборника Book of iButton Standards (AN937), где описаны общие для всех устройств временные параметры. Где расчёт или оценка наши, это сказано прямо.
Коротко
- Линии: данные DQ и общий провод. Выходы всех устройств — с открытым стоком, линию подтягивает к питанию один резистор, в даташите DS18B20 — 4,7 кОм.
- Обмен: каждую операцию начинает ведущий. Сброс — ноль не меньше 480 мкс, ответ ведомых — импульс присутствия 60–240 мкс. Бит занимает тайм-слот 60–120 мкс, данные идут младшим битом вперёд.
- Скорость: до 16,3 кбит/с на стандартной скорости и до 142 кбит/с в режиме overdrive, который есть не у всех устройств.
- Адрес: 64-битный ROM-код — 8 бит кода семейства (у DS18B20 — 28h), 48 бит серийного номера и 8 бит CRC с полиномом X⁸ + X⁵ + X⁴ + 1.
- DS18B20: −55…+125 °C, погрешность ±0,5 °C в диапазоне −10…+85 °C, разрешение 9–12 бит, преобразование до 750 мс, питание 3,0–5,5 В от вывода VDD или паразитное от линии.
- Длина: зависит от ведущего и кабеля. По AN148 ведущий с подтяжкой резистором держит сеть общей длиной около 200 м, ведущий с активной подтяжкой — до 500 м; звезду производитель не рекомендует.
Как устроена шина 1-Wire
Все устройства подключены к одной линии данных и к общему проводу. Каждое из них умеет только прижать линию к нулю или отпустить её: выход у всех — открытый сток. Единицу создаёт подтягивающий резистор, поэтому в покое на линии высокий уровень. Если линию одновременно тянут несколько устройств, побеждает ноль — это «монтажное И», как в I²C. На нём держатся общий импульс присутствия от нескольких устройств и поиск устройств на шине.
Тактовой линии нет. Каждый бит начинается спадом, который делает ведущий, а ведомое отсчитывает время от этого спада своим внутренним таймером: по нему оно решает, когда читать линию в слоте записи и сколько держать ноль в слоте чтения. Так механизм описан, например, в даташите DS2401. Поэтому надёжность 1-Wire упирается во время: ведущий должен выдерживать длительности, а линия — успевать подняться к тому моменту, когда её читают.
Отдельная линия питания ведомому не нужна. Пока линия в единице, оно заряжает внутренний конденсатор, а пока в нуле — живёт за его счёт. Это паразитное питание. Тем, кому нужно больше энергии, — DS18B20 во время измерения, EEPROM во время записи — её дают через сильную подтяжку, о ней ниже.
Ещё три свойства шины, важные на практике:
- Пауза между битами может быть любой. Пока линия в единице, ведомые ждут следующий слот сколько угодно: максимального времени восстановления нет. Поэтому прерывания можно разрешать между слотами.
- Долгий ноль — это сброс. Если линия в нуле дольше 480 мкс, все устройства сбрасываются (даташит DS18B20). При обрыве контакта ведомые тоже уходят в сброс, а когда напряжение возвращается, сообщают о себе импульсом присутствия (AN1796).
- Младший бит первым. Команды, данные и ROM-код передаются младшим битом вперёд.
Уникальный 64-битный ROM-код
В каждое ведомое при производстве записан 64-битный код. Младший байт — код семейства, он говорит о типе микросхемы: 28h — DS18B20, 01h — DS2401 и DS1990A, 2Dh — DS2431, 3Ah — DS2413. Следующие 48 бит — серийный номер, старший байт — CRC первых 56 бит. По Book of iButton Standards тип устройства задают младшие семь бит кода семейства, а старший бит помечает заказные версии, так что стандартных семейств может быть 128. 48 бит серийного номера — это 2,8·10¹⁴ номеров в каждом семействе.
Код передаётся начиная с младшего бита кода семейства, поэтому программы и библиотеки обычно печатают его побайтно в порядке приёма: первым идёт код семейства, последним — CRC. Так, ROM-код DS18B20 в выводе библиотеки OneWire всегда начинается с 28. Даташиты рисуют тот же код наоборот, старшим байтом слева. Сравнивая коды из разных программ, сначала выясните, в каком порядке они записаны.
Последовательность обмена
Обращение к ведомому всегда состоит из трёх шагов (даташит DS18B20, раздел 1-Wire Bus System):
- Инициализация: ведущий посылает импульс сброса, ведомые отвечают импульсом присутствия.
- ROM-команда: выбор устройства по коду, обращение ко всем или поиск. За командой следуют её данные, например 64 бита кода.
- Функциональная команда конкретного устройства — у DS18B20 это запуск измерения, чтение или запись блокнота — и обмен данными.
Если шаг пропущен или нарушен порядок, устройство не ответит. Исключение — команды поиска Search ROM и Alarm Search: после них ведущий снова начинает со сброса.
Временные слоты 1-Wire
Весь обмен складывается из четырёх операций: сброс, запись 1, запись 0 и чтение бита. Все их, кроме импульса присутствия, начинает ведущий. Ниже — длительности по даташиту DS18B20 и Book of iButton Standards и рекомендованные значения из AN126.
Сброс и импульс присутствия
Ведущий прижимает линию к нулю не меньше чем на 480 мкс (tRSTL), потом отпускает её и не меньше 480 мкс (tRSTH) слушает. Ведомое, увидев фронт, выжидает 15–60 мкс (tPDHIGH) и отвечает импульсом присутствия — нулём длительностью 60–240 мкс (tPDLOW). Если на шине несколько устройств, их импульсы накладываются и выглядят как один.
AN126 рекомендует проверять линию через 70 мкс после того, как ведущий её отпустил. Число не случайное: самое медленное ведомое начинает импульс присутствия не позже чем через 60 мкс, а самое быстрое держит ноль как минимум до 15 + 60 = 75 мкс. Момент 70 мкс попадает в окно 60–75 мкс, где ноль от любого исправного устройства гарантирован.
Слишком длинный сброс тоже вреден. Book of iButton Standards советует укладывать импульс сброса вместе с фронтом в 960 мкс, чтобы не заглушить сигналы прерывания, которые подают некоторые устройства. А DS18B20 с паразитным питанием, по даташиту, при импульсе сброса длиннее 960 мкс может перезапуститься по питанию: всё это время он живёт только за счёт внутреннего конденсатора.
Запись нуля и единицы
Каждый бит передаётся в тайм-слоте длительностью 60–120 мкс (tSLOT), а между слотами линия должна побыть в единице хотя бы 1 мкс (tREC). Чтобы записать 1, ведущий опускает линию и отпускает её не позже чем через 15 мкс: tLOW1 — от 1 до 15 мкс. Чтобы записать 0, он держит ноль весь слот, 60–120 мкс (tLOW0). Ведомое читает линию в окне от 15 до 60 мкс после спада, у DS18B20 типично через 30 мкс. Отсюда смысл границ: при записи 1 линия должна подняться раньше, чем откроется окно, а при записи 0 — оставаться в нуле, пока оно не закроется.
Чтение бита: когда опрашивать линию
Ведомое передаёт данные, только когда ведущий даёт ему слот чтения. Слот начинается так же, как запись 1: ведущий опускает линию хотя бы на 1 мкс и отпускает. Если ведомому нужно передать 1, оно ничего не делает, и линия поднимается. Чтобы передать 0, оно подхватывает линию и держит её в нуле. Данные действительны 15 мкс от спада (tRDV), поэтому ведущий должен прочитать линию не позже чем через 15 мкс от начала слота. Отпускает линию ведомое через 15–60 мкс: по Book of iButton Standards после tRDV проходит ещё от 0 до 45 мкс (tRELEASE).
Эти 15 мкс делятся на три части: ведущий держит ноль (TINIT), линия поднимается через резистор (TRC), ведущий читает уровень (TSAMPLE). Даташит DS18B20 советует делать первые две как можно короче, а читать ближе к концу 15 мкс: тогда при передаче единицы у линии больше всего времени, чтобы подняться.
Самая частая ошибка программного ведущего, по AN148, — читать линию слишком поздно. Код, который читает через 30 мкс, может пройти лабораторные испытания: многие ведомые держат ноль заметно дольше 15 мкс. Но разброс времени у ведомых большой и меняется с температурой, напряжением и от партии к партии. Пример из AN148: если ноль у ведомых закончится через 29 мкс вместо 32, такой ведущий начнёт ошибаться. Граница 15 мкс — требование, а не рекомендация.
Рекомендуемые задержки из AN126
AN126 описывает операции через десять задержек и даёт значения, которые, по словам Maxim, обеспечивают самый надёжный обмен со всеми устройствами при разных состояниях линии:
| Задержка | Где используется | Стандартная скорость, мкс | Overdrive, мкс |
|---|---|---|---|
| A | ноль в начале записи 1 и чтения | 6 | 1,0 |
| B | запись 1: остаток слота и восстановление | 64 | 7,5 |
| C | запись 0: длительность нуля | 60 | 7,5 |
| D | запись 0: восстановление | 10 | 2,5 |
| E | чтение: от отпускания линии до чтения | 9 | 1,0 |
| F | чтение: остаток слота и восстановление | 55 | 7 |
| G | пауза перед сбросом | 0 | 2,5 |
| H | импульс сброса | 480 | 70 |
| I | от отпускания линии до проверки присутствия | 70 | 8,5 |
| J | остаток последовательности сброса | 410 | 40 |
Отсюда длительности операций на стандартной скорости: запись 1 — A + B = 70 мкс, запись 0 — C + D = 70 мкс, чтение — A + E + F = 70 мкс, сброс — G + H + I + J = 960 мкс. Бит каждые 70 мкс — это около 14,3 кбит/с. AN126 ставит два условия: задержку в 1 мкс (0,25 мкс для overdrive) нужно формировать точно и повторяемо, а операцию нельзя прерывать, пока она формируется. В примере кода той же AN126 для overdrive стоят A = 1,5 мкс и E = 0,75 мкс, не как в таблице, — на этой скорости сверяйтесь ещё и с даташитом устройства.
Стандартная скорость и overdrive
Overdrive ускоряет все временные параметры, включая сброс и присутствие, примерно на порядок. Значения ниже — для классических устройств 1-Wire, по сравнительной таблице в даташите DS2431 и по Book of iButton Standards:
| Параметр | Стандартная скорость | Overdrive |
|---|---|---|
| Тайм-слот вместе с восстановлением, не меньше | 61 мкс | 7 мкс |
| Импульс сброса tRSTL | от 480 мкс | 48–80 мкс |
| Ожидание перед присутствием tPDH | 15–60 мкс | 2–6 мкс |
| Импульс присутствия tPDL | 60–240 мкс | 8–24 мкс |
| Ноль при записи 0 tW0L | 60–120 мкс | 6–16 мкс |
| Ноль при записи 1 и в начале чтения | 1–15 мкс | 1–2 мкс |
| Данные действительны после спада tRDV | 15 мкс | 2 мкс |
| Наибольшая скорость обмена | 16,3 кбит/с | 142 кбит/с |
На стандартной скорости работают все устройства 1-Wire. В overdrive переходят только те, что его поддерживают: команда Overdrive Skip ROM (3Ch) переводит все такие устройства, Overdrive Match ROM (69h) — одно выбранное. Обратно их возвращает обычный сброс длительностью не меньше 480 мкс. У новых микросхем скорость чуть ниже: у DS2431 — 15,4 и 125 кбит/с, у DS2413 — 14,9 и 100 кбит/с; производитель объясняет это увеличенным временем восстановления у входа с улучшенной помехоустойчивостью. DS18B20 режима overdrive не имеет, а AN148 предупреждает, что overdrive рассчитан только на очень короткие соединения и для сетей с кабелем не годится.
ROM-команды 1-Wire
После импульса присутствия ведущий посылает ROM-команду — один байт, который определяет, с каким устройством он будет говорить. Команды общие для всех устройств 1-Wire, но не каждое поддерживает все: у DS18B20 их пять, у DS2401 и DS1990A — только чтение кода и поиск.
| Команда | Код | Что делает | Когда применять |
|---|---|---|---|
| Read ROM | 33h | ведомое выдаёт свой 64-битный код | только когда на шине одно устройство; DS2401 и DS1990A понимают ещё и 0Fh |
| Match ROM | 55h | за командой ведущий передаёт 64 бита кода, дальше отвечает только совпавшее устройство | обращение к конкретному устройству на общей шине |
| Skip ROM | CCh | обращение ко всем без адреса | команда всем сразу, например запуск измерения во всех DS18B20, или шина с одним устройством |
| Search ROM | F0h | поиск кодов всех устройств | при запуске системы и для проверки состава шины |
| Alarm Search | ECh | тот же поиск, но отвечают только устройства с флагом тревоги | у DS18B20 — температура вне порогов TH и TL |
| Overdrive Skip ROM | 3Ch | Skip ROM с переводом всех поддерживающих устройств в overdrive | DS2431, DS2413 и другие с overdrive; у DS18B20 нет |
| Overdrive Match ROM | 69h | Match ROM на скорости overdrive, выбранное устройство переходит в overdrive | то же |
| Resume | A5h | повторное обращение к последнему выбранному устройству без передачи кода | DS2431, DS2413 и другие новые устройства |
Пояснения:
- Read ROM на шине с несколькими устройствами даёт столкновение: отвечают все сразу, линия складывает коды по «монтажному И», и результат не проходит проверку CRC. Book of iButton Standards советует читать код поиском даже при одном устройстве: такой код работает и на общей шине.
- Skip ROM удобен для общих команд: Skip ROM и Convert T запускают измерение во всех DS18B20 одновременно. Читать данные после Skip ROM можно, только если устройство на шине одно, иначе ответы столкнутся.
- Resume экономит 64 бита адреса при повторных обращениях к одному устройству. Бит RC, на который она смотрит, устанавливают Match ROM, Search ROM и Overdrive Match ROM, а обращение к другому устройству его сбрасывает, поэтому ответить двоим не получится.
Поиск устройств на шине: алгоритм Search ROM
Поиск по команде F0h — это обход двоичного дерева, в листьях которого лежат коды устройств (AN187). Все участвующие ведомые выдают на линию первый, младший бит своего кода, затем этот же бит в инверсии. Ведущий читает оба значения, и каждое из них — «монтажное И» ответов всех устройств:
| Бит | Инверсия | Что это значит |
|---|---|---|
| 0 | 1 | у всех оставшихся устройств в этом разряде 0 |
| 1 | 0 | у всех оставшихся устройств 1 |
| 0 | 0 | есть и 0, и 1 — развилка |
| 1 | 1 | никто не отвечает: устройств нет или одно из них отключили во время поиска |
Затем ведущий записывает выбранное значение бита. Устройства, у которых в этом разряде другое значение, выбывают и ждут следующего сброса. Так повторяется 64 раза — по три слота на разряд, — и в конце ведущий знает код одного устройства. Чтобы найти остальные, поиск повторяют, на развилках выбирая другие ветви. Правило из AN187 для развилки:
- разряд раньше последней развилки прошлого прохода — тот же бит, что в прошлый раз;
- разряд совпадает с последней развилкой — 1;
- разряд дальше — 0, и номер этого разряда запоминается.
Последняя развилка, где выбран 0, становится точкой ветвления для следующего прохода. Если таких развилок не было, найдено последнее устройство. Проходов столько, сколько устройств на шине.
Разберём на учебном примере: три устройства с 4-битными кодами D1 = 0101, D2 = 0110 и D3 = 1001 (биты в порядке передачи). Реальный код длиннее, но работает всё так же.
| Проход | Бит 1 | Бит 2 | Бит 3 | Бит 4 | Найдено | Следующая развилка |
|---|---|---|---|---|---|---|
| 1 | 0/0: развилка, новая — 0; D3 выбывает | 1/0: у всех 1 | 0/0: развилка, новая — 0; D2 выбывает | 1/0 | D1 = 0101 | бит 3 |
| 2 | 0/0: раньше бита 3 — как в прошлый раз, 0 | 1/0 | 0/0: последняя развилка — 1; D1 выбывает | 0/1 | D2 = 0110 | бит 1 |
| 3 | 0/0: последняя развилка — 1; D1 и D2 выбывают | 0/1 | 0/1 | 1/0 | D3 = 1001 | нет, поиск закончен |
У реальных датчиков одного типа первые 8 бит совпадают — это код семейства, — поэтому развилки начинаются в серийном номере. Один проход занимает сброс и 8 + 64 × 3 = 200 слотов, то есть около 15 мс при задержках AN126, так что десять датчиков находятся примерно за 0,15 с. Реализация на C по AN187, с функциями нижнего уровня из раздела про AVR ниже:
static uint8_t rom[8]; /* last found ROM code, rom[0] = family code */
static uint8_t last_discrepancy; /* bit 1..64 where 0 was taken last time, 0 = none */
static uint8_t last_device;
/* Finds the next device. Returns 1 and fills rom[]; 0 = no more devices or an error. */
uint8_t ow_search_next(void)
{
uint8_t last_zero = 0;
if (last_device || !ow_reset()) {
last_discrepancy = 0;
last_device = 0;
return 0;
}
ow_write_byte(0xF0); /* Search ROM */
for (uint8_t n = 1; n <= 64; n++) { /* bit 1 = LSB of rom[0] */
uint8_t *byte = &rom[(n - 1) / 8];
uint8_t mask = (uint8_t)(1 << ((n - 1) % 8));
uint8_t bit = ow_read_bit();
uint8_t cmp = ow_read_bit(); /* complement of the same bit */
uint8_t dir;
if (bit && cmp) { /* nobody answered */
last_discrepancy = 0;
return 0;
}
if (bit != cmp) {
dir = bit; /* all remaining devices agree */
} else { /* fork: both 0 and 1 present */
if (n < last_discrepancy)
dir = (*byte & mask) != 0; /* same branch as last time */
else
dir = (n == last_discrepancy); /* 1 at the last fork, 0 at a new one */
if (!dir)
last_zero = n;
}
if (dir) *byte |= mask; else *byte &= (uint8_t)~mask;
ow_write_bit(dir); /* devices with the other bit drop out */
}
if (ow_crc8(rom, 8) != 0) { /* CRC over all 8 bytes must give 0 */
last_discrepancy = 0; /* damaged code: start over next time */
return 0;
}
last_discrepancy = last_zero;
if (last_discrepancy == 0)
last_device = 1;
return 1;
}
uint8_t ow_search_first(void)
{
last_discrepancy = 0;
last_device = 0;
return ow_search_next();
}
Логику этого кода мы проверили моделью шины с «монтажным И»: на 200 случайных наборах до 12 устройств он находит все коды, а на примере из таблицы делает те же три прохода.
AN187 описывает ещё три варианта на тех же переменных. Проверка конкретного устройства: записать его код в rom, поставить последнюю развилку 64 и выполнить поиск — устройство на месте, если код не изменился. Поиск семейства: записать код семейства в первый байт, остальные обнулить и поставить последнюю развилку 64 — первым найдётся устройство этого семейства, если оно есть. Пропуск семейства: продолжить поиск с последней развилки внутри первых 8 бит, чтобы не перебирать остальных устройств того же типа.
Аппаратные ведущие берут часть работы на себя. У DS2482 есть команда 1-Wire Triplet (78h): два слота чтения и слот записи по одной команде, на устройство их нужно 64. DS2480B ускоряет поиск сам, а DS2490 по AN187 выполняет его целиком.
Поиск — самая требовательная операция на шине: только в нём, не считая импульса присутствия, линию одновременно тянут все устройства. Поэтому проблемы сети по AN148 проявляются прежде всего так: устройства то находятся, то пропадают из результатов поиска.
Термодатчик DS18B20
DS18B20 — цифровой термометр с интерфейсом 1-Wire. Он выпускается в корпусе TO-92 с тремя выводами (DS18B20), в SO-8 (DS18B20Z) и µSOP-8 (DS18B20U). В корпусе TO-92 вывод 1 — GND, 2 — DQ, 3 — VDD.
Характеристики DS18B20
| Параметр | Значение |
|---|---|
| Диапазон измерения | −55…+125 °C |
| Погрешность | ±0,5 °C при −10…+85 °C, ±1 °C при −30…+100 °C, ±2 °C при −55…+125 °C |
| Разрешение | 9, 10, 11 или 12 бит — шаг 0,5, 0,25, 0,125 или 0,0625 °C; заводская настройка — 12 бит |
| Время преобразования, не больше | 93,75 мс при 9 битах, 750 мс при 12 битах |
| Питание | 3,0–5,5 В на выводе VDD или паразитное от линии при подтяжке 3,0–5,5 В |
| Потребление | в покое 750 нА типично, до 1000 нА при температуре до +70 °C; при измерении и записи EEPROM — 1 мА типично, до 1,5 мА |
| Пороги входа DQ | ноль — не выше 0,8 В; единица — не ниже 2,2 В при внешнем питании и 3,0 В при паразитном |
| Выход DQ | открытый сток, не меньше 4 мА при 0,4 В |
| Ёмкость вывода DQ | до 25 пФ |
| EEPROM для TH, TL и конфигурации | 50 тыс. циклов записи, хранение 10 лет (при −55…+55 °C), запись до 10 мс |
| Код семейства | 28h |
Функциональные команды
| Команда | Код | Что делает | Что после команды |
|---|---|---|---|
| Convert T | 44h | запускает измерение температуры | при внешнем питании слоты чтения дают 0, пока идёт измерение, и 1, когда оно закончено; при паразитном — сильная подтяжка не позже чем через 10 мкс и на всё время измерения |
| Read Scratchpad | BEh | читает блокнот начиная с байта 0 | до 9 байт; чтение можно прервать сбросом |
| Write Scratchpad | 4Eh | пишет TH, TL и конфигурацию в байты 2–4 блокнота | ведущий передаёт три байта младшим битом вперёд, все три — до сброса |
| Copy Scratchpad | 48h | копирует TH, TL и конфигурацию в EEPROM | при паразитном питании — сильная подтяжка не позже чем через 10 мкс и не меньше 10 мс |
| Recall E² | B8h | загружает TH, TL и конфигурацию из EEPROM в блокнот | слоты чтения: 0 — идёт загрузка, 1 — готово; при включении питания это делается само |
| Read Power Supply | B4h | показывает, есть ли на шине датчики с паразитным питанием | в слоте чтения такие датчики тянут линию к нулю, датчики с внешним питанием оставляют единицу |
Блокнот и регистр конфигурации
Блокнот (scratchpad) — 9 байт оперативной памяти, через которые идёт весь обмен:
| Байт | Содержимое | После включения |
|---|---|---|
| 0 | температура, младший байт | 50h |
| 1 | температура, старший байт | 05h, вместе с байтом 0 — 0550h, то есть +85 °C |
| 2 | порог TH или пользовательский байт 1 | из EEPROM |
| 3 | порог TL или пользовательский байт 2 | из EEPROM |
| 4 | регистр конфигурации | из EEPROM |
| 5 | резерв | FFh |
| 6 | резерв | — |
| 7 | резерв | 10h |
| 8 | CRC байтов 0–7 | — |
Байты 2–4 хранятся в EEPROM и при включении сами загружаются в блокнот. Если тревога не нужна, TH и TL можно использовать как два байта своей памяти, например для номера датчика. EEPROM выдерживает 50 тыс. циклов записи, поэтому копировать блокнот при каждом включении не стоит: записывайте, только если значение действительно изменилось.
В регистре конфигурации два значащих бита, R1 и R0, остальные зарезервированы: бит 7 всегда 0, биты 4–0 — единицы.
| R1 R0 | Разрешение | Шаг | Время преобразования, не больше | Байт конфигурации |
|---|---|---|---|---|
| 00 | 9 бит | 0,5 °C | 93,75 мс | 1Fh |
| 01 | 10 бит | 0,25 °C | 187,5 мс | 3Fh |
| 10 | 11 бит | 0,125 °C | 375 мс | 5Fh |
| 11 | 12 бит | 0,0625 °C | 750 мс | 7Fh |
Каждый бит разрешения удваивает время измерения. Если важнее частота опроса, чем сотые доли градуса, 10 или 11 бит дают выигрыш в 4 или 2 раза.
Формат температуры: дополнительный код и шаг 0,0625 °C
Температура хранится в байтах 0 и 1 как 16-битное число в дополнительном коде, расширенное знаком: старшие пять бит повторяют знак. Младшие четыре бита — дробная часть, поэтому при 12 битах единица младшего разряда равна 1/16 = 0,0625 °C. Чтобы получить градусы, нужно сложить байты в знаковое 16-битное число и умножить на 0,0625. Примеры из таблицы 1 даташита:
| Температура | Код | Расчёт |
|---|---|---|
| +125 °C | 07D0h | 2000 × 0,0625 = 125 |
| +85 °C | 0550h | 1360 × 0,0625 = 85, значение после включения |
| +25,0625 °C | 0191h | 401 × 0,0625 = 25,0625 |
| −10,125 °C | FF5Eh | FF5Eh − 10000h = −162; −162 × 0,0625 = −10,125 |
| −25,0625 °C | FE6Fh | −401 × 0,0625 = −25,0625 |
| −55 °C | FC90h | −880 × 0,0625 = −55 |
Отрицательное значение удобно проверять так: 10000h − FF5Eh = A2h = 162, значит FF5Eh — это −162. На C всё сводится к одному приведению типа, и знак получается сам:
int16_t raw = (int16_t)((uint16_t)sp[1] << 8 | sp[0]); /* sp[] = scratchpad bytes */
float celsius = raw / 16.0f; /* 0x0191 -> 25.0625, 0xFF5E -> -10.125 */
При разрешении ниже 12 бит младшие биты не определены: при 11 битах — бит 0, при 10 — биты 1 и 0, при 9 — биты 2–0. Их нужно обнулять до пересчёта, иначе в результате появится мусор в последних знаках. При 9 битах это raw & ~7: если в неопределённых битах окажутся единицы, как в коде FE6Fh, маска даст FE68h, то есть −25,5 °C — значение с шагом 0,5 °C.
Почему DS18B20 показывает 85 °C
85 °C — значение регистра температуры после включения питания (код 0550h). Если программа его читает, датчик ещё не закончил ни одного преобразования после включения или после перезапуска. Причин три:
- Измерение не запускали. Команду 44h не отправили или отправили не тому устройству.
- Прочитали слишком рано. При 12 битах преобразование длится до 750 мс. Пока оно идёт, в блокноте остаётся прошлое значение, а у только что включённого датчика прошлого значения нет.
- Датчику не хватило питания. При паразитном питании без сильной подтяжки резистор не может дать ток до 1,5 мА, который нужен во время измерения, датчик может перезапуститься и снова покажет 85 °C.
Настоящие 85 °C датчик тоже может измерить, поэтому само значение ещё не ошибка. Признак ошибки — 85 °C сразу после включения или при заведомо другой температуре.
Точность ±0,5 °C: где она действует
±0,5 °C гарантированы только в диапазоне −10…+85 °C. В диапазоне −30…+100 °C погрешность — до ±1 °C, во всём диапазоне −55…+125 °C — до ±2 °C. Это пределы 3σ, то есть так ведут себя практически все экземпляры. После 1000 часов работы при +125 °C показания могут сместиться ещё на ±0,2 °C. Разрешение 0,0625 °C — не точность: оно показывает, насколько мелко датчик различает изменения, а абсолютная ошибка остаётся в пределах ±0,5 °C.
Тревога: пороги TH и TL и Alarm Search
После каждого измерения DS18B20 сравнивает температуру с порогами TH и TL — однобайтовыми числами в дополнительном коде. В сравнении участвуют биты 11–4 регистра температуры, то есть целые градусы. Если температура не выше TL или не ниже TH, датчик ставит флаг тревоги; следующее измерение пересчитывает флаг. Команда Alarm Search (ECh) работает как поиск, но отвечают только датчики с флагом, и ведущий за несколько проходов узнаёт, где температура вышла за пределы, не читая все датчики подряд.
Как выглядит обмен с датчиками
Один датчик с внешним питанием, адрес не нужен:
- Сброс, присутствие, Skip ROM (CCh), Convert T (44h).
- Слоты чтения, пока датчик не ответит 1, — не дольше 750 мс при 12 битах.
- Сброс, присутствие, Skip ROM (CCh), Read Scratchpad (BEh), девять байт, проверка CRC.
Несколько датчиков, по примеру 1 из даташита:
- Один раз при запуске — поиск, коды датчиков сохраняются.
- Сброс, Skip ROM (CCh), Convert T (44h) — измеряют все сразу. При паразитном питании сразу после команды включается сильная подтяжка на время tCONV.
- Для каждого датчика: сброс, Match ROM (55h) и его 64-битный код, Read Scratchpad (BEh), девять байт и проверка CRC.
При задержках AN126 сброс занимает 960 мкс, а каждый бит — 70 мкс. Чтение одного датчика по адресу — это 8 + 64 + 8 + 72 = 152 слота плюс сброс, около 11,6 мс. Измерение при 12 битах длится до 750 мс, поэтому цикл опроса десяти датчиков с общим запуском измерения укладывается примерно в 0,87 с, а с поочерёдным запуском занял бы больше 7,5 с.
Подключение DS18B20
Внешнее питание: три провода и резистор 4,7 кОм
Самая надёжная схема — с внешним питанием: на каждый датчик идут три провода, VDD, DQ и GND, а линию DQ подтягивает к питанию один резистор 4,7 кОм у микроконтроллера. Так подключение нарисовано в даташите. Датчик при этом может отвечать о конце преобразования, а линия свободна для обмена с другими устройствами, пока он измеряет.
Вывод VDD нельзя оставлять неподключённым: при паразитном питании его соединяют с GND, при внешнем — с питанием. В тексте даташита для подтяжки назван резистор «около 5 кОм», а на всех схемах стоит 4,7 кОм — ближайший к 5 кОм номинал ряда E12.
Расчёт подтяжки: ток и время нарастания
У резистора подтяжки две границы. Нижнюю задаёт ток: когда ведомое тянет линию к нулю, через него течёт ток резистора, а DS18B20 гарантирует ноль не выше 0,4 В только при токе до 4 мА:
При 3,3 В та же граница — 725 Ом. Резистор 4,7 кОм при 5 В даёт ток около 0,98 мА — с четырёхкратным запасом.
Верхнюю границу задаёт время нарастания. После того как ведущий отпустил линию, её ёмкость C заряжается через резистор R, и до порога VIH напряжение доходит за время
При 5 В до порога 2,2 В (внешнее питание) это 0,58RC, до 3,0 В (паразитное) — 0,92RC. В слоте записи 1 по AN126 ведущий держит ноль 6 мкс, а DS18B20 может прочитать линию уже через 15 мкс от спада, так что на подъём остаётся 9 мкс. Отсюда постоянная времени RC должна быть не больше 15,5 мкс при внешнем питании и 9,8 мкс при паразитном. С резистором 4,7 кОм это 3,3 и 2,1 нФ ёмкости линии вместе с датчиками.
Сколько это в метрах? AN148 оценивает кабель категории 5e примерно в 52 пФ на метр, так что 2,1–3,3 нФ — это порядка 40–60 м витой пары при 5 В. При 3,3 В те же расчёты дают около 1,7 нФ (около 34 м) при внешнем питании и всего 0,8 нФ (около 15 м) при паразитном. Это наша оценка по простой RC-модели: она не учитывает отражения в кабеле и разброс порогов у ведущего, но порядок верный. Для сравнения, AN148 называет 200 м для ведущего с подтяжкой 1 кОм: у такой цепи на 200 м кабеля постоянная времени 1 кОм × 200 м × 52 пФ/м = 10,4 мкс, тот же порядок. Посчитать RC для своей линии поможет калькулятор RC-цепи.
Отсюда практические выводы:
- 4,7 кОм — хороший номинал для платы и проводов в несколько метров или десятков метров.
- 10 кОм вдвое уменьшает допустимую ёмкость: на длинном проводе единица будет читаться как ноль, и это проявится ошибками CRC.
- Уменьшать резистор ниже 1,5–2 кОм при 5 В стоит только вместе с проверкой нуля на линии осциллографом: ток растёт, и уровень нуля поднимается.
Несколько датчиков на одной линии
Датчики подключаются параллельно к тем же трём проводам. Резистор подтяжки остаётся один на всю линию. Это важно для готовых модулей, у которых резистор 4,7 кОм уже стоит на плате: пять таких модулей на одной линии — это пять резисторов параллельно, 940 Ом, и ток нуля при 5 В — (5 − 0,4) / 940 Ом ≈ 4,9 мА, больше гарантированных 4 мА. Резисторы на модулях, кроме одного, нужно снять.
Порядок работы: один раз найти все датчики поиском и сохранить их коды, затем запускать измерение во всех сразу командой Skip ROM и Convert T и читать каждый по своему коду через Match ROM. Коды стоит хранить в программе с привязкой к месту установки — «котельная», «улица». Номер датчика в результатах поиска для этого не годится: поиск выдаёт устройства в порядке, который задают сами коды, и после замены одного датчика нумерация остальных может сдвинуться.
Паразитное питание и сильная подтяжка
При паразитном питании к датчику идут два провода: DQ и GND, а его вывод VDD соединяют с GND. Пока линия в единице, датчик заряжает внутренний конденсатор CPP и питается от него, когда линия в нуле. Для обмена этого хватает, а для измерения температуры и записи в EEPROM — нет: датчику нужно до 1,5 мА. Через резистор 4,7 кОм такой ток дал бы, по закону Ома, падение 1,5 мА × 4,7 кОм = 7,05 В — больше всего напряжения питания. Даже чтобы удержать на линии 3,0 В при подтяжке к 5 В, ток через резистор не может превышать (5 − 3) / 4,7 кОм ≈ 0,43 мА.
Поэтому на время измерения линию подключают прямо к питанию транзистором — это сильная подтяжка. Даташит DS18B20 требует включить её не позже чем через 10 мкс (tSPON) после последнего бита команды 44h или 48h и держать всё время преобразования (до 750 мс) или записи (не меньше 10 мс). Схема из AN4206 — P-канальный MOSFET BSS84, затвор которого управляется отдельным выводом с открытым стоком, а резистор 10 кОм держит транзистор закрытым, пока вывод отпущен:
Чем платят за экономию провода:
- Линия занята на всё время измерения. Пока включена сильная подтяжка, любой другой обмен на шине запрещён — это до 750 мс при 12 битах.
- Конец измерения не узнать. Слоты чтения после 44h при паразитном питании не работают, поэтому ведущий ждёт максимальное время преобразования для выбранного разрешения.
- Ток суммируется. Если запустить измерение во всех датчиках сразу, через транзистор пойдёт до 1,5 мА на каждый: десять датчиков — 15 мА.
- Не выше +100 °C. Производитель не рекомендует паразитное питание выше +100 °C: из-за токов утечки датчик может перестать отвечать.
- Порог выше. Единица на входе DQ при паразитном питании — от 3,0 В, а не от 2,2 В. Для 3,3-вольтовой системы запас всего 0,3 В, и AN4206 прямо требует в такой системе сильную подтяжку. Кроме того, импульс сброса длиннее 960 мкс может перезапустить датчик.
Узнать, есть ли на шине датчики с паразитным питанием, можно командой Read Power Supply (B4h) после Skip ROM: в следующем слоте чтения такие датчики прижмут линию к нулю. Так делает библиотека DallasTemperature при запуске.
Длинные линии и топология сети (AN148)
1-Wire придумывали для коротких соединений, например чтобы добавить память на одну ножку процессора. Сети на десятки и сотни метров возможны, но требуют правильного ведущего, кабеля и топологии. Основной документ здесь — AN148 «Guidelines for Reliable Long Line 1-Wire Networks». Его рекомендации относятся к витой паре категории 5e и питанию сети 5 В от ведущего.
Радиус и вес сети
AN148 описывает сеть двумя числами:
- Радиус — длина провода от ведущего до самого дальнего ведомого.
- Вес — общая длина провода в сети.
Вес ограничивает время нарастания фронтов: чем больше провода, тем больше ёмкость, которую заряжает подтяжка. Радиус определяет, когда возвращаются отражения. Ведомые тоже добавляют вес: устройство в обычном корпусе — примерно как 0,5 м кабеля, iButton — как 1 м. 100 таблеток iButton добавляют 100 м веса, и на столько же нужно сократить кабель. Дорожки на плате и защитные цепи тоже нагружают линию: ёмкость 24 пФ AN148 приравнивает к 0,5 м веса.
Линия, отводы и звезда
AN148 различает три топологии:
- Линия: одна пара идёт от ведущего к самому дальнему устройству, остальные подключены отводами короче 3 м. Это лучший вариант.
- Магистраль с отводами 3 м и длиннее. Отражения от концов отводов возвращаются в магистраль и мешают остальным устройствам.
- Звезда: несколько ветвей расходятся от ведущего или рядом с ним. В точке разветвления сильно не согласованы сопротивления, отражение от конца одной ветви проходит путь, равный почти всему весу сети, и портит данные. AN148 называет звезду без коммутации самой трудной для надёжной работы, не рекомендует её и не даёт для неё гарантий.
Если сеть смешанная, AN148 советует применять самый строгий из критериев. Если без ветвей не обойтись, их коммутируют: каждую ветвь подключают аналоговым ключом по очереди, и электрически сеть остаётся линией. В примере AN148 сеть с радиусом 150 м и весом 450 м после коммутации ветвей нагружает ведущего как линия весом 150 м. Удобная готовая замена ключам — восьмиканальный ведущий DS2482-800, у которого каждая ветвь подключена к своему каналу.
Сколько метров выдержит линия
| Ведущий | Предел по AN148 |
|---|---|
| Простая подтяжка резистором | вес около 200 м |
| Ключ с ограничением скорости спада и подтяжкой 1 кОм (приложение A) | радиус и вес до 200 м |
| DS2480B с RC-фильтром 470 пФ (приложение B) | радиус или вес до 200 м; фильтр нужен для сетей 10–100 м |
| Ведущий с активной подтяжкой по AN244 | радиус и вес до 500 м |
Скорость распространения сигнала в кабеле — около 2/3 скорости света. В кабеле длиной 750 м сигнал идёт туда и обратно 7,5 мкс, и это уже сопоставимо с длительностью нуля в начале слота: ведущий просто не сможет общаться с быстрым ведомым у себя под боком. Так AN148 объясняет, почему радиус ограничен даже при идеальной подтяжке.
Ведущий из одного вывода микроконтроллера с резистором 4,7 кОм рассчитан на короткие сети. AN4206 описывает такие схемы для радиуса до 1 м и трёх–пяти ведомых, а у ведущего I²C — 1-Wire DS2482-100 ёмкость линии на стандартной скорости ограничена 1 нФ. По нашей оценке выше, обычная подтяжка 4,7 кОм к выводу микроконтроллера даёт при 5 В десятки метров кабеля.
Как сделать длинную линию надёжной
- Топология — линия, отводы короче 3 м, без звёзд. Ветви — через ключи или отдельные каналы ведущего.
- Кабель — витая пара категории 5e: именно для неё AN148 даёт свои цифры. Линию данных и общий провод разумно вести одной парой.
- Внешнее питание датчиков. При паразитном питании на большой сети самый тяжёлый случай — длинная серия нулей: линия почти всё время внизу, и ведомые не успевают подзарядиться. Ошибки тогда зависят от данных и появляются то и дело. Ведомое, у которого питание просело, сбрасывается, а потом посылает импульс присутствия и может испортить чужой обмен.
- Длиннее пауза между слотами. Восстановление не ограничено сверху, и лишние микросекунды в единице дают линии подняться и подзарядить ведомых.
- Последовательные резисторы на отводах. AN148 описывает 150 Ом в каждой точке подключения отвода: несогласованность в этой точке уменьшается примерно на 20 %, отражения от отвода — на 40 %, но помехоустойчивость падает примерно на 80 %. 100 Ом тоже работают хорошо и меньше ухудшают помехоустойчивость. С активной подтяжкой DS2480B и DS2484 этот приём несовместим.
- Специальный ведущий для сотен метров: DS2480B или схема с активной подтяжкой из AN244.
- Без overdrive. На кабелях — только стандартная скорость.
Если нужно передавать данные на сотни метров по одной паре и узлы — не датчики 1-Wire, а контроллеры, удобнее дифференциальный RS-485.
Аппаратные ведущие: DS2482 и DS2480B
Отдельная микросхема-ведущий снимает с процессора точные задержки: она сама формирует слоты, сброс и присутствие, а процессор только передаёт ей байты по I²C или UART.
| Микросхема | Связь с процессором | Возможности |
|---|---|---|
| DS2482-100 | I²C, 100 и 400 кГц; адрес 0x18–0x1B, задаётся выводами AD1 и AD0 | стандартная скорость и overdrive, внутренняя подтяжка 1–1,675 кОм или активная, сильная подтяжка и вывод PCTLZ для внешнего MOSFET, команда 1-Wire Triplet для поиска; питание 2,9–5,5 В |
| DS2482-800 | I²C | восемь независимых каналов 1-Wire |
| DS2480B | UART или RS-232: 9600 бит/с по умолчанию, 19 200, 57 600 и 115 200 бит/с | ограничение скорости фронтов и активная подтяжка для длинных линий, сильная подтяжка до 5 В, программирование EPROM от 12 В, настраиваемые длительности; питание только 4,5–5,5 В |
DS2482-100 управляется восемью командами: сброс микросхемы (F0h), установка указателя чтения (E1h), запись конфигурации (D2h), сброс 1-Wire (B4h), один бит (87h), запись байта (A5h), чтение байта (96h) и Triplet (78h). Свои слоты у неё такие (типичные значения): импульс сброса 600 мкс, проверка присутствия через 70 мкс, слот 69,3 мкс, ноль 8 мкс при записи 1 и 64 мкс при записи 0, чтение через 14 мкс. У DS2482 внутренняя подтяжка, отдельный резистор 4,7 кОм ей не нужен.
AN4206 называет DS2480B самым сильным одиночным ведущим 1-Wire, способным обслуживать большое число ведомых. AN148 добавляет, что его длительности по умолчанию рассчитаны на небольшие сети, а для сетей побольше их нужно настроить, и программа должна переводить DS2480B в гибкий режим.
CRC8 в 1-Wire
Контрольная сумма 1-Wire — 8-битная CRC с полиномом X⁸ + X⁵ + X⁴ + 1. Ею защищён ROM-код: старший байт — CRC первых семи байт. У DS18B20 ещё и блокнот: байт 8 — CRC байтов 0–7. В железе это сдвиговый регистр из восьми ячеек: входной бит складывается по модулю 2 с выходом последней ячейки, и результат через элементы «исключающее ИЛИ» после 4-й и 5-й ячеек возвращается в регистр (рис. 11 даташита DS18B20, AN27). Регистр в начале обнулён, данные входят в него младшим битом вперёд, как идут по линии, и после последнего бита в регистре остаётся CRC.
Полезные свойства из AN27:
- Остаток ноль. Если после данных пропустить через регистр и саму CRC, получится 00h. Поэтому проверка сводится к одному сравнению: CRC всех восьми байт ROM-кода должна быть равна нулю.
- Инверсия даёт 35h. Если вместо CRC пропустить её инверсию, результат всегда 35h. Это удобный тест для своей реализации.
- Что обнаруживается. Любое нечётное число ошибочных бит в 64-битном коде, любые две ошибки, любая пачка ошибок в пределах 8 бит подряд и большинство более длинных пачек.
Пример из AN27 — код с семейством 02h, серийным номером 00000001B81Ch и CRC A2h. Табличный метод из той же AN27 считает CRC по байтам: новое значение — элемент таблицы с индексом «текущая CRC XOR очередной байт».
| Байт по порядку | 02h | 1Ch | B8h | 01h | 00h | 00h | 00h | A2h — сама CRC |
|---|---|---|---|---|---|---|---|---|
| CRC после байта | BCh | AFh | 1Eh | DCh | F4h | 15h | A2h | 00h |
Побитовая реализация на C — без таблицы, восемь проходов цикла на байт:
#include <stdint.h>
/* 1-Wire CRC8: x^8 + x^5 + x^4 + 1, data LSB first, initial value 0 (Maxim AN27) */
uint8_t ow_crc8(const uint8_t *data, uint8_t len)
{
uint8_t crc = 0;
while (len--) {
uint8_t byte = *data++;
for (uint8_t i = 0; i < 8; i++) {
uint8_t mix = (crc ^ byte) & 0x01;
crc >>= 1;
if (mix)
crc ^= 0x8C; /* 0x31 (x^5 + x^4 + 1) with the bit order reversed */
byte >>= 1;
}
}
return crc;
}
/* Test vector from AN27: family 02h, serial number 00000001B81Ch, CRC A2h */
static const uint8_t an27_rom[8] = { 0x02, 0x1C, 0xB8, 0x01, 0x00, 0x00, 0x00, 0xA2 };
/* ow_crc8(an27_rom, 7) == 0xA2, ow_crc8(an27_rom, 8) == 0x00 */
Мы проверили эту функцию на примере AN27, на свойстве с инверсией и сравнили со всей таблицей из AN187: значения совпадают. Если память не жалко, таблица из 256 байт (она приведена в AN27 и AN187) ускоряет расчёт до одного обращения на байт. В avr-libc есть готовая функция _crc_ibutton_update() в util/crc16.h с тем же полиномом, и в её документации проверка сделана на том же коде 02h … A2h.
Две ловушки:
- Нули проходят проверку. CRC восьми нулевых байт — тоже ноль. Если линия замкнута на землю, ведущий прочитает одни нули, и блокнот «сойдётся». Поэтому одни нули нужно проверять отдельно — так делает и DallasTemperature.
- Датчик CRC не проверяет. По даташиту DS18B20 ничто внутри датчика не мешает продолжать обмен при неверной CRC: решение — за ведущим.
Для блоков памяти в микросхемах EEPROM и iButton AN27 описывает ещё CRC-16; ROM-коды и блокнот DS18B20 используют только 8-битную CRC.
Программная реализация на AVR
Программный ведущий нужен там, где под 1-Wire не выделили отдельную микросхему, а это почти любой проект на AVR. Линию DQ подключают к обычному выводу порта с внешним резистором 4,7 кОм. Открытый сток имитируют направлением вывода: бит PORT остаётся нулём, и чтобы прижать линию, вывод делают выходом, а чтобы отпустить — входом без встроенной подтяжки.
#include <avr/io.h>
#include <util/atomic.h>
#include <util/delay.h> /* define F_CPU, e.g. -DF_CPU=16000000UL, and build with -Os */
/* DQ on PB0 with an external 4.7 kOhm pull-up: the pin only pulls low or releases */
#define OW_DDR DDRB
#define OW_PORT PORTB
#define OW_PIN PINB
#define OW_BIT PB0
static inline void ow_low(void) { OW_DDR |= (1 << OW_BIT); } /* output, PORT bit = 0 */
static inline void ow_release(void) { OW_DDR &= ~(1 << OW_BIT); } /* input, no internal pull-up */
static inline uint8_t ow_level(void) { return (OW_PIN >> OW_BIT) & 1; }
void ow_init(void)
{
OW_PORT &= ~(1 << OW_BIT);
ow_release();
}
/* Reset and presence (AN126: H = 480, I = 70, J = 410 us). Returns 1 if a device answered. */
uint8_t ow_reset(void)
{
uint8_t presence;
ow_low();
_delay_us(480); /* an interrupt here only makes the reset pulse longer */
ATOMIC_BLOCK(ATOMIC_RESTORESTATE) {
ow_release();
_delay_us(70);
presence = !ow_level(); /* 0 on the line = presence pulse */
}
_delay_us(410);
if (!ow_level())
return 0; /* still low after the reset: the line is shorted */
return presence;
}
void ow_write_bit(uint8_t bit)
{
if (bit) {
ATOMIC_BLOCK(ATOMIC_RESTORESTATE) {
ow_low();
_delay_us(6); /* A: 1..15 us */
ow_release();
}
_delay_us(64); /* B: the slave samples 15..60 us after the edge */
} else {
ATOMIC_BLOCK(ATOMIC_RESTORESTATE) {
ow_low();
_delay_us(60); /* C: 60..120 us */
ow_release();
}
_delay_us(10); /* D: recovery */
}
}
uint8_t ow_read_bit(void)
{
uint8_t bit;
ATOMIC_BLOCK(ATOMIC_RESTORESTATE) {
ow_low();
_delay_us(6); /* A */
ow_release();
_delay_us(8); /* E = 9 us in AN126, minus the overhead: stay below 15 us */
bit = ow_level();
}
_delay_us(55); /* F */
return bit;
}
void ow_write_byte(uint8_t byte)
{
for (uint8_t i = 0; i < 8; i++) { /* LSB first */
ow_write_bit(byte & 1);
byte >>= 1;
}
}
uint8_t ow_read_byte(void)
{
uint8_t byte = 0;
for (uint8_t i = 0; i < 8; i++) {
byte >>= 1;
if (ow_read_bit())
byte |= 0x80;
}
return byte;
}
Что здесь важно:
- Прерывания запрещены только внутри слота. Если прерывание растянет ноль при записи 0, слот может выйти за 120 мкс; если отложит чтение — ведущий прочитает линию позже 15 мкс. Восстановление после слота прерывания не портят: пауза между слотами не ограничена. Импульс сброса тоже не защищён целиком — 480 мкс с запрещёнными прерываниями могут стоить, например, потерянных байтов UART, а прерывание лишь удлинит импульс. С паразитным питанием помните об ограничении 960 мкс.
- Задержки — константы.
_delay_us()из avr-libc считает такты на этапе компиляции, поэтому её аргумент должен быть константой, F_CPU — заданным, а оптимизация — включённой. На частоте 1 МГц команда длится микросекунду, и требование AN126 о повторяемой задержке в 1 мкс выполнить трудно. - Чтение раньше 15 мкс. Вызов функций, сам
ATOMIC_BLOCKи чтение порта добавляют такты, поэтому задержка E уменьшена на 1 мкс. Проверьте момент чтения осциллографом, если меняете частоту или компилятор: такты команд AVR помогут оценить накладные расходы.
Чтение одного DS18B20 с внешним питанием на этих функциях:
uint8_t ow_crc8(const uint8_t *data, uint8_t len); /* see the CRC section */
/* One DS18B20 with external power. Returns 1 and the temperature in 1/16 degC, 0 on error. */
uint8_t ds18b20_read(int16_t *t16)
{
uint8_t sp[9];
uint8_t any = 0;
if (!ow_reset())
return 0; /* no presence pulse */
ow_write_byte(0xCC); /* Skip ROM: the only device on the bus */
ow_write_byte(0x44); /* Convert T */
for (uint16_t n = 0; !ow_read_bit(); n++)
if (n > 11000) /* 11000 read slots * 70 us = 770 ms */
return 0;
if (!ow_reset())
return 0;
ow_write_byte(0xCC);
ow_write_byte(0xBE); /* Read Scratchpad, byte 0 first */
for (uint8_t i = 0; i < 9; i++) {
sp[i] = ow_read_byte();
any |= sp[i];
}
if (!any || ow_crc8(sp, 8) != sp[8]) /* all zeros pass the CRC, check them apart */
return 0;
*t16 = (int16_t)((uint16_t)sp[1] << 8 | sp[0]);
return 1;
}
Для нескольких датчиков вместо Skip ROM перед чтением ставится Match ROM: байт 55h и восемь байт кода, найденного поиском, начиная с кода семейства.
1-Wire через UART (AN214)
Если у микроконтроллера есть свободный UART со скоростью 115 200 бит/с, он может быть ведущим 1-Wire без программных задержек. Идея AN214: один байт UART — один тайм-слот 1-Wire. Стартовый бит UART — это ноль, с которого начинается слот, а данные байта решают, сколько он продлится.
Выход TXD обычно двухтактный, поэтому к линии его подключают через буфер с открытым стоком. В AN214 два варианта: два транзистора 2N7002 с резистором 100 кОм или микросхема NC7WZ07. Вход RXD соединяют прямо с линией, и UART принимает байт на каждый переданный — как в режиме петли. Если вывод TX вашего микроконтроллера можно настроить как выход с открытым стоком, внешний буфер не нужен.
| Операция | Скорость UART | Передать | Что придёт в ответ | Ноль на линии |
|---|---|---|---|---|
| Сброс и присутствие | 9600 бит/с | F0h | F0h — никто не ответил; другое значение — есть импульс присутствия | 521 мкс: стартовый бит и четыре нуля |
| Запись 1 | 115 200 бит/с | FFh | FFh | 8,7 мкс: только стартовый бит |
| Запись 0 | 115 200 бит/с | 00h | 00h | 78 мкс: стартовый бит и восемь нулей |
| Чтение бита | 115 200 бит/с | FFh | FFh — прочитана 1; меньше FFh, младший бит 0, — прочитан 0 | 8,7 мкс от ведущего, дальше держит ведомое |
Формат кадра — 8 бит, без чётности, один стоп-бит. Почему это работает, видно из чисел. На 115 200 бит/с бит длится 8,68 мкс: стартовый бит попадает в окно 1–15 мкс для записи 1, а девять нулей подряд, 78 мкс, — в окно 60–120 мкс для записи 0. Приёмник UART читает каждый бит посередине, и младший бит данных он прочитает через 1,5 бита, то есть через 13 мкс после спада — до границы 15 мкс. На 9600 бит/с пять нулевых бит дают 521 мкс — это импульс сброса, а импульс присутствия, пришедший в оставшейся половине кадра, превращает принятый байт из F0h в другое значение.
Допуски у 1-Wire широкие, поэтому погрешность скорости UART в пару процентов на обмен не влияет — проверить её для своей частоты поможет калькулятор скорости UART. Зато прерывания больше не страшны: слот формирует аппаратура, а между байтами может пройти сколько угодно времени. С очередями FIFO и DMA процессор отправляет целый байт 1-Wire — восемь байт UART — одной операцией.
/* Board-specific: change the baud rate, send a byte and return the byte received back */
extern void uart_set_baud(uint32_t baud);
extern uint8_t uart_txrx(uint8_t byte);
uint8_t ow_uart_reset(void) /* returns 1 if a presence pulse was seen */
{
uart_set_baud(9600);
uint8_t r = uart_txrx(0xF0);
uart_set_baud(115200);
return r != 0xF0;
}
uint8_t ow_uart_bit(uint8_t bit) /* writes 0 or 1; with bit = 1 also reads */
{
return uart_txrx(bit ? 0xFF : 0x00) & 0x01;
}
Arduino: библиотеки OneWire и DallasTemperature
В Arduino с 1-Wire работают две библиотеки. OneWire Пола Стоффрегена отвечает за слоты: сброс, запись, чтение, поиск и CRC. DallasTemperature Майлза Бёртона построена поверх неё и знает команды термометров DS18B20, DS18S20, DS1822 и DS1825. Подключение то же: DQ на цифровой вывод, резистор 4,7 кОм между DQ и 5 В — пример из OneWire прямо пишет, что резистор обязателен.
Как OneWire формирует слоты
В OneWire 2.3.8 длительности такие, а прерывания запрещены только на критичных участках:
| Операция | OneWire 2.3.8 | AN126 |
|---|---|---|
| Сброс | ноль 480 мкс, проверка через 70 мкс, ожидание 410 мкс | 480, 70 и 410 мкс |
| Запись 1 | ноль 10 мкс, затем 55 мкс | 6 и 64 мкс |
| Запись 0 | ноль 65 мкс, затем 5 мкс | 60 и 10 мкс |
| Чтение | ноль 3 мкс, чтение через 10 мкс, затем 53 мкс | 6, 9 и 55 мкс |
Обратите внимание на запись. После нуля OneWire не просто отпускает линию, а выставляет на ней единицу выходом микроконтроллера и отпускает вывод только после байта. Если вызвать write(0x44, 1), вывод так и останется в единице, и сам микроконтроллер станет сильной подтяжкой для датчика с паразитным питанием. Снять её можно функцией depower() или следующим сбросом. На короткой линии с одним-двумя датчиками этого хватает; для большего тока нужен транзистор.
Что делает DallasTemperature
begin()ищет все устройства, считает термометры, по команде B4h проверяет, нет ли датчиков с паразитным питанием, и запоминает наибольшее разрешение.requestTemperatures()посылает сброс, Skip ROM и 44h — измерение запускается во всех датчиках сразу. Дальше по умолчанию функция ждёт: при внешнем питании опрашивает слотами чтения, пока датчик не ответит 1, но не дольше 750 мс, а при паразитном выжидает фиксированное время — 94, 188, 375 или 750 мс для 9–12 бит.getTempC(адрес)читает блокнот по Match ROM и возвращает градусы. Если датчик не ответил импульсом присутствия, блокнот состоит из одних нулей или CRC не сошлась, вместо температуры приходит −127.getTempCByIndex(i)перед каждым чтением заново выполняет поиск до i-го устройства, поэтому для нескольких датчиков лучше один раз получить адреса черезgetAddress()и читать по ним.
Асинхронный режим освобождает программу на время измерения: setWaitForConversion(false) заставляет requestTemperatures() вернуться сразу, а дальше программа либо ждёт millisToWaitForConversion(), либо спрашивает isConversionComplete() — второе работает только при внешнем питании.
#include <OneWire.h>
#include <DallasTemperature.h>
OneWire oneWire(2); // DQ on pin 2, 4.7 kOhm to 5 V
DallasTemperature sensors(&oneWire);
DeviceAddress addr[4];
uint8_t count;
uint32_t started;
bool converting = false;
void setup() {
Serial.begin(115200);
sensors.begin(); // Search ROM, power mode, resolution
count = min(sensors.getDeviceCount(), (uint8_t)4);
for (uint8_t i = 0; i < count; i++) sensors.getAddress(addr[i], i);
sensors.setWaitForConversion(false); // requestTemperatures() returns at once
}
void loop() {
if (!converting) {
sensors.requestTemperatures(); // Skip ROM + 44h: all sensors at once
started = millis();
converting = true;
} else if (millis() - started >= sensors.millisToWaitForConversion(12)) {
for (uint8_t i = 0; i < count; i++) {
float t = sensors.getTempC(addr[i]);
if (t == DEVICE_DISCONNECTED_C) Serial.println("no answer or CRC error");
else Serial.println(t, 4);
}
converting = false;
}
// other work here: the bus is free while the sensors convert
}
Если датчики на паразитном питании и сильная подтяжка сделана транзистором, его затвор подключают к отдельному выводу и передают номер этого вывода вторым параметром конструктора: DallasTemperature sensors(&oneWire, 7). На время измерения библиотека выставит на нём ноль — под P-канальный транзистор из схемы выше. Делает она это только в блокирующем режиме, внутри ожидания: в асинхронном режиме транзистор придётся включать и выключать самому.
Что значат −127 и 85
- −127 — не температура, а константа
DEVICE_DISCONNECTED_C: датчик не ответил, блокнот пустой или CRC не сошлась. Проверяйте подтяжку, выводы, адрес и линию. Сравнивать с ней результат нужно до любых расчётов. - 85 — значение после включения питания, о нём выше. До версии 4.0.5 включительно DallasTemperature возвращала его как обычную температуру. В версии 4.0.6 (февраль 2026 года) появилась проверка: если в блокноте 50h и 05h, а в зарезервированном байте 6 — 0Ch,
getTemp()возвращает код ошибкиDEVICE_POWER_ON_RESET_RAW, аgetTempC()в этом случае отдаёт те же −127. Байт 6 даташит не описывает, это наблюдение авторов библиотеки. Значения FFh и 07h в байтах 0 и 1 версия 4.0.6 считает признаком нехватки питания и в этом случае тоже возвращает −127.
iButton и другие устройства 1-Wire
| Устройство | Код семейства | Что это | Особенности |
|---|---|---|---|
| DS18B20 | 28h | термометр | −55…+125 °C, 9–12 бит, внешнее или паразитное питание |
| DS1990A | 01h | серийный номер в корпусе iButton | только чтение кода и поиск; читается быстрее 5 мс; 16,3 кбит/с |
| DS2401 | 01h | серийный номер в обычном корпусе | TO-92, SOT-223, TSOC; питание от линии, подтяжка 2,8–6 В через 1,5–5 кОм |
| DS2431 | 2Dh | EEPROM на 1024 бита, четыре страницы по 256 бит | страницы можно защитить от записи; 15,4 и 125 кбит/с; подтяжка не больше 2,2 кОм |
| DS2413 | 3Ah | два ключа с открытым стоком | ключи на 28 В и до 20 мА; питание от линии; 14,9 и 100 кбит/с |
| DS2482-100 | — | ведущий I²C — 1-Wire | сам не ведомое, ROM-кода у него нет |
iButton — это микросхема 1-Wire в круглом корпусе MicroCan из нержавеющей стали диаметром 16,3 мм: крышка — контакт данных, нижняя часть с фланцем — общий провод, а ROM-код выгравирован на крышке. Микросхемы с номером на DS19 — всегда iButton (AN1796). Самая массовая из них — DS1990A с одним только серийным номером, её применяют для контроля доступа и учёта. Считыватель — контактная площадка, подключённая к линии 1-Wire, и ведущему достаточно время от времени посылать сброс: появился импульс присутствия — таблетку приложили. Book of iButton Standards описывает и обратный механизм: отсоединённая таблетка тянет свой вывод данных к нулю внутренним источником тока 5 мкА и, коснувшись линии, сама отвечает импульсом присутствия; у DS1990R такой импульс при касании гарантирован (AN1796). Поэтому поиск в сетях с iButton, по AN148, должен переживать случайные импульсы присутствия, а устройство из списка найденных удаляют, только если его не видно какое-то время.
DS2401 — тот же серийный номер, но для пайки на плату: им помечают платы, модули и сменные блоки, чтобы прибор узнавал, что в него вставили. DS2431 добавляет 128 байт памяти для калибровок и паспортных данных, а DS2413 — два управляемых вывода, например для светодиода и кнопки.
Типичные ошибки и отладка
| Симптом | Вероятная причина | Что проверить |
|---|---|---|
| Нет импульса присутствия, −127 | нет подтяжки, обрыв DQ или GND, перепутаны выводы, не тот вывод в программе | на свободной линии должно быть почти полное питание; выводы TO-92: 1 — GND, 2 — DQ, 3 — VDD |
| 85 °C | измерение не запускали, прочитали раньше времени, датчику не хватило питания | 44h перед чтением, ожидание до 750 мс, сильная подтяжка при паразитном питании |
| Один датчик работает, несколько — нет | на каждом модуле свой резистор, слишком большой вес линии | один резистор на линию; ток нуля не больше 4 мА |
| На столе работает, на объекте сбоит | длинный кабель, звезда, паразитное питание на большой сети | топология «линия», внешнее питание, сильнее ведущий — по AN148 |
| Ошибки CRC на длинном проводе, единицы читаются как нули | слишком большой резистор подтяжки, например 10 кОм, или слишком большая ёмкость линии | фронт осциллографом: к моменту чтения линия должна быть выше порога единицы; резистор 4,7 кОм или меньше, но не ниже предела по току |
| Редкие ошибки CRC | прерывания внутри слотов, чтение позже 15 мкс, помехи | запрет прерываний в слоте, момент чтения осциллографом |
| Устройства пропадают из результатов поиска | отражения, просадка паразитного питания, ложное срабатывание активной подтяжки | вес и радиус сети, отводы, питание датчиков |
| Неверный ROM-код | Read ROM при нескольких устройствах, перепутан порядок байтов | поиск вместо Read ROM; первым байтом должен идти код семейства |
| Все датчики показывают одно и то же или мусор | Skip ROM и Read Scratchpad при нескольких датчиках | чтение по Match ROM |
Что смотреть осциллографом
Осциллограф на DQ показывает сразу всё: уровни, длительности и форму фронтов. Сначала сброс — ноль не меньше 480 мкс от ведущего, затем пауза и импульс присутствия 60–240 мкс. На фронтах видно, успевает ли линия подняться: при записи 1 и при чтении единицы она должна выйти к порогу единицы задолго до 15 мкс от спада. Ноль от ведомого должен быть не выше 0,4–0,8 В — если выше, подтяжка слишком сильная. AN148 предупреждает: в любой точке сети, кроме стороны ведущего, сигнал смотрят только дифференциальным пробником, чтобы «земля» осциллографа не повлияла на линию.
Логический анализатор
Логический анализатор с декодером 1-Wire показывает обмен по командам: сброс, присутствие, ROM-команду, код, данные. Это быстрый способ понять, отвечает ли датчик и что именно он отвечает. Частоту выборки берите с запасом — хотя бы несколько мегагерц, чтобы декодер уверенно различал нули в 1–15 мкс. Аналоговых проблем анализатор не видит: медленные фронты и высокий ноль он покажет как случайные ошибки, поэтому при странных результатах переходите к осциллографу.
Дальше по теме: I²C — другая шина с открытым стоком и подтяжкой, SPI — для быстрого обмена внутри платы, RS-485 — для длинных линий. Остальные интерфейсы — в разделе интерфейсы, микроконтроллеры, к которым подключают датчики, — в разделе AVR.
Частые вопросы
Какой резистор подтяжки нужен для DS18B20: 4,7 кОм или 10 кОм?
4,7 кОм между DQ и питанием — номинал из даташита DS18B20, один резистор на всю линию у ведущего. 10 кОм хуже: фронты затягиваются, и на длинном проводе единица не успевает установиться к моменту чтения. Слишком маленький резистор тоже не годится: DS18B20 гарантированно втягивает 4 мА при 0,4 В, поэтому при 5 В нижняя граница — около 1,15 кОм. Другие устройства требуют своего: DS2431 — не больше 2,2 кОм, DS2401 — 1,5–5 кОм.
Почему DS18B20 показывает 85 °C?
85 °C, код 0550h, — значение регистра температуры сразу после включения питания. Его читают, если датчик ещё не закончил ни одного преобразования: не отправлена команда 44h, блокнот прочитан раньше, чем прошли 750 мс при 12 битах, или датчик перезапустился из-за нехватки питания во время измерения. Последнее типично для паразитного питания без сильной подтяжки.
Что значит −127 °C в библиотеке DallasTemperature?
Это не температура, а код ошибки DEVICE_DISCONNECTED_C. getTempC() возвращает его, если датчик не ответил импульсом присутствия, если прочитанный блокнот состоит из одних нулей или если не сошлась CRC. Частые причины — нет подтяжки, обрыв, перепутаны выводы, неверный адрес, помехи на длинной линии. Начиная с версии 4.0.6 тот же код возвращается и при чтении датчика, который ещё не измерял температуру после включения.
Сколько датчиков DS18B20 можно подключить к одной линии?
Адресов хватит на любое число: у каждого датчика свой 48-битный серийный номер. Ограничивает нагрузка на линию. По AN148 каждое устройство в обычном корпусе добавляет к сети столько же, сколько примерно 0,5 м кабеля, а ведущий с резистивной подтяжкой вытягивает около 200 м такой нагрузки. При паразитном питании нужен ещё и ток: при измерении каждый датчик берёт до 1,5 мА, и десять одновременных измерений требуют 15 мА через сильную подтяжку.
Какая максимальная длина линии 1-Wire?
Единой цифры нет: длина зависит от ведущего, кабеля, топологии и числа устройств. AN148 даёт ориентиры для витой пары категории 5e и питания 5 В: ведущий на ключе с подтяжкой 1 кОм — до 200 м, DS2480B с RC-фильтром — до 200 м, ведущий с активной подтяжкой по AN244 — до 500 м, причём в топологии «линия». С обычным резистором 4,7 кОм у вывода микроконтроллера по оценке в статье надёжны десятки метров.
Можно ли питать DS18B20 от 3,3 В?
Да: и внешнее, и паразитное питание по даташиту — от 3,0 до 5,5 В. Но при паразитном питании порог единицы на входе DQ — 3,0 В, и при 3,3 В запас всего 0,3 В: линия должна подняться почти до питания, поэтому длинный провод и много датчиков не получатся. При 3,3 В надёжнее подать на датчики внешнее питание, а если нужно паразитное — ставить сильную подтяжку, как советует AN4206.
Источники
- Analog Devices (Maxim Integrated). DS18B20 Programmable Resolution 1-Wire Digital Thermometer, 19-7487, Rev 6, 7/19 — таблицы DC и AC — пороги, токи, длительности слотов; рис. 4 и табл. 1 — формат температуры; рис. 6 и 7 — подключение; рис. 9 и 10 — блокнот и конфигурация; табл. 3 — функциональные команды; рис. 15–18 — сброс, запись и чтение
- Maxim Integrated. Application Note 126: 1-Wire Communication Through Software, версия 2.3 — табл. 1 и 2 — четыре операции и рекомендуемые задержки A–J для стандартной скорости и overdrive
- Maxim Integrated. Application Note 187: 1-Wire Search Algorithm — табл. 1 и 3 — разбор пары бит и выбор направления, табл. 4 — варианты поиска, код на C
- Maxim Integrated. Tutorial 148: Guidelines for Reliable Long Line 1-Wire Networks, 2014 — радиус и вес сети, топологии, вес устройств и кабеля, пределы для разных ведущих, ошибки программного ведущего
- Maxim Integrated. Tutorial 214: Using a UART to Implement a 1-Wire Bus Master, 2002 — рис. 2 — буфер с открытым стоком, рис. 4–8 — байты и скорости UART для сброса, записи и чтения
- Maxim Integrated. Application Note 27: Understanding and Using Cyclic Redundancy Checks with Maxim 1-Wire and iButton Products — полином CRC8, свойства, пример расчёта для кода 02h, 00000001B81Ch, A2h, табличный метод
- Dallas Semiconductor. Application Note 937: Book of iButton Standards, 1997 — гл. 4 — временные параметры стандартной скорости и overdrive, tRDV и tRELEASE; гл. 5 — ROM-команды и структура кода семейства
- Maxim Integrated. Application Note 4206: Choosing the Right 1-Wire Master for Embedded Applications, 2008 — рис. 1 — сильная подтяжка на BSS84 с резистором 10 кОм; категории ведущих, DS2480B и DS2482
- Maxim Integrated. Tutorial 1796: Overview of 1-Wire Technology and Its Use, 2008
- Analog Devices (Maxim Integrated). DS2482-100 Single-Channel 1-Wire Master, 19-4930, Rev 10, 1/15 — адрес I2C, команды, временные параметры, ёмкость линии не больше 1 нФ
- Analog Devices. DS2401 Silicon Serial Number, 19-5860, Rev 12/23
- Analog Devices (Maxim Integrated). DS2480B Serial to 1-Wire Line Driver
- Analog Devices (Maxim Integrated). DS2431 1024-Bit 1-Wire EEPROM, 19-4675, Rev 16, 5/21 — сравнительная таблица временных параметров стандартной скорости и overdrive, команды Resume и Overdrive
- Analog Devices (Maxim Integrated). DS2413 1-Wire Dual Channel Addressable Switch; DS1990A Serial Number iButton, 19-8145
- Paul Stoffregen и др. Библиотека OneWire для Arduino, версия 2.3.8 — OneWire.cpp — длительности сброса, записи и чтения, параметр power
- Miles Burton и др. Библиотека DallasTemperature (Arduino-Temperature-Control-Library), версия 4.0.6 — DallasTemperature.cpp — requestTemperatures(), ожидание преобразования, коды ошибок
- avr-libc: модуль util/crc16.h, функция _crc_ibutton_update — тот же полином и тот же тестовый код 02h … A2h; требования к _delay_us() — в описании модуля util/delay.h
Смотрите также
- ИнтерфейсыUART, RS-232, RS-485, I²C, SPI, CAN: уровни, схемы, выбор
- I²CSDA и SCL, START/STOP, ACK, адреса, скорости, расчёт подтяжек
- SPISCLK, MOSI, MISO, CS, режимы 0–3, daisy chain, частота, SPI в AVR
- RS-485Уровни, длина линии, терминаторы, смещение, MAX485, Modbus RTU
- AVRATmega, ATtiny, AVR Dx/Ex: семейства, прошивка, инструменты