Программирование AVR AVR318: мастер шины 1-Wire Thu, November 21 2024  

Поделиться

Нашли опечатку?

Пожалуйста, сообщите об этом - просто выделите ошибочное слово или фразу и нажмите Shift Enter.


AVR318: мастер шины 1-Wire Печать
Добавил(а) microsin   

• Поддерживается протокол Dallas 1-Wire® на стандартной скорости.
• Реализация совместима со всеми микроконтроллерами AVR.
• Может быть выбрана работа по опросу или по прерываниям.
• Вариант с опросом не требует никакой аппаратуры микроконтроллера.

Здесь приведен перевод даташита Atmel AVR318: Dallas 1-Wire® master [1].

[Введение]

Устройства Dallas 1-Wire® уникальны тем, что для обмена данными им требуется только один сигнальный провод и общий провод. И подача питания, и передача данных в обоих направлениях осуществляется только по 1 проводу (отсюда и пошло название шины 1-Wire). Устройства 1-Wire завоевали заслуженную популярность в качестве электронных ключей (ключи-таблетки iButton серий DS1990) и датчиков температуры (DS18B20).

1 wire_devices iButton-size

Для того, чтобы микроконтроллер смог обмениваться данными по протоколу 1-Wire, нужен только 1 вывод порта ввода/вывода GPIO. Этот апноут показывает, как можно реализовать мастера шины 1-Wire на микроконтроллере AVR в двух вариантах: либо чисто программно (вариант с опросом), либо с задействованием модуля USART (UART).

[Немного теории: как работает протокол Dallas 1-Wire]

Как уже упоминалось, шина 1-Wire использует только 1 провод для передачи питания и сигналов. Обмен данными асинхронный и полудуплексный, и следует жесткой схеме master-slave (главный-подчиненный). Одно или сразу несколько slave-устройств могут быть подключены одновременно к одной шине, причем на этой шине может работать только один мастер.

В состоянии ожидания (idle) на шине высокий уровень, для этого должен присутствовать верхний нагрузочный резистор (pull-up), через который одновременно приходит питание. Чтобы определить величину pull-up резистора, загляните в даташит на slave-устройство. Все устройства, подключенные к шине, должны иметь возможность притянуть уровень шины к лог. 0. После master требуется наличие буфера с выходом в виде открытого коллектора или открытого стока, если у master нет возможности перевести порт подключения в третье состояние.

Обмен сигналами по шине 1-Wire разделен на слоты по 60 мкс. В течение одного слота передается один бит данных. На длительность слота существуют большие допуски от номинала, что позволяет упростить и удешевить изготовление slave-устройств. Однако все равно от master требуется высокая точность в формировании интервалов времени шины, чтобы обеспечить возможность обмена данными со slave-устройствами с разной базой времени. Так что очень важно укладываться в лимиты времени, описанные в следующих секциях. Более подробно про протокол 1-Wire на русском языке можно почитать в статье [2].

Базовые сигналы шины 1-Wire

Устройство master (микроконтроллер) начитает любую процедуру обмена на шине путем притягивания сигнала шины к лог. 0. Это означает, что при передаче каждого бита, независимо от направления передачи, мастер всегда инициирует передачу бита. Это всегда осуществляется переводом шины master-ом в лог. 0, что синхронизирует логику времени участников обмена шины. Имеется 5 базовых команд для обмена по шине 1-Wire: "Write 1", "Write 0", "Read", "Reset" и "Presence".

Write 1. Этот сигнал показан на рис. 1. Master переводит шину в состояние лог. 0 на время от 1 до 15 мкс. Затем master отпускает шину на оставшееся время слота.

AVR318-Write-1

Рис. 1. Команда-сигнал "Write 1".

Write 0. Этот сигнал показан на рис. 2. Master переводит шину в состояние лог. 0 на время как минимум 60 мкс, но не дольше 120 мкс.

AVR318-Write-0

Рис. 2. Команда-сигнал "Write 0".

Read. Команда чтения показана на рис. 3. Master переводит шину в лог. 0 на время от 1 до 15 мкс. После этого устройство slave удерживает шину в состоянии лог. 0, если оно хочет передать 0. Если slave хочет передать 1, то оно не будет захватывать шину, шина останется непритянутой к земле за время слота, и на ней будет прочитана лог. 1. Таким образом, master должен прочитать состояние шины через 15 мкс после того, как шина была притянута к лог. 0 в момент начала слота. С точки зрения master формирование команды Write 1 точно такое же, как и сигнала Read. Реальный вид сигнала будет зависеть от внутреннего состояния slave-устройства, а не от сигнала master, который управляет шиной одинаково для сигналов Write 1 и Read.

AVR318-Read

Рис. 3. Команда-сигнал "Read".

