То тогда работает четко. Процедура обработки кнопок взята отсюда viewtopic.php?p=1704144#p1704144 Сам опрос крутится в 1мс таймере, TRESHOLD 20 мс. эта часть вопросов не вызывает. Кстати в самой функции GetPressedButton() небольшая неточность. else там лишние. Если их оставить то код кнопки возвращается всегда, независимо нажата или нет. У меня эта функция получилась вот такого вида.
То тогда работает четко. Процедура обработки кнопок взята отсюда viewtopic.php?p=1704144#p1704144 Сам опрос крутится в 1мс таймере, TRESHOLD 20 мс. эта часть вопросов не вызывает. Кстати в самой функции GetPressedButton() небольшая неточность. else там лишние. Если их оставить то код кнопки возвращается всегда, независимо нажата или нет. Вопрос, почему не работают if если функцию GetPressedButton() вызывать непосредственно из if?
Вам нужно в момент времени Т определить, какая нажата кнопка. Вы ОДИН раз должны обратится в момент Т к этой функции, зафиксировать этот результат, а потом уже заняться его анализом. В вашем же примере вы вызываете функцию в ТРИ разных момента времени Т1, Т2 и Т3 (каждый if в свой момент времени). Состояние кнопок может быть непредсказуемым, особенно, если учесть, что работает прерывание 1 мсек. Таким образом ваш вопрос совершенно не к языку Си. Захромало понимание алгоритма. Насчет else сам не понимаю, почему их вписал. Текст набирал вручную, был бы копипаст из фрагмента, там бы этого не было. Ну, лишний раз доказывает, что вы таки разобрались с этим вариантом решения. Наверняка увидели и то, что решение частное. Этот способ не отслеживает состояние кнопки. Варианты придумайте сами, там не сложно.
Вопрос, почему не работают if если функцию GetPressedButton() вызывать непосредственно из if?
Я так полагаю, раз вы догадались до вот этого
Код:
timer_1 = GetPressedButton();
то сами должны понять, в чем проблема.
Нет, серьезно, вопрос детский. Уровня средней школы, где алгоритмы только начинают изучать.
Кстати объяснение автора кода (я правильно понял?), как это ни парадоксально, тоже не совсем точное. Момент времени там почти один и тот же, и если бы там происходил именно опрос кнопок, всё бы работало. Но дело в счетчиках. Когда функция однажды вернула какую-либо кнопку, она уже второй раз её вернуть не может. Поэтому если в первом if'е была возвращена кнопка 2, к примеру, то повторный вызов функции в следующем if'е уже не вернет такое же значение.
Я сперва не всё посмотрел. Кривоватая реализация этих счетчиков, как по мне. Я всегда делал переменную с флагами, которые устанавливаются непосредственно там, где и происходит опрос кнопок (например, прерывание таймера). Счетчики обрабатываются у меня тоже обычно исключительно в том же прерывании. И надо не забывать про атомарность операций, к примеру блокировать прерывание, на время работы с этими переменными в главном цикле.
P.P.P.P.S. Более надежно проверять переполнение счетчика оператором >=,и только им. Использование == зачастую и приводит вот к таким последствиям.
Таким образом ваш вопрос совершенно не к языку Си. Захромало понимание алгоритма.
Это понятно, не совсем корректно задал вопрос. Но сам алгоритм работы этой функции не догоняю... В прерывании крутится счетчик. Если кнопка, предположим key_1 была нажата, то факт нажатия и до момента отпускания зафиксирован в счетчике button_cnt_1. Пока кнопка нажата значение button_cnt_1 равно TRESHOLD. Если в этот момент вызвать функцию GetPressedButton() то она вернет код нажатой кнопки key_1. Одновременно увеличив счетчик button_cnt_1 на единицу. Что не даст при повторном вызове функции пока кнопка еще не отпущена повторного возвращения кода кнопки. Вроде тут я все правильно понял? Из за этого и получается, если предположим была нажата key_2, а вызов GetPressedButton() был например из первого IF, то при повторном вызове из второго IF пока кнопка не была отпущена и повторно нажата GetPressedButton() вернет 0?
Foks писал(а):
Нет, серьезно, вопрос детский. Уровня средней школы, где алгоритмы только начинают изучать.
Я в школе учился когда еще и калькуляторов не было Так что для меня эти вопросы довольно сложные для понимания. Если бы понимал все, то не задавал бы вопросов, а отвечал на них. P.S. Вообщем разобрался я с обработкой нажатия используя эту функцию. Получилось с помощью нее сделать небольшую менюшку на 4 таймера и в каждом обрабатывать каждую цифру по отдельности. То есть бегать по разрядам (динамический вывод на 4 разрядный семисегментник) и изменять значение каждого разряда по отдельности. По колхозному конечно, но работает без сбоев и ошибок. Причешу немного код, и спрошу ваших советов как сделал я, и как делать такое меню правильно. Спасибо за каменты и ответы на вопросы.
Если в этот момент вызвать функцию GetPressedButton() то она вернет код нажатой кнопки key_1. Одновременно увеличив счетчик button_cnt_1 на единицу. Что не даст при повторном вызове функции пока кнопка еще не отпущена повторного возвращения кода кнопки. Вроде тут я все правильно понял? Из за этого и получается, если предположим была нажата key_2, а вызов GetPressedButton() был например из первого IF, то при повторном вызове из второго IF пока кнопка не была отпущена и повторно нажата GetPressedButton() вернет 0?
В первом куске кода мы сравниваем условие и флаги с помощью ==, а во втором &. Когда-нибудь так можно нарваться на ошибку.
Мне показалось, что и во втором случае имеет место быть оператор сравнения. В неявном виде.
Код:
if( var & mask ) ...
эквивалентно
Код:
if( (var & mask) == TRUE ) ...
В любом случае результирующее действие будет зависеть от результата выполнения условия, а оно может быть только двух типов. TRUE or FALSE. Что бы мы там в условии не наворотили.
разные вещи. В первом куске кода мы сравниваем условие и флаги с помощью ==, а во втором &. Когда-нибудь так можно нарваться на ошибку.
А на какую именно ошибку можно нарватся? Я например всегда использую второй способ. (первый способ иногда может не отработать... зато он исключает неоднозначности.....)
Можно подробнее, какую ошибочную ситуацию вы имеете ввиду?
Так, немного подробнее, а то не понимаем друг-друга.
Возьмем свитч:
Код:
switch(var) { case 0x01: ... break; }
Он эквивалентен следующему:
Код:
if (var == 0x01) { ... }
Но ни в коем случае не такому:
Код:
if (var & 0x01) { .... }
Если переменная содержит набор битовых флагов, то первый if сработает тогда и только тогда, когда установлен только нулевой бит. Если в переменной будут установлены еще какие-нибудь биты, то условие не сработает. Скорей всего это не то, что хотелось бы при работе с битовыми флагами.
Если переменная содержит набор взаимоисключающих непересекающихся значений (к примеру, enum со списком цветов Red|White|Blue|Green), то второе условие будет срабатывать каждый раз, когда установлен нулевой бит. Это тоже, скорее всего, не то, что хотелось бы при работе с такими данными.
Ну это понятно, что если говорить о: вообще операции сравнения, то тут куча вариантов того что как будет работать..... Но мы сейчас говорим о функции обработки регистра флагов нажатых кнопок....
Тут единственно в данном решении нужно не забывать правильно дефайнить те же key_1 2 3... Так как я понимаю в if идет побитовое И. И если например key_3 задефайнить как
Код:
#define key_1 1 #define key_2 2 #define key_3 3
то в результате key_1 & key_3 даст не нулевой результат. Если же задефайнить так
Код:
#define key_1 1 #define key_2 2 #define key_3 4
тогда результат в любом сочетании будет правильный. ИМХО
Ну, я это заметил, но ведь там было 0x01, 0x02 и 0x04. Ошибка с трехкратным вызовом функции была более вопиющей, поэтому я уже и не стал об этом писать.
Хотя вообще использование == там действительно более правильное, т.к. две кнопки одновременно функцией всё-равно никогда не возвращаются, и возможное число кнопок возрастает экспоненциально.
А я себе давно уже такую библиотечку слепил, обрабатывает короткие и длинные нажатия 4-х кнопок. Если чуть допилить то и на STM можно...
Вообще можно и == и & применять.....
Если в сравнении стоит ==, то например в ситуации когда в основном цикле обрабатывалась какая то тяжелая функция, и за это время успели последовательно нажать несколько разных кнопок, то потом в сравнении не отработается ни один путь... т.к. будут установлены несколько флагов, что не будет соответствовать ни одному сравнению.....
Если в сравнении стоит &, то в той же ситуации последовательно отработаются оба нажатия..... НО, есть одно НО.... последовательность вызова соответствующих функций будет определятся порядком сравнения в программе, а не порядком нажатия кнопок, что может привести к неправильной последовательности действий.....
Но, т.к. в простых задачах в основном цикле обычно нет таких тяжелых функций.... да и так быстро обычно кнопки не нажимают.... то по сути оба варианта будут нормально работать.
Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 13
Вы не можете начинать темы Вы не можете отвечать на сообщения Вы не можете редактировать свои сообщения Вы не можете удалять свои сообщения Вы не можете добавлять вложения