Работа с битами
- Войдите на сайт для отправки комментариев
День добрый!
Есть такая задача, нужно из данных в виде четырёх шестибитных цифр, сделать шесть четырёхбитных, при этом не сильно нагрузив контроллер, ибо это всё делается внутри цикла.
То есть к примеру у нас есть B111111 B100000 B100000 B010101, числа доступны из заданных переменных, и каждый раз разные.
Нужно взять четыре старших бита из первого числа в первую переменную, во вторую переменную два младших бита из первого числа, и два старших из второго, в третью переменную четыре младших из второго числа, ну и со второй парой проделать то же самое.
Собственно как взять определённые биты, - вполне понятно, непонятно как без танцев с бубнами взять в переменную два младших из одного и два старших бита из другого числа, так что бы это превратилось в ззначение переменной,(если с указанными выше числами) типа - B1110.
Плиз хелп!
Добрый!
Первое, что пришло в голову, bitRead(), bitWrite(), сложно сказать на сколько это нагрузит системе, я новенький ))
Например по этой ссылке
https://www.youtube.com/watch?v=rH_uSDIMhVw&index=5&list=PL39560B9703BCFE53
Интересно. А как вы храните в памяти 4 шестибитные и 6 четырехбитные числа?
Переменную какого типа для этого используете?
Сколько пространства отводится в памяти на каждую переменную?
<< , >>
То есть к примеру у нас есть B111111 B100000 B100000 B010101, числа доступны из заданных переменных, и каждый раз разные.
Нужно взять четыре старших бита из первого числа в первую переменную, во вторую переменную два младших бита из первого числа, и два старших из второго, в третью переменную четыре младших из второго числа, ну и со второй парой проделать то же самое.
Собственно как взять определённые биты, - вполне понятно, непонятно как без танцев с бубнами взять в переменную два младших из одного и два старших бита из другого числа, так что бы это превратилось в ззначение переменной,(если с указанными выше числами) типа - B1110.
d1=(c1>>2)&0x0F;
d2=((c1<<2)&0x0C) | ((c2>>4)&0x03);
и т.д.
Andy А вот в последней строке присвоение d2, если я напишу вместо 0x0C - B001100 и вместо 0x03 - B000011 это сработает?
Конечно сработает.
при этом не сильно нагрузив контроллер, ибо это всё делается внутри цикла.
Судя по этой фразе задача практическая
То есть к примеру у нас есть B111111 B100000 B100000 B010101, числа доступны из заданных переменных, и каждый раз разные.
поскольку задача практическая, то самая маленькая переменная будет, как ни крути, занимать 8 бит. следовательно надо читать из 0b00111111 (0b-arduino все-ж : -), 0b00100000, 0b00100000, 0b00010101 и соответственно получить: 0b00001111, 0b00001110, 0b00000000, 0b00001000, 0b00000001, 0b00000101
Исходя из есть и надо напишите используя сдвиги влево и в право, сумирование сначала все по действиям. если цикл использовать очень надо перепешите в цикл.
если задача теоретическая, кто его знает может препод требует (я сказал и все!), шестибитное и четырехбитное объявил, придумал препод так, то двигайте без учетов первых двух нулей.
Да, это сугубо практическая задача. И нет, если дополнять до полного бита, выходит неверно.
Чтоб не было разночтений, - речь идёт о генерации IR пакета, который имеет вид:
111111 000000 111111 0000000 11 00 1111
первые четыре поля по 6 бит, это соответственно скорость моторов, Вправо/Влево, Вперёд/назад и трим(соотношение скорости между двумя моторами). Далее два бита указывающие канал и ещё два это вкл/вкл Лед подсветки.
Собственно известно что последние четыре бита, это CRC. И я проверил по десятку пакетов, расчитывается она однозначно верно, если разделить всё до CRC на группы по четыре бита, сложить их, из суммы взять младшие четыре бита, и следать реверс, - поменять все единицы на нули, а нули на единицы(просто бывает ещё с лево на право реверс).
Пакет нужно отсылать непрерывно, а считается он сложно, в двух вложенных циклах.
Вот я и думаю как бы мне самым минимальным выражением, подсчитывать CRC. Пока я сделал функцию которую вызываю сразу за получением в цикл параметров, и которая возвращает переменную с этими четырьмя битами. Но что-то пока не очень..
Так что если есть предложения - велком. :)
Кстати, есть ли простой способ проверять выражения в коде, не мучая каждый раз ардуинку и вписывая кучу лишнего(типа вывода в сериал, всех промежуточных значений)?
mahatm,
Вас уже спрашивали в каких переменных Вы храните свои шестибитовые числа. Почему Вы не отвечаете? От этого многое зависит.
Пока, я вижу наиболее кошерное решение безо всяких сдвигов и прочих танцев с бубнами, путём накладывания одних чисел на другие в памяти. Т.е. просто сложить все шестибитовые подряд в памяти, а потом из той же самой памяти прочитать их как 4-битовые, и всего делов.
Вот смотрите:
Но если Вам надо что-то ещё, то не знаю.
Переменные принимаются в функцию непосредственно передачи IR , в виде byte name1...
Дальше они складываются в массив и оттуда уже всячески достаются и мучаются.
А беруться они просто из аналогового порта, - переменника(резистора). Правда щас я собираю новый шилд, на нём переменники в виде джойстика, но это не суть важно. В общем на данный момент мне наконец удалось выиграть если не войну то сражение с битовыми операциями, и мой вертолётик наконец полетел.. Правда пока "нызенко, нызенко".. :)
Переменные принимаются в функцию непосредственно передачи IR , в виде byte name1...
Дальше они складываются в массив и оттуда уже всячески достаются и мучаются.
Ну, тогда складывайте их как я написал, а потом вытаскивайте - никакиях явных преобразований. Если чего ещё надо - говорите, обсудим.
Вот окончательно работающий код для моего вертолётика, может пригодиться кому. Код сурово закоментирован, но(сорри) не вычищен от остатков вылизывания. Ещё раз подчёркиваю он полностью рабочий. С удовольствием приму каменты по возможной правке в сторону красоты и главное эфективности.
Вертолётик серии 8185, такие продают в сети "Детский мир". Они там средние по цене.
Для собственно управления был сделан шилд, 4х6 см, из стандартной готовой для пайки платы с дырочками, двухсторонней. На нём размещены: три последовательно соединённых IR LED, Потенциометр в виде джойстика для Throttle, Два потенциометра в виде второго джойстика для управления Left/Right и Forward/Back, отдельный маленький потенциометр для trim.
С двух сторон были впаяны штырьки, что бы оно всё втыкалось в плату (Leonardo) в одну секунду, и так же снималось.
Стоит добавить что леды подключены через транзистор NPN, соответственно установленный в нижнем плече, и управляемый через малоомный резюк с пина ардуины(база транзистора, на пин ардуины).
Код был оптимизирован, решил добавить. Плюс теперь большая часть кода с каментами.