Reset/Presence. Сигналы Reset (сброс) и Presence (присутствие на шине) взаимосвязаны, поэтому здесь они показаны совместно (см. рис. 4). Имейте в виду, что на картинке длительность сигналов показана условно, на самом деле масштаб может отличаться. Сначала master переводит шину в лог. 0 на время как минимум 8 тайм-слотов (т. е. 480 мкс), и затем освобождает её. Этот интервал называется сигналом Reset. Если на шине присутствует подключенное устройство slave, то оно должно после сигнала Reset выдать на шину импульс лог. 0 через 60 мкс после отпускания master-ом шины, и удерживать лог. 0 в течение как минимум 60 мкс. Этот ответ называется сигналом Presence. Если на шине не появился сигнал Presence, то мастер должен предположить, что к шине не подключено никакое подчиненное устройство, так что дальнейший обмен данными невозможен.

AVR318-Reset-Presence

Рис. 4. Сигналы "Reset" и "Presence".

Программное генерирование сигналов. Генерация сигналов 1-Wire с помощью AVR делается непосредственно с помощью управления режимом порта GPIO. Т. е. меняется направление работы порта, и его выходное состояние путем записи соответствующих значений в регистры DDRx и PORTx, и это делается с участием программно задаваемых задержек. Подробное описание процесса приведено в секции реализации.

Генерирование сигналов с помощью UART. Базовый набор сигналов 1-Wire также может быть сгенерирован с помощью аппаратного UART, встроенного в ядро микроконтроллера AVR. Этот способ требует, чтобы к шине были подключены оба сигнала TXD и RXD аппаратного UART. Также требуется наличие внешнего буфера с открытым коллектором или открытым стоком, чтобы обеспечить возможность освобождения шины, когда на выходе UART присутствует лог. 1. На рис. 5 показана реализация такого буфера на транзисторах NPN. Номиналы резисторов и типы транзисторов ориентировочные, указаны только в качестве рекомендации. Для точного значения pull-up резистора см. рекомендации в даташите на slave-устройство, которое подключаете к шине 1-Wire.

AVR318-open-collector-buffer

Рис. 5. Буфер на биполярных транзисторах (открытый коллектор).

Для генерации сигнала 1-Wire используется формат фрейма данных UART 8 бит, без четности (no parity), 1 стоп-бит. Один фрейм данных UART используется для одного бита или для последовательности RESET/PRESENCE. В таблице 1 показано, как нужно настроить модуль UART, чтобы генерировать нужные формы сигнала, и как они интерпретируются на приеме. Соответствующие шаблоны битов UART показаны на рис. 6..10.

Таблица 1. Сигналы UART для эмуляции протокола 1-Wire.

Сигнал Скорость Передаваемое значение Принимаемое значение
Write 1 115200 FFh FFh
Write 0 115200 00h 00h
Read 115200 FFh FFh эквивалентен прочитанному биту 1. Все другие значения эквивалентны биту 0.
Reset/Presence 9600 F0h F0h соответствует отсутствию сигнала presence. Любое другое значение соответствует наличию сигнала presence.

Прим. переводчика: скорее всего, длительности протокола 1-Wire специально проектировались под стандатные скорости работы RS-232, потому что даже в момент первого появления на рынке устройств 1-Wire уже были доступны простые считыватели slave-устройств, подключаемые к COM-порту компьютера. Был также опубликован апноут Dallas, описывающий такое подключение. Открытость протокола и простота подключения к компьютеру положительно сказывались на популяризации протокола 1-Wire.

AVR318-Write-1-UART

Рис. 6. Сигнал Write 1 и соответствующий набор бит UART.

AVR318-Write-0-UART

Рис. 7. Сигнал Write 0 и соответствующий набор бит UART.

AVR318-Read-0-UART

Рис. 8. Сигнал Read 0 и соответствующий набор бит UART.

AVR318-Read-1-UART

Рис. 9. Сигнал Read 1 и соответствующий набор бит UART.

AVR318-Reset-Presence-UART

Рис. 10. Сигнал Reset/Presence и соответствующий набор бит UART.

Команды ROM. Каждое устройство 1-Wire содержит глобальный, уникальный 64-битный номер (идентификатор), хранимый в постоянной неперезаписываемой памяти (ROM). Этот номер может использоваться для упрощения адресации как числовой идентификатор отдельных устройств на шине. Именно этот идентификатор выбит на корпусе ключей iButton в виде шестнадцатеричного числа.

DS1990A-F5 DS1921GB

64-битный идентификатор состоит из 3 частей: 8-битный код семейства, 48-битный серийный номер и 8-битная CRC, которая вычисляется от первых 56 бит идентификатора. Для работы с этим 64-битным идентификатором имеется небольшой набор команд, они называются команды ROM. В таблице 2 показаны эти 6 команд ROM.

Таблица 2. Команды ROM.

Команда Код Назначение
READ ROM 33h Идентификация
SKIP ROM CCh Пропуск адресации
MATCH ROM 55h Адресация определенного устройства.
SEARCH ROM F0h Получить 64-битные идентификаторы всех устройств на шине
OVERDRIVE SKIP ROM 3Ch Версия команды SKIP ROM на повышенной скорости
OVERDRIVE MATCH ROM 69h Версия команды MATCH ROM на повышенной скорости

