Форум Микро-Чип
Поиск и заказ электронных компонентов
 

Вернуться   Форум Микро-Чип > Продукция MICROCHIP

Продукция MICROCHIP Технические вопросы по всей продукции Microchip

Ответ
 
Опции темы Опции просмотра
Старый 04.10.2009, 14:45   #1
Dmitry_177
Senior Member
 
Регистрация: 25.06.2009
Возраст: 32
Сообщений: 114
Вес репутации: 100/32
Dmitry_177 will become famous soon enoughDmitry_177 will become famous soon enough
По умолчанию Нажатие кнопки + антидребезг (16F877, HI-TECH)

При нажатии на кнопку нужно чтобы светодиоды RB6-RB7 включались/выключались и пищалка которая висит на RB5 два раза быстро пикнула..

Делаю я так:

Код:
int spk = 0;  // флаг сработала ли кнопка
 
void main (void)
	{
		int i;

		TRISB	= 0b00000001;
		RB5	= 0;
		RB6	= 0;
		RB7	= 0;

		INTEDG	= 0;

		INTE	= 1;
		GIE	= 1;

		while(1)
			{
				if(spk==1)  // если сработала
					{
						RB6 ^= 1; // меняем состояние светодиодов
						RB7 ^= 1;

						RB5 = 1;  // работа пищалки с задержкой циклом
						for(i=0; i<3000; i++)
							{
								i++;
								i--;
							}

						RB5 = 0;
						for(i=0; i<2000; i++)
							{
								i++;
								i--;
							}

						RB5 = 1;
						for(i=0; i<3000; i++)
							{
								i++;
								i--;
							}


						RB5 = 0;
						spk = 0;  // сбрасываем флаг сработавшей кнопки

						INTE = 1; // разрешаем прерывания INT
					}
			}
	}


static void interrupt isr(void) 
	{
		if(INTE && INTF)
			{
				INTE	= 0;  // запрещаем прерывание INT

				T1CKPS1	= 0;  // устанавливаем таймер на TMR1 на 100мс для подавления дребезга кнопки
				T1CKPS0	= 1;
				T1OSCEN	= 1;
				T1SYNC	= 1;
				TMR1CS	= 0;
				TMR1H	= 0x3C;
				TMR1L	= 0xB0;

				TMR1ON	= 1;
				TMR1IE	= 1;

				INTF	= 0;
			}

		if(TMR1IE && TMR1IF)
			{
					spk	= 1; // устанавливаем флаг что кнопка сработала
			
					TMR1IE	= 0; // запрещаем прерывание TMR1 выключаем его
					TMR1ON	= 0;

					TMR1IF	= 0;
			}
	}
По идее все вроде просто, должно работать, а вот почему-то не работает, нажатия кнопки не ловятся.. Подскажите пожалуйста что не так?
Dmitry_177 вне форума   Ответить с цитированием
Старый 04.10.2009, 15:41   #2
tester
Super Moderator
 
Аватар для tester
 
Регистрация: 28.02.2007
Возраст: 40
Сообщений: 3,577
Вес репутации: 4386/117
tester has a reputation beyond reputetester has a reputation beyond reputetester has a reputation beyond reputetester has a reputation beyond reputetester has a reputation beyond reputetester has a reputation beyond reputetester has a reputation beyond reputetester has a reputation beyond reputetester has a reputation beyond reputetester has a reputation beyond reputetester has a reputation beyond repute
По умолчанию Re: Нажатие кнопки + антидребезг (16F877, HI-TECH)

Ну и каша!

Конкретно ошибка в том, что не установлен бит PEIE (INTCON.6), поэтому никогда не сработает прерывание по TMR1 (его код обработался бы, если б в прерывание попали по какой-то другой причине, но другой причины нет, т.к. INTE сбрасывается)

По алгоритму: ты странно подавляешь дребезг. При твоем алгоритме флаг spk устанавливается по-любому через 100мс после срабатывания INTF. Т.е. даже при импульсной помехе программа будет думать, что кнопка была нажата. В обработчике TMR1IF флаг spk нужно было устанавливать только при RB0==0. А если RB0!=0, то восстанавливать прерывание INTE. (А у тебя INTE восстанавливается черт-те где. Программа чуток вырастет - и появятся новые проблемы, и опять будешь писать сюда "почему не работает?")

Кроме того, в обработчике INTF перед установкой TMR1IE желательно сбрасывать TMR1IF. В конкретном случае это все равно, но лучше всегда делать именно так, т.е. перед установкой бита разрешения прерывания (xxxE) сбрасывать бит события (xxxF).
tester вне форума   Ответить с цитированием
Старый 04.10.2009, 17:28   #3
Dmitry_177
Senior Member
 
Регистрация: 25.06.2009
Возраст: 32
Сообщений: 114
Вес репутации: 100/32
Dmitry_177 will become famous soon enoughDmitry_177 will become famous soon enough
По умолчанию Re: Нажатие кнопки + антидребезг (16F877, HI-TECH)

Спасибо за ответ!

Вот подправил:

Код:
void main (void)
	{
		int i;

		TRISB	= 0b00000001;
		RB5	= 0;
		RB6	= 0;
		RB7	= 0;

		INTEDG	= 0;

		INTE	= 1;
		PEIE	= 1;
		GIE	= 1;

		while(1)
			{
				if(spk==1)
					{
						RB6 ^= 1;
						RB7 ^= 1;

						RB5 = 1;
						for(i=0; i<3000; i++)
							{
								i++;
								i--;
							}

						RB5 = 0;
						for(i=0; i<2000; i++)
							{
								i++;
								i--;
							}

						RB5 = 1;
						for(i=0; i<3000; i++)
							{
								i++;
								i--;
							}


						RB5 = 0;
						spk = 0;

						INTE = 1;
					}
			}
	}


