Nikitoc 0 21 августа, 2011 Опубликовано 21 августа, 2011 · Жалоба Может я засиделся сегодня у компа, но что-то меня заклинило: как правильно писать обработчик прерывания по нажатию кнопки? Суть вопроса сводится к расположению задержки (~30мс) для "устранения " дребезга контактов кнопки. Ведь существует неписанное правило о том, что обработчики прерывания должны быть как можно короче по времени исполнения, а введение "антидребезговой" задержки этому как-то не способствует. Или это неизбежное зло и таким обработчикам просто следует назначать наименьший приоритет? Если тема боян - ткните носом. Не нашел. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
_noise 0 22 августа, 2011 Опубликовано 22 августа, 2011 · Жалоба Кто запрещает что-то другое делать, пока задержка. Почему обязательно всё это время висеть в прерывании. Кто разрешил делать предположения о принципиальной возможности других подходов к. Не нашел. Длительность импульсов в "дребезге контактов" например заголовок, простой и логичный. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
alexeyv 0 22 августа, 2011 Опубликовано 22 августа, 2011 (изменено) · Жалоба Примерно лет шесть делаю так: // в .h-файле: // кол-во времени до события "длинное нажатие" #define TIMER_COUNT 250 // кол-во кнопок #define KEY_COUNT 4 // время автоинкремента #define TIMER_SCROLL 20 // состояние кнопки enum {KN_DOWN =0, KN_UP =1, KN_PRESS=2 }; // тип функции кнопки typedef byte(KeyFunc)(void); // структура хранящая набор переменных для каждой кнопки typedef struct key_struct__ { byte state; // состояние кнопки byte mask; // маска клавиши byte pins; // буфер значений с клавиши byte count; // счетчик нажатий KeyFunc * exec_down; KeyFunc * exec_up; KeyFunc * exec_pres; }key_struct; // в .c-файле: //***************************************************************************** // Драйвер кнопок // назначение кнопок // 1- MiNUS 2-PLUS 3- Select 4- Enter //***************************************************************************** //============================================================================= // состояния кнопок static key_struct key_mass [KEY_COUNT] = { //state mask pins count exec_down exec_up exec_pres {KN_UP, PIN_KEY_MINUS, 0xFF,0x00, kn_empty, kn_minus_up ,kn_minus_up } ,{KN_UP, PIN_KEY_PLUS, 0xFF,0x00, kn_empty, kn_plus_up ,kn_plus_up } ,{KN_UP, PIN_KEY_SELECT, 0xFF,0x00, kn_empty, kn_select_up ,kn_empty } ,{KN_UP, PIN_KEY_ENTER, 0xFF,0x00, kn_empty, kn_empty ,kn_enter_press } }; //============================================================================= ISR(TIMER1_COMPA_vect) { #define Sta key->state #define Pin key->pins #define Cnt key->count #define Msk key->mask #define Down key->exec_down #define Up key->exec_up #define Pres key->exec_pres key_struct * key = key_mass; for(byte i=0; i< KEY_COUNT ; i++) { Pin *=2; // * or << if(KEY_PIN & Msk) Pin |= 0x01; if(Sta == KN_UP) { if(!Pin) // начало счета - нажатие { Down(); Sta = KN_DOWN; Cnt = 0x00; } } else // down or press { if(Pin==0xFF) // отпустили { if(Sta == KN_DOWN) Up(); Sta = KN_UP; } else// удерживаем { if(Cnt <= TIMER_COUNT) ++Cnt; if(Cnt == TIMER_COUNT) // длительное удержание - попадаем один раз!! { if(Pres()) Cnt = TIMER_COUNT - TIMER_SCROLL; else Sta = KN_PRESS; } } } key++; } } Таймер в CTC-режиме на порядка 5....15 мсек Изменено 22 августа, 2011 пользователем alexeyv Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
777777 0 22 августа, 2011 Опубликовано 22 августа, 2011 · Жалоба Может я засиделся сегодня у компа, но что-то меня заклинило: как правильно писать обработчик прерывания по нажатию кнопки? Суть вопроса сводится к расположению задержки (~30мс) для "устранения " дребезга контактов кнопки. Ведь существует неписанное правило о том, что обработчики прерывания должны быть как можно короче по времени исполнения, а введение "антидребезговой" задержки этому как-то не способствует. Или это неизбежное зло и таким обработчикам просто следует назначать наименьший приоритет? Если тема боян - ткните носом. Не нашел. А задержка в вашем представлении это обязательно delay_ms()? Мне например за свою жизнь никогда подобные задержки не требовались. Запусти таймер на 30 мс и сравни значение кнопки до и после. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
SSerge 4 22 августа, 2011 Опубликовано 22 августа, 2011 · Жалоба Сама идея прерываний от кнопки не очень хороша. Из-за дребезга придётся или отрабатывать десятки прерываний на каждое нажатие или мутить с их разрешением/запрещением. Обычно проще оказывается просто регулярно опрашивать кнопки в низкоприоритетном процессе, благо мгновенной реакции не требуется, задержку до 100 .. 150 мс человек не замечает. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Nikitoc 0 22 августа, 2011 Опубликовано 22 августа, 2011 (изменено) · Жалоба Спасибо всем за ответы. Прокомментируйте, пожалуйста, следующий вариант обработки нажатия кнопки: по нажатию на кнопку устанавливаем в обработчике флаг соотв. кнопки и запускаем таймер (и выходим из прерывания), по прерыванию от которого проверяем состояние кнопки (чей флаг предварительно был установлен) и устанавливаем флаг нажатия кнопок, который (в паре с флагом соотв. кнопки) обрабатываем в основной программе. P.S. Учитывая пост Sserge добавляем запрещение соотв. прерывания в первом обработчике и разрешение во втором. Изменено 22 августа, 2011 пользователем Nikitoc Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
whiteTigr 0 22 августа, 2011 Опубликовано 22 августа, 2011 · Жалоба Спасибо всем за ответы. Прокомментируйте, пожалуйста, следующий вариант обработки нажатия кнопки: по нажатию на кнопку устанавливаем в обработчике флаг соотв. кнопки и запускаем таймер (и выходим из прерывания), по прерыванию от которого проверяем состояние кнопки (чей флаг предварительно был установлен) и устанавливаем флаг нажатия кнопок, который (в паре с флагом соотв. кнопки) обрабатываем в основной программе. P.S. Учитывая пост Sserge добавляем запрещение соотв. прерывания в первом обработчике и разрешение во втором. Возможно, заработает. Возможно, будет даже немного лучше чем вообще без антидребезга. Возможно... По хорошему алгоритм в следующем: Опрос кнопки в прерывании от таймера, раз в 0.5-5мс Счетчик - от 0 до N, где N задает время антидребезга (порядка 10-200мс) Буфер - состояние кнопки после антидребезга. 1. Если кнопка нажата и счетчик меньше максимума - прибавляем счетчик 2. Если кнопка отжата и счетчик больше нуля - убавляем счетчик 3. Если счетчик в максимуме, устанавливаем буфер в '1' 4. Если счетчик в нуле, устанавливаем буфер в '0' 5. По переходу буфера '0' -> '1' или '1' -> '0' делаем вывод о нажатии/отжатии кнопки. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
MrYuran 16 22 августа, 2011 Опубликовано 22 августа, 2011 · Жалоба Я вообще не вижу смысла вешать кнопку на вход прерывания, кроме одного случая - когда это используется для вывода процессора из спячки. Равно как и использование отдельного таймера под обработку. У меня сделано так: В прерывании от системного таймера (Т=1мс) сканируется порт клавиатуры, и если обнаружено изменение состояния (NextState != PrevState), выставляется соответствующий флаг. По этому флагу в основном цикле запускается обработчик, который отмеряет задержки, анализирует длительность нажатия (single/fixed) и запускает необходимые функции. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
ILYAUL 0 22 августа, 2011 Опубликовано 22 августа, 2011 · Жалоба Запускаешь АЦП и никаких тебе дребезгов и задержек очена подходит к случаю описанному alexeyv Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
whiteTigr 0 23 августа, 2011 Опубликовано 23 августа, 2011 (изменено) · Жалоба Запускаешь АЦП и никаких тебе дребезгов и задержек очена подходит к случаю описанному alexeyv Что-то я не совсем понял каким боком тут АЦП оказалось и как оно поможет с кнопкой. Изменено 23 августа, 2011 пользователем whiteTigr Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
ILYAUL 0 23 августа, 2011 Опубликовано 23 августа, 2011 · Жалоба Что-то я не совсем понял каким боком тут АЦП оказалось и как оно поможет с кнопкой. А я не понял , что не понятного? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
whiteTigr 0 23 августа, 2011 Опубликовано 23 августа, 2011 · Жалоба А я не понял , что не понятного? Зачем целый АЦП выделять под кнопку? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
ILYAUL 0 23 августа, 2011 Опубликовано 23 августа, 2011 · Жалоба Зачем целый АЦП выделять под кнопку? А почему под кнопку? Я написал для кого проекта это удобно использовать. Запускаешь АЦП и никаких тебе дребезгов и задержек очена подходит к случаю описанному alexeyv И к тому же один канал на 8 кнопок. Если уж очень постараться то и 12 кнопок влезут. Учитывая , что каналы (8 шт.) можно переключать во время работы и никто не запрещал менять настройки АЦП , во время работы, то проще выделить просто один канал под кнопки , а с отальными I/O делать , что душе угодно. В том числе и просто как входы -выходы Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
skripach 5 23 августа, 2011 Опубликовано 23 августа, 2011 · Жалоба Ни в одном проекте не использовал прерывания для кнопок, опрос в прерывании таймера самое оно как по мне, там же и дребезг и фильтрация от помех. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
ARV 0 23 августа, 2011 Опубликовано 23 августа, 2011 · Жалоба вообще не понимаю, зачем для столь низкоприоритетного процесса, как работа с кнопками, задействовать прерывания или таймеры. в большинстве обычных ситуаций обработка кнопок премило делается в основном цикле путем поллинга с традиционными программными задержками - а вот фоновые процессы пусть крутятся в прерываниях. прерывание требуется для обеспечения немедленной реакции на внешнее событие, причем "немедленно" - по меркам микроконтроллера, а не человека. назовите хотя бы какую-то ситуацию, где действительно необходимо реагировать на кнопку за 5-10 микросекунд. кстати - даже если придумаете, это будет бесполезно, т.к. подавление дребезга все равно заставит затянуть процесс до 10-15 миллисекунд, т.е. примерно в 1000 раз. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться