Почему не работает опрос кнопки?

Обсуждаем контроллеры компании Atmel.
Ответить
Открыл глаза
Аватара пользователя
Сообщения: 64
Зарегистрирован: Чт июн 09, 2016 18:24:41

Сообщение Billi34 »

Я начинающий в этой области, с большим прошлым по простой электронике. Написал прогу для Меги16. Сбственно программа-то работает, хочется чтоб она запускалась по событию (нажатие кнопки- единица на PINB.3) "Этого как раз и не происходит (запуск).Работаю в CV первое что попалось в инете. Прошу не сильно пинать. Помогите понять причину ну или подправьте код. Подтяжка к VCC реализована внешне. На 4 ноге МЕГи 1\0 переключается, а программа не выходит из строки IF. Код IF.... взят из другого кода. Хотел написать в ветке "CV вопросы и ответы" а получилось здесь. Просьба к модераторам перенести в соотв. тему. Практика уже есть-несколько устройств уже собрал (АТмега8, АТмега 16), но нигде не получилось "увидеть " кнопку.
Вложения
16 мега для китая.txt
(8.3 КБ) 252 скачивания
Реклама
Друг Кота
Сообщения: 19495
Зарегистрирован: Чт фев 20, 2014 18:57:55

Сообщение Morroc »

Если вы хотите "быстро мигать" - уберите для начала весь остальной код, а то может оно и работает, но вы ждете чего то другого. Кнопку долго держали нажатой ? А то там у вас задержки нехилые, в момент которых кнопка, конечно, ничего не делает.
Последний раз редактировалось Morroc Пт июн 10, 2016 10:17:25, всего редактировалось 1 раз.
"Вся военная пропаганда, все крики, ложь и ненависть исходят от людей, которые на эту войну не пойдут !" / Джордж Оруэлл /
"Война - это,когда за интересы других,гибнут совершенно безвинные люди." / Уинстон Черчилль /
Реклама
Открыл глаза
Аватара пользователя
Сообщения: 64
Зарегистрирован: Чт июн 09, 2016 18:24:41

Сообщение Billi34 »

Нет, нет! Смысл как раз в остальном коде. Мигать это, так сказать, для визуализации где "застряла" прога. Держал долго по 2-5 секунд. А про какие задержки вы говорите?
Последний раз редактировалось Billi34 Пт июн 10, 2016 10:19:23, всего редактировалось 1 раз.
Друг Кота
Сообщения: 19495
Зарегистрирован: Чт фев 20, 2014 18:57:55

Сообщение Morroc »

Вот и убедитесь, что мигалка работает сама по себе :))
"Вся военная пропаганда, все крики, ложь и ненависть исходят от людей, которые на эту войну не пойдут !" / Джордж Оруэлл /
"Война - это,когда за интересы других,гибнут совершенно безвинные люди." / Уинстон Черчилль /
Реклама
Эиком - электронные компоненты и радиодетали
Открыл глаза
Аватара пользователя
Сообщения: 64
Зарегистрирован: Чт июн 09, 2016 18:24:41

Сообщение Billi34 »

Как сделать постоянный опрос кнопки и запуск по изменению состояния? Этот код я взял из примера. Там как раз описывалось нужное мне поведение, а не заработало. Скорее всего в примере нужено пере-включение (сброс) для прохода этого условия. А нет нажатия и прога будет здесь крутиться.
Последний раз редактировалось Billi34 Пт июн 10, 2016 10:28:08, всего редактировалось 1 раз.
Реклама
Опытный кот
Сообщения: 804
Зарегистрирован: Чт мар 12, 2009 16:31:05

Сообщение Vov123 »

http://radioparty.ru/literatura/370-sam ... -avr-belov

В п.4.4 и п.3.7 ожидает счастье.
Реклама
Открыл глаза
Аватара пользователя
Сообщения: 64
Зарегистрирован: Чт июн 09, 2016 18:24:41

Сообщение Billi34 »