static void interrupt isr(void) 
	{
		if(INTE && INTF)
			{
				INTE		= 0;

				T1CKPS1	= 0;
				T1CKPS0	= 1;
				T1OSCEN	= 1;
				T1SYNC		= 1;
				TMR1CS		= 0;
				TMR1H		= 0x3C;
				TMR1L		= 0xB0;

				TMR1ON		= 1;
				TMR1IF		= 0;
				TMR1IE		= 1;

				INTF		= 0;
			}

		if(TMR1IE && TMR1IF)
			{
				if(RB0==0)
					{
						spk	= 1;
			
						TMR1IE	= 0;
						TMR1ON	= 0;

						TMR1IF	= 0;
					}
				else
					{
						INTE	= 1;
					}
			}
	}
Работает, но при самом первом нажатии кнопки(после подачи напряжения на МК) кнопка почему-то не срабатывает.. И при периодическом(где-то раз в 1-2 секунды) нажатии на кнопку она не всегда бывает сработает, раза 3-4 сработает, на 5-й раз нет.. Почему так?

Цитата:
По алгоритму: ты странно подавляешь дребезг. При твоем алгоритме флаг spk устанавливается по-любому через 100мс после срабатывания INTF. Т.е. даже при импульсной помехе программа будет думать, что кнопка была нажата. В обработчике TMR1IF флаг spk нужно было устанавливать только при RB0==0. А если RB0!=0, то восстанавливать прерывание INTE. (А у тебя INTE восстанавливается черт-те где. Программа чуток вырастет - и появятся новые проблемы, и опять будешь писать сюда "почему не работает?")
У меня так и было по условию RB0==0, просто когда не работает, уже не знаешь чего убрать.. А почему INTE восстанавливается черт знает где, так это потому что если сделать так:
Код:
if(TMR1IE && TMR1IF)
	{
		if(RB0==0)
			{
				spk	= 1;
			
				TMR1IE	= 0;
				TMR1ON	= 0;

				TMR1IF	= 0;
			}
		INTE	= 1;
	}
То светодиоды переключаются, а пищалка почему-то бывает только один раз пикнет, а бывает один раз пикнет, а второй раз включится и не выключается, т.е. остается пищать до следующего нажатия кнопки..
Dmitry_177 вне форума   Ответить с цитированием
Старый 04.10.2009, 17:36   #4
tester
Super Moderator
 
Аватар для tester
 
Регистрация: 28.02.2007
Возраст: 40
Сообщений: 3,577
Вес репутации: 4386/117
tester has a reputation beyond reputetester has a reputation beyond reputetester has a reputation beyond reputetester has a reputation beyond reputetester has a reputation beyond reputetester has a reputation beyond reputetester has a reputation beyond reputetester has a reputation beyond reputetester has a reputation beyond reputetester has a reputation beyond reputetester has a reputation beyond repute
По умолчанию Re: Нажатие кнопки + антидребезг (16F877, HI-TECH)

Цитата:
Сообщение от Dmitry_177 Посмотреть сообщение
Работает, но при самом первом нажатии кнопки(после подачи напряжения на МК) кнопка почему-то не срабатывает.. И при периодическом(где-то раз в 1-2 секунды) нажатии на кнопку она не всегда бывает сработает, раза 3-4 сработает, на 5-й раз нет.. Почему так?
100 мс - многовато. Возможно, ты отпускаешь кнопку раньше, чем произойдет повторная проверка.

Цитата:
А почему INTE восстанавливается черт знает где, так это потому что если сделать так:
Код:
if(TMR1IE && TMR1IF)
    {
        if(RB0==0)
            {
                spk    = 1;
            
                TMR1IE    = 0;
                TMR1ON    = 0;

                TMR1IF    = 0;
            }
        INTE    = 1;
    }
То светодиоды переключаются, а пищалка почему-то бывает только один раз пикнет, а бывает один раз пикнет, а второй раз включится и не выключается, т.е. остается пищать до следующего нажатия кнопки..
Так надо ошибку в алгоритме искать, а не перемещать операции туда-сюда по всему коду, пока не заработает кое-как. По этому коду даже видно, где ошибка. тут всего 7 строчек, так что ищи внимательно.

Добавлено: ага, вижу, и в последнем полном коде у тебя та же ошибка, что и в этом примерчике.

Последний раз редактировалось tester; 04.10.2009 в 17:43.
tester вне форума   Ответить с цитированием
Старый 04.10.2009, 17:46   #5
Dmitry_177
Senior Member
 
Регистрация: 25.06.2009
Возраст: 32
Сообщений: 114
Вес репутации: 100/32
Dmitry_177 will become famous soon enoughDmitry_177 will become famous soon enough
По умолчанию Re: Нажатие кнопки + антидребезг (16F877, HI-TECH)

Цитата:
100 мс - многовато. Возможно, ты отпускаешь кнопку раньше, чем произойдет повторная проверка.
А сколько обычно делают задержку на практике?

