Страница 1 из 1

проблема: хитрая обработка нажатия кнопок

Добавлено: Вс июл 17, 2016 11:06:23
Dr.Seldom
Всем привет!
есть вопрос с которым мучаюсь вторую неделю
есть AVR и CVAVR
есть две кнопки
при нажатии на одну начинает мигать светодиод с периодом 300мс
при нажатии на вторую мигает второй светодиод с периодом 100мс
при нажатии на обе мигают оба светодиода по очереди со своими временными интервалами 100 и 300мс

реализовано как
x=100; (реальности показания АЦП, т.е. переменным резистором можно менять значение, но соотношение 1к3 должно остаться)
если на пинБ.1==1 то (portC.1=1; delay_ms(x); delay_ms(x); delay_ms(x);portC.1=0; )
если на пинБ.2==1 то (portC.2=1; delay_ms(x); portC.2=0; )

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

Re: проблема: хитрая обработка нажатия кнопок

Добавлено: Вс июл 17, 2016 11:28:07
Alkul
Я бы сделал опрос кнопок через прерывания. Инициализировал таймер на переполнение через 50мс. Для светодиода 1 завел переменную L1. Кроме того, для каждого светодиода выделил по одному биту режима, установка которого означает необходимость зажигания/гашения данного светодиода.
В обработчике прерывания для каждой кнопки сделал изменение состояния "своего" бита.
Обработчик прерывания таймера проверяет бит режима первого светодиода, если он сброшен, светодиод гасится, если установлен, то инкрементируется переменная L1, если после инкремента она стала равна 3, то переменная обнуляется, а состояние светодиода 1 изменяется. Для второго светодиода при установленном бите режима состояние меняется при каждом входе в обработчик прерывания таймера.
Задача элементарная на самом деле.
Можно кнопки опрашивать и без прерываний, просто в основном цикле программы, там же и биты режима изменять, а изменение состояний светодиодов и отсчет времени - как я ранее написал, в прерывании таймера. Конечно с дребезгом нужно будет побороться, но это потом, для начала в симуляторе проверьте, там дребезга не будет.

Re: проблема: хитрая обработка нажатия кнопок

Добавлено: Вс июл 17, 2016 11:52:10
Dr.Seldom
смущает опрос.
если нажатие короткое произошло в промежутке от 1 до 49 мс то ничего не сработает. так или я основа запутался?

Re: проблема: хитрая обработка нажатия кнопок

Добавлено: Вс июл 17, 2016 11:58:07
Alkul
Почему нажатие не должно сработать? Время выполнения обработчика прерывания таймера - максимум несколько десятков микросекунд, после выхода из обработчика хоть внешние прерывание для кнопок, хоть прямой их опрос вполне себе выполняются.
Я про предложенный мной вариант алгоритма говорю, конечно.

Re: проблема: хитрая обработка нажатия кнопок

Добавлено: Вс июл 17, 2016 12:04:42
Dr.Seldom
таймер, переполнение каждые 50мс, т.е. что-то в коде прерывания по переполнению будет срабатывать каждые 50мс и длится допустим 5мс.
т.е. инициатором срабатывания кода на кнопке является сам таймер который проверяет условия каждые 50мс. т.е. если что-то происходит ДО момента срабатывания прерывания по переполнению останется незамеченным.

Re: проблема: хитрая обработка нажатия кнопок

Добавлено: Вс июл 17, 2016 12:06:34
AlanDrakes
У меня другой принцип обработки кнопок с антидребезгом и прочими радостями.
Есть основной цикл программы, в нём каждую 1мс срабатывает прерывание таймера (считающее милисекунды, логично, да?) и после него (либо в нём) вызывается процедура опроса кнопок. При этом, основная часть программы будет продолжать работать по завершении обработки прерывания.
Получаем опрос состояний каждую милисекунду.
Далее. Сравниваем текущее состояние кнопок со старым состоянием. Если изменилось - либо записываем, либо поднимаем флаг "Антидребезг" и запоминаем время (или иным образом обрабатываем паузу в несколько тиков). Если по истечении паузы антидребезга, старое состояние всё ещё отличается от нового - запоминаем новое состояние и взводим флаг "Нажата такая-то кнопка".
И уже в основном цикле обрабатываем это нажатие.
+ Антидребезг можно регулировать
+ Любые события будут отслежены, если они дольше периода подавления дребезга кнопки
+ Основной поток программы будет работать как будто ничего и не случилось
- Основной поток должен просматривать флаг нажатий и реагировать на них
- Код получается более разрозненным и части одного действия реализуются в разных модулях
- Естественно, немного бОльше кода.

Re: проблема: хитрая обработка нажатия кнопок

Добавлено: Вс июл 17, 2016 13:14:38
Dr.Seldom
прикинул тут...
на двух независимых мк все должно получится просто. Две ноги (выходы) мк соединены вместе и оба смотрят чтобы уровень был 0 , и если так то мигает своим светодиодом, а если не так ждет пока уровень не упадет в 0.

должно работать, но это не сильно красиво ;)

Re: проблема: хитрая обработка нажатия кнопок

Добавлено: Вс июл 17, 2016 13:41:16
Alkul
Dr.Seldom писал(а):инициатором срабатывания кода на кнопке является сам таймер который проверяет условия каждые 50мс.
Нет, Вы совсем не поняли предложенный мной алгоритм.
Код обработки кнопок работает совершенно независимо от кода обработки прерывания.

Для AlanDrakes - Ваш способ хорош (я применял в том числе и его), хотя на самом деле вариантов опроса кнопок несколько и каждый из них имеет свои достоинства и особенности применения. Мне просто показалось, что мой вариант будет проще для топикстартера.

Автор, вариант с несколькими МК для такой задачи- это даже не смешно. Она вообще решается на паре D-триггеров, двух генераторах на трех логических элементах каждый и еще паре лог.элементов для блокировки триггерами выходов генераторов, к которым светодиоды подключены

Re: проблема: хитрая обработка нажатия кнопок

Добавлено: Вс июл 17, 2016 14:35:58
Dr.Seldom
Вот что хотелось бы получить в итоге, картинка отражающая время и длительность включения светодиодов, при этом порядок нажатий случайный, и если постоянно нажата кнопка включения светодиода нр1 то он мигает пока кнопка замкнута, тоже и для светодиода нр2
длительность включения светодиодов от 0.05с до 0.15с от этого времени считаются длительности пауз и длительность включения светодиодов: пауза равна времени включения нр1 а время включения нр2 в 3 раза дольше чем нр1.

Изображение

Re: проблема: хитрая обработка нажатия кнопок

Добавлено: Вс июл 17, 2016 14:36:57
codenamehawk
Есть тупой вариант :
вместо

Код: Выделить всё

(portC.1=1; delay_ms(x); delay_ms(x); delay_ms(x);portC.1=0; )
делаете

Код: Выделить всё

 vtoraja_knopka_byla_nazata=0;//net
portC.1=1; 
for (i=0;i++;i<(x*3)) 
{
  delay_ms(x/100);//разбиваем задержку на маленькие куски и опрашиваем кнопку
  if (PINB.2 == 1) vtoraja_knopka_byla_nazata=1;//da

}
portC.1=0; 
Что делать далее додумаетесь?

Re: проблема: хитрая обработка нажатия кнопок

Добавлено: Вс июл 17, 2016 14:43:00
Dr.Seldom
codenamehawk, а интересно!!! Надо пробовать!


упд
ЗАРАБОТАЛО!!!
СПАСИБО!