Книга качается.
while(PINB.3==0)
{
} \\ видимо так, опрос будет в цикле, По изменению состояния -выход
Друг Кота
Сообщения: 19495
Зарегистрирован: Чт фев 20, 2014 18:57:55

Сообщение Morroc »

да и ваш вариант вроде тоже должен работать, попробуйте кнопку подержать нажатой секунды 3
ищите пример сразу с антидребезгом, варианты без него в реальности работают черте как
"Вся военная пропаганда, все крики, ложь и ненависть исходят от людей, которые на эту войну не пойдут !" / Джордж Оруэлл /
"Война - это,когда за интересы других,гибнут совершенно безвинные люди." / Уинстон Черчилль /
Открыл глаза
Аватара пользователя
Сообщения: 64
Зарегистрирован: Чт июн 09, 2016 18:24:41

Сообщение Billi34 »

Нифига. Не выходит из условия.
Друг Кота
Сообщения: 19495
Зарегистрирован: Чт фев 20, 2014 18:57:55

Сообщение Morroc »

Ну выходить он у вас и не должен, входить и мигать должен :))
"Вся военная пропаганда, все крики, ложь и ненависть исходят от людей, которые на эту войну не пойдут !" / Джордж Оруэлл /
"Война - это,когда за интересы других,гибнут совершенно безвинные люди." / Уинстон Черчилль /
Открыл глаза
Аватара пользователя
Сообщения: 64
Зарегистрирован: Чт июн 09, 2016 18:24:41

Сообщение Billi34 »

Код заработал.

while(1)
{
while(PINB.3==1)
{
}
/////////////здесь код
}
Я и раньше так пробовал, но почему-то не работало.
Спасибо, за участие.
Прошу модератора перенести мою тему в раздел о CV. Все должно быть на месте.
Друг Кота
Сообщения: 19495
Зарегистрирован: Чт фев 20, 2014 18:57:55

Сообщение Morroc »

Бесконечные циклы так себе идея.
"Вся военная пропаганда, все крики, ложь и ненависть исходят от людей, которые на эту войну не пойдут !" / Джордж Оруэлл /
"Война - это,когда за интересы других,гибнут совершенно безвинные люди." / Уинстон Черчилль /
Поставщик валерьянки для Кота
Сообщения: 2200
Зарегистрирован: Вс ноя 15, 2009 23:13:59
Откуда: Харьков

Сообщение watchmaker »

Если нужна мгновенная реакция на кнопку - тут без внешнего интеррапта не обойтись.
Иногда мой питомец уходит в такую спячку, что разбудить его можно только щелчком по первой ноге...
Контактная информация:
Это не хвост, это антенна
Сообщения: 1492
Зарегистрирован: Ср июн 25, 2008 15:19:44

Сообщение Demiurg »

watchmaker писал(а):...
Что за мода вешать кнопки на внешнее прерывание? Сам интерфейс человек-кнопка очень медленный для МК. Плюс обработка антидребезга. Время на подавление дребезга от 20 мс. Сам собой напрашивается вопрос, на куа вешать кнопки на внешнее прерывание? Да и вообще "мгновенно" реагировать на нажатие? Смысл?
Контактная информация:
Держит паяльник хвостом
Сообщения: 933
Зарегистрирован: Ср апр 13, 2011 11:09:20
Откуда: Екатеринбург

Сообщение Alkul »

Demiurg писал(а):Что за мода вешать кнопки на внешнее прерывание?
В общем случае Вы правы. Но если делать опрос не через внешнее прерывание, то в программе нужно реализовать механизм, когда по периодическому срабатыванию таймера выполняются какие-то действия - проверки состояния регистров и тому подобное. В этом случае, как говорится, сам бог велел тут же делать и опрос кнопок. Если же такого механизма в программе по какой-то причине не предусмотрено, то вариант опроса по прерыванию вполне имеет место быть.
По сути - чем плох опрос кнопок по прерыванию? Это может создать проблему только если внешние прерывания нужны для чего-то другого. А если они не используются ни для каких задач - почему б не "повесить" на них кнопки?
Конечно, есть еще третий вариант - опрашивать кнопки в бесконечном цикле только в те моменты, когда программа ожидает обязательного нажатия на какую-то из них, если при этом в программе есть только такой опрос кнопок - не постоянно, а в некоторые моменты.

