Как инвертировать полученные данные

Skeep
Offline
Зарегистрирован: 30.05.2013

Оцифровываю сигнал и получаю число на пример 700 это в двоичной 1010111100, мне нужно инвертировать двоичный крод -> 0101000011 и передать его уже в десятичной, это 323, через Serial.println на монитор компьютера. Помогите с программой для инверсии.

leshak
Offline
Зарегистрирован: 29.09.2011

К сожалению, этот раздел документации не перевели, так что "только оригинал" Arduino - BitwiseXorNot

 

leshak
Offline
Зарегистрирован: 29.09.2011
unsigned long value=700;
Serial.println(~value,DEC);

 

Skeep
Offline
Зарегистрирован: 30.05.2013

leshak пишет:

unsigned long value=700;
Serial.println(~value,DEC);

 

Не работает( 

leshak
Offline
Зарегистрирован: 29.09.2011

Только еще один нюанс не забудте. У нас нет типа данных размером в 10 бит. Ближайшие куда влезет наше 700 - двух-байтовое что-то.

А значит, 700, в двоичном у нас будет B0000001010111100

То есть слева оно дополнится нулями. До тех пор, пока вы не инвертнули числа - эти нуля рояля не играют. Но после инвертирования - они станут единицами, и станут "заметны".

Получится B1111110101000011, что в десятчином уже совсем не 323, а 64835 если мы взяли беззнаковый тип, или вообще отрицательное число если знаковый взяли. 

leshak
Offline
Зарегистрирован: 29.09.2011

Skeep пишет:

leshak пишет:

unsigned long value=700;
Serial.println(~value,DEC);

 

Не работает( 

Супер. Очень информативно. Ну значит нужно "что-то сделать".

Skeep
Offline
Зарегистрирован: 30.05.2013

А как сделать чтобы поменять метсами байты, например первый со вторым 5 с 9 и т.д.??

leshak
Offline
Зарегистрирован: 29.09.2011

Если же есть желание, инвертировать только "младшие биты", а старшие оставить "как есть".

То тут поможет чтение Arduino - BitwiseAnd

Предположим что нам нужно инвертить только 10-ть бит, а остальные "оставить нулями".

Тогда есть два пути: уже после конвертации обнулять все что старше, с помощью "Bitwise AND (&)"

unsigned int value=700;
unsigned int invValue=~value;// инвертировали
invValue&=B1111111111; // сбросили все кроме младших 10-ти битов
Serial.println(invValue,DEC);

Либо почитать эту ссылку дальше и всмотрется в оператор "Bitwise XOR (^)"  (если проблема с английским - гуглим любой справочник С/C++ и ищем раздел про битовые операторы - это они и есть).

Вообщем XOR как раз и позволяет задать маску по которой будет сделана инвертация, не трогая все остальное

unsigned int value=700;
unsigned int invValue=value ^ B1111111111;// инвертировали только младшие 10-ть бит
Serial.println(invValue,DEC);

И еще. Поймите простую вещь. Что у вас на мониторе происходит - никто не видите. Так что если "что-то не выходит", до тех пор пока вы детально не опишите - никто вам помочь не сможет.

leshak
Offline
Зарегистрирован: 29.09.2011

Skeep пишет:

А как сделать чтобы поменять метсами байты, например первый со вторым 5 с 9 и т.д.??

Видимо вы имели ввиду биты.

Подход простой. Читаем значение 5-того, запоминаем во временную переменную. Потом читаем 9-тый, устанавливаем 5-тый, в значение 9-того. Потому 9-тому, ставим то что запомнили во временную. 

Вообщем обычное "поменять местами значение двух переменных". Только вместо присвоения переменных - используем операции астановки/снятия битов.

Отдельные биты читать/ставить - А вот все теми же Arduino - BitwiseAnd

(кстати выше как раз пример, как я сбрасывал  в нулю старшие биты, после конвертации).

Вообщем откройте учебник по C/C++ и проштудируйте битовые операции. Не раз и не два пригодится.

Хотя, если покопатесь в документации Arduino - Reference в разделе "Bits and Bytes" сможете найти парочку готовых функций помогалок для установки/чтения битов. Но это, все-таки, лучше делать после того как уже будете уметь через & и | читать/ставить. Потому как 99% примеров и инете найдете именно через "& и |" и их все равно нужно понимать, а "ардуино функции" - только место в памяти занимают. Вообщем они "для чайников" :)

 

leshak
Offline
Зарегистрирован: 29.09.2011

И на всяк, случай, можете еще раз прочитать (даже если читали) Serial.println() | Аппаратная платформа Arduino

Обратите внимание, что .println умеет и в двоичном виде выводить переменные. Может оказатся очень удобно при разбирательствах/осваивании битовых операций.

Skeep
Offline
Зарегистрирован: 30.05.2013

Спасибо большое разобрался. Только вот какая проблема теперь: делаю XOR z^B111111111111, а при компиляции оно принимает B111111111111 не за число, а за переменную и выдает ошибку, что делать?  

leshak
Offline
Зарегистрирован: 29.09.2011

Skeep пишет:

Спасибо большое разобрался. Только вот какая проблема теперь: делаю XOR z^B111111111111, а при компиляции оно принимает B111111111111 не за число, а за переменную и выдает ошибку, что делать?  

Ну что же вы все время по одним и тем же граблям бегаете? Я же програмист, а не телепат.

Ну покажите код свой (предварительно, прочитав, если не читали, Вставка программного кода в тему/комментарий). Напишите какая именно ошибка.

leshak
Offline
Зарегистрирован: 29.09.2011

Ага. Зря наехал. Это мой же пример не компилится (могли бы и скать, что "ваш пример не работает" ;)

Никогда не думал, что дуина не воспринимает бинарные константы больше байта (если взять не 10-ть единиц, а 8-ми - тогда компилится).

Счас придумае что-нибудь.

Skeep
Offline
Зарегистрирован: 30.05.2013

Я уже придумал, можно просто это число в десятичном виде написать и всё работает) 