Цитата:
Так надо ошибку в алгоритме искать, а не перемещать операции туда-сюда по всему коду, пока не заработает кое-как. По этому коду даже видно, где ошибка. тут всего 7 строчек, так что ищи внимательно.
Наверно нашел:
Код:
		if(TMR1IE && TMR1IF)
			{
				if(RB0==0)
					{
						spk		= 1;
					}

				TMR1IE	= 0;
				TMR1ON	= 0;

				INTE	= 1;

				TMR1IF	= 0;
			}
сейчас попробую как работать будет..
Dmitry_177 вне форума   Ответить с цитированием
Старый 04.10.2009, 18:01   #6
tester
Super Moderator
 
Аватар для tester
 
Регистрация: 28.02.2007
Возраст: 40
Сообщений: 3,577
Вес репутации: 4386/117
tester has a reputation beyond reputetester has a reputation beyond reputetester has a reputation beyond reputetester has a reputation beyond reputetester has a reputation beyond reputetester has a reputation beyond reputetester has a reputation beyond reputetester has a reputation beyond reputetester has a reputation beyond reputetester has a reputation beyond reputetester has a reputation beyond repute
По умолчанию Re: Нажатие кнопки + антидребезг (16F877, HI-TECH)

Цитата:
Сообщение от Dmitry_177 Посмотреть сообщение
А сколько обычно делают задержку на практике?
По-разному. От кнопки зависит, от условий эксплуатации.

Цитата:
Наверно нашел:
Код:
        if(TMR1IE && TMR1IF)
            {
                if(RB0==0)
                    {
                        spk        = 1;
                    }

                TMR1IE    = 0;
                TMR1ON    = 0;

                INTE    = 1;

                TMR1IF    = 0;
            }
сейчас попробую как работать будет..
Не забывай INTF сбрасывать перед установкой INTE. Пока ты держал кнопку (100 мс), из-за дребезга этот флаг сам установится еще раз (он устанавливается вне зависимости от INTE). Поэтому ты сразу же попадешь в обработчик INTE.

Кроме того, твой алгоритм не учитывает обработку дребезга по отпусканию.
tester вне форума   Ответить с цитированием
Старый 04.10.2009, 19:05   #7
Dmitry_177
Senior Member
 
Регистрация: 25.06.2009
Возраст: 32
Сообщений: 114
Вес репутации: 100/32
Dmitry_177 will become famous soon enoughDmitry_177 will become famous soon enough
По умолчанию Re: Нажатие кнопки + антидребезг (16F877, HI-TECH)

Цитата:
Не забывай INTF сбрасывать перед установкой INTE. Пока ты держал кнопку (100 мс), из-за дребезга этот флаг сам установится еще раз (он устанавливается вне зависимости от INTE). Поэтому ты сразу же попадешь в обработчик INTE.
А.. точно, нужно приучиться чтобы это было уже привычкой

Вобщем теперь все работает! Спасибо большое! Остался последний вопрос, правильно ли здесь использовать TMR1 или логичней было бы использовать другой? Или всеравно без разницы?

Цитата:
Кроме того, твой алгоритм не учитывает обработку дребезга по отпусканию.
Разве таймер на 100мс при дребезге не сработает при отпускании? А там уже не пройдет условие RB0==0.. или не так?
Dmitry_177 вне форума   Ответить с цитированием
Старый 04.10.2009, 19:33   #8
tester
Super Moderator
 
Аватар для tester
 
Регистрация: 28.02.2007
Возраст: 40
Сообщений: 3,577
Вес репутации: 4386/117
tester has a reputation beyond reputetester has a reputation beyond reputetester has a reputation beyond reputetester has a reputation beyond reputetester has a reputation beyond reputetester has a reputation beyond reputetester has a reputation beyond reputetester has a reputation beyond reputetester has a reputation beyond reputetester has a reputation beyond reputetester has a reputation beyond repute
По умолчанию Re: Нажатие кнопки + антидребезг (16F877, HI-TECH)

Цитата:
Сообщение от Dmitry_177 Посмотреть сообщение
Остался последний вопрос, правильно ли здесь использовать TMR1 или логичней было бы использовать другой? Или всеравно без разницы?
Если говорить о правильности, то вообще-то сам подход у тебя неправильный. Тут масса минусов:
1. Две помехи редко, но могут прийти с интервалом ровно в один период ожидания. Лучше опрашивать несколько раз с интервалом поменьше.
2. Нет возможности повесить 2-ю кнопку. Так что INTF - не для кнопок.
3. Одна кнопка отнимает два вектора прерываний, причем монопольно. Не жирно ли?
4. Сам таймер, получается, может работать только на кнопку. В 877-м не так много таймеров, чтобы их транжирить.
5. Не учтен шорох контакта. А зря: год проработает нормально, а потом начнутся сбои. (Это к вопросу обработки дребезга при отпускании)
6. Проблематично модифицировать программу так, чтобы получать различные состояния кнопки: короткое нажатие, длительное удерживание, только что нажата, только что отпущена.


Цитата:
Разве таймер на 100мс при дребезге не сработает при отпускании? А там уже не пройдет условие RB0==0.. или не так?
Проблемы будут не при отпускании, а при удерживании.Ты нажал кнопку и держишь, но при этом может происходить кратковременная потеря контакта между клеммами кнопки, а из-за этого будет появляться ложное прерывание, и программой это будет воспринято как повторное нажатие. В конкретной программе - это пофиг (ну продудит она не два раза, а четыре), но даже в бытовых устройствах (я уж не говорю о промышленных) - это очень плохо.
tester вне форума   Ответить с цитированием
Старый 04.10.2009, 20:33   #9
Dmitry_177
Senior Member
 
Регистрация: 25.06.2009
Возраст: 32
Сообщений: 114
Вес репутации: 100/32
Dmitry_177 will become famous soon enoughDmitry_177 will become famous soon enough
По умолчанию Re: Нажатие кнопки + антидребезг (16F877, HI-TECH)

Да уж, не все так и просто как казалось..
А у Вас есть заготовочка по которой Вы чаще всего пользуетесь? Интересно было бы взглянуть..
Dmitry_177 вне форума   Ответить с цитированием
Старый 04.10.2009, 20:49   #10
tester
Super Moderator
 
Аватар для tester
 
Регистрация: 28.02.2007
Возраст: 40
Сообщений: 3,577
Вес репутации: 4386/117
tester has a reputation beyond reputetester has a reputation beyond reputetester has a reputation beyond reputetester has a reputation beyond reputetester has a reputation beyond reputetester has a reputation beyond reputetester has a reputation beyond reputetester has a reputation beyond reputetester has a reputation beyond reputetester has a reputation beyond reputetester has a reputation beyond repute
По умолчанию Re: Нажатие кнопки + антидребезг (16F877, HI-TECH)

Цитата:
Сообщение от Dmitry_177 Посмотреть сообщение
Да уж, не все так и просто как казалось..
А у Вас есть заготовочка по которой Вы чаще всего пользуетесь? Интересно было бы взглянуть..
Сейчас только для RTOS решение под рукой, но оно громоздкое и сложное. Завтра с работы что-нибудь отошлю, там наверняка осталось что попроще.
tester вне форума   Ответить с цитированием
Старый 04.10.2009, 21:10   #11
Dmitry_177
Senior Member
 
Регистрация: 25.06.2009
Возраст: 32
Сообщений: 114
Вес репутации: 100/32
Dmitry_177 will become famous soon enoughDmitry_177 will become famous soon enough
По умолчанию Re: Нажатие кнопки + антидребезг (16F877, HI-TECH)

ОК, буду ждать
Dmitry_177 вне форума   Ответить с цитированием
Старый 04.10.2009, 21:22   #12
tester
Super Moderator
 
Аватар для tester
 
Регистрация: 28.02.2007
Возраст: 40
Сообщений: 3,577
Вес репутации: 4386/117
tester has a reputation beyond reputetester has a reputation beyond reputetester has a reputation beyond reputetester has a reputation beyond reputetester has a reputation beyond reputetester has a reputation beyond reputetester has a reputation beyond reputetester has a reputation beyond reputetester has a reputation beyond reputetester has a reputation beyond reputetester has a reputation beyond repute
По умолчанию Re: Нажатие кнопки + антидребезг (16F877, HI-TECH)

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

Для кнопки заведена переменная:
Код:
// Данные от кнопки

struct 
{
    uchar cHoldCounter;          // Счетчик для определения длительного удерживания
    uchar cJitter        : 2;    // Счетчик для подавления дребезга
    uchar bPressed       : 1;    // =1 - кнопка нажата
    uchar bHold          : 1;    // =1 - кнопка удерживается дольше секунды
    uchar bShort         : 1;    // =1 - кнопка была отпущена ранее, чем через секунду
    uchar bJustPressed   : 1;    // =1 - кнопка только что нажата (сбрасывается вручную)
} m_ButtonState;
А в прерывании с интервалом 20 мс выполняется такой код:
Код:
//------------------------------------------------------------------------------
//  Кнопка еще не нажата
//------------------------------------------------------------------------------

if (!m_ButtonState.bPressed)
{
    m_ButtonState.cJitter++;
    if (pin_BUTTON) m_ButtonState.cJitter = 0;  // Подавляем дребезг

    if (m_ButtonState.cJitter == 3)             // Перестала дребезжать
    {
        m_ButtonState.bPressed = 1;             // Нажата
        m_ButtonState.bJustPressed = 1;         // Нажата только что (сбрасывается вручную)
        m_ButtonState.bHold = 0;                // Не удерживается
        m_ButtonState.bShort = 0;               // Не короткое нажатие
        m_ButtonState.bHoldCounter = 0;
    }   // if jitter
} else {    // if button pressed

//------------------------------------------------------------------------------
//  Кнопка нажата, проверяем удерживание
//------------------------------------------------------------------------------

    m_ButtonState.cJitter++;
    if (!pin_BUTTON) m_ButtonState.cJitter = 0; // Подавляем шорох

    if (m_ButtonState.cJitter == 3)             // Кнопку только что отпустили
    {
        m_ButtonState.bPressed = 0;

        if (!m_ButtonState.bHold)               // Если не было удерживаниядольше 1 сек,
            m_ButtonState.bShort = 1;           // то установить флаг "короткого нажатия"

        m_ButtonState.bHold = 0;
        m_ButtonState.bHoldCounter = 0;

    }   // if jitter

    m_ButtonState.bHoldCounter++;

    if (m_ButtonState.bHoldCounter >= 50)       // Проверяем удерживание
        m_ButtonState.bHold = 1;

}   // if button pressed
tester вне форума   Ответить с цитированием
Старый 04.10.2009, 21:26   #13
syv
Guest
 
Сообщений: n/a
По умолчанию Re: Нажатие кнопки + антидребезг (16F877, HI-TECH)

Цитата:
Сообщение от Dmitry_177 Посмотреть сообщение
А.. точно, нужно приучиться чтобы это было уже привычкой

Вобщем теперь все работает! Спасибо большое! Остался последний вопрос, правильно ли здесь использовать TMR1 или логичней было бы использовать другой? Или всеравно без разницы?



Разве таймер на 100мс при дребезге не сработает при отпускании? А там уже не пройдет условие RB0==0.. или не так?
ПМСМ, надо опрос кнопок выделить в отдельный процесс.
На каждую кнопку заводим счетчик. В прерывании от любого из таймеров инкрементируем счетчик той кнопки, где на данный момент активный сигнал. Далее, через равные промежутки времени, опрашиваем счетчики и присваиваем значения регистру кнопок исходя из определенных критериев. В простейшем случае - это просто некое значение соответствующего счетчика.
А принятие решений в основной программе будет строится на состоянии регистра кнопок.
Меняя время между прерываниями и время опроса счетчиков можно опрашивать не только кнопки, но и реле.
  Ответить с цитированием
Старый 06.10.2009, 01:23   #14
Dmitry_177
Senior Member
 
Регистрация: 25.06.2009
Возраст: 32
Сообщений: 114
Вес репутации: 100/32
Dmitry_177 will become famous soon enoughDmitry_177 will become famous soon enough
По умолчанию Re: Нажатие кнопки + антидребезг (16F877, HI-TECH)

Спасибо! Посижу поразбираюсь.. Интересно очень!

А вот еще такой вопросик, тоже очень интересно.. У меня в прерывании TMR1 устанавливается флаг spk, а в главном цикле, в функции main, он каждый раз проверяется, но он не проверится еще раз пока пищалка не пикнет два раза.. А еслиб там было какое-то более долговременное действие? Или вообще долговременное действие которое выполняется постоянно в цикле? Тогда получается пока все это не проработает, пока заново цикл не начнется, только тогда опять проверится.. Так вот можно ли как-то сделать чтобы по нажатию кнопки все нужные действия по нажатию кнопки сразу происходили, т.е. этот цикл как бы прерывался как только сработала кнопка?
Dmitry_177 вне форума   Ответить с цитированием
Старый 06.10.2009, 01:36   #15
tester
Super Moderator
 
Аватар для tester
 
Регистрация: 28.02.2007
Возраст: 40
Сообщений: 3,577
Вес репутации: 4386/117
tester has a reputation beyond reputetester has a reputation beyond reputetester has a reputation beyond reputetester has a reputation beyond reputetester has a reputation beyond reputetester has a reputation beyond reputetester has a reputation beyond reputetester has a reputation beyond reputetester has a reputation beyond reputetester has a reputation beyond reputetester has a reputation beyond repute
По умолчанию Re: Нажатие кнопки + антидребезг (16F877, HI-TECH)

Цитата:
Сообщение от Dmitry_177 Посмотреть сообщение
А вот еще такой вопросик, тоже очень интересно.. У меня в прерывании TMR1 устанавливается флаг spk, а в главном цикле, в функции main, он каждый раз проверяется, но он не проверится еще раз пока пищалка не пикнет два раза.. А еслиб там было какое-то более долговременное действие? Или вообще долговременное действие которое выполняется постоянно в цикле? Тогда получается пока все это не проработает, пока заново цикл не начнется, только тогда опять проверится.. Так вот можно ли как-то сделать чтобы по нажатию кнопки все нужные действия по нажатию кнопки сразу происходили, т.е. этот цикл как бы прерывался как только сработала кнопка?
Ты говоришь о многозадачности. Тут тебя спасет либо обработка кнопки в прерывании (если она длится не более нескольких десятков тактов), либо ОСРВ
tester вне форума   Ответить с цитированием
Старый 06.10.2009, 11:18   #16
Dmitry_177
Senior Member
 
Регистрация: 25.06.2009
Возраст: 32
Сообщений: 114
Вес репутации: 100/32
Dmitry_177 will become famous soon enoughDmitry_177 will become famous soon enough
По умолчанию Re: Нажатие кнопки + антидребезг (16F877, HI-TECH)

RTOS?
Dmitry_177 вне форума   Ответить с цитированием
Старый 06.10.2009, 13:16   #17
tester
Super Moderator
 
Аватар для tester
 
Регистрация: 28.02.2007
Возраст: 40
Сообщений: 3,577
Вес репутации: 4386/117
tester has a reputation beyond reputetester has a reputation beyond reputetester has a reputation beyond reputetester has a reputation beyond reputetester has a reputation beyond reputetester has a reputation beyond reputetester has a reputation beyond reputetester has a reputation beyond reputetester has a reputation beyond reputetester has a reputation beyond reputetester has a reputation beyond repute
По умолчанию Re: Нажатие кнопки + антидребезг (16F877, HI-TECH)

Цитата:
Сообщение от Dmitry_177 Посмотреть сообщение
RTOS?
RTOS, RTOS...
tester вне форума   Ответить с цитированием
Старый 06.10.2009, 15:13   #18
petrd
Senior Member
 
Регистрация: 09.02.2008
Адрес: Воронеж
Возраст: 45
Сообщений: 1,643
Вес репутации: 1486/65
petrd has much to be proud ofpetrd has much to be proud ofpetrd has much to be proud ofpetrd has much to be proud ofpetrd has much to be proud ofpetrd has much to be proud ofpetrd has much to be proud ofpetrd has much to be proud ofpetrd has much to be proud ofpetrd has much to be proud of
Отправить сообщение для petrd с помощью ICQ
По умолчанию Re: Нажатие кнопки + антидребезг (16F877, HI-TECH)

Цитата:
Сообщение от tester Посмотреть сообщение
Дома нашел только для одной кнопки. Не самый удачный подход, но для одной кнопки - самое то. (Я его немного порезал, там было еще определение того, как долго кнопка удерживается).
Ё-моё! Виктор, если ЭТО не самый удачный подход, покажите, пожалуйста, более удачный. А если лень копаться, то хотя бы в двух словах поясните Ваши подходы к обработке кнопок. Спасибо!
__________________
License MikroC, MikroC PRO and EasyPIC5 by mikroElektronika (the dead mikroICD replaced PICKit2 & PICKit3)
petrd вне форума   Ответить с цитированием
Старый 06.10.2009, 15:32   #19
tester
Super Moderator
 
Аватар для tester
 
Регистрация: 28.02.2007
Возраст: 40
Сообщений: 3,577
Вес репутации: 4386/117
tester has a reputation beyond reputetester has a reputation beyond reputetester has a reputation beyond reputetester has a reputation beyond reputetester has a reputation beyond reputetester has a reputation beyond reputetester has a reputation beyond reputetester has a reputation beyond reputetester has a reputation beyond reputetester has a reputation beyond reputetester has a reputation beyond repute
По умолчанию Re: Нажатие кнопки + антидребезг (16F877, HI-TECH)

Цитата:
Сообщение от petrd Посмотреть сообщение
Ё-моё! Виктор, если ЭТО не самый удачный подход, покажите, пожалуйста, более удачный. А если лень копаться, то хотя бы в двух словах поясните Ваши подходы к обработке кнопок. Спасибо!
Подход не самый удачный, потому что исключает возможность простого добавления еще одной кнопки (добавив вторую кнопку, мы увеличим расходы ресурсов в два раза). Я обычно пользуюсь такой схемой: есть несколько переменных, каждая из которых является маской какого-то состояния:
- нажата/отпущена,
- только что нажата,
- только что отпущена,
- удерживается дольше секунды,
- отпущена раньше чем через секунду.

Такой подход позволяет отследить практически любую комбинацию, например, короткое нажатие кнопки 2 во время удерживания кнопок 1 и 5. Я нашел этот кусок кода, просто его подчистить надо (неаккуратно написан, туда подмешан основной алгоритм программы). Если интересно, потом выложу, как освобожусь. При преимуществе такого подхода в виде универсальности есть и недостатки:
- требует 8 байт ресурсов;
- подавление дребезга - одно на всех. Т.е. если на каком-то контакте постоянный шум, то кнопки не будут работать.

По подавлению дребезга будет интересно ознакомиться с этой ссылкой: http://www.piclist.com/techref/micro...glek8hlc18.htm
Преимущества такого подхода - дребезг подавляется отдельно для каждой кнопки, как следствие недостаток - требуется больше ресурсов RAM для самих вертикальных счетчиков (в количество раз = количеству кнопок).

Последний раз редактировалось tester; 06.10.2009 в 15:40. Причина: синтаксис
tester вне форума   Ответить с цитированием
Старый 06.10.2009, 16:17   #20
petrd
Senior Member
 
Регистрация: 09.02.2008
Адрес: Воронеж
Возраст: 45
Сообщений: 1,643
Вес репутации: 1486/65
petrd has much to be proud ofpetrd has much to be proud ofpetrd has much to be proud ofpetrd has much to be proud ofpetrd has much to be proud ofpetrd has much to be proud ofpetrd has much to be proud ofpetrd has much to be proud ofpetrd has much to be proud ofpetrd has much to be proud of
Отправить сообщение для petrd с помощью ICQ
По умолчанию Re: Нажатие кнопки + антидребезг (16F877, HI-TECH)

Спасибо большое! Будет возможность, не сочтите за труд, покажите код.
__________________
License MikroC, MikroC PRO and EasyPIC5 by mikroElektronika (the dead mikroICD replaced PICKit2 & PICKit3)
petrd вне форума   Ответить с цитированием
Старый 06.10.2009, 17:01   #21
masterzx
Senior Member
 
Аватар для masterzx
 
Регистрация: 21.09.2007
Адрес: Барнаул
Возраст: 31
Сообщений: 1,475
Вес репутации: 826/59
masterzx is a splendid one to beholdmasterzx is a splendid one to beholdmasterzx is a splendid one to beholdmasterzx is a splendid one to beholdmasterzx is a splendid one to beholdmasterzx is a splendid one to beholdmasterzx is a splendid one to behold
Отправить сообщение для masterzx с помощью ICQ
По умолчанию Re: Нажатие кнопки + антидребезг (16F877, HI-TECH)

Я код под microC приводил
__________________
Если проблему можно решить за деньги, то это не проблема, это расходы. Еврейская мудрость.
masterzx вне форума   Ответить с цитированием
Старый 06.10.2009, 20:41   #22
tester
Super Moderator
 
Аватар для tester
 
Регистрация: 28.02.2007
Возраст: 40
Сообщений: 3,577
Вес репутации: 4386/117
tester has a reputation beyond reputetester has a reputation beyond reputetester has a reputation beyond reputetester has a reputation beyond reputetester has a reputation beyond reputetester has a reputation beyond reputetester has a reputation beyond reputetester has a reputation beyond reputetester has a reputation beyond reputetester has a reputation beyond reputetester has a reputation beyond repute
По умолчанию Re: Нажатие кнопки + антидребезг (16F877, HI-TECH)