READ ROM. Эта команда может использоваться на шине, к которой подключено одно slave-устройство, чтобы прочитать уникальный 64-битный идентификатор. Если к шине подключено несколько slave-устройств, то результатом этой команды будет результат AND от всех идентификаторов (т. е. распознать данные каждого идентификатора по отдельности нельзя). И конечно же, если предположить, что передача данных произошла без ошибок, при наличии нескольких устройств на шине контрольная сумма CRC не совпадет.

SKIP ROM. Эта команда может использоваться, целью является не на какое-то конкретное slave-устройство. На шине, где присутствует только одно slave-устройство, достаточно использовать команду SKIP ROM для адресации этого устройства. При наличии на шине нескольких slave-устройств команда SKIP ROM может использоваться для адресации всех устройств сразу. Это может быть полезным только в том случае, когда надо подать команду всем устройствам одновременно, например запустить измерения температуры на всех сенсорах сразу. При наличии на шине нескольких slave-устройств использовать для чтения команду SKIP ROM невозможно.

MATCH ROM. Команда MATCH ROM используется для адресации отдельных slave-устройств на шине. После команды MATCH ROM по шине передается полный 64-битный идентификатор. Когда это завершилось, разрешено отвечать только тому устройству на шине, которое имеет точно этот идентификатор - пока не будет принят следующий импульс reset.

SEARCH ROM. Команда SEARCH ROM может использоваться, когда идентификаторы всех slave-устройств не известны заранее. Она дает возможность определить все идентификаторы устройств, которые подключены сейчас к шине. Сначала команда SEARCH ROM передается по шине мастером. Затем мастер читает один бит из шины. Каждое slave-устройство помещает свой первый бит идентификатора на шину. Таким образом, мастер прочитает логическое AND от всех первых бит идентификаторов устройств, подключенных на шине. Затем мастер читает следующий бит на шине. Тогда каждое slave-устройство помещает на шину дополнение к своему первому биту. Мастер прочитает этот бит как логическое AND от всех логических дополнений первого бита от всех подчиненных устройств. Если все устройства имели в первом бите лог. 1, то мастер прочитает 10b. Если же все устройства имели в первом бите 0, то мастер прочитает 01b. В этих двух случаях бит может быть сохранен как первый бит у всех адресов. Тогда мастер запишет этот бит обратно, это даст эффект, что все подчиненные устройства продолжат посылать свои идентификаторы. Если на шине присутствуют устройства, у которых первый бит идентификатора отличается (т. е. у одного устройства первый бит 0, у другого первый бит 1), то мастер прочитает на шине 00. В этом случае мастер должен сделать выбор - хочет ли он обращаться по адресу, где в первом бите будет 0, или по адресу, где в первом бите будет 1. Выбор будет передан на шину, в результате чего все устройства, у которых в первом бите окажется не соответствующий выбранному значению бит, останутся в состоянии ожидания.

Затем мастер переходит к следующему биту, и процесс повторяется до тех пор, пока не будут прочитаны все 64 бита. В результате будет прочитан один 64-битный идентификатор устройства, которое подключено к шине. Чтобы распознать другие идентификаторы, команда SEARCH ROM должна быть запущена заново, но на этот раз на спорном бите выбор должен быть сделан на противоположный. Повторение этой процедуры для каждого починенного устройства приведет к тому, что все их идентификаторы будут распознаны. Обратите внимание на то, что когда закончен поиск одного идентификатора, то все подчиненные устройства, кроме одного, должны находиться в состоянии ожидания (idle). Так что теперь можно осуществлять обмен данными с этим устройством без специальной адресации его командой MATCH ROM.

Overdrive ROM. Команды overdrive ROM здесь не рассматриваются, поскольку данный документ относится только к командам, работающим на стандартной скорости.

Memory/function. Команды доступа к памяти/функциям относятся к специфическим командам, зависящим от конкретного slave-устройства. Эти команды обычно работают с чтением и записью внутренней памяти и регистров slave-устройств. Определено некоторое количество этих команд, но не все команды используются всеми устройствами. Порядок чтения и записи специфичен для конкретного устройства, и основной стандарт это не определяет. Подробно команды памяти здесь не рассматриваются.

Итак, все 1-Wire устройства следуют базовой последовательности обмена данными:

1. Мастер посылает на шину сигнал Reset.
2. Slave-устройство (или устройства, если их несколько на шине) отвечают импульсом Presence.
3. Мастер посылает команду ROM, которая эффективно адресует одно или несколько slave-устройств.
4. Мастер посылает команду Memory.

Обратите внимание, что для начала каждого шага нужно завершить сделанный последний шаг. Однако это необязательно делать для завершения всей последовательности. Например, можно послать новый Reset после завершения команды ROM для начала нового цикла обмена.

CRC. Контрольная сумма, Cyclic Redundancy Check (CRC) используется устройствами 1-Wire для того, чтобы гарантировать целостность данных. Теория CRC здесь не рассматривается. Для получения дополнительной информации про CRC см. [2].

В устройствах 1-Wire можно найти главным образом две разных CRC. Одна 8-битная (называется Dallas
One Wire CRC, DOW-CRC, или просто CRC8), вторая 16-битная (CRC16). CRC8 используется в секции ROM всех устройств. Также CRC8 используется в некоторых устройствах для проверки других данных, наподобие команд, выданных на шине. CRC16 используется в некоторых устройствах для проверки на ошибки в достаточно больших наборах данных.

Аппаратный эквивалент 8-битной CRC, используемой на 64-битном идентификаторе, показан на рис. 11. Блоками представлены отдельные биты регистра сдвига. Эквивалентный полином для этой CRC будет X8 + X5 + X4 + 1.

AVR318-1-Wire-hardware-CRC8

Рис. 11. Аппаратный эквивалент CRC8, используемой в 1-Wire устройствах.

Аппаратный эквивалент 16-битной CRC, используемой в некоторых устройствах 1-Wire, показан на рис. 12. Блоками представлены отдельные биты регистра сдвига. Эквивалентный полином для этой CRC будет X16 + X15 + X2 + 1.

AVR318-1-Wire-hardware-CRC16

Рис. 12. Аппаратный эквивалент CRC16, используемой в 1-Wire устройствах.

[Реализация]

Здесь рассмотрены 3 разные реализации 1-Wire (драйверы): чисто программная обработка GPIO с периодическим опросом (без прерываний), использование периодического опроса UART (без прерываний) и использование UART с задействованием прерываний. Ниже дано короткое описание каждой реализации, подробная информация по использованию не включена в этот документ. Пожалуйста, см. документацию в исходном коде для этого апноута для получения информации, как использовать различные драйверы.

Можно реализовать протокол 1-Wire только программно, без применения какой-либо дополнительной аппаратуры. Достоинство такого решения в простоте - задействован только 1 вывод GPIO, и подключен 1 pull-up резистор. Поскольку все выводы GPIO микроконтроллеров AVR двунаправленные, и у них есть подключаемый внутренние pull-up резисторы, то AVR могут управлять шиной 1-Wire без поддержки внешних схем. В тех случаях, когда номинал встроенного резистора не подходит под текущую конфигурацию подключенных slave-устройтв, из внешней аппаратуры требуется только один внешний резистор. Недостаток этой реализации в том, что микроконтроллер загружен непроизводительными задержками на ожидание для отработки интервалов времени Reset/Presence и битовых сигналов. Чтобы обеспечить корректные интервалы времени шины 1-Wire, во время передачи битов прерывания должны быть запрещены. Допустимая задержка между передачей двух соседних бит (recovery time, время восстановления) не ограничена сверху, так что можно безопасно обрабатывать прерывания после передачи каждого бита. Когда шина 1-Wire активна, из-за длительности сигнала Reset/Presence получается латентность в обработке прерывания для самого худшего случая меньше 1 мс.

Опрашиваемый драйвер UART использует встроенный аппаратный UART микроконтроллера AVR (который есть почти на всех AVR) для генерации требуемых сигналов шины 1-Wire. Остальная часть драйвера эквивалентна программному драйверу, который был описан в предыдущем абзаце. Главное достоинство этого драйвера в сравнении с чисто программным в том, что меньше размер кода, и еще тот факт, что не надо отключать прерывания во время передачи битов, потому что модуль UART выдерживает нужные задержки интервалов времени аппаратно. Недостаток в том, что нужно использовать два GPIO, причем определенные GPIO (привязанные к TX и RX аппаратуры UART), также нужна некоторая внешняя схема.

Драйвер на основе UART с задействованием прерываний генерирует сигналы шины точно так же, как это делает драйвер UART с программным опросом. Дополнительное достоинство в том, что прерывания позволяют автоматизировать прием и передачу до 255 бит данных с минимальной загрузкой вычислительного ядра AVR.

Драйверы с опросом разделены на две части: генерация сигналов на уровне бита, и более высокоуровневые команды наподобие передачи байт и реализации команд ROM. Между двумя программными версиями драйвера различаются только процедуры уровня бит (поскольку сигналы шины формируются в одном случае чтением/записью регистров GPIO, в другом случае чтением/записью регистров UART), но далее реализован общий интерфейс, что позволяет выполнять высокоуровневые команды с любым драйвером.

[Программная реализация на основе управления GPIO]

