Опрос кнопок микроконтроллером
-
Alexeyslav
- Друг Кота
- Сообщения: 4550
- Зарегистрирован: Чт май 05, 2011 21:26:34
- Откуда: Украина, Славутич
- Контактная информация:
Re: Помогите опросить кнопку
Если ничего не получается с наскоку, то... перво-наперво все стереть и нарисовать блок-схему будущего алгоритма. Для прерывания - одну, для программы - другую.
Причем делать так как ты делаешь - нельзя. в твоем случае этого вобщем-то не так заметно, но переменная button у тебя используется как программой так и прерыванием, а прерывание может возникнуть в ЛЮБОЙ МОМЕНТ времени, даже непосредственно перед проверкой! А у тебя подряд идут целых 8 проверок. Перед такими проверками надо обеспечить неизменность переменной, иначе получишь такую ситуацию значение button = 5, только что проверили значение на 5 - совпало что-то делаем и тут возникает прерывание, button меняется на 6 заканчиваем действие и происходит очередное сравнение button с числом 6 - это условие тоже срабатывает...
Беда в том что отловить такую ситуацию крайне сложно, в тестах она будет возникать довольно редко - когда момент проверки во времени совпадет с прерыванием да еще в нужной фазе.
Как это обеспечить? до окончания проверок запретить прерывания, или скопировать значение переменной и сравнивать уже копию.
Но лучше, действовать через флаги - в прерывании можно только установить флаг, а в основной программе только сбросить и только один раз. Тогда никаких конфликтов не происходит.
Причем делать так как ты делаешь - нельзя. в твоем случае этого вобщем-то не так заметно, но переменная button у тебя используется как программой так и прерыванием, а прерывание может возникнуть в ЛЮБОЙ МОМЕНТ времени, даже непосредственно перед проверкой! А у тебя подряд идут целых 8 проверок. Перед такими проверками надо обеспечить неизменность переменной, иначе получишь такую ситуацию значение button = 5, только что проверили значение на 5 - совпало что-то делаем и тут возникает прерывание, button меняется на 6 заканчиваем действие и происходит очередное сравнение button с числом 6 - это условие тоже срабатывает...
Беда в том что отловить такую ситуацию крайне сложно, в тестах она будет возникать довольно редко - когда момент проверки во времени совпадет с прерыванием да еще в нужной фазе.
Как это обеспечить? до окончания проверок запретить прерывания, или скопировать значение переменной и сравнивать уже копию.
Но лучше, действовать через флаги - в прерывании можно только установить флаг, а в основной программе только сбросить и только один раз. Тогда никаких конфликтов не происходит.
Re: Помогите опросить кнопку
Как это обеспечить?
Просто почитать про атомарные операции. А ещё лучше - понять, что это такое.
Применительно к Си советую глянуть тут
Да, это все здорово. Но к чему я это?
А к тому, что у нас тут есть еще и прерывание. В котором может быть изменены наши значения, а еще тот милый факт что прерывание, будучи разрешенным, может выскочить между двух любых инструкций. И при этом родить очень адский глюк которой может ВНЕЗАПНО вылезти через пару лет безглючной работы, а потом также бесследно исчезнуть, оставив разработчика задумчиво чесать репу на предмет «ЧТО ЭТО БЫЛО»? Часто тут грешат на глюки железа и дырявые процы. Хотя на самом то деле просто программа была корявая
Alexeyslav, это не вам разумеется, это в дополнение
- dr.doc
- Это не хвост, это антенна
- Сообщения: 1368
- Зарегистрирован: Вс мар 28, 2010 12:52:22
- Откуда: Беларусь
Re: Помогите опросить кнопку
А я буквально на днях написал похожий велосипед... По прерываниям у меня идет динамическая индикация (5 мС). Нажатие на кнопку устанавливает флаг, отжатие - сбрасывает. Если нажата кнопка, счетчик в прерываниях инкрементируется и сравнивается с константой - задатчиком длительности антидребезга. При каждом отпускании кнопки в момент опроса счетчик сбрасывается. Подпрограммы выполнения нажатий вызываются по соответствию флага (установлен или нет). В каждой подпрограмме и происходит сравнение инкрементного счетчика с антидребезгом. После одиночного срабатывания подпрограммы выставляется 2-й флаг для запрета выполнения процедуры до отпускания и следующего нажатия на кнопку.
Таким образом, в прерывании выполняется примерно 50 - 200 строк кода (на 4 кнопки) в зависимости от нажатий. При этом нет никаких задержек в прерывании.
Таким образом, в прерывании выполняется примерно 50 - 200 строк кода (на 4 кнопки) в зависимости от нажатий. При этом нет никаких задержек в прерывании.
«Еще я хотел бы, чтобы наши ученые изобрели какой-то новый источник энергии, чтобы мы на коленях не ползали даже перед нашими братьями, умоляя их и выпрашивая тонну нефти или кубометр газа», — рассказал белорусский президент.
-
Alexeyslav
- Друг Кота
- Сообщения: 4550
- Зарегистрирован: Чт май 05, 2011 21:26:34
- Откуда: Украина, Славутич
- Контактная информация:
Re: Помогите опросить кнопку
Счетчик лишний, чтобы подавить дребезг опроса каждые 5мс вполне достаточно если дребезг кнопки длится меньше 5мс, если около 5мс - опрашиваешь кнопку через раз.
Просто в таком случае, самое неприятное что может произойти из-за дребезга это зарегистрируешь нажатие на один опрос позже.
Просто в таком случае, самое неприятное что может произойти из-за дребезга это зарегистрируешь нажатие на один опрос позже.
- dr.doc
- Это не хвост, это антенна
- Сообщения: 1368
- Зарегистрирован: Вс мар 28, 2010 12:52:22
- Откуда: Беларусь
Re: Помогите опросить кнопку
Когда вместо кнопок что зря (попадалось раз, ... его) с переходным процессом в 150 мС (+-)... Сколько я промучился (делал дистанционно - настроил с кнопками на столе, а в поле . . .)
«Еще я хотел бы, чтобы наши ученые изобрели какой-то новый источник энергии, чтобы мы на коленях не ползали даже перед нашими братьями, умоляя их и выпрашивая тонну нефти или кубометр газа», — рассказал белорусский президент.
-
Alexeyslav
- Друг Кота
- Сообщения: 4550
- Зарегистрирован: Чт май 05, 2011 21:26:34
- Откуда: Украина, Славутич
- Контактная информация:
Re: Помогите опросить кнопку
Со 150мс уже проще применять аппаратные подавители - например перезапускаемые одновибраторы - так и дребезг будет проглочен и момент нажатия не упущен. А если момент нажатия не важен - с таким дребезгом опрашивать каждые 250мс, 500мс...
- RGB
- Родился
- Сообщения: 17
- Зарегистрирован: Пт ноя 09, 2012 17:22:37
- Откуда: Москва
- Контактная информация:
Re: Помогите опросить кнопку
Ребят, если я правильно понял вас, то у меня должно получиться что то типо вот этого?
прерывания срабатывают каждые 8 ms исходя из того что тактовая частота 8MHz и пределитель стоит на 64
Код: Выделить всё
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: Помогите опросить кнопку
Оператор цикла for (насколько я помню С++) считает до 20-ти тактов? Если так, то этого может быть мало (дребезг). А так, идею уловили.
«Еще я хотел бы, чтобы наши ученые изобрели какой-то новый источник энергии, чтобы мы на коленях не ползали даже перед нашими братьями, умоляя их и выпрашивая тонну нефти или кубометр газа», — рассказал белорусский президент.
- Аlex
- Модератор
- Сообщения: 4614
- Зарегистрирован: Чт мар 18, 2010 23:09:57
- Откуда: Планета Земля
- Контактная информация:
Re: Помогите опросить кнопку
Вот только чью... не понятно...А так, идею уловили.
Зачем эти циклы нужны ? Нужно просто опросить ПИН и сравнить его с предыдущим значением, установив флаг.
- RGB
- Родился
- Сообщения: 17
- Зарегистрирован: Пт ноя 09, 2012 17:22:37
- Откуда: Москва
- Контактная информация:
Re: Помогите опросить кнопку
Аlex то бишь вот так?
y - глобальная переменная.
А в основном цикле мы делаем уже инкремент "button" с обнулением глобальной переменной "y"
то бишь вот так
Почему в обработчике прерываний сразу начинаю опрашивать кнопку, просто моё мнение (может и не прав) но мне кажеться что если кнопка не нажата, то пусть обработчик просто прогонит пустой цикл, тем самым не нагружая его!
Код: Выделить всё
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;}
}
}А в основном цикле мы делаем уже инкремент "button" с обнулением глобальной переменной "y"
то бишь вот так
Код: Выделить всё
while(1)
{
if (y == 1) { button++; y = 0; }
.......
.......
.......
.......
if(button == 8) button = 0;
} Почему в обработчике прерываний сразу начинаю опрашивать кнопку, просто моё мнение (может и не прав) но мне кажеться что если кнопка не нажата, то пусть обработчик просто прогонит пустой цикл, тем самым не нагружая его!
- dr.doc
- Это не хвост, это антенна
- Сообщения: 1368
- Зарегистрирован: Вс мар 28, 2010 12:52:22
- Откуда: Беларусь
Re: Помогите опросить кнопку
Не заметил последней строки про 8 мС.
Alex - циклы нужны там, где 8 мС времени между прерываниями не обеспечивают четкое срабатывание кнопки. 2 таких цикла дадут 16 мС без значительного прироста затрат машинного времени.
PS С особо не знаю, пишу на Ассемблере, поэтому я мог не совсем понять приведенный участок кода.
Alex - циклы нужны там, где 8 мС времени между прерываниями не обеспечивают четкое срабатывание кнопки. 2 таких цикла дадут 16 мС без значительного прироста затрат машинного времени.
PS С особо не знаю, пишу на Ассемблере, поэтому я мог не совсем понять приведенный участок кода.
«Еще я хотел бы, чтобы наши ученые изобрели какой-то новый источник энергии, чтобы мы на коленях не ползали даже перед нашими братьями, умоляя их и выпрашивая тонну нефти или кубометр газа», — рассказал белорусский президент.
- Аlex
- Модератор
- Сообщения: 4614
- Зарегистрирован: Чт мар 18, 2010 23:09:57
- Откуда: Планета Земля
- Контактная информация:
Re: Помогите опросить кнопку
Не совсем понимаю что у Вас написано, но что-то не то.Аlex то бишь вот так?
Зачем второе вложенное условие, если оно такое-же ? Понятно что оно выполнится, по этому оно лишнее.
И что за переменная button, которую Вы всё пытаетесь инкрементировать ?
-
Alexeyslav
- Друг Кота
- Сообщения: 4550
- Зарегистрирован: Чт май 05, 2011 21:26:34
- Откуда: Украина, Славутич
- Контактная информация:
Re: Помогите опросить кнопку
Какая-то фигня...
Ты опять проверяешь значение которое может изменится в любой момент два раза и на этом строится алгоритм... он обязательно будет давать сбои! Причем сбои именно из-за дребезга(от чего боролись на то и напоролись)!
Достаточно считать значение с порта зафиксировать его(скопировать во временную переменную) и сравнить его с предыдущим, потом после сравнения скопировать в предыдущее.
Тогда ты запросто можешь различить 4 разных состояния кнопки - нажата, отпущена, момент нажатия(один раз, когда предыдущее равно 0 а текущее 1), момент отпускания(когда предыдущее равно 1 а текущее 0).
В том-то и дело что если момент дребезга попадет на прерывание то существует вероятность что сравниваемые значения в условиях будут разными! и если первое условия будет выполнено, то второе иногда может и не выполнится даже если кнопка идеальная. Ведь переключение может произойти и в момент между проверками.
...
if ((PIND&0x80) == 0)
{ temp = PIND;
if ((PIND&0x80) == 0)
...
Ты опять проверяешь значение которое может изменится в любой момент два раза и на этом строится алгоритм... он обязательно будет давать сбои! Причем сбои именно из-за дребезга(от чего боролись на то и напоролись)!
Достаточно считать значение с порта зафиксировать его(скопировать во временную переменную) и сравнить его с предыдущим, потом после сравнения скопировать в предыдущее.
Тогда ты запросто можешь различить 4 разных состояния кнопки - нажата, отпущена, момент нажатия(один раз, когда предыдущее равно 0 а текущее 1), момент отпускания(когда предыдущее равно 1 а текущее 0).
Зачем второе вложенное условие, если оно такое-же ? Понятно что оно выполнится
В том-то и дело что если момент дребезга попадет на прерывание то существует вероятность что сравниваемые значения в условиях будут разными! и если первое условия будет выполнено, то второе иногда может и не выполнится даже если кнопка идеальная. Ведь переключение может произойти и в момент между проверками.
- Аlex
- Модератор
- Сообщения: 4614
- Зарегистрирован: Чт мар 18, 2010 23:09:57
- Откуда: Планета Земля
- Контактная информация:
Re: Помогите опросить кнопку
Тут я согласен, полностью. Но я имел ввиду - какой смысл от двух одинаковых вложенных условий. Мне интересно, о чём думал человек, писав этоВ том-то и дело что если момент дребезга попадет на прерывание то существует вероятность что сравниваемые значения в условиях будут разными! и если первое условия будет выполнено, то второе иногда может и не выполнится даже если кнопка идеальная. Ведь переключение может произойти и в момент между проверками.
А так, безусловно, Вы правы, нужно сначала прочитать, потом работать. О чём человеку уже и было сказано.
- RGB
- Родился
- Сообщения: 17
- Зарегистрирован: Пт ноя 09, 2012 17:22:37
- Откуда: Москва
- Контактная информация:
Re: Помогите опросить кнопку
Вот всё казалось бы понял но:
ни как не въеду, от кудо берёться предыдущее значение? если я допустим только что запустил МК, от куда в нём предыдущее значение
хоть убей не пойму
Достаточно считать значение с порта зафиксировать его(скопировать во временную переменную) и сравнить его с предыдущим, потом после сравнения скопировать в предыдущее.
ни как не въеду, от кудо берёться предыдущее значение? если я допустим только что запустил МК, от куда в нём предыдущее значение
- Аlex
- Модератор
- Сообщения: 4614
- Зарегистрирован: Чт мар 18, 2010 23:09:57
- Откуда: Планета Земля
- Контактная информация:
Re: Помогите опросить кнопку
Если только включили, то оно (значение) будет определённым Вами, т.б. то, которое Вы напишите при инициализации. А дальше, оно будет сохраняться из текущего.
-
Alexeyslav
- Друг Кота
- Сообщения: 4550
- Зарегистрирован: Чт май 05, 2011 21:26:34
- Откуда: Украина, Славутич
- Контактная информация:
Re: Помогите опросить кнопку
В процессе инициализации, предыдущее значение можно записать тем что имеется на входе на самом деле, например включили с нажатой кнопкой - и в таком случае событие "момент нажатия" не будет зарегистрировано в обработчике прерывания. Но если надо обязательно отреагировать как на нажатие - то просто записать "отжата" в процессе инициализации контролллера, и через 8мс когда возникнет прерывание он посмотрит что кнопка была отжата а стала нажата - значит произошло нажатие и обработает как полагается.
- RGB
- Родился
- Сообщения: 17
- Зарегистрирован: Пт ноя 09, 2012 17:22:37
- Откуда: Москва
- Контактная информация:
Re: Помогите опросить кнопку
не выходит ни как
Код: Выделить всё
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: Помогите опросить кнопку
Примерно так. ТОлько нужно сохранить состояние вывода в темп, а потом с ним уже работать.
И чара многовато будет для 1 бита, хотя можно сначала и с чарами побаловаться, потом, когда поймёте принцп, создадите уже битовые поля.
И чара многовато будет для 1 бита, хотя можно сначала и с чарами побаловаться, потом, когда поймёте принцп, создадите уже битовые поля.
-
Alexeyslav
- Друг Кота
- Сообщения: 4550
- Зарегистрирован: Чт май 05, 2011 21:26:34
- Откуда: Украина, Славутич
- Контактная информация:
Re: Помогите опросить кнопку
Так верно, в temp_1 сохраняется весь порт... любое изменение в любых битах и будет срабатывать нажатие.
ты сначала сохрани один раз в temp_1 = PIND&0x80, и потом используй только temp_1 в условиях и т.д.
и у тебя сейчас происходит копирование temp_1 = PIND только когда кнопка нажата... и что в результате останется в переменной когда кнопка не нажата? да еще и не инициализированной...
Рано тебе программы писать "с наскока". Начни с блок-схем. На них хорошо видны все возможные ситуации и узкие места.
ты сначала сохрани один раз в temp_1 = PIND&0x80, и потом используй только temp_1 в условиях и т.д.
и у тебя сейчас происходит копирование temp_1 = PIND только когда кнопка нажата... и что в результате останется в переменной когда кнопка не нажата? да еще и не инициализированной...
Рано тебе программы писать "с наскока". Начни с блок-схем. На них хорошо видны все возможные ситуации и узкие места.