Дмитрий Андреевич

Подавление Дребезга Клавиш В Прерывании

23 сообщения в этой теме

Здравствуйте!

Пишу на С. МК мега16. проблема заключается в том, что когда дребезджит контакт, подающий сигнал на PD2 (INT0), то прерывание вызывается дважды. Пытался решить проблему путем вставкм задержки, но результата это не дало. Как проще всего избавится от такого?

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

Быстрый заказ печатных плат

Полный цикл производства PCB по низким ценам!

  • x
    мм
Заказать Получить купон на $5.00
Alexeyslav    584

Контакты никогда не вешают на прерывания напрямую. Единственный выход если надо сохранить прерывание - аппаратный подавитель дребезга контактов - ждущий мультивибратор с перезапуском тобиш.

А, да .. я сразу не приметил замечательный факт - дважды. один раз при нажатии другой при отпускании. Прерывание-то повидимому вызывается при изменении состояния порта - здесь надо анализировать состояние и пропускать прерывание при отпускании.

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
wowa    4

Вобщем не раекомендуется на прерывания вешать кнопки :) Уж лучше таймером просыпаться и опрашивать ну или как посоветовали - внешне подавить дребезг. И вообще непонятно что может быть так важного что его надо вешать на прерывание???

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
mazzi    3

Почему нельзя вешать кнопки на вход прерывания?

Нормальное решение, но нужно давить дребезг.

1) В обработчике прерывания запрещаем это прерывание.

2) Включаем отсчёт времени для подавления дребезга (50миллисекунд например, или больше, это дело вкуса )

.....

.....

3) если время подавления уже вышло, то сбрасываем флажки запроса на прерывание( если уже успели установиться )

4) разрешаем прерывание.

Всё.

Удачи!

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
wowa    4

Я не спорю что так можно делать но сам факт то что всёравно при подавлении пропускаете прерывание :) Зачем это надо?? Кнопку всёравно быстро не нажмёте и не отпустите.. Если правильно сканировать програмно кнопку - то всё можно обработать в разы проще и главное надёжней!!!

  • Одобряю 1

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
my504    157

С Вовой согласен в смысле бездарного расходования входов внешних интерраптов на примитивные кнопки..., причем один вход - одна кнопка (если без доп.схемотехники)...

Поделиться сообщением


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

Нет, прерывание стоит по возростанию уровня.

Вобщем не раекомендуется на прерывания вешать кнопки

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

очему нельзя вешать кнопки на вход прерывания?

Нормальное решение, но нужно давить дребезг.

1) В обработчике прерывания запрещаем это прерывание.

2) Включаем отсчёт времени для подавления дребезга (50миллисекунд например, или больше, это дело вкуса )

.....

.....

3) если время подавления уже вышло, то сбрасываем флажки запроса на прерывание( если уже успели установиться )

4) разрешаем прерывание.

Всё.

Удачи!

О! это как раз то, ято мне нужно (в прерывании итак есть програмная пауза (так надо!))

Как сбросить флажки запроса на прерывание?

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
my504    157

Дима. Вам, прежде чем писать программу с использованием прерываний, необходимо разобратся с механизмом их функционирования. Человек, который не знает что такое флаги прерываний - не знает про прерывания ничего...

Нельзя такие вещи писать интуитивно - не выйдет...

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
Goodefine    92
Контакты никогда не вешают на прерывания напрямую...

Правда никогда? Даже с целью пробудить проц из глубокого анабиоза?...

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
Дима. Вам, прежде чем писать программу с использованием прерываний, необходимо разобратся с механизмом их функционирования. Человек, который не знает что такое флаги прерываний - не знает про прерывания ничего...

Нельзя такие вещи писать интуитивно - не выйдет...

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

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

Bit 6 – INTF0: External Interrupt Flag 0

When an edge or logic change on the INT0 pin triggers an interrupt request, INTF0

becomes set (one). If the I-bit in SREG and the INT0 bit in GICR are set (one), the MCU

will jump to the corresponding interrupt vector. The flag is cleared when the interrupt

routine is executed. Alternatively, the flag can be cleared by writing a logical one to it.

This flag is always cleared when INT0 is configured as a level interrupt.

Для того, чтобы прерывание не повторялось, нужно обнулить бит 6 регистра GIFR?

Я правильно понимаю?

Да, еще, не совсем ясно представляю, как это сделать. Можно ли просто написать:

GIFR=GIFR&0b100000;

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
Alexeyslav    584

Иногда, чтобы исправить "небольшой баг" приходится переделывать половину проекта :)

GIFR=GIFR&0b100000;
- вот так точно писать не нужно! таким образом ты только оставишь нужный бит, все остальные обнуляются. тебе надо использовать логическую операцию OR или применить битовую команду.