С чисто программной реализацией, которая описана в этом апноуте, можно реализовать сразу несколько шин 1-Wire, подключенных к одному AVR. Все шины должны быть подключены к одному и тому же порту ввода/вывода (например только к PORTB, или только к PORTD), но какой порт будет использоваться - можно выбрать опциями перед компиляцией. Это ограничивает количество шин до 8, однако распределение шин по разрядам порта полностью конфигурируемо. Все выводы, которые не задействованы под шины 1-Wire, остаются нетронутыми. Поскольку все шины 1-Wire подключены к одному и тому же порту, то можно одновременно выполнять несколько операций в одно и то же время на нескольких шинах. Это возможно путем задействования аргумента для выбора нужного вывода или выводов, который передается каждой функции. Этот аргумент должен содержать в себе битовую маску для выводов, которые должны использоваться для этой операции. К примеру, это дает возможность послать сигнал Reset одновременно на 8 шин, если передать 0xff в аргументе маски выводов. Значение, которое будет возвращено, является битовой маской от всех шин, где одно или большее количество slave-устройств ответило сигналом presence. Эта битовая маска может быть затем передана в качестве аргумента выводов в функцию, которая выдает команду SKIP ROM, и так далее. Все функции в этой реализации поддерживают выбор выводов. Как основное правило все команды, которые записывают данные на шины, могут адресовать одновременно несколько шин. Команды, которые читают более одного бита с шины, могут адресовать только одну шину.

Инициализация. Процедура инициализации для программной реализации драйвера интерфейса 1-Wire очень проста. Она заключается в настройке выводов шин 1-Wire в режим ввода, и разрешение на этих выводах внутренних резисторов pull-up, и если это необходимо, перевод шины в состояние ожидания (idle mode). Некоторые устройства среагируют на фронт нарастания уровня на шине как на окончание сигнала Reset, и ответят выдачей сигнала Presence. Чтобы гарантировать, что этот сигнал не повлияет на любой обмен данными, после инициализации порта добавлена задержка, равная времени восстановления из сигнала Reset.

Битовые функции нижнего уровня. Эти функции реализованы в соответствии с апноутом AN126 компании Dallas Semiconductors. Все параметры времени удовлетворяют рекомендуемым значениям в этом апноуте. Требуется 10 различных задержек, которые перечислены в таблице 3.

Таблица 3. Задержки, которые применяются на уровне формирования передачи битов.

Параметр Рекомендуемая задержка (мкс)
A 6
B 64
C 60
D 10
E 9
F 55
G 0
H 480
I 70
J 410

Обратите внимание, что задержка G в стандартном режиме равна 0.

Поскольку операции ввода/вывода реализованы на C, не на ассемблере, то настройки оптимизации компилятора и другие факторы могут повлиять на формируемые задержки. Рекомендуется проанализировать форму сигнала с помощью осциллографа, и подстроить задержки, если это необходимо.

Реализация функций слоя передачи бит показана на рис. 13. Обратите внимание, что функция DetectPresence и отправляет сигнал Reset, и слушает шину на предмет появления сигнала Presence. Все функции уровня передачи бит могут адресовать несколько шин одновременно.

AVR318-bit-transfer-layer-functions

Рис. 13. Функции слоя передача бит.

Приложены два макроса для притягивания шины к лог. 0 и для освобождения шины. Они реализованы как макросы, потому что используются часто, так что устраняется ненужная нагрузка в виде вызова функции и возврата из функции, что положительно влияет на точность формирования диаграмм сигналов по времени.

[Реализация на основе опроса UART]

В этой реализации все задержки времени для формирования сигналов шины обслуживаются модулем UART. Чтобы отправить бит, устанавливается скорость UART (Baud Rate) на подходящее значение, и регистр данных UART загружается значение, которое генерирует нужную форму сигнала, как это было описано в секции "Генерирование сигналов с помощью UART" (см. также рис. 6..10).

Инициализация. Чтобы инициализировать драйвер UART с программным опросом, аппаратура UART должна быть настроена с правильными параметрами. Разрешение передачи и приема, установка формата данных 8 бит, без четности (no parity), 1 стоп-бит и скорость обмена 115.2 килобод.

Это приведет к тому, что вывод TXD модуля UART перейдет в состояние ожидания (idle) с уровнем лог. 1. Подчиненные устройства воспримут фронт нарастания сигнала TXD как окончания сигнала RESET, и ответят сигналом presence.

Битовые функции нижнего уровня. Все эти функции реализованы в драйвере с опросом UART через одну общую функцию OWI_TouchBit. Эта функция выводит первый входной аргумент в модуль UART, ждет завершения приема UART, и затем возвращает принятое значение. Каждая из битовых функций вызывает OWI_TouchBit со значением, которое генерирует корректное значение сигнала на шине.

Интерфейс к этим функциям тот же самый, что и в реализации драйвера с программным опросом порта (без UART). Аргумент pins однако не требуется в драйвере UART с опросом. Набор макросом делает возможным вызов этих функций с аргументом pins или без него. Если аргумент pins присутствует, то он будет удален макросом.

Функции высокого уровня. Обратите внимание, что многие функции на этом уровне принимают в качестве аргумента тип указатель на беззнаковое целое (unsigned char pointer). Этот указатель должен указывать на массив памяти из 8 байт, который может использоваться функцией. Выделение этих массивов в памяти, а иногда и их инициализация должна выполняться вызывающей функцией. Этот документ четко показывает, когда память должна быть инициализирована специальным образом перед вызовом функции.

