Часто возникает потребность сформировать сложную последовательность импульсов. Сложная последовательность — это значит что частота, фаза, длительность, скважность импульсов могут меняться по некоему закону. А закон этот может оказаться довольно причудливым, да ещё меняться из-за каких-то факторов. В итоге схема на простой логике может оказаться непомерно сложной и надо привлекать программируемые средства.
Для чего могут понадобиться такие последовательности? Ну, например, для синхронизации нескольких устройств в схеме, когда каждому устройству требуется свой синхросигнал — своей частоты, да сдвинутый относительно других определённым образом. Или для передачи простой информации, например, кода нажатой кнопки или сработавшего датчика.
Для начала посмотрим как такие задачи решались раньше, когда компьютеры были большие, микропроцессоры медленные, и микроконтроллеры немощные 🙂
Одним из способов было использование ПЗУ — постоянного запоминающего устройства. ПЗУ — это микросхема, имеющая некоторое количество ячеек памяти, в которые можно записать произвольные данные. При отключении питания данные не уничтожаются. Записать данные в микросхему можно с помощью программатора.
Для примера рассмотрим схему на основе ПЗУ, имеющей 32 ячейки памяти, каждая ячейка хранит слово длиной 4 бита.
Что тут есть. Генератор формирует тактовые импульсы. Просто куча одинаковых импульсов с одним и тем же периодом. Счётчик … их считает 🙂 И выдаёт на выход номер пришедшего импульса в двоичном виде. Т.е. в начальном состоянии (когда не было ещё ни одного импульса) на выходах счётчика будут нули, с приходом первого импульса появится 0001, второго 0010 и т.д. Пятнадцатый импульс даст 1111, шестнадцатый сбросит счётчик в 0000.
За счётчиком стоит ПЗУ с параллельным интерфейсом. Она имеет входы (шина адреса) и выходы (шина данных) . Адрес — это номер ячейки памяти. Данные — значение (слово), записанное в эту ячейку. В нашей схеме счётчик имеет только 4 выхода, т.е. может адресовать 16 ячеек из имеющихся 32.
Схема работает так. В начальном состоянии (до прихода импульса) на выходе счётчика 0000, на выходе ПЗУ значение ячейки с номером 00000. Первый импульс перебросит счётчик на значение 0001 и на шине данных появится значение из ячейки 00001. И так по кругу будут перебираться ячейки с 0 по 15.
Занесём в ПЗУ какие-нибудь данные. Для начала пропишем в старший разряд каждой ячейки последовательность 0-1-0-1… Остальные разряды (биты) пока не трогаем. И посмотрим что будет на выходе:
Видим что на каждый тактовый импульс значение выхода D3 меняется на противоположное: если в бит записан 0, будет низкий уровень, если 1 — высокий. Заметим что поменять состояние выхода мы можем только один раз за период тактового сигнала. Т.е. максимальная частота, которую мы можем получить на выходе будет равна половине тактовой частоты. Или можно сказать что разрешение (разрешающая способность) схемы равна двум периодам тактового генератора.
Так, займёмся битом D2. Запишем в каждую ячейку такую же последовательность, только начинающуюся с 1:
На выходе D2 видим импульсы, аналогичные D3, только в противофазе.
0-1-0-1 не интересно! Давайте попробуем так: 0-0-0-1…
Ого! На выходе D1 появились короткие импульсы с длинными промежутками между ними!
Ну а в D0 накидаем какого-нибудь трэша:
Во! Два коротких, промежуток, длинный, промежуток покороче, снова короткие. Творим что хотим! 🙂
Теперь посмотрим как можно использовать незадействованный старший разряд шины адреса ПЗУ. Прикрутим к нему цепь, позволяющую менять логический уровень на входе A4:
При замкнутой кнопке на A4 будет 0, при разомкнутой — 1.
Пока на A4 будет 0, всё останется как прежде — счётчик будет в цикле перебирать адреса с 0 по 15 (00000 — 01111). А если подать на A4 лог. 1, всё изменится! Теперь наш счётчик будет перебирать адреса 10000-11111, т.е. с 16 по 31. А в ячейки с этими адресами мы можем записать совсем другие данные и кнопкой выбирать какая именно упячка будет твориться на выходах!
Получилась как бы страничная адресация ПЗУ. Страницу мы выбираем кнопкой, а данные внутри страницу перебирает схема генератор-счётчик.
Подведём предварительные итоги.
- С помощью очень простой схемы можно формировать последовательности импульсов любой сложности. Сложность последовательности (длина неповторяющегося фрагмента) зависит только от объёма ПЗУ.
- Мы можем формировать одновременно несколько разных последовательностей, связанных (синхронизированных) друг с другом.
- Эта схема очень быстрая. Частота выходного сигнала зависит только от быстродействия ПЗУ. Мегагерцовые упячки — совсем не проблема!
Как это можно использовать:
- Формировать сложные синхросигналы одновременно для нескольких устройств, связанных друг с другом. Здесь надо учесть пару факторов.
- Во-первых, внимательно смотреть что будет происходить при переполнении (обнулении) счётчика и при переходе с максимального адреса на нулевой. Синхропоследовательность не должна сбиваться. Т.е. данные надо формировать с учётом цикличности процесса.
- И второе: ПЗУ имеет особенность — при переключении адреса на выходе шины данных появляется «иголка» — короткий паразитный импульс. Который может вызвать сбой в устройстве, чувствительном к качеству синхры. Надо предпринять меры по устранению (фильтрации) иголок.
- Передавать какие-то простые данные типа нажатия кнопок, срабатывания датчиков и т.п. Нюансы тоже есть.
- Надо позаботиться о приёмном устройстве. Оно должно чётко понимать когда начинается массив данных — чтобы адекватно их принять и декодировать. Решить это можно по-разному. Можно делать паузы между посылками (некоторое кол-во нулей подряд) чтобы приёмник чухнул: «Ага, пауза, а сейчас попрут данные!». Или передавать по отдельной линии стробы — импульсы, обозначающие начало передачи.
- Надо соблюсти принцип целостности данных. Страница не должна переключаться посреди передачи посылки. Если начало пакета придёт с одной страницы, а конец с другой, приёмник может подумать невесть что. Поэтому переключать страницы ПЗУ надо в промежутке между посылками, а значит простая схема вроде приведённой на последнем чертеже не годится. Надо что-то мудрить с буферизацией и стробированием.
- Если надо подключить несколько кнопок, сложность формирования массива данных существенно возрастает. Надо прописать целую кучу вариантов (страниц) данных — для каждой комбинации нажатых кнопок. При увеличении количества кнопок объём данных возрастает в прогрессии.
- Ничто не мешает совместить эти две задачи (кроме сложности формирования массива данных).
Да, получается многовато. Придётся разбить статью на две части. Во второй части, в соответствии с названием статьи займёмся реализацией приведённого алгоритма на микроконтроллере.