Опрос кнопок микроконтроллером

Дисплеи, датчики и прочие функциональные узлы, управляемые МК.
Alexeyslav
Друг Кота
Сообщения: 4550
Зарегистрирован: Чт май 05, 2011 21:26:34
Откуда: Украина, Славутич
Контактная информация:

Re: Помогите опросить кнопку

Сообщение Alexeyslav »

Если ничего не получается с наскоку, то... перво-наперво все стереть и нарисовать блок-схему будущего алгоритма. Для прерывания - одну, для программы - другую.

Причем делать так как ты делаешь - нельзя. в твоем случае этого вобщем-то не так заметно, но переменная button у тебя используется как программой так и прерыванием, а прерывание может возникнуть в ЛЮБОЙ МОМЕНТ времени, даже непосредственно перед проверкой! А у тебя подряд идут целых 8 проверок. Перед такими проверками надо обеспечить неизменность переменной, иначе получишь такую ситуацию значение button = 5, только что проверили значение на 5 - совпало что-то делаем и тут возникает прерывание, button меняется на 6 заканчиваем действие и происходит очередное сравнение button с числом 6 - это условие тоже срабатывает...
Беда в том что отловить такую ситуацию крайне сложно, в тестах она будет возникать довольно редко - когда момент проверки во времени совпадет с прерыванием да еще в нужной фазе.

Как это обеспечить? до окончания проверок запретить прерывания, или скопировать значение переменной и сравнивать уже копию.

Но лучше, действовать через флаги - в прерывании можно только установить флаг, а в основной программе только сбросить и только один раз. Тогда никаких конфликтов не происходит.
Аватара пользователя
ploop
Модератор
Сообщения: 13490
Зарегистрирован: Ср ноя 26, 2008 16:34:25
Откуда: Тамбовская обл.

Re: Помогите опросить кнопку

Сообщение ploop »

Как это обеспечить?

Просто почитать про атомарные операции. А ещё лучше - понять, что это такое.
Применительно к Си советую глянуть тут

Да, это все здорово. Но к чему я это?
А к тому, что у нас тут есть еще и прерывание. В котором может быть изменены наши значения, а еще тот милый факт что прерывание, будучи разрешенным, может выскочить между двух любых инструкций. И при этом родить очень адский глюк которой может ВНЕЗАПНО вылезти через пару лет безглючной работы, а потом также бесследно исчезнуть, оставив разработчика задумчиво чесать репу на предмет «ЧТО ЭТО БЫЛО»? Часто тут грешат на глюки железа и дырявые процы. Хотя на самом то деле просто программа была корявая


Alexeyslav, это не вам разумеется, это в дополнение :)
Аватара пользователя
dr.doc
Это не хвост, это антенна
Сообщения: 1368
Зарегистрирован: Вс мар 28, 2010 12:52:22
Откуда: Беларусь

Re: Помогите опросить кнопку

Сообщение dr.doc »

А я буквально на днях написал похожий велосипед... По прерываниям у меня идет динамическая индикация (5 мС). Нажатие на кнопку устанавливает флаг, отжатие - сбрасывает. Если нажата кнопка, счетчик в прерываниях инкрементируется и сравнивается с константой - задатчиком длительности антидребезга. При каждом отпускании кнопки в момент опроса счетчик сбрасывается. Подпрограммы выполнения нажатий вызываются по соответствию флага (установлен или нет). В каждой подпрограмме и происходит сравнение инкрементного счетчика с антидребезгом. После одиночного срабатывания подпрограммы выставляется 2-й флаг для запрета выполнения процедуры до отпускания и следующего нажатия на кнопку.
Таким образом, в прерывании выполняется примерно 50 - 200 строк кода (на 4 кнопки) в зависимости от нажатий. При этом нет никаких задержек в прерывании.
«Еще я хотел бы, чтобы наши ученые изобрели какой-то новый источник энергии, чтобы мы на коленях не ползали даже перед нашими братьями, умоляя их и выпрашивая тонну нефти или кубометр газа», — рассказал белорусский президент.
Alexeyslav
Друг Кота
Сообщения: 4550
Зарегистрирован: Чт май 05, 2011 21:26:34
Откуда: Украина, Славутич
Контактная информация:

Re: Помогите опросить кнопку

Сообщение Alexeyslav »

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

Просто в таком случае, самое неприятное что может произойти из-за дребезга это зарегистрируешь нажатие на один опрос позже.
Аватара пользователя
dr.doc
Это не хвост, это антенна
Сообщения: 1368
Зарегистрирован: Вс мар 28, 2010 12:52:22
Откуда: Беларусь

Re: Помогите опросить кнопку

Сообщение dr.doc »

Когда вместо кнопок что зря (попадалось раз, ... его) с переходным процессом в 150 мС (+-)... Сколько я промучился (делал дистанционно - настроил с кнопками на столе, а в поле . . .)
«Еще я хотел бы, чтобы наши ученые изобрели какой-то новый источник энергии, чтобы мы на коленях не ползали даже перед нашими братьями, умоляя их и выпрашивая тонну нефти или кубометр газа», — рассказал белорусский президент.
Alexeyslav
Друг Кота
Сообщения: 4550
Зарегистрирован: Чт май 05, 2011 21:26:34
Откуда: Украина, Славутич
Контактная информация:

Re: Помогите опросить кнопку

Сообщение Alexeyslav »

Со 150мс уже проще применять аппаратные подавители - например перезапускаемые одновибраторы - так и дребезг будет проглочен и момент нажатия не упущен. А если момент нажатия не важен - с таким дребезгом опрашивать каждые 250мс, 500мс...
Аватара пользователя
RGB
Родился
Сообщения: 17
Зарегистрирован: Пт ноя 09, 2012 17:22:37
Откуда: Москва
Контактная информация:

Re: Помогите опросить кнопку

Сообщение RGB »

Ребят, если я правильно понял вас, то у меня должно получиться что то типо вот этого?

Код: Выделить всё

ISR (TIMER0_OVF_vect)

 unsigned char temp, temp_1 = 0xFF , i;

     if ((PIND&0x80) == 0)
   {  temp = PIND;
        for (i=0; i<20;i++)
        { if ((PIND&0x80) == 0)
          { temp_1 = PIND;}
                              }
                   if( temp == temp_1) {button++;}
              }
if(button == 8) button=0;
}

прерывания срабатывают каждые 8 ms исходя из того что тактовая частота 8MHz и пределитель стоит на 64
Последний раз редактировалось RGB Сб ноя 10, 2012 21:02:12, всего редактировалось 1 раз.
Аватара пользователя
dr.doc
Это не хвост, это антенна
Сообщения: 1368
Зарегистрирован: Вс мар 28, 2010 12:52:22
Откуда: Беларусь

Re: Помогите опросить кнопку

Сообщение dr.doc »

Оператор цикла for (насколько я помню С++) считает до 20-ти тактов? Если так, то этого может быть мало (дребезг). А так, идею уловили.
«Еще я хотел бы, чтобы наши ученые изобрели какой-то новый источник энергии, чтобы мы на коленях не ползали даже перед нашими братьями, умоляя их и выпрашивая тонну нефти или кубометр газа», — рассказал белорусский президент.
Аватара пользователя
Аlex
Модератор
Сообщения: 4614
Зарегистрирован: Чт мар 18, 2010 23:09:57
Откуда: Планета Земля
Контактная информация:

Re: Помогите опросить кнопку

Сообщение Аlex »

А так, идею уловили.
Вот только чью... не понятно...
Зачем эти циклы нужны ? Нужно просто опросить ПИН и сравнить его с предыдущим значением, установив флаг.
Аватара пользователя
RGB
Родился
Сообщения: 17
Зарегистрирован: Пт ноя 09, 2012 17:22:37
Откуда: Москва
Контактная информация:

Re: Помогите опросить кнопку

Сообщение RGB »

Аlex то бишь вот так?

Код: Выделить всё