step962
Offline
Зарегистрирован: 23.05.2011

Skeep пишет:

Спасибо большое разобрался. Только вот какая проблема теперь: делаю XOR z^B111111111111, а при компиляции оно принимает B111111111111 не за число, а за переменную и выдает ошибку, что делать?  

Заглянуть в файл "./hardware/arduino/cores/arduino/binary.h" и понять, что определены только B-константы размером не более 8 бит.

Попутно уяснить для себя механизм определения таких констант и сделать пару-тройку-надцать новых определений под свои потребности.

leshak
Offline
Зарегистрирован: 29.09.2011

Ага. И винить некого, так и написанно в доке Целочисленные константы | Аппаратная платформа Arduino : "

2 ( binary - двоичный)  B1110111  первая B  только для 8-бит значений (0-255), разрешенные знаки 0 и 1"

Ну фиг с ним. Раз для 16-ти ричных такой оговорки нет, значит задатим константу шестнадцатерично 0x3FF

void setup(){
  Serial.begin(57600);
  unsigned int value=700;
  unsigned int invValue=~value;// инвертировали
  invValue=value ^ 0x3FF ; // инвертнули 10-ть битов. 0x3FF=B1111111111
  Serial.print("value=");Serial.println(value,DEC);
  Serial.print("invValue=");Serial.println(invValue,DEC);

}

void loop(){
}

Выводит:

value=700
invValue=323

Как и ожидалось.

leshak
Offline
Зарегистрирован: 29.09.2011

Но, из принципа, можно все-таки и двоично :)  Собрать из двух байтов

 invValue=value ^ ((B11<<8) | (B11111111)) ;

Или замиксовать (что-бы 8-мь единиц на глаз не набирать)

  invValue=value ^ ((B11<<8) | 0xFF ) ;

 

step962
Offline
Зарегистрирован: 23.05.2011

или написать

#define B1111111111 1023

и пользоваться "десятибитовой" B-константой.

leshak
Offline
Зарегистрирован: 29.09.2011

step962 пишет:

или написать

#define B1111111111 1023

и пользоваться "десятибитовой" B-константой.

Ну или так. Честно говоря, в голову не приходилое что это через директивы препроцессора сделано.

Всегда считал что это "синтаксис языка", а значит на уровне компиляторо должно быть реализованно.

Ну "будем знать".

Geronimo
Offline
Зарегистрирован: 06.05.2013

leshak пишет:

step962 пишет:

или написать

#define B1111111111 1023

и пользоваться "десятибитовой" B-константой.

Ну или так. Честно говоря, в голову не приходилое что это через директивы препроцессора сделано.

Всегда считал что это "синтаксис языка", а значит на уровне компиляторо должно быть реализованно.

Ну "будем знать".

конструкции типа B010101

я только на ардуино форумах увидел...

kisoft
kisoft аватар
Offline
Зарегистрирован: 13.11.2012

А я еще в детства привык к HEX, бинарные константы, да еще сделанные через одно место не перевариваю. Но это каждому своё.