Функции передачи байта

AVR318-byte-transmission-functions

Рис. 14. Функции передачи байта.

Команды ROM. Реализованы все основные команды ROM для стандартной скорости обмена. Самая простая из них команда SKIP ROM. Она просто вызывает функцию SendByte, которая получает байт команды SKIP ROM в качестве аргумента. Алгоритмы для команд READ ROM и MATCH ROM показаны на рис. 15.

AVR318-Read-ROM-flowchart

Рис. 15. Алгоритм работы Read ROM (чтение ROM).

Алгоритм для команды SEARCH ROM показан на рис. 16. Эта функция ищет одно slave-устройство при каждом своем запуске, пока не останется ни одного нераспознанного устройства на шине. Во время последнего запуска она вернет OWI_ROM_SEARCH_FINISHED. В дополнение к параметру pin, который используется для выбора шины, в эту функцию должны быть переданы 2 параметра: lastDeviation и bitPattern. Эти параметры управляют поиском slave-устройства. Обратитесь к таблице 4, чтобы понять, как использовать эти параметры для завершения полного поиска всех подчиненных устройств.

Таблица 4. Использование bitPattern и lastDeviation.

BitPattern lastDeviation
Первый раз 8-байтный массив заполняется нулями. 0
Последующие запуски Копия 8-байтного массива, возвращенного через указатель bitPattern на последнем запуске. Значение, возвращенное из SearchRom на последнем запуске.

Функция реализована таким способом для того, чтобы дать вызывающему коду максимум гибкости. Пример программного обеспечения для драйвера с опросом показывает, как его можно использовать для выполнения полного поиска.

AVR318-Search-ROM-command

Рис. 16. Команда Search ROM (поиск ROM).

Тактирование. Важно генерировать сигналы шины максимально точно, насколько это возможно. Чтобы добиться этого, нужно точно формировать задержки. Количество необходимых циклов тактов для задержки в определенное количество микросекунд вычисляется во время компиляции. Когда генерируются сигналы, некоторые такты теряются, когда шина притягивается к лог. 0, и когда шина освобождается. Эти циклы тактов вычитаются их количества тактовых циклов, нужных для генерирования задержки. Если тактовая частота слишком мала, то может получиться отрицательная задержка. Нужна тактовая частота не ниже 2.17 МГц, чтобы получить самые короткие задержки.

[Реализация на основе UART с задействованием прерываний]

Для драйвера UART с прерываниями требования к аппаратуре те же самые, что и для драйвера UART с опросом. Базовая функциональность реализации с прерываниями, показанной в этом апноуте, состоит в том, чтобы обеспечить автоматическую передачу и прием больших порций данных на шине. Это реализовано в двух обработчиках прерывания (Interrupt Service Routines, ISR). Для настройки всех необходимых параметров должны вызываться несколько вспомогательных функций, и эти ISR завершают транзакцию автоматически. Это возможно для последовательности Reset/Presence или для передачи любого количества бит данных от 1 до 255 в одном направлении, без какого-то дополнительного вмешательства в запущенный процесс.

Чтобы сделать ISR-ы максимально простыми, не делается различие для процессов передачи и приема. UDRE ISR просто отправляет один бит из буфера данных каждый раз при своем запуске. RXC ISR принимает тот же б бит, и помещает его обратно в буфер данных независимо от направления, в котором передаются данные. Во время передачи отправленные данные будут идентичны принятым, и буфер данных не поменяется. Во время приема должны передаваться только единички, поскольку форма сигнала "write 1" совпадает с формой сигнала чтения. Сигнал на шине опрашивается, чтобы считать значение, которое послало slave-устройство. Затем это значение будет помещено в буфер данных.

Три глобальных флага сигнализируют о состоянии драйвера 1-Wire: busy, presence и error. Флаг busy установлен, пока еще есть данные для передачи. Флаг presence установлен, если детектирован сигнал Presence, когда отправляется сигнал Reset. Этот флаг остается установленным, пока сигнал Reset по шине не получил в ответ сигнал Presence. Флаг error устанавливается, когда приемник UART детектировал ошибку фрейма. В этой ситуации по шине должен быть передан новый сигнал Reset. Это приведет к сбросу всех slave-устройств на шине, а также внутреннего состояния обработчиков UDRE ISR и RXC ISR.

Поскольку ISR-ы должны завершить свою работу как можно быстрее, более сложные функции, наподобие команд ROM, не реализованы в обработчиках ISR. Прилагаемый код примера показывает, как такое поведение должно быть реализовано в машине конечных состояний (Finite State Machine, FSM).

Обработчики прерываний (Interrupt Service Routine, ISR). Алгоритмы для ISR показаны на рис. 17 и 18. Обработчик ISR события опустошения данных UART Data Register Empty (UDRE) запускается всякий раз, когда появляется свободное место в буфере передачи UART. Обработчик ISR для события завершения приема UART Receive Complete (RXC) запускается каждый раз, когда данные приняты, и находятся в готовности в буфере приема UART.

