Страница 1 из 3
Почему не работает опрос кнопки?
Добавлено: Пт июн 10, 2016 09:35:35
Billi34
Я начинающий в этой области, с большим прошлым по простой электронике. Написал прогу для Меги16. Сбственно программа-то работает, хочется чтоб она запускалась по событию (нажатие кнопки- единица на PINB.3) "Этого как раз и не происходит (запуск).Работаю в CV первое что попалось в инете. Прошу не сильно пинать. Помогите понять причину ну или подправьте код. Подтяжка к VCC реализована внешне. На 4 ноге МЕГи 1\0 переключается, а программа не выходит из строки IF. Код IF.... взят из другого кода. Хотел написать в ветке "CV вопросы и ответы" а получилось здесь. Просьба к модераторам перенести в соотв. тему. Практика уже есть-несколько устройств уже собрал (АТмега8, АТмега 16), но нигде не получилось "увидеть " кнопку.
Re: Почему не работает опрос кнопки?
Добавлено: Пт июн 10, 2016 10:13:31
Morroc
Если вы хотите "быстро мигать" - уберите для начала весь остальной код, а то может оно и работает, но вы ждете чего то другого. Кнопку долго держали нажатой ? А то там у вас задержки нехилые, в момент которых кнопка, конечно, ничего не делает.
Re: Почему не работает опрос кнопки?
Добавлено: Пт июн 10, 2016 10:17:07
Billi34
Нет, нет! Смысл как раз в остальном коде. Мигать это, так сказать, для визуализации где "застряла" прога. Держал долго по 2-5 секунд. А про какие задержки вы говорите?
Re: Почему не работает опрос кнопки?
Добавлено: Пт июн 10, 2016 10:18:31
Morroc
Вот и убедитесь, что мигалка работает сама по себе

Re: Почему не работает опрос кнопки?
Добавлено: Пт июн 10, 2016 10:24:38
Billi34
Как сделать постоянный опрос кнопки и запуск по изменению состояния? Этот код я взял из примера. Там как раз описывалось нужное мне поведение, а не заработало. Скорее всего в примере нужено пере-включение (сброс) для прохода этого условия. А нет нажатия и прога будет здесь крутиться.
Re: Почему не работает опрос кнопки?
Добавлено: Пт июн 10, 2016 10:25:47
Vov123
Re: Почему не работает опрос кнопки?
Добавлено: Пт июн 10, 2016 10:37:46
Billi34
Книга качается.
while(PINB.3==0)
{
} \\ видимо так, опрос будет в цикле, По изменению состояния -выход
Re: Почему не работает опрос кнопки?
Добавлено: Пт июн 10, 2016 10:42:09
Morroc
да и ваш вариант вроде тоже должен работать, попробуйте кнопку подержать нажатой секунды 3
ищите пример сразу с антидребезгом, варианты без него в реальности работают черте как
Re: Почему не работает опрос кнопки?
Добавлено: Пт июн 10, 2016 11:09:31
Billi34
Нифига. Не выходит из условия.
Re: Почему не работает опрос кнопки?
Добавлено: Пт июн 10, 2016 11:14:13
Morroc
Ну выходить он у вас и не должен, входить и мигать должен

