Разработка электроники,
Систем автоматики,
Программного обеспечения
ООО "Антех ПСБ",
Санкт-Петербург
+79811865082
anteh@bk.ru
26.10.2015 https://anteh.ru
Речь об использовании аппаратного TWI/I2C интерфейса 8 битных AVR контроллеров для управления RTC DS1307 (VCC 4.5-5.5V) или его более современного аналога DS1338 (DS1338-18 1.71-5.5V, DS1338-3 2.7-5.5V, DS1338-33 3.0-5.5V).
Тема избитая, для бытового применения RTC+LCD или USART и пр. Для промышленного решения, когда RTC является одним из винтиков в общей массе используемых узлов, доступного решения не нашлось. Код должен быть универсальным, компактным, с минимальными задержками на выполнение, учитывать возможные нюансы работы RTC. По корыстным причинам "вылизанный" код, удовлетворяющий всем перечисленным требованиям, не приводится. Приведён полностью рабочий код AVR Assembler, который позволит быстро разобраться, что к чему и при желании довести до своего совершенства.
Рассматриваются режимы работы TWI Master transmitter(MT), Master receiver(MR). Режимы Slave transmitter(ST), Slave receiver(SR) не рассматриваются.
Фото первого макета разрабатываемого контроллера на котором отрабатывалась работа с DS1338-33:
При первоначальной подаче питания на DS13xx с подключённой 3V батареей резервного питания её регистры находятся в произвольном состоянии. Нужно их инициализировать. По крайней мере, первые 8 отвечающие за работу и настройки RTC.
Описание регистров есть в многочисленной документации и сети. Документацию лучше искать на DS1307
Пишем драйвер
Инициализация TWI:
Пины SCL SDA AVR контроллера настраиваем в третье состояние. В коем они по умолчанию и находятся. TWI выход DS13xx, это открытый сток или коллектор, нужно подтянуть к VCC. Можно использовать встроенные подтягивающие резисторы AVR контроллера. Но их номинал для больших скоростей обмена велик 20k-100k и подойдёт для работы TWI/I2C на малых частотах с небольшим количеством устройств на шине. Номинал резистора зависит от рабочей частоты, от количества устройств на шине, емкости шины. Есть рекомендация 1k-4.7k при +5V. Документ AVR1320 рекомендует 2k для частоты 400kHz. Если устройств на шине несколько, то для уверенности в надёжности обмена данными, нужно воспользоваться осциллографом, импульсы на SCL SDA должны быть похожи на прямоугольные. Ниже будет осциллограмма для 1.2k pull-up резисторов, AtMega128A, 320kHz и одно устройство на шине DS1338-33.
Для AtMega128A настройка SCL SDA в третье состояние:
|
Настройка TWI регистров:
|
Другие TWI регистры не трогаем.
Добавляем буфер для работы с DS13xx:
|
Область между StartRAM EndRAM обнуляется при инициализации контроллера:
|
В памяти программ создаём 2 посылки инициализации DS13xx
|
DS1338_init –последовательность байт записываемая при инициализации DS13xx при первом включении, когда DS1338_first_init_flag !=0xA5
DS1338_sub_init –последовательность байт записываемая при каждом перезапуске контроллера. По непроверенным слухам 07h конфигурационный регистр DS13xx может слетать. Поэтому пока предусмотрена процедура его инициализации при запуске контроллера. Сюда же можно добавить проверку корректности CH бита –в чём смысла не вижу, ибо если он действительно слетает, то вместе с ним нужно и время подправлять. Если SQW/OUT не используется, то "слетане" 07h ни на что не повлияет. Нужно уделить внимание стабильности 32.768kHz кварца.
Функция копирования из CSEG в DSEG:
|
В ESEG размещаем:
|
Для работы с DS13xx достаточно 2х функций записи и чтения регистров:
(1)
;Функция используемые регистры не сохраняет. В прерываниях не запускать
;Z -Передаваемая последовательность байт в DS1338 из DSEG
;Формат посылки записи данных в регистры DS13xx:
;DS1338_buf = [N][SLA+W][adr][data0][data1]...[data63]
;[N] -количество байт передаваемых в DS13xx без учёта самого байта длины
;[SLA+W] =0xD0 статический адрес SLAVE DS13xx и флаг записи данных
;[adr] -адрес регистра начала записи в DS13xx
;[data0]-[data63] -значения регистров DS13xx любое количество байт, в том числе и =0 т.е. данных может не быть, нужно для настройки на чтение данных с произвольного регистра DS13xx
Z_to_DS1338:
…
ret
(2)
;Чтение данных из DS13xx
;Для настройки на нужный регистр для чтения, нужно произвести запись в DS13xx байта статического адреса и байта адреса регистра. Затем произвести операцию чтения, в DS1338_to_Z это реализовано в функции автоматически
;Формат последовательности байт чтения из DS13xx:
;В функцию DS1338_to_Z передаётся: DS1338_buf = [N][adr]
;[N] -количество байт читаемых из DS13xx
;[adr] -адрес регистра начала чтения из DS13xx
;Из функции DS1338_to_Z возвращается DS1338_buf = [N][data0][data1]..[dataN]
;[N] -количество байт прочтённое из DS13xx
;[data0][data1]..[dataN] -прочитанные данные
DS1338_to_Z:
…
ret
Обмен данными сводится к заполнению DS1338_buf посылкой к чтению или записи в приведённом выше формате и запуску функции Z_to_DS1338(запись) или DS1338_to_Z(чтение).
Функция инициализации DS13xx с проверкой, была ли произведена полная инициализация. И если была, то запуск частичной инициализации:
|
И теперь собственно сами загадочные и волшебные Z_to_DS1338 и DS1338_to_Z:
|
|
Из функций чтения записи можно убрать проверку статуса операции, что значительно сократит количество кода. Проверка использовалась для отладки.
Оптимально убрать из функций задержки на ожидание выполнения TWI операций. Для этого нужно организовать независимое/мульти задачное/параллельное выполнение кода обмена данными с RTC таймером, это позволит читать время из RTC на любой частоте не оказывая влияния на работу остального кода. Влияние будет в несколько десятков тактов, запрет прерываний в коде обмена с DS13xx не используется. Ниже приведена видео демонстрация работы такого кода.
Чтение данных состоит из 2х операций:
1. 2 байта, записываются в DS13xx настраивая указатель на регистр, с которого будет производиться чтение. Это TWI адрес DS13xx и адрес регистра, с которого начнётся чтение данных.
2. Чтение 7 байт даты и времени. Последний, конфигурационный байт не читается, не нужен.
Осциллограммы pull-up=1.2k Ftwi=320kHz DS1338-33
Более подробно:
Питание DS1338-33: VCC=5V.
На осциллограммах чётко просматривается короткий импульс после восьмого бита при записи данных в DS13xx и после 9го при чтении полагаю, это связано с ACK.
Если кому интересно: DS1338-33 Rpull-up=1.2k, постоянный опрос без задержек или опрос с периодом 2ms, не работает на Ftwi=770kHz, TWBR=1. На Ftwi=715kHz работает TWBR=2.
Проверил, для DS1338-33 на Ftwi=715kHz с TWBR=2 работает отлично с Rpull-up=1.2k и =4.7k с 4.7k фронты конечно "покруглее", но работает чётко. Для максимально заявленной в документации на DS1338-33 Ftwi=400kHz pull-up можно и побольше поставить. А если выбрать частоту ещё меньше, то и встроенных pull-up контроллера будет достаточно. Минимальная частота для кварца контроллера 14.7456MHz Ftwi=444 Hz. Проверено, DS1338-33 VCC=5V минимум работает на 444Hz-740kHz частотах TWI Rpull-up=4.7k.
Качество видео, демонстрирующего мульти задачный обмен данными с DS13xx вышло не очень, но смысл передаёт. Видео демонстрирует, реализацию вышеприведённого подхода. Обмен с DS1338-33 на Ftwi=444 Hz, кварц AtMega128A=14.7456MHz, TWBR=255 и TWSP=11 пред делитель TWI =64. И циклическая передача посылки данных между USART0 USART1 2xRS485 на 115200. Посылка состоит из 2х частей первая статическая около 30 байт, она формируется только один раз при инициализации контроллера и далее циркулирует от USART0 к USART1 и обратно в бесконечном цикле. Т.е. если произойдут какие-либо сбои или ошибки, то посылка будет испорчена и это сразу будет видно по выводу снифера. Вторая часть этой же посылки динамическая -это дата и время читаемое с DS1338-33, эта часть посылки формируется с заданным интервалом -270ms и длится 210ms. Напоминаю Ftwi=444 Hz кварц AtMega128A=14.7456MHz настройки TWI на минимальную частоту чтобы показать, что TWI и 2 USARTа, настроенные на максимальную частоту, друг другу не мешают.
(1) По X 100 мкс в клетке. Частота Ftwi=740kHz USART0 и USART1 =115200. Опрос DS1338 постоянный. Желтый верхний канал SCL, синий средний SDA, сиреневый нижний USARTx RS485 дифференциальный выход. Видео демонстрирует отсутствие каких либо задержек при смежной работе 2хUSART и TWI и ещё ряда функций:
(2) Частоты TWI и USART те же. Но добавлен период опроса DS1338 несколько десятков миллисекунд. Демонстрируется небольшое влияние на TWI работы USARTов и остального кода прошивки, это выражено в псевдо случайном увеличении периодов между байтами данных TWI:
Задержки можно уменьшить, если у используемого контроллера TWI регистры будут с прямым доступом а также, для хранения промежуточных переменных использовать свободные регистры, а не память.
(3) Частота Ftwi=440 Hz. Частота RS485 USART 115200. Опрос постоянный. TWI также не вносит никаких задержек и сам не теряется:
(4) Тоже, что и (3) но опрос DS13xx с периодом несколько десятков миллисекунд, что позволяет детально разглядеть обмен чтения даты времени по TWI:
За дорого, по безналичному расчёту могу предложить выше расхваливаемую мультизадачную функцию, точнее несколько функций управления DS13xx RTC таймером. AVR Assembler. Помимо всего можно удобно читать и записывать все регистры DS1338 DS1307. Рассматривается вопрос разработки подобного кода под Ваши устройства для самых разнообразных датчиков и контролируемых узлов