Цитата:
Сообщение от petrd Посмотреть сообщение
Спасибо большое! Будет возможность, не сочтите за труд, покажите код.
В общем, запарился я разбираться с этой функцией, никак не отделить мух от котлет (плохо и неаккуратно я ее написал, но, собственно, давно и не пользуюсь ей). Так что приведу пример RTOS'овской обработки, которой сейчас пользуюсь. По ссылке внизу полная версия файла для RTOS с возможностью всяких настроек.

Для наглядности немного порезал этот код (он стал универсальным без настроек). Функция вызывается раз в 20 мс. Следует отметить, что макси JustPressed, JustReleased, Short и Changed - это события, а не состояния, и их нужно обнулять вручную после обработки.

Код:
// Можно задать до 8 кнопок

#define pin_BUTTON0     RB0
#define pin_BUTTON1     RB1
#define pin_BUTTON2     RB2
#define pin_BUTTON3     RB3
#define pin_BUTTON4     RB4
#define pin_BUTTON5     RB5
#define pin_BUTTON6     RB6
#define pin_BUTTON7     RB7


typedef struct
{
    unsigned char   ucPressed;            // Состояния кнопок
    unsigned char   ucJitter    : 2;      // Для подавления дребезга
    unsigned char   ucCounter   : 6;      // Для проверки удерживания
    unsigned char   ucHold;               // Состояние длительного удерживания
                                          // События:
    unsigned char   ucShort;              // Короткое нажатие и отпускание
    unsigned char   ucJustPressed;        // Кнопки только что нажаты
    unsigned char   ucJustReleased;       // Кнопки только что отпущены
    unsigned char   ucChanged;            // Состояние кнопок изменилось

} TBUTTONS;

volatile TBUTTONS    m_Buttons;


void Task_Buttons (void)
{
    static  unsigned char s_ucPort;     // Предыдущее состояние портов
            unsigned char ucTemp;       

    ucTemp = 0x00;

    if (!pin_BUTTON0) ucTemp |= 0x01;
    if (!pin_BUTTON1) ucTemp |= 0x02;
    if (!pin_BUTTON2) ucTemp |= 0x04;
    if (!pin_BUTTON3) ucTemp |= 0x08;
    if (!pin_BUTTON4) ucTemp |= 0x10;
    if (!pin_BUTTON5) ucTemp |= 0x20;
    if (!pin_BUTTON6) ucTemp |= 0x40;
    if (!pin_BUTTON7) ucTemp |= 0x80;

    ucTemp      ^= s_ucPort;            // Изменения с момента последнего выполнения
    s_ucPort    ^= ucTemp;              // Текущее состояние портов

    if (ucTemp)                         // Подавление дребезга
    {
        m_Buttons.ucJitter = 0;
        return;
    }
    //------------------------------------------------------------------------------
    
    m_Buttons.ucJitter++;
    ucTemp = s_ucPort ^ m_Buttons.ucPressed;// Маска изменения состояние

    if (!m_Buttons.ucJitter && ucTemp)      // Состояние изменилось, дребезг подавлен
    {
        //------------------------------------------------------------------------------
        //  Проверяем отпущенные кнопки
        //------------------------------------------------------------------------------
        
        if (m_Buttons.ucPressed & ucTemp)   // Есть отпущенные
        {
            m_Buttons.ucJustReleased    |=  ucTemp;
            m_Buttons.ucChanged         |=  ucTemp;
            m_Buttons.ucShort           |=  ucTemp;
            m_Buttons.ucShort           &= ~m_Buttons.ucHold;
            m_Buttons.ucHold            &= ~ucTemp;
        }   // if released
        //------------------------------------------------------------------------------
        //  Проверяем нажатые кнопки
        //------------------------------------------------------------------------------
        if ((m_Buttons.ucPressed ^ ucTemp) & ucTemp)    // Есть нажатые
        {
            m_Buttons.ucChanged         |=  ucTemp;
            m_Buttons.ucJustPressed     |=  ucTemp;
            m_Buttons.ucShort           &= ~ucTemp;
        }   // if pressed

        m_Buttons.ucPressed = s_ucPort;
        m_Buttons.ucCounter = 0;
    }   // if changed and debounced

    m_Buttons.ucCounter++;
    //------------------------------------------------------------------------------
    //  Проверяем длительное удерживание
    //------------------------------------------------------------------------------
    
    if (m_Buttons.ucCounter == 50)
    {
        m_Buttons.ucChanged |= m_Buttons.ucHold ^ m_Buttons.ucPressed;
        m_Buttons.ucHold = m_Buttons.ucPressed;
    }

}
Результат работы - переменная структура с именем m_Buttons, по полям которой можно определять:
- какие кнокпи нажаты;
- какие нажаты и удерживаются;
- короткое нажатие кнопки;
- короткое нажатие кнопки при удерживании другой (или других);
- состояние каких кнопок изменилось (и как) с последней проверки;
- и т.д.

А по ссылке - полная версия для RTOS. Чтобы использовать без RTOS, нужно убрать из Task_Buttons() вечный цикл и вызов OS_Delay(), а саму функцию вызывать с нужным периодом (например, раз в 20 мс).