Кстати говоря, это от дребезга контактов ТОЖЕ НЕ СПАСЕТ. Ведь при отпускании кнопки так же возникает пачка ипульсов, как и при её нажатии! Единственный простой выход в данной ситуации - использовать аппаратный подавитель дребезга в виде одновибратора. Более сложный - отказаться от использования прерывания в этих целях(только для пробудки контроллера).

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
my504    157

При использовании прерываний в обработке дребезга совершенно безразлично какой дребезг подавлять - при нажатии или при отпускании. Разница лишь в том, что при нажатии его факт фиксируется ДО задержки, а при отпускании ПОСЛЕ. Т.е. каждое нажатие (и последующее за ним отпускание приведет к обработке ДВУХ прерываний. Смысл каждого примитивно прост - выключить прерывания по ЭТОМУ ВХОДУ на время дребезга. Для этого не нужно торчать в обработчике, достаточно после первого входа выставить флаг нажатия, запустить таймер на время дребезга, сбросить флаг этого прерывания и мигом вылететь из обработчика. Когда таймер свое отсчитает, снова разрешить эти прерывания и при следующем входе по нему все повторить, но после таймера уже сбросить флаг нажатой кнопки. Сам этот флаг и будет семафором(переключателем) в программе...

При таком раскладе в прерывании мы торчим минимум и программа не блокируется на время дребезга.

ЗЫ. Кста, прерываний может быть и поболее чем два, это если кнопка гавнецо и шуршит в нажатом состоянии. Тогда после второй задержки ее состояние останется нажатым и программа будет повторять цикл задержки...

Изменено пользователем my504

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
mazzi    3
Да, еще, не совсем ясно представляю, как это сделать. Можно ли просто написать:

GIFR=GIFR&0b100000;

Для сброса бита( сбрасываемый бит равен нулю )

GIFR &= 0b11101111;

Для установки бита ( устанавливаемый бит равен 1 )

GIFR |= 0b10000;

Изменено пользователем mazzi

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
Для сброса бита( сбрасываемый бит равен нулю )

GIFR &= 0b11101111;

Для установки бита ( устанавливаемый бит равен 1 )

GIFR |= 0b10000;

:) Я понял - все наоборот надо делать))) на против тех, что не надо обнулять, ставится 1)))

только у меня номер бита - 6, а здесь, по моему, 4-й обнуляется и выставляется :huh:

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
mazzi    3
:) Я понял - все наоборот надо делать))) на против тех, что не надо обнулять, ставится 1)))

только у меня номер бита - 6, а здесь, по моему, 4-й обнуляется и выставляется :huh:

Совершенно верно.

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
malecdima    0

Прошу помочь с решением сл. задачи:

Имеется 4 кнопки, подключенных к порту мк, опрос провожу в основном цикле + антидребезг, вобщем на выходе имеем регистр с флагами состояния кнопок. Нужно чтобы МК фиксировал нажатие 1 раз: нажали кнопку, мк зафиксировал нажатие, установил флаг кнопки, а при следующем опросе кнопок сбрасывал флаг нажатия, пока кнопка не будет отпущена.

Второй день думаю, ничего толкового не получается. Надеюсь на помощь!

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
Alexeyslav    584

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

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
malecdima    0

То есть сравнение этих двух регистров нужно проводить перед процедурой обработки нажатой кнопки и при состоянии нажато - нажато

просто пропускать эту процедуру? Про дополнительный рег-р думал и даже завел его, понятно что нужно запомнить предидущее состояние и впоследствии сравнивать его сновым, но вот реализовать сам алгоритм никак не получалось... :rolleyes:

Изменено пользователем malecdima

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

char

detect_buttons_in_delay(

int

delay)

{

static

char

previous_port = 0xFF;

int

quant_count = delay / 10;

for

(

int

quant_number = 0; quant_number < quant_count;

++quant_number)

{

char

current_port = PIND;

char

buttons = ~current_port & previous_port;

previous_port = current_port;

if

(buttons)

return

buttons;

_delay_ms(10);

}

return

0x00;

} попробуй такой оброботчик кнопки у меня всегда работает без отказно да и еще попробуй конденсатор поставить с кнопкой в парарель

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
Alexeyslav    584

ужас-ужас, отлучать за такое надо от церкви. Дребезг же подавляется путем синхронного считывания состояния кнопки с интервалом 1..10мс и больше. Это прекрасно реализуется прерыванием от таймера, или в других частях прошивки где будет гарантировано считывание состояния кнопки не чаще чем 1 раз в 1..10мс.

конденсатор с кнопкой - плохой вариант, конденсатор со временем только усилит износ контактов кнопки, а дребезг не подавит.

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

Создайте аккаунт или войдите в него для комментирования

Вы должны быть пользователем, чтобы оставить комментарий

Создать аккаунт

Зарегистрируйтесь для получения аккаунта. Это просто!

Зарегистрировать аккаунт

Войти

Уже зарегистрированы? Войдите здесь.

Войти сейчас