реклама на сайте
подробности

 
 
2 страниц V   1 2 >  
Reply to this topicStart new topic
> Обработка прерывания кнопки
Nikitoc
сообщение Aug 21 2011, 21:35
Сообщение #1


Местный
***

Группа: Validating
Сообщений: 207
Регистрация: 14-01-09
Из: Днепропетровск
Пользователь №: 43 367



Может я засиделся сегодня у компа, но что-то меня заклинило: как правильно писать обработчик прерывания по нажатию кнопки? Суть вопроса сводится к расположению задержки (~30мс) для "устранения " дребезга контактов кнопки. Ведь существует неписанное правило о том, что обработчики прерывания должны быть как можно короче по времени исполнения, а введение "антидребезговой" задержки этому как-то не способствует. Или это неизбежное зло и таким обработчикам просто следует назначать наименьший приоритет? Если тема боян - ткните носом. Не нашел.
Go to the top of the page
 
+Quote Post
нечитатель
сообщение Aug 22 2011, 02:25
Сообщение #2


Местный
***

Группа: Участник
Сообщений: 235
Регистрация: 20-11-10
Пользователь №: 61 032



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

Цитата
Не нашел.
Длительность импульсов в "дребезге контактов" например заголовок, простой и логичный.
Go to the top of the page
 
+Quote Post
alexeyv
сообщение Aug 22 2011, 04:20
Сообщение #3


Местный
***

Группа: Участник
Сообщений: 298
Регистрация: 26-01-09
Из: Пермь
Пользователь №: 43 940



Примерно лет шесть делаю так:



CODE

// в .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 мсек

Сообщение отредактировал alexeyv - Aug 22 2011, 04:22
Go to the top of the page
 
+Quote Post
777777
сообщение Aug 22 2011, 06:12
Сообщение #4


Профессионал
*****

Группа: Участник
Сообщений: 1 091
Регистрация: 25-07-07
Из: Саратов
Пользователь №: 29 357



Цитата(Nikitoc @ Aug 22 2011, 01:35) *
Может я засиделся сегодня у компа, но что-то меня заклинило: как правильно писать обработчик прерывания по нажатию кнопки? Суть вопроса сводится к расположению задержки (~30мс) для "устранения " дребезга контактов кнопки. Ведь существует неписанное правило о том, что обработчики прерывания должны быть как можно короче по времени исполнения, а введение "антидребезговой" задержки этому как-то не способствует. Или это неизбежное зло и таким обработчикам просто следует назначать наименьший приоритет? Если тема боян - ткните носом. Не нашел.

А задержка в вашем представлении это обязательно delay_ms()? Мне например за свою жизнь никогда подобные задержки не требовались. Запусти таймер на 30 мс и сравни значение кнопки до и после.
Go to the top of the page
 
+Quote Post
SSerge
сообщение Aug 22 2011, 09:00
Сообщение #5


Профессионал
*****

Группа: Свой
Сообщений: 1 719
Регистрация: 13-09-05
Из: Novosibirsk
Пользователь №: 8 528



Сама идея прерываний от кнопки не очень хороша. Из-за дребезга придётся или отрабатывать десятки прерываний на каждое нажатие или мутить с их разрешением/запрещением. Обычно проще оказывается просто регулярно опрашивать кнопки в низкоприоритетном процессе, благо мгновенной реакции не требуется, задержку до 100 .. 150 мс человек не замечает.


--------------------
Russia est omnis divisa in partes octo.
Go to the top of the page
 
+Quote Post
Nikitoc
сообщение Aug 22 2011, 09:19
Сообщение #6


Местный
***

Группа: Validating
Сообщений: 207
Регистрация: 14-01-09
Из: Днепропетровск
Пользователь №: 43 367



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

P.S. Учитывая пост Sserge добавляем запрещение соотв. прерывания в первом обработчике и разрешение во втором.

Сообщение отредактировал Nikitoc - Aug 22 2011, 09:27
Go to the top of the page
 
+Quote Post
whiteTigr
сообщение Aug 22 2011, 10:06
Сообщение #7


Участник
*

Группа: Участник
Сообщений: 55
Регистрация: 25-07-11
Пользователь №: 66 407



Цитата(Nikitoc @ Aug 22 2011, 13:19) *
Спасибо всем за ответы. Прокомментируйте, пожалуйста, следующий вариант обработки нажатия кнопки: по нажатию на кнопку устанавливаем в обработчике флаг соотв. кнопки и запускаем таймер (и выходим из прерывания), по прерыванию от которого проверяем состояние кнопки (чей флаг предварительно был установлен) и устанавливаем флаг нажатия кнопок, который (в паре с флагом соотв. кнопки) обрабатываем в основной программе.

P.S. Учитывая пост Sserge добавляем запрещение соотв. прерывания в первом обработчике и разрешение во втором.


Возможно, заработает. Возможно, будет даже немного лучше чем вообще без антидребезга. Возможно...

По хорошему алгоритм в следующем:
Опрос кнопки в прерывании от таймера, раз в 0.5-5мс
Счетчик - от 0 до N, где N задает время антидребезга (порядка 10-200мс)
Буфер - состояние кнопки после антидребезга.

1. Если кнопка нажата и счетчик меньше максимума - прибавляем счетчик
2. Если кнопка отжата и счетчик больше нуля - убавляем счетчик
3. Если счетчик в максимуме, устанавливаем буфер в '1'
4. Если счетчик в нуле, устанавливаем буфер в '0'
5. По переходу буфера '0' -> '1' или '1' -> '0' делаем вывод о нажатии/отжатии кнопки.
Go to the top of the page
 
+Quote Post
MrYuran
сообщение Aug 22 2011, 10:10
Сообщение #8


Беспросветный оптимист
******

Группа: Свой
Сообщений: 4 640
Регистрация: 26-12-07
Из: Н.Новгород
Пользователь №: 33 646



Я вообще не вижу смысла вешать кнопку на вход прерывания, кроме одного случая - когда это используется для вывода процессора из спячки.
Равно как и использование отдельного таймера под обработку.
У меня сделано так:
В прерывании от системного таймера (Т=1мс) сканируется порт клавиатуры, и если обнаружено изменение состояния (NextState != PrevState), выставляется соответствующий флаг.
По этому флагу в основном цикле запускается обработчик, который отмеряет задержки, анализирует длительность нажатия (single/fixed) и запускает необходимые функции.


--------------------
Программирование делится на системное и бессистемное. ©Моё :)
— а для кого-то БГ — это Bill Gilbert =)
Go to the top of the page
 
+Quote Post
ILYAUL
сообщение Aug 22 2011, 12:36
Сообщение #9


Профессионал
*****

Группа: Свой
Сообщений: 1 940
Регистрация: 16-12-07
Из: Москва
Пользователь №: 33 339



Запускаешь АЦП и никаких тебе дребезгов и задержек очена подходит к случаю описанному alexeyv


--------------------
Закон Мерфи:

Чем тщательнее составлен проект, тем больше неразбериха, если что-то пошло не так
Go to the top of the page
 
+Quote Post
whiteTigr
сообщение Aug 23 2011, 04:57
Сообщение #10


Участник
*

Группа: Участник
Сообщений: 55
Регистрация: 25-07-11
Пользователь №: 66 407



Цитата(ILYAUL @ Aug 22 2011, 16:36) *
Запускаешь АЦП и никаких тебе дребезгов и задержек очена подходит к случаю описанному alexeyv

Что-то я не совсем понял каким боком тут АЦП оказалось и как оно поможет с кнопкой.

Сообщение отредактировал whiteTigr - Aug 23 2011, 04:59
Go to the top of the page
 
+Quote Post
ILYAUL
сообщение Aug 23 2011, 07:43
Сообщение #11


Профессионал
*****

Группа: Свой
Сообщений: 1 940
Регистрация: 16-12-07
Из: Москва
Пользователь №: 33 339



Цитата(whiteTigr @ Aug 23 2011, 08:57) *
Что-то я не совсем понял каким боком тут АЦП оказалось и как оно поможет с кнопкой.

А я не понял , что не понятного?


--------------------
Закон Мерфи:

Чем тщательнее составлен проект, тем больше неразбериха, если что-то пошло не так
Go to the top of the page
 
+Quote Post
whiteTigr
сообщение Aug 23 2011, 07:47
Сообщение #12


Участник
*

Группа: Участник
Сообщений: 55
Регистрация: 25-07-11
Пользователь №: 66 407



Цитата(ILYAUL @ Aug 23 2011, 11:43) *
А я не понял , что не понятного?


Зачем целый АЦП выделять под кнопку?
Go to the top of the page
 
+Quote Post
ILYAUL
сообщение Aug 23 2011, 07:59
Сообщение #13


Профессионал
*****

Группа: Свой
Сообщений: 1 940
Регистрация: 16-12-07
Из: Москва
Пользователь №: 33 339



Цитата(whiteTigr @ Aug 23 2011, 11:47) *
Зачем целый АЦП выделять под кнопку?

А почему под кнопку? Я написал для кого проекта это удобно использовать.
Цитата
Запускаешь АЦП и никаких тебе дребезгов и задержек очена подходит к случаю описанному alexeyv

И к тому же один канал на 8 кнопок. Если уж очень постараться то и 12 кнопок влезут. Учитывая , что каналы (8 шт.) можно переключать во время работы и никто не запрещал менять настройки АЦП , во время работы, то проще выделить просто один канал под кнопки , а с отальными I/O делать , что душе угодно. В том числе и просто как входы -выходы


--------------------
Закон Мерфи:

Чем тщательнее составлен проект, тем больше неразбериха, если что-то пошло не так
Go to the top of the page
 
+Quote Post
skripach
сообщение Aug 23 2011, 12:42
Сообщение #14


■ ■ ■ ■
*****

Группа: Свой
Сообщений: 1 100
Регистрация: 9-08-06
Пользователь №: 19 443



Ни в одном проекте не использовал прерывания для кнопок, опрос в прерывании таймера самое оно как по мне, там же и дребезг и фильтрация от помех.


--------------------
Делай что должен и будь что будет.
Go to the top of the page
 
+Quote Post
ARV
сообщение Aug 23 2011, 12:54
Сообщение #15


Профессионал
*****

Группа: Свой
Сообщений: 1 143
Регистрация: 30-09-08
Из: Новочеркасск
Пользователь №: 40 581



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

прерывание требуется для обеспечения немедленной реакции на внешнее событие, причем "немедленно" - по меркам микроконтроллера, а не человека. назовите хотя бы какую-то ситуацию, где действительно необходимо реагировать на кнопку за 5-10 микросекунд. кстати - даже если придумаете, это будет бесполезно, т.к. подавление дребезга все равно заставит затянуть процесс до 10-15 миллисекунд, т.е. примерно в 1000 раз.


--------------------
Я бы взял частями... но мне надо сразу.
Go to the top of the page
 
+Quote Post

2 страниц V   1 2 >
Reply to this topicStart new topic
2 чел. читают эту тему (гостей: 2, скрытых пользователей: 0)
Пользователей: 0

 


RSS Текстовая версия Сейчас: 20th July 2025 - 05:54
Рейтинг@Mail.ru


Страница сгенерированна за 0.01491 секунд с 7
ELECTRONIX ©2004-2016