Последний раз редактировалось vitalka; 04.08.2010 в 16:48.
tester вне форума   Ответить с цитированием
Старый 06.10.2009, 21:49   #23
master19
Senior Member
 
Регистрация: 22.01.2008
Возраст: 39
Сообщений: 237
Вес репутации: 162/39
master19 has a spectacular aura aboutmaster19 has a spectacular aura about
По умолчанию Re: Нажатие кнопки + антидребезг (16F877, HI-TECH)

Цитата:
Сообщение от tester Посмотреть сообщение
Так что приведу пример RTOS'овской обработки, которой сейчас пользуюсь.
постоянно в работе всплывает эта тема, пока так и не придумал формализованного универсального описания. В принципе Ваш алгоритм близок к идеалу, но есть один серьезный недостаток - если кнопок больше 16? или если это не кнопки, а сигналы с датчиков, которых может быть больше 32 или 64? конечно не у всех такие задачи. в общем для большого кол-ва сигналов масками пользоваться не получается
master19 вне форума   Ответить с цитированием
Старый 06.10.2009, 23:08   #24
tester
Super Moderator
 
Аватар для tester
 
Регистрация: 28.02.2007
Возраст: 40
Сообщений: 3,577
Вес репутации: 4386/117
tester has a reputation beyond reputetester has a reputation beyond reputetester has a reputation beyond reputetester has a reputation beyond reputetester has a reputation beyond reputetester has a reputation beyond reputetester has a reputation beyond reputetester has a reputation beyond reputetester has a reputation beyond reputetester has a reputation beyond reputetester has a reputation beyond repute
По умолчанию Re: Нажатие кнопки + антидребезг (16F877, HI-TECH)

Цитата:
Сообщение от master19 Посмотреть сообщение
постоянно в работе всплывает эта тема, пока так и не придумал формализованного универсального описания. В принципе Ваш алгоритм близок к идеалу, но есть один серьезный недостаток - если кнопок больше 16? или если это не кнопки, а сигналы с датчиков, которых может быть больше 32 или 64?
Это не недостаток, а область применения. Для большего, чем 8, количества кнопок такой подход не совсем удачный. Когда кнопок больше 8, уже целесообразно пользоваться матричной клавиатурой.

Цитата:
конечно не у всех такие задачи. в общем для большого кол-ва сигналов масками пользоваться не получается
А чем же еще пользоваться? Надо же где-то хранить текущее состояние и пр. Так что без масок не обойтись, просто они будут не в виде unsigned char'ов, а в виде массивов unsigned char'ов. В своем пианино я применял такой подход. Да и не все же виды состояний нужны, т.е. не нужно заводить массивы для состояний длительного удерживания, момента срабатывания и пр. (кстати, в моем примере buttons.c директивами условной компиляции все ненужное можно исключить).
tester вне форума   Ответить с цитированием
Старый 06.10.2009, 23:30   #25
DL36
Senior Member
 
Регистрация: 25.02.2007
Адрес: Херсон
Сообщений: 3,642
Вес репутации: 1983/94
DL36 has a brilliant futureDL36 has a brilliant futureDL36 has a brilliant futureDL36 has a brilliant futureDL36 has a brilliant futureDL36 has a brilliant futureDL36 has a brilliant futureDL36 has a brilliant futureDL36 has a brilliant futureDL36 has a brilliant futureDL36 has a brilliant future
По умолчанию Re: Нажатие кнопки + антидребезг (16F877, HI-TECH)

Цитата:
Сообщение от master19 Посмотреть сообщение
постоянно в работе всплывает эта тема, пока так и не придумал формализованного универсального описания. В принципе Ваш алгоритм близок к идеалу, но есть один серьезный недостаток - если кнопок больше 16? или если это не кнопки, а сигналы с датчиков, которых может быть больше 32 или 64? конечно не у всех такие задачи. в общем для большого кол-ва сигналов масками пользоваться не получается
Подход правильный, с моей колокольни, я тоже использую подобный принцип для датчиков,
Код:
typedef struct          //
  {   
    unsigned blink        : 1;// 
    unsigned bSound       : 1;// 
    unsigned bCabelTest   : 1;//  
    unsigned trigger      : 1;// 
    unsigned bCanal       : 1;// 
    unsigned invert       : 1;//                         
    unsigned bKwit        : 1;// 
    unsigned control      : 1;// 
//---------------------------------
    unsigned char delay     ;// 
    unsigned char preDelay  ;//  
    unsigned char freqBlink ;//  
    void (*service)(void); 
}
Обработчик похож, вызываю через 50 ms.
DL36 вне форума   Ответить с цитированием
Ответ

Метки
антидребезг, кнопка


Здесь присутствуют: 1 (пользователей: 0 , гостей: 1)
 
Опции темы
Опции просмотра

Ваши права в разделе
Вы не можете создавать новые темы
Вы не можете отвечать в темах
Вы не можете прикреплять вложения
Вы не можете редактировать свои сообщения

BB коды Вкл.
Смайлы Вкл.
[IMG] код Вкл.
HTML код Выкл.

Быстрый переход

Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Нет реакции на нажатие кнопки, pic12f629 Autotronic Вопросы начинающих 20 04.03.2009 05:27
нажатие кнопки на телефоне(модем Sim300) war Общетехнические вопросы 1 31.03.2007 21:50


Часовой пояс GMT +3, время: 09:10.


Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2017, Jelsoft Enterprises Ltd. Перевод: zCarot