ISR (TIMER0_OVF_vect)

 unsigned char temp, temp_1 = 0xFF, i;

     if ((PIND&0x80) == 0)
   {  temp = PIND;
        if ((PIND&0x80) == 0)
          { temp_1 = PIND;}
           if( temp == temp_1) {y = 1;}
   }

}
y - глобальная переменная.
А в основном цикле мы делаем уже инкремент "button" с обнулением глобальной переменной "y"
то бишь вот так

Код: Выделить всё

while(1)
        {
if (y == 1) { button++; y = 0; }
.......
.......
.......
.......
if(button == 8) button = 0;
}

Почему в обработчике прерываний сразу начинаю опрашивать кнопку, просто моё мнение (может и не прав) но мне кажеться что если кнопка не нажата, то пусть обработчик просто прогонит пустой цикл, тем самым не нагружая его!
Аватара пользователя
dr.doc
Это не хвост, это антенна
Сообщения: 1368
Зарегистрирован: Вс мар 28, 2010 12:52:22
Откуда: Беларусь

Re: Помогите опросить кнопку

Сообщение dr.doc »

Не заметил последней строки про 8 мС.
Alex - циклы нужны там, где 8 мС времени между прерываниями не обеспечивают четкое срабатывание кнопки. 2 таких цикла дадут 16 мС без значительного прироста затрат машинного времени.
PS С особо не знаю, пишу на Ассемблере, поэтому я мог не совсем понять приведенный участок кода.
«Еще я хотел бы, чтобы наши ученые изобрели какой-то новый источник энергии, чтобы мы на коленях не ползали даже перед нашими братьями, умоляя их и выпрашивая тонну нефти или кубометр газа», — рассказал белорусский президент.
Аватара пользователя
Аlex
Модератор
Сообщения: 4614
Зарегистрирован: Чт мар 18, 2010 23:09:57
Откуда: Планета Земля
Контактная информация:

Re: Помогите опросить кнопку

Сообщение Аlex »

Аlex то бишь вот так?
Не совсем понимаю что у Вас написано, но что-то не то.
Зачем второе вложенное условие, если оно такое-же ? Понятно что оно выполнится, по этому оно лишнее.
И что за переменная button, которую Вы всё пытаетесь инкрементировать ?
Alexeyslav
Друг Кота
Сообщения: 4550
Зарегистрирован: Чт май 05, 2011 21:26:34
Откуда: Украина, Славутич
Контактная информация:

Re: Помогите опросить кнопку

Сообщение Alexeyslav »

Какая-то фигня...
...
if ((PIND&0x80) == 0)
{ temp = PIND;
if ((PIND&0x80) == 0)
...


Ты опять проверяешь значение которое может изменится в любой момент два раза и на этом строится алгоритм... он обязательно будет давать сбои! Причем сбои именно из-за дребезга(от чего боролись на то и напоролись)!

Достаточно считать значение с порта зафиксировать его(скопировать во временную переменную) и сравнить его с предыдущим, потом после сравнения скопировать в предыдущее.

Тогда ты запросто можешь различить 4 разных состояния кнопки - нажата, отпущена, момент нажатия(один раз, когда предыдущее равно 0 а текущее 1), момент отпускания(когда предыдущее равно 1 а текущее 0).

Зачем второе вложенное условие, если оно такое-же ? Понятно что оно выполнится

В том-то и дело что если момент дребезга попадет на прерывание то существует вероятность что сравниваемые значения в условиях будут разными! и если первое условия будет выполнено, то второе иногда может и не выполнится даже если кнопка идеальная. Ведь переключение может произойти и в момент между проверками.
Аватара пользователя
Аlex
Модератор
Сообщения: 4614
Зарегистрирован: Чт мар 18, 2010 23:09:57
Откуда: Планета Земля
Контактная информация:

Re: Помогите опросить кнопку

Сообщение Аlex »

В том-то и дело что если момент дребезга попадет на прерывание то существует вероятность что сравниваемые значения в условиях будут разными! и если первое условия будет выполнено, то второе иногда может и не выполнится даже если кнопка идеальная. Ведь переключение может произойти и в момент между проверками.
Тут я согласен, полностью. Но я имел ввиду - какой смысл от двух одинаковых вложенных условий. Мне интересно, о чём думал человек, писав это :)
А так, безусловно, Вы правы, нужно сначала прочитать, потом работать. О чём человеку уже и было сказано.
Аватара пользователя
RGB
Родился
Сообщения: 17
Зарегистрирован: Пт ноя 09, 2012 17:22:37
Откуда: Москва
Контактная информация:

Re: Помогите опросить кнопку

Сообщение RGB »

Вот всё казалось бы понял но:
Достаточно считать значение с порта зафиксировать его(скопировать во временную переменную) и сравнить его с предыдущим, потом после сравнения скопировать в предыдущее.

ни как не въеду, от кудо берёться предыдущее значение? если я допустим только что запустил МК, от куда в нём предыдущее значение :? хоть убей не пойму
Аватара пользователя
Аlex
Модератор
Сообщения: 4614
Зарегистрирован: Чт мар 18, 2010 23:09:57
Откуда: Планета Земля
Контактная информация:

Re: Помогите опросить кнопку

Сообщение Аlex »

Если только включили, то оно (значение) будет определённым Вами, т.б. то, которое Вы напишите при инициализации. А дальше, оно будет сохраняться из текущего.
Alexeyslav
Друг Кота
Сообщения: 4550
Зарегистрирован: Чт май 05, 2011 21:26:34
Откуда: Украина, Славутич
Контактная информация:

Re: Помогите опросить кнопку

Сообщение Alexeyslav »

В процессе инициализации, предыдущее значение можно записать тем что имеется на входе на самом деле, например включили с нажатой кнопкой - и в таком случае событие "момент нажатия" не будет зарегистрировано в обработчике прерывания. Но если надо обязательно отреагировать как на нажатие - то просто записать "отжата" в процессе инициализации контролллера, и через 8мс когда возникнет прерывание он посмотрит что кнопка была отжата а стала нажата - значит произошло нажатие и обработает как полагается.
Аватара пользователя
RGB
Родился
Сообщения: 17
Зарегистрирован: Пт ноя 09, 2012 17:22:37
Откуда: Москва
Контактная информация:

Re: Помогите опросить кнопку

Сообщение RGB »

не выходит ни как :(

Код: Выделить всё

ISR (TIMER0_OVF_vect)
{ unsigned char temp_1;

 if ((PIND&0x80) == 0) temp_1 = PIND; // Достаточно считать значение с порта зафиксировать его
 if (temp_1 == temp) {y = 1;}              // и сравнить его с предыдущим
  temp = temp_1;                                //потом после сравнения скопировать в предыдущее
     

}
Аватара пользователя
Аlex
Модератор
Сообщения: 4614
Зарегистрирован: Чт мар 18, 2010 23:09:57
Откуда: Планета Земля
Контактная информация:

Re: Помогите опросить кнопку

Сообщение Аlex »

Примерно так. ТОлько нужно сохранить состояние вывода в темп, а потом с ним уже работать.
И чара многовато будет для 1 бита, хотя можно сначала и с чарами побаловаться, потом, когда поймёте принцп, создадите уже битовые поля.
Alexeyslav
Друг Кота
Сообщения: 4550
Зарегистрирован: Чт май 05, 2011 21:26:34
Откуда: Украина, Славутич
Контактная информация:

Re: Помогите опросить кнопку

Сообщение Alexeyslav »

Так верно, в temp_1 сохраняется весь порт... любое изменение в любых битах и будет срабатывать нажатие.

ты сначала сохрани один раз в temp_1 = PIND&0x80, и потом используй только temp_1 в условиях и т.д.

и у тебя сейчас происходит копирование temp_1 = PIND только когда кнопка нажата... и что в результате останется в переменной когда кнопка не нажата? да еще и не инициализированной...

Рано тебе программы писать "с наскока". Начни с блок-схем. На них хорошо видны все возможные ситуации и узкие места.
Ответить

Вернуться в «Периферия»