Использование прерываний и микросхемы-дешифратора
- Войдите на сайт для отправки комментариев
Чт, 22/10/2015 - 07:02
Начитался статей наподобие http://avrproject.ru/publ/kak_podkljuchit/kogda_ne_khvataet_nog_chast_1_deshifrator_4_16/2-1-0-12
собрал эту схему, написал код
byte massa = B0; const int buttonPin1 = 10; // номер выхода управление дешифратором const int buttonPin2 = 11; // номер выхода управление дешифратором const int buttonPin3 = 12; // номер выхода управление дешифратором const int buttonPin4 = 13; // номер выхода управление дешифратором int knopf ; //переменная состояния кнопки const int buttonPin = 2; // номер входа прерывания unsigned long previousMillis ; // для таймеров void setup() { attachInterrupt(0, blink, FALLING ); // прерывание по 2 пину при переходе с высокого на низкий уровень Serial.begin(9600); //монитор порта pinMode(buttonPin1, OUTPUT); //инициализация вывода управления дешифратором pinMode(buttonPin2, OUTPUT); //инициализация вывода управления дешифратором pinMode(buttonPin3, OUTPUT); //инициализация вывода управления дешифратором pinMode(buttonPin4, OUTPUT); //инициализация вывода управления дешифратором pinMode(buttonPin, INPUT); //вход на атмеге с дешифратора (клавиатура) } void loop() { unsigned long currentMillis = millis(); if (currentMillis - previousMillis > 10) { Serial.println(knopf); // тестовая строка previousMillis = currentMillis; if ( massa <= B1111 ) { digitalWrite( 10, bitRead( massa , 0 )); digitalWrite( 11, bitRead( massa , 1 )); digitalWrite( 12, bitRead( massa , 2 )); digitalWrite( 13, bitRead( massa , 3 )); /* Serial.print(digitalRead(buttonPin1)); //тестовая строка состояний пинов на входе в дешифратор. Serial.print(digitalRead(buttonPin2)); Serial.print(digitalRead(buttonPin3)); Serial.println(digitalRead(buttonPin4)); */ massa = massa + 1; if ( massa > B1111 ) { massa = B0; } } } } void blink() { //прерывание по нажатию кнопки, присвоение значения нажатой кнопки if ( massa == B1111 ) { knopf = 0 ; } if ( massa == B0111 ) { knopf = 15 ; } if ( massa == B1011 ) { knopf = 14 ; } if ( massa == B0011 ) { knopf = 13 ; } if ( massa == B1101 ) { knopf = 12 ; } if ( massa == B0101 ) { knopf = 11 ; } if ( massa == B1001 ) { knopf = 10 ; } if ( massa == B0001 ) { knopf = 9 ; } if ( massa == B1110 ) { knopf = 8 ; } if ( massa == B0110 ) { knopf = 7 ; } if ( massa == B1010 ) { knopf = 6 ; } if ( massa == B0010 ) { knopf = 5 ; } if ( massa == B1100 ) { knopf = 4 ; } if ( massa == B0100 ) { knopf = 3 ; } if ( massa == B1000 ) { knopf = 2 ; } if ( massa == B0000 ) { knopf = 1 ; } }
Вроде все должно работать, но у меня такое ощущение, что прерывание работает не так, как я думал: при нажатии на кнопку оно присваевает значение переменной knopf, но при повтороном нажатии на кнопку оно его меняет на некоторое другое. И так с каждой кнопкой. Не могу понять, почему так происходит(
Строку 8 изменил на
не полегчало
Теперь сделай для 1 строки так же.
42 строка: massa++
В 34-37 вместо bitread лучше использовать сдвиг.
И не вижу гашение дребезга.
Ну, во-первых, давайте сначала упростим код. Например, Ваша длинющая функция blink() полностью эквивалента вот такой маленькой:
Во-вторых, если есть сомнения в том, что присваивается переменной - её нужно печатать и смотреть. Вывод в сериал внутри оработчика прерывания само по себе плохо и в окончательной программе этого быть не должно, но для отладки поставьте и посмотрите.
КОгда сделаете, если останутся непонятки, выложите свежий код и лог того, что печаталось с пояснениями, что нажимали.
И ещё: в данном компиляторе с опциями по умолчанию всё работет как надо, но я всё же не советовал бы Вам так использовать двоичные константы. Начинайте их с нуля. Т.е. вместо B1111, пишите B01111. Разницы никакой, но зато есть гарантия что шибко умный компилятор не развернёт Вашу константу в отрицательное число.
Теперь сделай для 1 строки так же.
42 строка: massa++
В 34-37 вместо bitread лучше использовать сдвиг.
И не вижу гашение дребезга.
добавил volatile и для первой строки. Изменил massa на massa++. Касаемо bitread я проверял, она рабтает отлично: я делал вывод в монитор порта состояний выводов, замечаний не было. Поэтому пока трогать не буду.
По поводу защиты от дребезга, а есть ли смысл? при смене уровня сигнала даже если и будет дребезг, просто прерывание вызовется несколько раз, но переменная knopf все равно должна приравниваться к одному и тому же числу. (я его сделаю, но потом, мне кажется, что проблема все таки не в дребезге).
Не полегчало. Все равно knopf принимает рандомные значения. при задержке нажатия кнопки и (иногда) при повторном значении
Ну, во-первых, давайте сначала упростим код. Например, Ваша длинющая функция blink() полностью эквивалента вот такой маленькой:
Во-вторых, если есть сомнения в том, что присваивается переменной - её нужно печатать и смотреть. Вывод в сериал внутри оработчика прерывания само по себе плохо и в окончательной программе этого быть не должно, но для отладки поставьте и посмотрите.
КОгда сделаете, если останутся непонятки, выложите свежий код и лог того, что печаталось с пояснениями, что нажимали.
И ещё: в данном компиляторе с опциями по умолчанию всё работет как надо, но я всё же не советовал бы Вам так использовать двоичные константы. Начинайте их с нуля. Т.е. вместо B1111, пишите B01111. Разницы никакой, но зато есть гарантия что шибко умный компилятор не развернёт Вашу константу в отрицательное число.
исправил функцию blink на Ваш вариант. Касаемо лога, сделал так:
вгрузил и запустил монитор порта. Там было следующее
Что мы тут видим, нули вначале появляются при нажатии кнопки и если ее зажать. При нажатии второй кнопки появляется число 512, если же ее зажать то выводятся еще три нуля. Затем 512 и все вновь.
Вторая кнопка? o_0
У тебя же в лупе идет щелканье выходами из изменение massa, а в прерывании вывод в порт числа из массива по индексу massa.
Замени еще в 25 строке INPUT на INPUT_PULLUP, чтобы вход Маяк не ловил. :)
Вторая кнопка? o_0
У тебя же в лупе идет щелканье выходами из изменение massa, а в прерывании вывод в порт числа из массива по индексу massa.
Замени еще в 25 строке INPUT на INPUT_PULLUP, чтобы вход Маяк не ловил. :)
Эээ, ну да, вторая и третья, и четвертая... Я же говорил, что собрал схему из http://avrproject.ru/publ/kak_podkljuchit/kogda_ne_khvataet_nog_chast_1_deshifrator_4_16/2-1-0-12
она там на последней картинке. Касаемо пуллапа, то вход через резистор в 10кОм подянут к плюсу. Хотя не спорю, можно просто прописать пуллап и убрать резистор. Но пока не заработает оригинальная схема, мне бы не хотелось, что-либо в ней менять.
Касаемо работы программы, я думаю, что она работает так:
каждые 10 милисекунд происходит изменение переменной massa, потом она разделяется на биты и биты записываются в сосотояние выводов. Соответственно микросхема-дешифратор выдает на одной из 16 ножек-выходов низкое напряжение. Повторюсь, каждые 10 милисекунд состояние меняется. Если же мы нажимаем кнопку, то до тех пор, пока massa не образует комбинацию такую, что на выходе дешифратора с нажатой кнопкой не образуется низкий сигнал прерывание происходить не будет, т.к обычное состояние выводов дешифратора высокое. Как только эта комбинация достигнута, программа прерывается, в прерывании переменной knopf присваивается значение из массива соответствующее текущему значению massa. Но в примере из интернета другая логика работы программы.
Убрал резистор, использовал внутренню подтяжку к плюсу. В серийном порте получил следующее:
при нажатии на 1 кнопку 512 и если удерживать то три нуля, потом зацикливается, при нажатии на вторую 769 и один ноль, потом зацикливается. Откуда там такие числа???
вывод в порт написал так
исправил функцию blink на Ваш вариант. Касаемо лога, сделал так:
Что мы тут видим, ...
Нет, так не пойдёт - ничего мы тут не видим. Надо и massa печатать. Как-нибудь так:
Теперь Вы будете видеть какой была knopf в момент прерывания, какой была massa и как поменялась knopf. Тогда Вы сможете что-то понять.
Почему все новички так любят работать вслепую? :))))
исправил функцию blink на Ваш вариант. Касаемо лога, сделал так:
Что мы тут видим, ...
Нет, так не пойдёт - ничего мы тут не видим. Надо и massa печатать. Как-нибудь так:
Теперь Вы будете видеть какой была knopf в момент прерывания, какой была massa и как поменялась knopf. Тогда Вы сможете что-то понять.
Почему все новички так любят работать вслепую? :))))
Потому что когда не видно - не страшно)
слегка исправил Ваш пример
получил следующее
как я вижу, прерывание вызывается в любой момент, т.е. оно почему-то не ждет перепада уровня, а прсто работает неограниченно от 1 перепада? Откуда оно вообще такие числа как 512 берет??? это может не десятичная система???
del
LOW = !HIGH
Что не так?
но прерывание же у меня вызывается как
attachInterrupt(0, blink, FALLING );
где FALLING именно перепад, именно с HIGH на LOW, а не постоянное состояние.
Подключение еще проверь. Питание дешифратора, наличие соплей. Просто так пин на землю коротиться не должен.
Пожалуйста. уберите двойки и десятки из всех принтов.
Дайте полный скетч (текущую версию) и лог Seriala обязательно с самого начала. Я посмотрю.
оно почему-то не ждет перепада уровня, а прсто работает неограниченно от 1 перепада?
Ладно, сделайте то, что я просил - будем думать где она 512 берёт.
Кстати,
byte
massa = B0;
тоже нужно сделать volatile
текущий скетч
лог
при нажатии (при нажатии и удержании) на кнопку:
при нажатии на дргую кнопку
фото. что бы все могли убедиться, что аппаратно схема правильная:
Уберите PROGMEM из строки 51 и скажите поменялся ли лог (так же ли там всё время 0 и 512 или нет).
после того как убрал
кнопка первая
кнопка вторая
Так, уже лучше. Значения присваиваются правильные. Т.е. knopf изменяется так, как и должна.
То, что на одно нажатие вываливается много прерываний - следствие дребезга или неверной схемы.
Ещё какие-то вопросы остались? Что-то ещё непонятно? Знаете, как от дребезга избавиться?
Так, уже лучше. Значения присваиваются правильные. Т.е. knopf изменяется так, как и должна.
То, что на одно нажатие вываливается много прерываний - следствие дребезга или неверной схемы.
Ещё какие-то вопросы остались? Что-то ещё непонятно? Знаете, как от дребезга избавиться?
Про дребезг догадываюсь, но с удовольствием выслушаю Ваш вариант.
Спасибо за помощь
Про дребезг - вот здесь самое лучшее, что я видел. Можно сказать "энциклопедия боьбы с дребезгом" и программно, и аппаратно - http://www.eng.utah.edu/~cs5780/debouncing.pdf
Про дребезг - вот здесь самое лучшее, что я видел. Можно сказать "энциклопедия боьбы с дребезгом" и программно, и аппаратно - http://www.eng.utah.edu/~cs5780/debouncing.pdf
премного благодарен, когда я перенес с макетки на плату с пайкой, оно заработало отлично, дело действительно было то ли в дребезге, то ли где-то что-то отходило.
Обнаружил следующую фичу:
я писал про задваивание значений, сперва одно, потом другое. Кажись я понял в чем дело, это не дребезг, просто обращаясь к массиву со значениями knopf он переводит massa в десятичную систему, а там 010 и 10 одинаково равно 2 в десятичной. Видимо тсюда и идет задваивание. Такое возможно?
так как в логе видно при зажатии кнопки (massa в двоичной ситеме)
и еще мне кажется, что он читает байты справа налево...
при зажатии следующей кнопки видим другое
хотя на некоторых пинах все работает превосходно
Никто никого никуда не переводит. Все числа хранятся одинаково - их представления в разных системах - только для Вас, чтобы Вы читали - хранится всё одинаково.
Там он тупо использует massa в качестве индекса и берёт число из массива.
Нетникакой мистики, не забивайте себе голову. Следующие строки абсолютно идентичны:
a = 9;
a = 011;
a = b01001;
Абсолютно! Нет никакой разницы.
вероятно прерывание, вызываемое в любой момент, прерывает запись состояний выводов атмеги. И не смотря на то, что масса уже задана, выводы находятся еще не в том состоянии, в котором должны, что и вызывает множественные переключения (которые, кстати, всегда одни и те же). Т.е. сперва срабатывает одно ложное состояние, потом второе и .т.п. Так же это может быть связано с тем, что выводы записываются по очереди, а не одновременно, что и вызывает некий набор промежуточных состояний.
Тогда как Вам такая версия?