nabbla (nabbla1) wrote,
nabbla
nabbla1

Category:

Мучаем 5576ХС4Т - часть 5 - подавление дребезга кнопки

Часть 0 - покупаем, паяем, ставим драйвера и софт
Часть 1 - что это вообще за зверь?
Часть 2 - наша первая схема!
Часть 3 - кнопочки и лампочки
Часть 4 - делитель частоты
Часть 5 - подавление дребезга кнопки
Часть 6 - заканчиваем кнопочки и лампочки
Часть 7 - счетчики и жаба
Часть 8 - передатчик UART
Часть 9 - Hello, wolf!
Часть 'hA - приёмник UART
Часть 'hB - UART и жаба
Часть 'hC - полудуплексный UART.
Часть 'hD - МКО (МКИО, Mil-Std 1553) для бедных, введение.
Часть 'hE - приёмопередатчик МКО "из подручных материалов" (в процессе)
Часть 'hF - модуль передатчика МКО
Часть 'h10 - передатчик сообщений МКО
Часть 'h20 - работа с АЦП ADC124s051
Часть 'h21 - преобразование двоичного кода в двоично-десятичный (BCD)
Часть 'h22 - Bin2Bcd с последовательной выдачей данных
Часть 'h23 - перемножитель беззнаковых чисел с округлением
Часть 'h24 - перемножитель беззнаковых чисел, реализация
Часть 'h25 - передаём показания АЦП на компьютер
Часть 'h26 - работа над ошибками (быстрый UART)
Часть 'h27 - PNG и коды коррекции ошибок CRC32
Часть 'h28 - передатчик изображения PNG
Часть 'h29 - принимаем с ПЛИС изображение PNG
Часть 'h2A - ZLIB и коды коррекции ошибок Adler32
Часть 'h2B - ускоряем Adler32
Часть 'h2C - формирователь потока Zlib
Часть 'h2D - передаём сгенерированное PNG-изображение
Часть 'h2E - делим отрезок на равные части
Часть 'h2F - знаковые умножители, тысячи их!
Часть 'h30 - вычислитель множества Мандельброта
Часть 'h31 - ускоренные сумматоры
Часть 'h32 - ускоренные счётчики (делаем часы)
Часть 'h33 - ускоряем ВСЁ
Часть 'h34 - ускоренные перемножители
Часть 'h35 - умножители совсем просто
Часть 'h36 - уравновешенный четверичный умножитель


Немножко закрепим материал: научимся превращать нажатие на кнопки в единичный импульс, который будет включать-выключать лампочку.

Во многих магазинах радиодеталей маленькие кнопочки, крепящиеся на плату, ошибочно называют ТАКТОВЫМИ (пруф). Автор некоторое время наивно думал, что внутри действительно расположена какая-то схема, позволяющая с этой кнопки снять чистый импульс, способный выступить в роли тактового - запускать процесс, останавливать его и пр. Благо, в советских ЭВМ действительно применялись кнопки с микросхемкой 133ЛА3 (или чем-то похожим) на дне, а также одним замыкающим и одним размыкающим контактами, что позволяло организовать триггер, не допускающий никакого дребезга контактов на выходе, дающий чистый фронт и спад с заранее известными временнЫми характеристиками.

Но оказалось, что это какие-то надмозги перевели на русский язык tact-switch, сокращенно от tactile switch! То есть, это нифига не тактовые кнопки, а ТАКТИЛЬНЫЕ. Что означает всего навсего - она сопровождает своё включение характерным щелчком, так что мы не обязаны смотреть на свои руки, когда жмём на неё - сам палец почувствует, что кнопка нажалась. (чувствую, скоро фирма Apple родит откровение, что сенсорные экраны - не лучшая вещь, а нужны всё-таки кнопки - и все воскликнут - какие же они гении-первопроходцы!)

А дребезжат эти кнопки - мама не горюй! В части 4 нам это совершенно не мешало - сигнал на светодиодиках также дребезжал, но поскольку для человеческого глаза этот процесс слишком быстрый, мы не замечали никаких проблем. Но стоит лишь чуть усложнить схему, как первой заботой становится подавить этот дребезг.

Вот примерно как оно выглядит (утащил с яндекс.картинок):


Прежде чем кнопка надёжно замкнётся, её контакт некоторое время будет прыгать взад-вперёд, рождая толпу импульсов. У маленьких кнопок переходные процессы проходят довольно шустро, за 1-2 миллисекунды всё уже должно закончиться.


Напишем наиболее простой код для устранения дребезга контактов на Verilog:

module ButtonDebounce(input clk, output Q,
		      input ce,
		      input D);
	reg R1, R2;
	assign Q = (~R1) & R2;
	
	always @(posedge clk) begin
		R1 <= ce? D : R1;
		R2 <= R1;
	end