AVR318-UDRE-ISR

Рис. 17. Алгоритм ISR для UDRE.

AVR318-RXC-ISR

Рис. 18. Алгоритм RXC для UDRE.

Вспомогательные функции. Они нужны для установки некоторых параметров, которые нужны для автоматической передачи под управлением прерываний. После установки всех нужных параметров передача инициируется разрешением прерывания UDRE. Алгоритмы вспомогательных функций показаны на рис. 19.

Обратите внимание, что функция ReceiveData (функция для приема данных) в действительности заполняет буфер данных единичками, после чего вызывает функцию TransmitData (функция для передачи данных). RXC ISR будет делать выборки сигнала и поместит в буфер данных прочитанное значение, которое передало slave-устройство.

AVR318-helper-functions

Рис. 19. Вспомогательные функции.

[Вычисление CRC]

Далее описан алгоритм для вычисления двух разных типов CRC. Переменная crc либо установлена в 0, либо в начальное значение CRC, так называемое "seed". Это объясняется ниже. Сокращение LSB означает Least Significant Bit, т. е. самый младший бит. Сокращение MSB означает Most Significant Bit, т. е. самый старший бит.

1. Найти логическое исключающее или (XOR) между LSB у CRC и LSB у данных.
2. Если это значение равно 0, то:
    a. Сдвинуть вправо CRC.
3. Если это значение равно 1, то:
    a. Найти новое значение CRC путем выполнения операции XOR между CRC и полиномом CRC.
    b. Сдвинуть вправо CRC.
    c. Установить MSB у CRC в 1.
4. Сдвинуть вправо данные.
5. Повторить всю последовательность 8 (или 16) раз.

Этот алгоритм может использоваться одинаково как для вычисления CRC8, таки и для CRC16. Разница только в разрядности CRC и регистре сдвига для него (8 бит для CRC8, 16 бит для CRC16) и в значении числа полинома. Это число симулирует соединение элементов XOR в аппаратном вычислителе CRC. Значение полинома составляет 18h для CRC8 и 4002h для CRC16.

Алгоритмы реализованы для того, чтобы найти значение CRC по одному байту за раз, но CRC "seed" может быть передано как аргумент подпрограммам CRC. Таким способом результат от одной операции вычисления CRC может быть передан следующей операции вместе со следующим байтом, так что получается эффект вычисления CRC от произвольного количества байт.

Проверка CRC для 64-битных идентификаторов реализована в OWI_CheckRomCRC. Она просто вычисляет значение CRC8 от первых 56 бит, и сравнивает их с последними 8 битами идентификатора.

[Примеры кода]

Приведены 2 примера кода, которые иллюстрируют, как использовать разные реализации драйвера 1-Wire.

Пример кода с опросом. Этот пример для драйверов с опросом, которые делают поиск устройств на шинах, заданных как BUSES. Устройства сохраняются в массиве типа OWI_device. OWI_device является структурой, которая содержит информацию об устройстве, подключенном к шине, и его 64-битный идентификатор. Драйвер затем ищет среди доступных устройств сенсор температуры DS1820 и цифровой потенциометр DS2890. Если какое-то из этих устройств (или оба) найдено на шине, они будут постоянно опрашиваться в бесконечном цикле. В каждой итерации считывается температура из DS1820, и положение движка DS2890 увеличивается на единицу, обрезаясь по модулю 256. Температура выводится в PORTB, так что её можно наблюдать свечением светодиодов LED на плате разработчика STK500.

Пример кода предназначен просто показать, как использовать разные части драйвера. Код реализован самым общим образом, без оптимизации под какие-то требования. Поэтому имейте в виду, что пример кода не поместится в микроконтроллеры, у которых на борту меньше 4 килобайт памяти программ. Однако сам драйвер полностью совместим со всеми моделями AVR, включая устройства с 1 килобайтом памяти программ.

Пример кода с задействованием прерываний. В этом примере реализована машина FSM. Если драйвер не занят передачей данных по шине, то эта FSM вызывается в бесконечном цикле. Когда драйвер занят, то FSM пропускается, чтобы позволить работать другому коду. Сама по себе FSM подразумевает, что на шине присутствует единственный датчик температуры DS1820. Она читает текущую температуру, и вычисляет CRC, чтобы убедиться, что чтение было корректным. Затем температура помещается в глобальную переменную. Независимо от занятости драйвера, бесконечный цикл выводит температуру в PORTB, так что её изменение можно отслеживать по светодиодам платы разработчика STK500.

[Быстрый старт]

Исходный код. Его можно загрузить в виде zip-файла с сайта atmel.com (или см. [3]). Распакуйте исходный код в любую выбранную Вами папку. Убедитесь, что сохранена структура директорий в том виде, в каком она была в архиве. Здесь есть 3 подпапки: polled, interrupt_driven и common_files. Папка common_files содержит функции CRC, общие определения и определения, специфичные для применяемого микроконтроллера, которые используются для драйверов UART. Папки polled и interrupt_driven содержат драйвера и примеры кода.