Re: Почему не работает опрос кнопки?
Добавлено: Пт июн 10, 2016 11:23:13
Billi34
Код заработал.
while(1)
{
while(PINB.3==1)
{
}
/////////////здесь код
}
Я и раньше так пробовал, но почему-то не работало.
Спасибо, за участие.
Прошу модератора перенести мою тему в раздел о CV. Все должно быть на месте.
Re: Почему не работает опрос кнопки?
Добавлено: Пт июн 10, 2016 11:34:29
Morroc
Бесконечные циклы так себе идея.
Re: Почему не работает опрос кнопки?
Добавлено: Пт июн 17, 2016 10:18:58
watchmaker
Если нужна мгновенная реакция на кнопку - тут без внешнего интеррапта не обойтись.
Re: Почему не работает опрос кнопки?
Добавлено: Сб июн 18, 2016 02:33:49
Demiurg
watchmaker писал(а):...
Что за мода вешать кнопки на внешнее прерывание? Сам интерфейс человек-кнопка очень медленный для МК. Плюс обработка антидребезга. Время на подавление дребезга от 20 мс. Сам собой напрашивается вопрос, на куа вешать кнопки на внешнее прерывание? Да и вообще "мгновенно" реагировать на нажатие? Смысл?
Re: Почему не работает опрос кнопки?
Добавлено: Сб июн 18, 2016 15:40:55
Alkul
Demiurg писал(а):Что за мода вешать кнопки на внешнее прерывание?
В общем случае Вы правы. Но если делать опрос не через внешнее прерывание, то в программе нужно реализовать механизм, когда по периодическому срабатыванию таймера выполняются какие-то действия - проверки состояния регистров и тому подобное. В этом случае, как говорится, сам бог велел тут же делать и опрос кнопок. Если же такого механизма в программе по какой-то причине не предусмотрено, то вариант опроса по прерыванию вполне имеет место быть.
По сути - чем плох опрос кнопок по прерыванию? Это может создать проблему только если внешние прерывания нужны для чего-то другого. А если они не используются ни для каких задач - почему б не "повесить" на них кнопки?
Конечно, есть еще третий вариант - опрашивать кнопки в бесконечном цикле только в те моменты, когда программа ожидает
обязательного нажатия на какую-то из них, если при этом в программе есть только такой опрос кнопок - не постоянно, а в некоторые моменты.
Словом, вариантов опроса может быть много. И лучшего или худшего тут нет - все зависит от логики программы. Выбор же, как всегда, за программистом.
А совет в выборе способа опроса можно дать, если вопрос задан не отвлеченно - "как опросить кнопку", а вот так - "Логика работы программы такая-то, кнопки нужно опрашивать в такие-то моменты, свободные выводы контроллера такие-то. Как лучше реализовать?"
Re: Почему не работает опрос кнопки?
Добавлено: Сб июн 18, 2016 20:02:19
COKPOWEHEU
Помимо таймера, можно проверять в бесконечном цикле, особенно хорошо если время каждого цикла более-менее одинаково.
Если вешать на прерывание, может возникнуть проблема с дребезгом.
Ну и в зависимости от алгоритма использование прерывания может быть наиболее удачным вариантом (пульт от телевизора, например).
Re: Почему не работает опрос кнопки?
Добавлено: Сб июн 18, 2016 20:34:21
Alkul
COKPOWEHEU писал(а):Если вешать на прерывание, может возникнуть проблема с дребезгом.
Я делал опрос через прерывание. Никаких проблем с дребезгом не возникало.
Реализовывал так: в программе через каждые 2мс вызывался обработчик прерывания таймера, который управлял динамической индикацией на 2 семисегментных индикатора. На этот же обработчик было "подвешено еще несколько функций и среди них - "антидребезговая" функция.
При нажатии на кнопку в обработчике внешнего прерывания первым делом запрещалось прерывание для этой кнопки, инициализировался счетчик, равный количеству 2-х миллисекундных "тиков" антидребезговой задержки, после чего выполнялся программный код собственно действия по нажатию этой кнопки и делался выход из обработчика.
Упомянутый выше счетчик антидребезговой задержки у меня был равен 0xB4 (180D), что при умножении на 0,002 давало 0,36 секунд задержки. В обработчике прерывания таймера каждые 2 мс этот счетчик декрементировался, при достижении нуля прерывание для данной кнопки снова разрешалось.
Таким образом, проблема дребезга решалась довольно просто и надежно. При удержании кнопки в нажатом состоянии действие, выполняемое при нажатии, повторялось каждые 0,36 с. Если подробнее, то там был параметр, изменяющийся от 0 до 99 и две кнопки - одна младший разряд, другая - старший. При нажатии на кнопку соответствующий разряд инкрементировался, при достижении максимального значения 9 следующее значение, соответственно, было 0 и так по циклу. Т.е., в наихудшем случае (например, при переходе от 22 к 11) для изменения параметра требовалось 18 нажатий - 9 на кнопку младшего разряда и 9 - на кнопку старшего разряда.
Re: Почему не работает опрос кнопки?
Добавлено: Вс июн 19, 2016 06:37:44
Demiurg
Цикл
статей Татарчевского. В 8 части про опрос клавиатуры.
Спойлер
Код: Выделить всё
//==================
#include "kbd_drv.h"
//==================
//==================
static u08 keys_prev;
static u08 keys_curr;
static u08 keys_buf;
//==================
//==================
void scan_keys (void)
{
/*
keys_curr = 0;
if (Set_Is_Key_Esc_Pressed ()) keys_curr |= KEY_ESC_BIT;
if (Set_Is_Key_Enter_Pressed ()) keys_curr |= KEY_ENTER_BIT;
if (Set_Is_Key_Prev_Pressed ()) keys_curr |= KEY_PREV_BIT;
if (Set_Is_Key_Next_Pressed ()) keys_curr |= KEY_NEXT_BIT;
if (Set_Is_Key_Minus_Pressed ()) keys_curr |= KEY_MINUS_BIT;
if (Set_Is_Key_Plus_Pressed ()) keys_curr |= KEY_PLUS_BIT;
*/
// Можно и сразу работать с keys_curr, но при таком подходе
// экономится объем кода. Нет лишних команд lds, sts.
u08 a = 0;
if (Set_Is_Key_Esc_Pressed ()) a |= KEY_ESC_BIT;
if (Set_Is_Key_Enter_Pressed ()) a |= KEY_ENTER_BIT;
if (Set_Is_Key_Prev_Pressed ()) a |= KEY_PREV_BIT;
if (Set_Is_Key_Next_Pressed ()) a |= KEY_NEXT_BIT;
if (Set_Is_Key_Minus_Pressed ()) a |= KEY_MINUS_BIT;
if (Set_Is_Key_Plus_Pressed ()) a |= KEY_PLUS_BIT;
keys_curr = a; // Единственная команда sts в этой строке.
// Экономия в коде при максимальной оптимизации 44 байта.
}
//------------------------------------------------------------------------
struct tab_key_cod __flash tab_kbd_drv_keys_cod [] =
{
{KEY_ESC_BIT, KEY_ESC_COD},
{KEY_ENTER_BIT, KEY_ENTER_COD},
{KEY_PREV_BIT, KEY_PREV_COD},
{KEY_NEXT_BIT, KEY_NEXT_COD},
{KEY_MINUS_BIT, KEY_MINUS_COD},
{KEY_PLUS_BIT, KEY_PLUS_COD},
{0xFF, 0xFF},
};
//==================
//==================
void kbd_drv (void)
{
static u08 _kbd_drv;
static soft_timer ST_KBD;
scan_keys ();
switch (_kbd_drv)
{
case KBD_DRV_INIT:
keys_prev = 0xFF;
_kbd_drv = KBD_DRV_NONE;
break;
case KBD_DRV_NONE:
if (keys_curr)
{
keys_prev = keys_curr;
set_soft_timer (ST_KBD, DEBOUNCE_DELAY, 0);
_kbd_drv = KBD_DRV_DOWN;
}
break;
case KBD_DRV_DOWN:
if (handle_soft_timer (ST_KBD))
{
if (keys_curr && keys_prev == keys_curr)
{
if (define_key_cod (keys_curr, keys_buf, tab_kbd_drv_keys_cod))
Set_Event (EV_ID_KEY_PRESSED);
set_soft_timer (ST_KBD, HOLD_DELAY, REPEAT_DELAY);
_kbd_drv = KBD_DRV_HOLD; // KBD_DRV_WAIT_UP;
}
else
_kbd_drv = KBD_DRV_NONE;
}
break;
case KBD_DRV_HOLD:
case KBD_DRV_REPEAT:
if (!(keys_curr))
{
_kbd_drv = KBD_DRV_WAIT_UP;
return;
}
if (keys_prev != keys_curr)
{
_kbd_drv = KBD_DRV_NONE;
return;
}
if (handle_soft_timer (ST_KBD))
{
if (define_key_cod (keys_curr, keys_buf, tab_kbd_drv_keys_cod))
Set_Event (EV_ID_KEY_PRESSED);
_kbd_drv = KBD_DRV_REPEAT;
}
break;
case KBD_DRV_WAIT_UP:
if (!(keys_curr))
{
set_soft_timer (ST_KBD, DEBOUNCE_DELAY, 0);
_kbd_drv = KBD_DRV_UP;
}
break;
case KBD_DRV_UP:
if (handle_soft_timer (ST_KBD))
{
if (!(keys_curr))
{
_kbd_drv = KBD_DRV_NONE;
Set_Event (EV_ID_KEY_UNPRESSED);
}
else
_kbd_drv = KBD_DRV_WAIT_UP;
}
break;
default:
break;
}
}
//==================
//==================
u08 GetKeyCode (void)
{
return keys_buf;
}
void SetKeyCod (u08 key)
{
keys_buf = key;
}
//==================
Re: Почему не работает опрос кнопки?
Добавлено: Вс июн 26, 2016 23:00:58
Billi34
Alkul писал(а):
А совет в выборе способа опроса можно дать, если вопрос задан не отвлеченно - "как опросить кнопку", а вот так - "Логика работы программы такая-то, кнопки нужно опрашивать в такие-то моменты, свободные выводы контроллера такие-то. Как лучше реализовать?"
Воспользуюсь советом уважаемого Alkul. Логика работы такая: проэкт указателя направления на перекрёстке. Сдвиг тактируется внешним сигналом на PIN.3 Мною был задан вопрос по опросу кнопки по причине не возможности смоделировать реальные условия работы устройства. По этому тактирующий сигнал был заменён кнопкой. Есть ещё одна ситуация : Приход нуля на PIN.4 запрещает сдвиг и вызывает повторение тактирующего сигнала всей полосой указателя (запрет движения). Тактирующий сигнал меандр 70 имп. в минуту. Сейчас загружу текст моих попыток. Хочется изящного решения, но к сожалению есть опыт извращённых решений . От анти дребезга я позже попробую избавиться. Что-то подсказывает что там нет дребезга. Ещё момент: тактирующий сигнал может исчезнуть в середине текста программы (после любого сдвига "стрелки" третьего, десятого ,двадцатого ) Для этого после каждого сдвига указателя прога снова проверяет PIN.3. Я позже ещё нарисую 2, 3 десятка "сдвигов". НО ход прогр. остановится до прихода нового PIN.3. А каждое новое указание надо-бы начать со строба( for(s=1;s<15;s++)
{
PORTB=0b00,PORTD=0b00000000,PORTC=0b00000000,PORTA=0b00000001,delay_ms(20) ;
PORTB=0b11,PORTD=0b11111111,PORTC=0b11111111,PORTA=0b11111111,delay_ms(50) ;
}
То есть через небольшое время застоя возвращать текущий момент программы на первую строчку if (PINB.4==0,PINB.3==1)
Я пробовал оператор GO TO M1 но CV ругается на неизвестный синтаксис. Может какую библ. подгрузить?
if (PINB.4==0,PINB.3==1) \\Здесь проверяются 2 условия, каким образом зациклить программу на этом месте (я хотел попробовать GO TO, но не срослось) пока есть единица на PIN.3 (меандр) и ноль на PIN.4 (запрет движения) ногах?
В принципе можно и не "циклить". После каждого "сдвига" стрелки проверять снова if (PINB.4==0,PINB.3==1) ДА-зажигаем всю стрелку, НЕТ-сдвиг . В голове каша, что-то не допонимаю.
Re: Почему не работает опрос кнопки?
Добавлено: Пн июн 27, 2016 04:00:24
Demiurg
Billi34 писал(а):В голове каша, что-то не допонимаю.
Действительно каша. Лично я ничего не понял. Соберитесь с мыслями и грамотно распишите ТЗ. Не надо вашего псевдоязыка. Простыми русскими словами. Четко и ясно.