endmodule


На clk подаём, разумеется, тактовую частоту. Её точное значение нас не сильно волнует, 80 МГц нас вполне устроят.

На ce мы подаём выход ce_fast от рассмотренного в части 5 GenHID, на него поступают импульсы длительностью в один такт, с периодом между импульсами 1 кГц или чуть ниже.

На D подаётся вход от кнопки, причём здесь мы полагаем, что нажатая кнопка замкнёт вход D на лог. "0". Если кнопка при нажатии подаёт лог. "1", то нужно в первой строчке always-блока заменить D на ~D.

На выход Q будет подаваться импульс длительностью один такт в ответ на каждое нажатие кнопки.

Разбираемся, как это всё работает. Первая строка в always-блоке:
R1 <= ce? D : R1;


говорит "защёлкивать" текущее значение входа только по поступлению импульсов ce, то есть примерно один раз за миллисекунду. Собственно, это и есть наш главный "фильтр" - как бы мы не делали выборку через 1 мс сигнала, показанного на осциллограмме выше, мы уже получим приличный переход от единицы к нулю. Например, нам так "повезло", что один из импульсов ce пришёл аккурат в момент начала дребезга контактов. Тут у нас 50/50: либо в этот момент защёлкнется ноль, либо единица. Если защёлкнулась единица, значит мы продолжаем считать, что кнопка до сих пор не нажата. Ещё через миллисекунду дребезг уже прекратится, и мы защёлкнем надёжный нолик, и продолжим получать ноль, пока кнопка нажата. Именно тогда мы и сообразим, что кнопку нажали - и выдадим импульс. Если же у нас сразу появился ноль, то к следующему разу снова будет ноль - момент нажатия зарегистрируется миллисекундой ранее, но это не столь важно!

Наконец, объясним регистр R2 и выход Q.

Строкой
R2 <= R1;


мы просто задерживаем значение в регистре R1 на один такт.

Наконец, строка

assign Q = (~R1) & R2;


будет давать единицу на выход лишь в одном случае: когда R1 равен нулю, а R2 - единице. Такое происходит только когда R1 переключился с единицы на ноль, т.е как раз-таки при нажатии кнопки. А далее, сколько мы не будем держать кнопку нажатой, больше ничего не произойдёт.

Такая вот замечательная схемка, которая синтезируется ровно в 2 логические ячейки.

Создадим схемотехнический символ для нашего подавителя дребезга, и разместим на общей схеме:



Наверху - наш GenHID, который выдаёт сигналы разрешения счёта на частоте 1 кГц (но пока, для симуляции, мы выставили 800 кГц) и 2 Гц.

Сигнал 2 Гц по-прежнему подаётся на toggle, который по каждому разрешающему импульсу переключается с 0 на 1 и назад, заставляя мигать светодиод с периодом 1 с.

На второй же строке мы видим ButtonDebounce, подключённый к кнопке SA2. Выход с него идёт на ещё один toggle, который заставит по каждому нажатию кнопки менять состояние светодиода LED[1].

Промоделируем работу этой схемы. Создадим ышшо один Vector Waveform File, clk привычным движением зададим как Clk80MHz, а вот вход SA2 размалюем ручками, что-то смутно похожее на дребезг.

Вот что примерно получится:


Наконец, возвращаем на место Ffast = 1000 и прошиваем это дело в ПЛИС.

(здесь был видеоролик, но ненадлежащего качества. В ближайшее время залью новый)

Лично у меня ни разу кнопка не срабатывала дважды при работе по этой схеме - всё идеально. Если попались более тормознутые кнопки - значит, надо чуть снизить частоту поступления импульсов ce. Можно применять 10 .. 20 мс - тогда любая сколь угодно разболтанная кнопка должна срабатывать нормально. 100 мс - уже многовато, человек отчётливо будет чувствовать задержку, вещь достаточно раздражающая.
Tags: ПЛИС, работа, странные девайсы
Subscribe

Recent Posts from This Journal

  • Нахождение двух самых отдалённых точек

    Пока компьютер долго и упорно мучал симуляцию, я пытался написать на ассемблере алгоритм захвата на ближней дистанции. А сейчас на этом коде можно…

  • Слишком общительный счётчик

    Вчера я чуть поторопился отсинтезировать проект,параметры не поменял: RomWidth = 8 вместо 7, RamWidth = 9 вместо 8, и ещё EnableByteAccess=1, чтобы…

  • Балансируем конвейер QuatCore

    В пятницу у нас всё замечательно сработало на симуляции, первые 16 миллисекунд полёт нормальный. А вот прошить весь проект на ПЛИС и попробовать "в…

  • Post a new comment

    Error

    Anonymous comments are disabled in this journal

    default userpic

    Your IP address will be recorded 

  • 8 comments