Словом, вариантов опроса может быть много. И лучшего или худшего тут нет - все зависит от логики программы. Выбор же, как всегда, за программистом.

А совет в выборе способа опроса можно дать, если вопрос задан не отвлеченно - "как опросить кнопку", а вот так - "Логика работы программы такая-то, кнопки нужно опрашивать в такие-то моменты, свободные выводы контроллера такие-то. Как лучше реализовать?"
Последний раз редактировалось Alkul Сб июн 18, 2016 20:16:58, всего редактировалось 1 раз.
Говорящий с текстолитом
Аватара пользователя
Сообщения: 1525
Зарегистрирован: Чт июн 10, 2010 20:11:19

Сообщение COKPOWEHEU »

Помимо таймера, можно проверять в бесконечном цикле, особенно хорошо если время каждого цикла более-менее одинаково.
Если вешать на прерывание, может возникнуть проблема с дребезгом.
Ну и в зависимости от алгоритма использование прерывания может быть наиболее удачным вариантом (пульт от телевизора, например).
Держит паяльник хвостом
Сообщения: 933
Зарегистрирован: Ср апр 13, 2011 11:09:20
Откуда: Екатеринбург

Сообщение Alkul »

COKPOWEHEU писал(а):Если вешать на прерывание, может возникнуть проблема с дребезгом.
Я делал опрос через прерывание. Никаких проблем с дребезгом не возникало.
Реализовывал так: в программе через каждые 2мс вызывался обработчик прерывания таймера, который управлял динамической индикацией на 2 семисегментных индикатора. На этот же обработчик было "подвешено еще несколько функций и среди них - "антидребезговая" функция.
При нажатии на кнопку в обработчике внешнего прерывания первым делом запрещалось прерывание для этой кнопки, инициализировался счетчик, равный количеству 2-х миллисекундных "тиков" антидребезговой задержки, после чего выполнялся программный код собственно действия по нажатию этой кнопки и делался выход из обработчика.
Упомянутый выше счетчик антидребезговой задержки у меня был равен 0xB4 (180D), что при умножении на 0,002 давало 0,36 секунд задержки. В обработчике прерывания таймера каждые 2 мс этот счетчик декрементировался, при достижении нуля прерывание для данной кнопки снова разрешалось.

Таким образом, проблема дребезга решалась довольно просто и надежно. При удержании кнопки в нажатом состоянии действие, выполняемое при нажатии, повторялось каждые 0,36 с. Если подробнее, то там был параметр, изменяющийся от 0 до 99 и две кнопки - одна младший разряд, другая - старший. При нажатии на кнопку соответствующий разряд инкрементировался, при достижении максимального значения 9 следующее значение, соответственно, было 0 и так по циклу. Т.е., в наихудшем случае (например, при переходе от 22 к 11) для изменения параметра требовалось 18 нажатий - 9 на кнопку младшего разряда и 9 - на кнопку старшего разряда.
Это не хвост, это антенна
Сообщения: 1492
Зарегистрирован: Ср июн 25, 2008 15:19: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;
}
//==================
Контактная информация:
Открыл глаза
Аватара пользователя
Сообщения: 64
Зарегистрирован: Чт июн 09, 2016 18:24:41

Сообщение 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) ДА-зажигаем всю стрелку, НЕТ-сдвиг . В голове каша, что-то не допонимаю.
Вложения
Текущая программа .txt
(47.57 КБ) 196 скачиваний
Это не хвост, это антенна
Сообщения: 1492
Зарегистрирован: Ср июн 25, 2008 15:19:44

Сообщение Demiurg »

Billi34 писал(а):В голове каша, что-то не допонимаю.
Действительно каша. Лично я ничего не понял. Соберитесь с мыслями и грамотно распишите ТЗ. Не надо вашего псевдоязыка. Простыми русскими словами. Четко и ясно.
Контактная информация:
Ответить

Вернуться в «AVR»