Битовый сдвиг
- Войдите на сайт для отправки комментариев
Ср, 03/08/2016 - 08:39
Мне нужно управлять светодиодной матрицей. Пытаюсь получать из функции управляющий сигнал вида B00000000. т.е. для X = 3, Y = 2 должно получиться B01000010. - Младшие 4 бита - это Х координаты, старшие - Y.
Написал вот такую функцию
void LedOn(int x, int y) { int num = B00000000; //создаем переменную if (x < 5 && x > 0) { //Проверяем что введенные данные подходят для матрицы 4х4 int xn = 1; //создаем переменную равную 1 xn<<3; //делаем сдвиг влево, для перехода к младшим битам должно получиться 8(DEC) или 1000(BIN) xn<<x; //сдвигаем влево, что бы единица встала на нужное место. Для x = 3, должно получиться 01000000. num|xn; //делаем ИЛИ с num. Получится 01000000 Serial.println(num, BIN); // в Протеусе выдает 0 } if (y < 5 && y > 0) { int yn = 1; yn<<y-1; num|yn; //В результате для Х = 3 У= 2 должно было получиться 01000010. Но и тут протеус выдает 0. } }
У меня ошибка в коде или Протеус тупит?
У меня ошибка в коде или Протеус тупит?
DezmontDeXa, да похоже вся функция сплошная ошибка. Для начала поясните, как , цитата "для X = 3, Y = 2 должно получиться B01000010"
Если младшие пол-байта это X, то Y остаётся просто задвинуть на 4 бита влево, результат = x | (y<<4) , то есть будет B00100011
дело не в числах которые получаются. Мне важна последовательность битов. С ардуины этот байт попадет на сдвиговый регистр. При данных: X = 3, Y = 2. Я хочу получить подледовательность битов 0100 0010 - где
0100 - означает X = 3. Единица сдвинута влево на 3.
0010 - Y=2. Единица сдвинута влево на 2.
Не сомневаюсь, что можно использовать другую последовательность, для которой потребуется лишь изменить связи в Протеусе. Но вот уже дошел умом до чего-то подобного.
DezmontDeXa, тогда так: rezultat = (1<<x+3) | (1<< y-1);
Спасибо! Так работает, но я не понимаю что было не так. Ну всм, ваш код гораздо компактнее и понятнее, но смысл то вроде тот же. Или нет? Распишите, пожалуйста, нужно ведь учиться, а не тупо исправлять косяки)
DezmontDeXa, чессно говоря смотреть что в вашем не так -утомительно. В моём объяснялка простая - установить в переменной "результат" два бита , под номерами (х+3) и (у-1)
Спасибо! Так работает, но я не понимаю что было не так. Ну всм, ваш код гораздо компактнее и понятнее, но смысл то вроде тот же. Или нет? Распишите, пожалуйста, нужно ведь учиться, а не тупо исправлять косяки)
Только всё остальное сам, без меня, потому что гугл всё знает.
Кисофт, спасибо! Уже в котоырй раз выручаешь)
xn<<x; //сдвигаем влево, что бы единица встала на нужное место. Для x = 3, должно получиться 01000000.
Кому должно? Ну, сдвинули Вы, а результат куда? Выбросили? Присваивать его (результат) Вы чему-нибудь собираетесь?
Без разницы, но второе более системно.
Читайте о приоритетах операций.
Лично мне лень запоминать, в каком языке какие приоритеты, поэтому я всегда выбираю второй вариант.
Еще вопрос по теме битовых операций.
num=1<<x+3|1<<y-1;
Я упустил момент. Мне нужно инвертировать биты показывающие Y т.е. второй операнд ИЛИ должен быть инвертирован.
num=(1<<x+3)|(~(1<<y-1)); - так инвертируются все 16бит(или сколько там в типе int?)
не хватет мне мозгов придумать как это слелать)
Сделал вот такую функцию, но может есть способ проще?
rezultat = (1<<x+3) | 15 & ~(1<< y-1);
Как всегда потрясающе) Как можно блин, так легко решать пободные задачи одним блин выражение?!
DezmontDeXa, а вы поменьше пользуйтесь ардуиновскими функциями, тогда битовые операции волей-неволей станут намного ближе и понятней:)
Не могу нигде найти что за операции. Есть подозрение что битовые <<= и |=
Применительно к коду:
cardid <<= 8;
cardid |= uid[1];
На что более понятное можно заменить?
Не могу нигде найти что за операции. Есть подозрение что битовые <<= и |=
Применительно к коду:
cardid <<= 8;
cardid |= uid[1];
А чего их искать, вот они - операции http://ru.cppreference.com/w/cpp/language/operator_precedence
На что более понятное можно заменить?
А что Вам "более понятно"?
Не могу нигде найти что за операции. Есть подозрение что битовые <<= и |=
Применительно к коду:
cardid <<= 8;
cardid |= uid[1];
На что более понятное можно заменить?
вот почему, после таких вопросов, не банить? из милосердия
вот почему, после таких вопросов, не банить? из милосердия
Эвтаназия вроде как вне закона.
Дак пусть себе и жил бы на другом каком форуме. Но если за полтора года ничему не научился здесь, то нафига продолжать. И это реально милосердие. У чела жизнь одна, а он её так безцельно на ардуино тратит.
спасибо за помощь. Как всегда когда делаещь что то новое приходится разбираться в том что есть. А если буржуи таким способом переводят шестнадцатиричную систему в десятичную поэтому и возникают вопросы.
Готовых кодов читать карты под pn532 сложно найти. А как пользоваться библиотекой и подавно.
Это нормально?
Нормально.
А Вы чего ожидали?
А если так var= ((uint32_t)1 << 15); ?
Или var=(1UL <<15); ?
Нормально.
А Вы чего ожидали?
А я ожидал что единицу переместить до конца влево можно.
В функии вывода символа на LCD используется маска, еденица в которой последовательно перемещается слева направо.
Пока выводил символы шириной до 16, проблем не было.
Написал шрифт шириной 32 и (посадив шпионов во внутырь функции) обратил внимание что оператор "for" игнорится. Причина только одна - mask равна нулю.
поупражнявшись с выводом разных значений в бинарном виде вспомнил Хайяма.
.. " Мне известно, что мне ничего не известно.
Вот последняя правда открытая мной."
А если так var= ((uint32_t)1 << 15); ?
Или var=(1UL <<15); ?
Да, так получается.
for(mask=((uint32_t)1<<(width-1)); mask!=0; mask>>=1)
Теперь "шпионы" сказали что оператор выолняется.
В двух словах поясните?
А я ожидал что единицу переместить до конца влево можно.
Так она до конца и сдвигает. Ведь Вы что написали?
var = (1 << 1);
Сначала вычисляется правая часть, а потом выполняется присваивание. Что у Вас в правой части? Единица типа int. Вот её Вы и сдвигаете, а она 16-битная и знаковая! А уже результат этого сдвига будет преобразован в uint32_t и присвоен var.
Понятно?
Что делать Вам уже nik182 сказал.
Понятно?
Да, спасибо.
Опять я к вам. Только я не по поводу ограбленного Шпака, нет... Тут дело похлеще будет...
Atmega168P.
Есть глобальная переменная 16 бит.
При каждом цикле присваиваем случайное значение:
Затем в цикле "for" перебираем по битам.
Если бит установлен, читаем содержимое eeprom с номером установленного бита + 20.
Перебираем и находим какой по счёту бит установлен уже в восьми битной переменной.
Запоминаем, а затем значение сдвигаем на 1 бит влево. (или устанавливаем нулевой).
После чего записываем новое (сдвинутое на бит влево) значение в ту же ячейку до следующего раза.
Для чего это я делаю не важно наверное.
Проблема появляется в сдвиге, точнее после него. Причём если работать только с одним битом 16-и битной, то проблем нет. Всё как надо сдвигается. Но если 2 и больше, то с первым по счёту всё ОК,а в остальных после сдвига может появится единичка. Вот наглядно:
col - номер бита
rd1 - значение до сдвига
rd2 - после сдвига
dat - новые данные записанные в ее
rd3 - прочитанные из ее после записи (контрольно)
Нулевой или первый бит по по порядку, не важно. Всё как надо.
А остальные:
После сдвига просто появляется единица:
То есть даже не сдвигается.
Вот Этот же кусок кода целиком:
Сначала думал что с чтением из ЕЕ что то не так. Сдвигаю не так. Но если одна или первая без проблем, что потом не так? Грешу на железо... после рук естественно....
Конечно железо виновато, кто ж еще-то.
Где объявления переменных? Сделайте такой фрагмент, чтобы его можно было проверить на более другом железе.
Да я не утверждаю, а предпоЛАГАЮ.
Переменные локальные (кроме вышеупомянутой). Это собственно первая строчка в функции.
В общем то и реализация сводится к экономии всех типов памяти.
PS. Нашёл. Так тупо. Откуда, думаю, единички перетягиваются.
Перед повторным перебором байта предыдущий номер установленного бита обнулить надо...
Я его при объявлении во избежании подобных лагов обнулял. А в цикле for он та остаётся.
В любом случаи спасибо что откликнулись и не стали критиковать исполнение.