Каждая папка содержит в себе файл source.doc. Эти файлы содержат документацию по исходному коду. Пожалуйста обратитесь к этой документации для получения подробностей о том, как использовать разные драйверы.

Драйвер с опросом. Короткое описание каждого файла для драйвера с опросом дано в таблице 5.

Таблица 5. Файлы для драйвера с работой по опросу (без прерываний).

Файл Описание
main.c Пример кода для работы драйвера с опросом.
OWISWBitFunctions.c Битовые функции низкого уровня, реализованные с помощью программного опроса GPIO, без задействования прерываний.
OWIUARTBitFunctions.c Битовые функции низкого уровня, реализованные с помощью опроса UART.
OWIBitFunctions.h Общий заголовочный файл для функций модулей OWISWBitFunctions.c и OWIUARTBitfunctions.c.
OWIHighLevelFunctions.c Функции драйвера верхнего уровня.
OWIHighLevelFunctions.h Заголовочный файл для модуля OWIHighLevelFunctions.c.
OWIPolled.h Конфигурационный заголовочный файл для драйвера с опросом.
source.doc Документация по исходному коду в этой папке.

Чтобы начать работу с драйверами, работающими по опросу, выполните следующие шаги:

• Создайте новый проект в среде разработки IAR embedded workbench. В зависимости от версии IAR, это может потребовать также создания рабочего пространства (workspace).
• Добавьте в проект все файлы *.c из директорий polled и common_files.
• Выберите корневую папку проекта в браузере проектов IAR. Сделайте на неё правый клик и выберите Options..., при этом отобразится диалог настройки опций проекта.
• Под General/Target убедитесь, что выбраны правильный микроконтроллер и правильная модель памяти.
• Под General/Library configuration поставьте галочку на опции "Enable bit definitions in I/O include files".
• Под General/System установите стек данных Data stack (CSTACK) в значение 0x40 и стек возврата Return stack (RSTACK) в значение 0x10. Это требуется для примера, интенсивно использующего память. Размер под стеки меньше могут удовлетворять другим приложениям, которые используют этот драйвер.
• Если для отладки используется AVRStudio, то нужно поменять формат выходного файла. Под XLINK/Output выберите Format/Other, и затем выберите "ubrof 8 (forced)" из выпадающего списка Output format.
• Откройте файл OWIPolled.h для редактирования, и найдите там секцию с именем "User defines" (определения пользователя).
• Выберите либо только программный драйвер (software only) или драйвер UART путем раскомментирования одной из строк, как это описано в файле.
• Переместитесь вниз к секции, относящейся к выбранному драйверу.
• Подстройте определения в секции в соответствии с аппаратными установками, как это описано в файле.
• Теперь проект готов к компиляции.

Драйвер с прерываниями. Короткое описание каждого файла для драйвера с использованием прерываний показано в таблице 6.

Таблица 6. Файлы для драйвера с работой по прерываниям.

Файл Описание
main.c Пример кода для работы драйвера с прерываниями.
OWIInterruptDriven.h Конфигурационный заголовочный файл для драйвера с опросом.
OWIIntFunctions.c Реализация обработчиков прерывания и вспомогательных функций.
OWIIntFunctions.h Заголовочный файл для модуля OWIIntFunctions.c.
source.doc Документация по исходному коду в этой папке.

Чтобы начать работу с драйверами, работающими по прерываниям, выполните следующие шаги:

• Создайте новый проект в среде разработки IAR embedded workbench. В зависимости от версии IAR, это может потребовать также создания рабочего пространства (workspace).
• Добавьте в проект все файлы *.c из директорий interrupt_driven и common_files.
• Выберите корневую папку проекта в браузере проектов IAR. Сделайте на неё правый клик и выберите Options..., при этом отобразится диалог настройки опций проекта.
• Под General/Target убедитесь, что выбраны правильный микроконтроллер и правильная модель памяти.
• Под General/Library configuration поставьте галочку на опции "Enable bit definitions in I/O include files".
• Если для отладки используется AVRStudio, то нужно поменять формат выходного файла. Под XLINK/Output выберите Format/Other, и затем выберите "ubrof 8 (forced)" из выпадающего списка Output format.
• Откройте файл “OWIInterruptDriven.h” для редактирования, и найдите там секцию с именем "User defines" (определения пользователя).
• Поменяйте определения в секции "User defines", чтобы они отражали реальную конфигурацию аппаратуры.
• Теперь проект готов к компиляции.

[Ссылки]

1. AVR318: Dallas 1-Wire master site:atmel.com.
2. iButton: описание протокола, электронный замок на ключах-таблетках.
3. 141130AVR318.zip - исходный код примеров, документация.

 

Добавить комментарий


Защитный код
Обновить

Top of Page