В принципе это можно сделать с помощью таймера, но на самом деле это неудобно: и таймеры обычно заняты более полезными делами, и нет туг у нас каких-то жестких требований ни к стабильности, ни к форме сигнала. Потому мы воспользуется древним, как сами микропроцессоры, способом формирования временной задержки с помощью пустого цикла. Так как время выполнения всех команд точно известно, то этот способ для формирования импульса определенной длительности ничуть не хуже любого другого, а когда в МК еще не было никаких таймеров, он вообще был единственным доступным способом для таких целей.

Для формирования импульса воспользуемся счетчиком cnt (пусть это будет регистр из числа старших — от r16 до r31). Пустой цикл, повторенный NN раз, тогда запишется так:

           ldi cnt,NN

cyk_delay: dec cnt

           brne cyk_delay

Посчитаем, чему должно равняться число NN. Пусть мы хотим обеспечить скорость передачи для I2С около 100 кГц, тогда длительность одного импульса (полпериода тактовой частоты) должна равняться примерно 5 мкс. Сам цикл занимает 3 такта (команда dec 1 такт + команда brne с переходом — 2 такта), т. е., например, при частоте кварцевого генератора 4 МГц он будет длиться 0,75 мкс. Итого, чтобы получить при этой частоте импульс в 5 мкс, нам надо повторить цикл 6–7 раз. Точно подогнать частоту не удастся, но нам это, как мы говорили, и не требуется: опыт показывает, что при ошибке даже в два-три раза работоспособность I2С практически не нарушается.

Чтобы не отводить отдельный регистр только для такой частной задачи, как счет циклов в задержке, стоит дополнить цикл процедурами сохранения в стеке значения счетчика, тогда этот регистр можно безопасно использовать где-то еще. И вся процедура будет выглядеть так:

delay:  ;~5 мкс (кварц 4 МГц)

           push cnt

           ldi cnt,6

cyk_delay: dec cnt

           brne cyk_delay

           pop cnt

ret

Используя эту процедуру, можно сформировать весь протокол. Чтобы не загромождать текст этой главы, я вынес полный текст процедур обмена по I2С в Приложение 5 (раздел «Процедуры обмена по интерфейсу I2С», листинг П5.3). Подробно расшифровывать я его не буду, т. к. он полностью соответствует описанию протокола.

Указанный в Приложении 5 текст, кроме общих процедур посылки и приема байта (бесхитростно названных write и read), содержит процедуры для двух конкретных устройств: энергонезависимой памяти с интерфейсом I2С (типа АТ24) и часов реального времени (RTC) с таким же интерфейсом DS1307. Эти микросхемы имеют заданные I2С — адреса — при записи $А0 (10100000) у памяти и $D0 (11010000) у часов (соответственно, $А1 и $D1 при чтении, подробности см. далее). Сейчас мы займемся проектированием устройства, использующего эти возможности.

Как и сказано в Приложении 5, текст приведенной в листинге П5.3 программы следует скопировать и сохранить в виде отдельного подключаемого файла. Мы будем предполагать, что такой файл называется i2c.prg. Директиву. include "i2с. рrg" следует включать в текст программы обязательно после таблицы векторов прерываний, т. к., в отличие от файла макроопределений (m8535def.inc в данном случае), наш включаемый файл содержит команды, а не только инструкции компилятору. В принципе можно просто вставить текст из файла в основную программу (это и делает компилятор, когда встречает директиву include), только программа тогда станет совсем «нечитаемой».

Запись данных во внешнюю flash-пэмять

Задача, которую мы сейчас будем решать, формулируется так: предположим, мы хотим, чтобы данные с нашего измерителя температуры и давления не терялись, а каждые три часа записывались в энергонезависимую память. Разумеется, встроенной памяти нам надолго не хватит, потому придется прибегнуть к внешней. Схему измерителя (см. рис. 15.2) придется минимально доработать — так, как показано на рис. 16.4.

Рис. 16.4.Присоединение внешней EEPROM к измерителю температуры и давления

Здесь применяется энергонезависимая память типа АТ24С256. Она имеет структуру EEPROM (т. е. с индивидуальной адресацией каждого байта), но чтобы отличить ее от встроенной EEPROM, в дальнейшем мы будем внешнюю память называть flash (хотя это и не совсем корректно). Последнее число в обозначении означает объем памяти в килобитах, в данном случае это 256 Кбит или 32 768 байтовых ячеек (32 кбайт). Объем памяти в 32 кбайт кажется смешным в сравнении с современными разновидностями flash, которые уже достигают объемов 8 Гбайт, но, во-первых, для наших целей, как вы увидите, этого будет достаточно. Во-вторых, память принципиально больших объемов с интерфейсом ГС не выпускают — слишком он медленный.

Перейти на страницу:

Поиск

Похожие книги