Среднечастотный частотомер на AVR. Часть 2, статическая индикация.
В первой части статьи рассматривался вывод на дисплей с динамической индикацией. В этой будет рассмотрен вывод на дисплеи со статической индикацией. Как правило это достигается применением внешнего контроллера дисплея. Для кода применялся тот же включаемый файл FQMacros.inc, что и в первой части. Код регенерации динамической индикации из программы удален.
Статическая индикация на дисплее с торговой маркой TIC (TIC71, TIC265).
Индикаторы TIC представляют собой сборки СoG (чип на стекле) состоящие из многоразрядного семисегментного статического LCD индикатора и управляющего им одного или двух контроллеров ML1001. ML1001 это 40-разрядный сдвигающий CMOS регистр с защелками на выходах разрядов. Ближайший функциональный аналог — 74HC595. Кроме того он содержит встроенную схему регенерации LCD индикатора со встроенным генератором (обычно 125-2000Hz). Частота регенерации задается при изготовлении индикатора. Исполнение бескорпусное, после соединения индикатора и контроллера, последний заливается каплей компаунда. Выпускаются на заказ тайваньской фирмой Ampire, встречаются и в продаже. Управление стандартное для SPI, входы данных (DIN), синхроимпульсов (DCLK) и импульс переноса данных на выходы защелок (LOAD). Некоторые индикаторы имеют дополнительные вход LCLK и/или выход DOUT. И если с DOUT все понятно, это выход сдвигового регистра для каскадирования, со входом LCLK интереснее. Это вход от внешней схемы регенерации LCD дисплея. Казалось бы зачем, ведь контроллер уже содержит внутреннюю схему регенерации? Это сделано для снижения мощности токопотребления дисплея. Индикатор использующий внутреннюю схему может потреблять 5..50mkA. Зависит от размера и кол-ва символов, частоты регенерации и напряжения питания. Если используется внешняя (15-30Hz), энергопотребление может быть значительно снижено (1mkA и менее). Синхроимпульсы (DCLK) могут следовать с частотой до 500kHz, системный таймер программы должен ограничить частоту тактирования этим значением. Учитывая что мы имеем дело со статическим индикатором, и вывод на него производится только один раз за измерение, логика работы системного таймера немного изменена по сравнению с динамической индикацией. Теперь системный таймер основное время цикла работает с прескалером 1024 на частоте 8MHz/1024/256=
30,5Hz и занимается опросом кнопок. Как только программа подготовила результат измерения для вывода на индикатор, прескалер таймера закорачивается и выдача результата на индикатор происходит на частоте 8MHz/256=31,25kHz. После вывода таймер опять перезапускается с прескалером 1024 до следующей готовности результата измерений. Это был первый вариант, он и остался окончательным. Я пробовал увеличивать частоту системного таймера, т.е. загружать его делителем в прерывании. Выигрыш минимальный, а прерывание усложняется, нет смысла. Вывод результата на индикацию побитно по интерфейсу SPI производится флаговой подпрограммой. Ее особенностью является настраиваемый темп вывода. С какой периодичностью будет выставляться флаг MRK_SPI, с той же периодичностью будут выводиться символы по SPI. Периодичность флага определяет системный таймер.
Перед запуском подпрограммы требуется предварительная подготовка, установить параметры ее работы, перезапустить системный таймер.
Применение отдельной подпрограммы SetDisplayData вызвано тем, что выводить данные c одинаковыми параметрами требуется в двух местах. Сначала при инициализации выводится номер версии, в последующем результат измерений. К первому обращению подпрограмма вывода должна уже иметь в переменной BitMask первый символ из буфера (битовую маску) и указатель на следующий символ. После передачи первого символа, остальные она подгружает сама руководствуясь их кол-вом NumMask. Такое построение алгоритма впоследствии позволит адаптировать подпрограмму к другим контроллерам.
Рассмотрим в Proteus работу программы в течении цикла. Вывод производится на 9-разрядный дисплей TIC71, TIC265. Они различаются только наличием (TIC71) или отсутствием (TIC265) вывода LCLK. Ниже график работы программы со второй по третью секунду. Первые три сигнала DOUT, DCLK, LOAD это управление индикатором, LCLK — регенерация дисплея, вызывается из подпрограммы опроса кнопок.
Развернем экран на интересующую нас область. Первые четыре сигнала те же, а Tst0, Tst1, Tst2 это выполнение подпрограмм BINtoPackBCD, PackBCDtoUnpackBCD, UnpackBCDtoSymbolsCode соответственно. При желании курсорами можно измерить время исполнения любой части программы. В первой части уже измерялось время исполнения подпрограммы BINtoPackBCD — 192 mks, оно не изменилось, измерим теперь время вывода на дисплей 9 разрядов по SPI — 2,28 ms, чуть больше 0,2% времени выполнения цикла.
Статическая индикация на сдвиговых регистрах 74HC595.
Такая индикация для LED индикаторов неоднократно описана в литературе, легко находится поиском в инете, вот один из вариантов — Статический светодиодный цифровой индикатор, управляемый по SPI. Сама программа почти не отличается от программы управления индикаторами TIC, ведь по управлению они аналогичны. Различие в том, что регистры 74HC595 имеют двухтактные выходы "Push-Pull" и могут управлять LED индикаторами как с общим катодом, так и с общим анодом. Токи выходных каскадов и для низкого и для высокого уровней составляют 35 mA, что более чем достаточно. В программу заложена возможность управления обоими типами индикаторов. Достигнуто это с помощью средств условной компиляции препроцессора ассемблера. В программе определен дефайн, его применение просто инвертирует битовые маски семисегментных символов.
Видно что для индикаторов с ОК и ОА используются разные символы гашения знакоместа. Если для индикатора с ОК это все нули, для индикатора с ОА это все единицы.
Статическая индикация на дисплее с контроллером MAX7219.
- Индивидуальный контроль и управление сегментами
- Выбор BCD декодирование/отсутствие декодирования разрядов
- Режим Shutdown с низким энергопотреблением (150mkA)
- Цифровое и аналоговое управление яркостью
- Дисплей погашен при включении питания
- Предназначен для светодиодных дисплеев с общим катодом
- SPI последовательный интерфейс до 10 МГц
- 24-контактные DIP и SO корпуса
В программе используется уже рассмотренная ранее подпрограмма вывода бита по SPI с одним отличием, число выдвигается старшими разрядами вперед. Вспомним, что подпрограмма требует перед запуском занести в переменную BitMask первый символ, и передает NumMask кол-во символов. Нам же требуется сформировать 16-битный пакет, 8 бит адреса и 8 бит символьный код. Поэтому для первого символа заносим в BitMask адрес, передаем указатель на символ в буфере, в NumMask указываем передать один символ. Для остальных символов заносим в BitMask только адрес, в NumMask указываем передать один символ, автоинкремент указателя произведет подпрограмма вывода бита.
Предварительно необходимо занести в Cycler кол-во передаваемых символов и указатель на адрес буфера символов. Это сделано в конце предыдущей подпрограммы:
Кроме этого подпрограмма PackBCDtoUnpackBCD заменяет незначащие нули на символ гашения MAX7219 (0x0F), а также проверяется флаг начальной загрузки. Если флаг установлен, к буферу добавляется команда включения дешифраторов. Если точнее буфер RAM_UnBCD расширен за счет старшего байта RAM_BCD_3. Так числа мы уже преобразовали, его порча значения не имеет. Т.к. вместо 8-разрядного здесь применен 16-разрядный SPI, интересно будет посмотреть как изменилась длительность вывода 8 разрядов на дисплей:
Как и ожидалось, она выросла примерно в два раза, и занимает
0,4% цикла сканирования.
Статическая индикация на дисплее с контроллером HD44780.
HD44780 это полноценный контроллер матричного LCD дисплея с собственной системой команд, знакогенератором кодов символов ASCII. Вторая часть таблицы может содержать национальные символы. Восемь символов могут быть запрограммированы пользователем. Хорошо и коротко об этом рассказано здесь Алфавитно-цифровые индицирующие ЖК-модули на основе контроллера HD44780. Поэтому управление им кардинально отличается от ранее описанного. Программа написана для четырехпроводного подключения (для данных, еще два вывода — управление), без чтения бита BUSY, т.е. на задержках. Задержки расчитывались под частоту основного контроллера 8 MHz и дисплейного 250-270 kHz. Обращение на простых задержках сделано для упрощения, т.к. никаких отрицательных последствий для программы это не несет. При необходимости цикл задержки легко будет прерван коротким прерыванием, а небольшое увеличение времени задержки ничему не мешает. Теперь системному таймеру нет необходимости формировать дисплейные задержки и он постоянно работает с прескалером 1024 для сканирования клавиатуры. Длительности задержек были взяты из даташитов, подобраны и проверены в Proteus.
Код реализующий задержки:
Отправка байта команды или данных требует предварительного занесения в рабочие регистры слова величины задержки и передаваемого байта. Удобнее это оформить макросами:
Применение этих макросов позволяет оформить отсылку команды/данных в стиле ЯВУ:
Контроллер HD44780 принимает данные в виде стандартных кодов ASCII, поэтому хранить в программе таблицу перекодировки нет надобности, хотя необходимость перекодировки сохраняется.
Существуют клоны контроллера HD44780 с той же системой команд, но немного отличающиеся процедурой и таймингами инициализации, например ST7066U (кликабельно).
В программе заложена возможность работы с обоими видами контроллеров, если компилируется для ST7066U необходимо раскоментировать соответствующий дефайн.
В качестве примера реализована возможность загрузки двух символов пользователя. Это символы положительного (адрес 0х00) и отрицательного импульса (адрес 0х01). В программе они не используются. Т.к. коды команд дисплейного контроллера зараннее известны, лучше при определении сразу привязать их к символьным определениям выводов дисплея. Тогда при переопределении выводов, коды констант команд автоматом пересчитаются.
Вывод данных на контроллер очень прост, командой выставляется адрес строки, затем последовательно передаются данные. Автоинкремент адреса контроллер производит сам.
Теперь посмотрим сколько времени займет вывод на дисплей:
Вместе с командой установки строки вывод 7 цифр занимает 603 мкс, т.е. менее 0,1% времени цикла сканирования.
VGA предоставил свой код для быстрого вывода на дисплей TIC. Я его протестировал и с его разрешения решил включить этот вариант в статью. Т.к. теперь нет нужды использовать системный таймер для вывода результата измерений на индикатор, будем использовать его только для опроса клавиатуры.
Соответственно и по прерыванию будет устанавливаться только флаг опроса клавиатуры.
Немного видоизмененный код вывода результата по SPI от VGA, старую подпрограмму побитного вывода можно убрать.
перед вызовом этой подпрограммы необходимо занести в Cycler кол-во выводимых разрядов, а в регистр Х поместить адрес буфера символов.
Делается это в двух местах, в конце инициализации для вывода номера версии и в конце предыдущей подпрограммы UnpackBCDtoSymbolsCode. Посмотрим сколько займет вывод на 9-разрядный дисплей:
Для вывода 9 разрядов потребовалось 131 мкс, это в 17 раз быстрее чем предыдущая подпрограмма. Это лучше или хуже? Мне кажется что все равно. Предыдущая подпрограмма вывода по таймеру после передачи каждого бита выходит в главный цикл, а этот вариант до вывода всех битов управление не отдает. Возможно где то это и может иметь принципиальное значение, но данной программе все равно. Первое прерывание по переполнению счетного таймера 1 и входной частоте 3,2МГц может возникнуть через 65536/3200000=0,02048сек или
20,5 мс от начала цикла. А за это время успеют отработать и первый и второй варианты SPI. Так что используйте тот вариант, который вам больше нравится. Этот же код подойдет без переделки для управления статическим индикатором на сдвиговых регистрах 74НС595. А вот адаптировать этот вариант для вывода на дисплей MAX7219 будет сложнее. Возможно у этого варианта SPI есть другое ограничение, частота следования импульсов DCLK:
Как видно на графике один период синхроимпульсов занимает 1,63 мкс, что соответствует частоте
613 кГц. У меня сохранился старый даташит на ML1001, в нем частота DCLK ограничена 500 кГц. Сейчас вроде подняли эту частоту до 1000 кГц, не знаю как правильно.
При желании можно ускорить вывод и по таймерному прерыванию, для этого необходимо в нем грузить таймер делителем. Приведу и этот вариант.
С делителем 128 время вывода результата измерений на индикацию сократится в два раза. Конечно соответственно вырастет и частота опроса клавиатуры.
В приложенном архиве FreqStat.zip проекты AVR Studio и Proteus. Подробнее файл Readme внутри. В архиве 7219help.zip файл 7219help.chm русскоязычной помощи по MAX7219.
P.S. Продолжение доступно: Часть 3, + милливольтметр.
-
, ,
- 0
- 09 января 2018, 19:42
- 2
При тактовой частоте МК 8МГц длительность импульса tL составит 250нс, тогда как даташит на ML1001 требует не менее 400нс. Надо перед SBI воткнуть пару нопов. В принципе, пока выполняется код выборки следующего бита, необходимое время tH тоже пройдет, так что синхронизировать SPI по таймеру совершенно незачем. Ну если только из соображений «не морозить главный цикл на сотню микросекунд».
Также видно, что автора не смущает потупить 2-4мс (16-32к тактов) в процедуре вывода на SPI-дисплей, 1.5к тактов на перекодировку BIN->BCD его тоже не смущает, а вот 1к тактов на перемешивание битиков для MT1638 — это пиздец как долго и абсолютно неприемлемо, да-да.
А что мне стоит проверить?
Как видно длительность синхроимпульса 503нс и в даташит укладывается. А второе, операция BCD<-BIN является необходимой для BCD преобразования, и должна быть выполнена в любом случае. Перемешивание битиков для MT1638 — это криворукость проектировщиков чипа и обойтись без нее было несложно.