Вы находитесь на странице: 1из 10

1/3. Алгоритмы записи.

Понятия о предельных временных


характеристиках. Формулировка "фурункулезных" вопросов.

Начну с акцентирования Вашего внимания на следующем факте: в значительной части


информации (той, которая мне известна), ее авторы вообще не работают с сигналом
АСК ("шарахаются" от него), то есть, они просто пережидают "переваривание
помощником проглоченного" байта, при помощи фиксированной задержки.
Мало того, после "прохождения" байта любой функциональности, они формируют
фиксированную задержку одной и той же ("огроменной") величины, расчитанную на
процедуру записи (как самой массивной"), хотя, для того чтобы сформировать
приемлемый (с точки зрения надежного "срабатывания" байта) "промежуток" между,
например, адресными байтами, достаточно и "мизерной" задержки.
На стадии первичного "въезда", так делать можно (программа получается простой), но
такого рода программы, во-первых, по своим скоростным качествам, являются
"тормозными", и во вторых, потенциально "кривоватыми", так как все-таки имеется
вероятность возникновения ошибок записи (чтения), которые устранить нельзя
(игнорируется критерий ошибки, которым является единичный уровень сигнала АСК, а
другого "железобетонного" критерия нет).
В конечном итоге, если речь идет о качественной программе (а к ней я и буду
стремиться), необходимо работать с сигналом АСК, то есть, в программе, необходимо
организовывать "плавающую" задержку на основе анализа состояний флага АСК.
В этом случае, программа, естественно, усложняется, но, тем не менее, она становится
быстрой и надежной.
С целью обозначения дальнейшего направления "вектора тяги", примите это к
сведению.
Итак, будем считать, что с записью одного байта данных и со всем, что с ней связано, в
основном, разобрались.
Поясняю практический смысл "перестраховочной" оговорки "в основном".
"Путь конструктора тернист" ("дракон" не дремлет), и никогда не стоит зарекаться, что в
будущем не "вылезет" какая-нибудь "бяка".
Относиться к этому нужно совершенно спокойно и по-рабочему, так как "бяки" есть
неотьемлемый атрибут творческого процесса.
Дело только в "ранге" той или иной "бяки".
В идеале, все "бяки" должны иметь "ранг пупырышка" или "мелочи пузатой", которые
можно с комфортом "прихлопнуть" на стадии "шлифовки" программы.
Так разобрались с записью или нет?
В основном, да, но в деталях, нет, так как, в понятийном смысле, имеются не
"пупырышки", а целые "фурункулы".
Ранее я уже упоминал о потоковой записи. Пришло время и ее "потерзать".
Теперь нужно кое-что объяснить.
Ранее я говорил, что 2-х разрядный счетчик адреса 24С64А может только
инкрементироваться (автоинкремент).
Суть автоинкремента, в приложении к счетчику адреса 24С64А (и к другим 24Схх),
состоит в том, что, после записи первого байта данных в ячейку памяти с изначально
(программно) заданным адресом, от него, происходит последовательное,
автоматическое приращение (+1 ... +1 ... +1 и т.д.) адреса, что и есть автоинкремент.
При этом, программно заданный адрес является, как бы, "начальной точкой отсчета", и
далее (в случае записи/чтения нескольких байтов), автоинкремент происходит от него и
в сторону величения числовых значений адресов.

1
То есть, если, для 1-го записываемого байта данных, программно задан адрес, например,
03h, то, после 1-го автоинкремента, 2-й байт запишется в ячейку памяти с адресом 04h,
после 2-го автоинкремента, 3-й байт запишется в ячейку памяти с адресом 05h и т.д.
В любой момент, эту потоковую запись "мастер" может прервать, сформировав стоп-
условие.
Сразу возникает вопрос: а что случится, если нужно записать один большой массив
байтов данных, состоящий, например, из 1000, 2000, 3000 и более байтов?
По здравому разумению, рано или поздно, эти "экспериметы" закончатся тем, что я
называю "закольцовкой", то есть, байты данных начнут записываться "по верху",
уничтожая ранее записанные байты текущего массива записываемых байтов, с
младшими адресами.
Вывод: должна существовать некая "страница", пределы которой переходить нельзя.
Самое удобное это то, когда весь объем памяти представляет собой одну страницу.
В этом случае, объем упомянутого выше массива байтов данных, в приложении к
24С64А, не должен превышать 8-ми килобайтов.
Имеет это место быть?
Да, имеет, но только при чтении, а при записи совсем другая "петрушка": весь объем
памяти (8 Кб.) делится на несколько страниц, и запись происходит только в пределах
изначально выбранной (по адресному запросу) страницы, причем, обращению к
странице соответствует обращение к любой из ее ячеек (а не только к первой).
Это нужно принять как данность ("правила игры", заданные разработчиками).
Каков объем одной страницы и сколько их?
Смотрю в фирменную (англицкую), техническую документацию 24С64А и
перечитываю русскоязычную информацию других авторов.
Везде сказано, что весь объем памяти (8 Кб.) разделен на 256 страниц (фрагментов) по 32
байта каждая.
Буквальный перевод с английского: "Память 24С64А внутренне организована как
256 страниц по 32 байта каждая".
Открываю книгу Патрика Гёлля и читаю его толкование.
Он утверждает, что объем одной страницы памяти всегда составляет 256 байтов, а число
этих страниц, в зависимости от объема памяти, может быть различным.
Так как, 256 страниц по 32 байта или 32 страницы по 256 байтов? Чему верить???
Здравый рассудок и 30-летний радиолюбительский опыт подсказывает, что и с
схемотехнической, и с понятийной точек зрения, второе гораздо предпочтительнее
первого: младший байт адреса не дробится на части (это и есть страница объемом 256
байтов), а номер страницы задается числовым значением старшего байта адреса.
В этом случае, "правила игры" абсолютно ясны, понятны, а аппаратные "закольцовки"
конца страницы на ее начало реализуются с максимальной схемотехнической
простотой.
А если объем страницы принять равным 32-м байтам, то сложность аппаратной
реализации такого рода 32-байтных "закольцовок" (а при организации страничной
памяти, они имеют место быть), многократно возрастает, что ведет, на мой взгляд, к не
вполне оправданному усложнению схемотехники м/схемы памяти.
Плюс понятийное (и иное) "бардальеро", и особенно в части касающейся работы с
м/схемами памяти различного объема памяти.
На данном этапе, я вовсе не утверждаю, какое именно из этих толкований истинно и кто
"врет безбожно", а могу сказать только то, что одно из этих толкований не верно.
Подобного рода "бардальеро" я и уподобляю мусорной куче, наваленной
коллективными усилиями.
Вот Вам и типичный пример затруднительной ситуации ("противофазного разнобоя"),

2
эффективно выйти из которой можно только посредством "хулиганства".
Что значит "посредством хулиганства"?
А то, что, позднее, когда будет составлена рабочая программа под "живую" м/схему
24С64А, истину можно будет выяснить с абсолютной точностью.
В этом даже есть какая-то интрига (жизнь нужно разнообразить), да и интересно в конце
концов, в чем тут "собака порылась" и кто из двух авторов "лоханулся", причем,
капитально?
А пока, принимаю на веру "фирменное" толкование, как, де-юре, наиболее
авторитетное.
По большому счету, для понимания сути потоковой записи, принципиально не важно,
какой именно объем имеет одна страница памяти, и поэтому "моя душа спокойна".
С деталями разберусь позднее.
Итак, особенность процедуры записи состоит в том, что, если адресный запрос
сформирован только один раз, то запись, вне зависимости от объема
записываемого массива байтов, может производиться только в пределах одной
страницы памяти.
"Правила игры".
1. Обращение к любой из ячеек страницы соответствует обращению к этой странице.
После такого обращения, в случае потоковой записи, вся "свистопляска" будет
происходить в пределах адресных "границ" именно этой страницы.
2. Если после заполнения текущей страницы (или по другой необходимости), нужно
перейти к записи байтов в другую страницу, то должен быть сформирован адресный
запрос к какой-либо из ячеек этой самой "другой" страницы.
Можно начать запись с адресного запроса к 1-й ячейке памяти страницы, а можно и с
любой другой ячейки, входящей в состав страницы.
В м/схемах памяти последовательного, типа не предусмотрена остановка записи по
окончании заполнения страницы, а посему, после записи байта в ячейку памяти с
самым старшим адресом (в пределах страницы) и последующей записи следующего
байта, он (байт) будет записан в ячейку памяти этой же страницы с самым младшим
(ячейки) адресом, причем, "по верху" "старого" байта ("старый" байт уничтожается).
Если далее продолжать потоковую запись, то такая же "участь" постигнет и байты,
"лежащие" в ячейках с более старшими (относительно самого младшего адреса)
адресами.
Короче, речь идет о самом натуральном, полном цикле записи страницы ("кольце"),
который, при объеме записи, многократно превышающем объем страницы памяти,
может повторяться многократно (по аналогии с любой многоцикловой программой).
Вывод из сказанного простой: в пределах одной страницы, для упорядочения
записи (устранения адресного "бардака", заключающегося в разрыве массива на части) и
недопущения выхода на второе кольцо записи (записи "по верху"), количество
записываемых байтов массива не должно превышать разницы между объемом
страницы и порядковым номером той ячейки, в которую записывается первый
байт массива.
С учетом автоинкремента, порядковый номер ячейки памяти страницы должен
отсчитываться от ячейки с самым младшим адресом.
В особо "экзотических" случаях, может быть и выход на 2-е (3-е, 4-е и т.д.) кольцо
записи, с целью реализации какой-то "хитропопой" записи. Ради Бога. Не возбраняется.
Как говорится, хозяин - барин.
С чтением проще: в наличии имеется всего одна страница - весь объем памяти, и
естественно, в случае выхода на второе (и последующие) "кольцо" считывания, данные
не уничтожаются, а просто повторно считываются, начиная с адреса ячейки 00h и

3
далее.
Вернусь к записи.
Так как же быть, если нужно записать массив байтов с объемом, значительно
превышающим объем страницы памяти?
Для того чтобы максимально упростить процедуру записи и полностью (рационально,
без "пробелов") заполнить несколько страниц памяти, нужно раздробить этот большой
массив байтов на части объемом, в данном случае, по 32 байта (на маленькие массивы
байтов), плюс "хвостик" (остаток), а после этого, формируя адресные запросы к первым
ячейкам страниц, поочередно (последовательно) записать эти маленькие массивы
байтов в страницы (один маленький массив - одна страница).
Обычно (и это проще всего), такого рода запись производится в порядке
последовательного возрастания (инкремента) номеров страниц, но ничто не мешает
работать и по принципу "Фигаро здесь, Фигаро там" (можно, но зачем нужны лишние
проблемы?).
По-любому, это есть "геморрой", но куда деваться? "Правила игры" такие
(многостраничная память).
Как тут не вспомнить о вычисляемом переходе и не сравнить его со страничной
записью?
Он тоже "строптивый", разница только в специфике, а суть одна и та же (шаг за
"границу" - "бяка").
Очередной раз "окидывая орлиным взором поле битвы", начинаю безбожно и ехидно
придираться ко всему, что вызывает вопросы (сущность, то есть, данность такая).
В абсолютно всей прочитанной мной информации по м/схемам 24Схх говорится, что
чтение от текущего адреса возможно, а запись от текущего адреса не возможна.
Расшифровываю, что значит "от текущего адреса".
Например, стандартно читается массив байтов.
Это означает, что, в начале процедуры чтения, "мастером" выдается адресный запрос к
той ячейке памяти, из которой нужно считать 1-й байт массива (примечание: массив
байтов может состоять и из одного, и из нескольких байтов).
После завершения процедуры чтения всего массива байтов, формируется стоп-условие.
Затем - ждущий режим.
Затем - старт.
А дальше, если нужно считать следующий массив байтов, 1-й байт которого "лежит" в
ячейке памяти, адрес которой на единицу больше адреса той ячейки памяти, с которой
считался последний байт предыдущего массива, то формировать адресный запрос уже
не нужно по той простой причине, что, после чтения любого байта, счетчик адреса
инкрементируется, а проще говоря, нужный адрес в счетчике команд уже установлен, и
еще раз подтверждать его нет смысла.
Теперь "устремляю взор" на запись.
После записи любого байта, счетчик адреса инкрементируется точно таким же образом,
как и при чтении (только в пределах текущей страницы).
Тогда почему чтение от текущего адреса возможно, а запись от текущего адреса (в
пределах страницы) не возможна?
А ведь это вопрос принципиальный!
Если это как-то связано с особенностями процедуры записи, схемотехникой (или еще с
чем-то), то почему отсутствует хотя бы намек на какое-то из этих обстоятельств (даже и
на горизонте не видно)?
Такая "муть", вне зависимости от результата "разборок", лично у меня, вызывает
рефлекторную реакцию "убийства комара, назойливо жужжащего над ухом".
Ну не могу я принимать на веру то, что вызывает безответные вопросы, хоть тресни: мне

4
от этого плохо становится, а ночью кикиморы снятся.
Да и с обучающей точки зрения, это "убийство комара" есть "зер гут".
Закладываю этот пункт плана дальнейших действий в свой "биокомпьютер".
Теперь можно двигаться дальше, то есть, для начала, "разрисовать" потоковую запись в
пределах одной страницы.
Получилась вот такая "живопись":

Например, в 1-ю страницу памяти нужно записать массив из 10-ти байтов.


Пусть объем страницы памяти будет равным 32-м байтам.
На счет старт-стопных условий и режимного байта "распространяться" не буду (не хочу
повторяться).
Итак, адресные байты.
А вот это, в приложении к страничной записи, очень важно (вспомните про "бяку").
В пределах страницы, адрес можно задать любой.
Какой конкретно?
В 1-й странице памяти расположены ячейки с адресами 00h ... 1Fh.
32 больше 10, поэтому, если 1-я страница задействуется только под данный массив
байтов (например, одна запись, с последующими многократными считываниями) или
под однотипные, периодически переписываемые (обновляемые), по тем же самым
адресам, массивы байтов и т.д., то 1-й байт массива, состоящего из 10-ти байтов, можно
записывать по любому адресу из диапазона 00h ... 16h.
По любому из адресов диапазона 17h ... 1Fh, 1-й байт этого массива записывать нельзя,
так как, в этом случае, произойдет адресная "закольцовка", приводящая к дроблению
массива байтов на 2 части и уничтожению байтов (запись "по верху"), ранее записанных
в ячейки с младшими адресами.
Если массив байтов состоит из более чем 10-ти байтов (но не более чем из 32-х байтов),
то "граница", разделяющая указанные выше диапазоны, дискретно (и на
соответствующую величину) смещается в сторону младших адресов.
Обычно, не мудрствуя лукаво, 1-й байт массива байтов записывают в 1-ю ячейку
страницы (в данном случае, по адресу 00h).
Во-первых, порядка больше, а во-вторых, такая "привязка" позволяет записать, в одну

5
страницу памяти, массив байтов максимально дозволенного объема (в данном случае, 32
байта), то есть, полностью заполнить страницу (без адресной "закольцовки").
Если объем массива байтов превышает объем одной страницы, то массив байтов
"дробится" на более "мелкие" массивы объемом, в данном случае, по 32 байта (плюс
"хвостик", если объем массива байтов не делится на целое число раз на объем одной
страницы).
Естественно, под каждый такой "мелкий" массив, нужно формировать свою "начальную
точку отсчета".
В этом случае, "начальными точками отсчета" являются ячейки соответствующих
страниц памяти с самыми младшими адресами (напоминаю про автоинкремент).
С точки зрения максимальной простоты программной реализации такого рода записи,
заполнение страниц байтами нужно производить в порядке строго последовательного
увеличения (+1, часто) или уменьшения (-1, реже) номеров страниц, хотя, редко, но
могут быть и "рваные" случаи, это зависит от специфики разрабатываемого устройства.
В качестве примера, ниже приведен рисунок, иллюстрирующий процедуру записи
"большого" массива байтов (в данном случае, 60 байтов), разделенного
("раздробленного") на 2 "мелких" массива данных ("полноценный", объемом 32 байта и
"хвостик" объемом 28 байтов).
Суть этой картинки можно "трансформировать" и на большее (ударение на "о")
количество "дроблений", причем, "хвостик" (остаток, если он есть) всегда только один.
Порядок старшинства этих "мелких" массивов определяет программист, исходя из
соображений максимальной простоты программной реализации "связки" процедур
записи-чтения.

Не трудно заметить, что на рисунке 2 изображены две аналогичные, последовательные


процедуры записи массива байтов (сравните с рис. 1), только с разными "начальными
точками отсчетов", то есть, с адресными запросами, в данном случае, к первой ячейке
той или иной (из двух) страницы памяти.
Проще и выгоднее задействовать 2 соседние страницы памяти (порядок их старшинства
назначает программист), а не использовать принцип "Фигаро здесь, Фигаро там" (хотя и
можно).
Внимательно посмотрите на рис. 2 и сравните оба массива байтов.
В результате этого сравнения, трудно не заметить, что числовые значения "однотипных"
("однофункциональных") байтов разные, за исключением режимных байтов (они
одинаковые).
Сразу же "вскакивает" "хитрый" вопрос : "А нельзя ли обойтись только одним, первым,
режимным байтом"?

6
Разве не реально предположение, что оперативная память настроек "помощника"
сохраняет свои настройки в части касающейся режимного байта? Такое вполне может
быть (а может, по каким-то причинам, и не быть).
"Рою" имеющуюся у меня информацию.
Полное "скудоумие", то есть, "полный ноль" и никаких намеков.
Вот напасть!
Внутренний голос: "Прикусил бы свой язычек" и "не дергался" бы. Так нет же, "полез на
рожен"...
После таких серьезных доводов, приходится признать, что "горбатого могила исправит".
А раз это есть данность, то и церемониться нечего.
Записываю в свой "талмуд" третий вопрос: "Можно ли, при организации процедуры
последовательной записи нескольких массивов байтов, обойтись только первым,
режимным байтом"?
Пошел дальше.
Глядя на рис. 2, "вскакивает" очередной вопрос (когда же вы, родимые, кончитесь-то?):
"Какова должна быть минимальная величина интервала времени между стопом
предыдущего массива байтов и стартом следующего массива байтов"?
Или по-другому: "Какова должна быть минимальная продолжительность ждущего
режима в "промежутке" между массивами байтов"?
Заметьте, вопрос сформулирован в общем виде, то есть, ответ на него носит
"глобальный" характер (относится и к процедуре записи, и к процедуре чтения).
"Вгрызаюсь".
Получается следующая "картина".
В наличии имеются формальные (общие), предельные временные характеристики,
которые "сваяла" фирма Philips ("мать родная" интерфейса I2C).
Когда она их "ваяла", м/схемы (и не только памяти, но и других типов), работающие по
интерфейсу I2C, были не такими "шустрыми" (быстрыми), как современные.
Соответственно, формализованная таблица предельных временных характеристик
интерфейса I2C содержит в себе величины времени, превышающие величины времени
предельных временных характеристик современных м/схем, работающих по интерфейсу
I2C.
Проще говоря, формализованная таблица фирмы Philips расчитана на максимальную
скорость обмена данными (во время "прохождения" байта. Это подразумевается и далее)
порядка 100...150 Кбит/сек., а современные м/схемы обеспечивают более высокую
скорость обмена данными (до 400 Кбит/сек. и более).
Для наглядности, произведу простейшее сравнение.
В соответствии с формализованной таблицей, минимальное время формирования
уровня 1 на линии такта не должно быть меньше, чем 4 мкс., а время формирования
уровня 0 не должно быть меньше 4,7 мкс.
Для м/схем памяти 24С128/256 (а 24С64А "из этой же оперы"), эти показатели, при
напряжении питания 5 в., равны 0,4 мкс. и 0,6 мкс. соответственно (можно
беспроблемно работать со скоростью до 1 Мбит/сек.).
Для других типов и видов м/схем, работающих по интерфейсу I2C (в том числе и в
зависимости от той или иной фирмы - производителя), эти показатели могут быть (и
есть) другими.
Короче, "анархия", чтоб ей пусто было.
Примечание (к слову): ранее я упоминал "круглую" цифру максимальной
продолжительности цикла записи 10 мс. Для указанных выше типов м/схем памяти, она
составляет 5 мс.
Как быть? К чему "привязаться" ("анархия" есть "убийство" эффективного "въезда")?

7
А "привязываться" всегда нужно к реалиям.
При "вгрызании" в I2C, предполагается использовать PIC16F84A.
Длительность его машинного цикла (кварц 4 Мгц.) равна 1 мкс.
На вскидку: для того чтобы сформировать один, самый короткий, период внешнего
такта, ему уже нужно 2 мкс.
Реально же, с учетом сопровождающих, "прибамбасов" (поймете позднее), этот период
будет больше.
Вот и получается, что, в данном случае, "к жизни ближе" формализованная таблица
фирмы Philips.
Она, конечно же, "тоже не мед" ("старушка", однако соотношения проясняет), но, на
стадии "въезда", лучше иметь хоть какие-то одни, четкие и однозначные "правила
игры", чем "разнокалиберный набор правил игр".
Это потом можно "жировать", а на стадии "въезда" это противопоказано ("не до жиру,
быть бы живу").
Итак, "привязываюсь" к формализованной таблице фирмы Philips, то есть, к интерфейсу
I2C как к таковому (без учета "м/схемного разброда и шатания").
А теперь можно ответить на заданный ранее вопрос: продолжительность ждущего
режима в "промежутке" между массивами байтов" должна составлять от 5 мкс. и более
(см. рис. 2).
Примечание: здесь и далее, для удобства, я округлил 4,7 мкс до 5 мкс. Имейте это
ввиду.
А каковы "делишки" с остальными предельными, временными характеристиками?
А таковы:

Это конечно "не Рио-де-Жанейро", но "отталкиваться" от этого вполне можно, а на


стадии "шлифовки" программы, "подрихтуем и бантик сверху повяжем".
Что там еще осталось?
Не хватает "глобализации" общего понятия о величинах временных "промежутков"
между байтами различной функциональности.

Если в работу "включена" "плавающая" задержка на основе анализа состояний


флага АСК, то, исходя из сказанного ранее, величины временных "промежутков"
- между режимным байтом и байтом старшего разряда адреса,
- между байтом старшего разряда адреса и байтом младшего разряда адреса,
- между байтом младшего разряда адреса и 1-м байтом данных
будут очень маленькими.

8
Величины временных "промежутков" между 1-м байтом данных и стопом будут
гораздо больше.

Пока и такой примитивной трактовки достаточно. Главное - понять общую тенденцию.


Итак, в части касающейся записи, многое прояснилось, но не все.
С целью упорядочения процесса своего будущего "хулиганства", "валю" все "нарытые"
проблемы "в общую кучу".
Получилась вот такая "страсть":
1. Что верно: 256 страниц по 32 байта или 32 страницы по 256 байтов? (и для
записи, и для чтения, в приложении к 24С64А)
2. Можно или нет организовать страничную запись от текущего адреса (только
для записи)?
3. Можно или нет, при организации процедуры последовательной записи
нескольких массивов байтов, обойтись только первым, режимным байтом?
Записываю эти вопросы на листе бумаги и вывешиваю его на своем рабочем месте с тем
расчетом, чтобы он "глаза мозолил".
Умный петух кур (проблемы) с умом топчет. В этом случае, яиц будет много.
На том и откланиваюсь.
Следующий подраздел будет посвящен алгоритмам процедуры чтения.

9
"Практикум по конструированию устройств на PIC контроллерах" http://ikarab.narod.ru E-mail: karabea@lipetsk.ru

10