Побитовое чтение из двухбайтного числа и перестановка байтов местами

freeman86
Offline
Зарегистрирован: 07.09.2016

Начал  делать чтение первого байта из числа, но получается ерунда на выводе. Случайно получилось, что младший байт считывается, хотя возможно это случайность. Не понимаю как в цикле с одной итерацией может считаться сразу 8 бит... Может чего подскажите, как правильно считать, сохранить, а потом собрать в один uint16_t ?

void setup() {
 Serial.begin(9600);
}

void loop() {
  uint8_t Byte_1;
   uint16_t B = 65500;
   for(uint8_t i = 0; i < 1; i++){
       Byte_1 += (B << i);
   }
   Serial.println(B, BIN);
   Serial.println(Byte_1, BIN); 
}

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

BOOM
BOOM аватар
Offline
Зарегистрирован: 14.11.2018

Может для начала в битовых операциях использовать двоичные данные (что для понимания проще, да и, наверное, лучше)?

А дальше по классике, представление, маска и так далее. Ну мне в 10м формате даже код не особо понятен, а самому пересчитывать лень. 

freeman86
Offline
Зарегистрирован: 07.09.2016

Когда  я делал так, результат получился тот же самый) 

uint16_t B = 0b1111111111011100

 

b707
Offline
Зарегистрирован: 26.05.2017
uint16_t B =65530;
uint8_t B_1 = B & 0x00FF;    // младший байт
uint8_t B_2 = (B & 0xFF00) >> 8;  // старший байт
uint16_t B2 = (uint16_t)(B_1 << 8) + B_2;   // поменять местами и собрать обратно uint16

 

DetSimen
DetSimen аватар
Онлайн
Зарегистрирован: 25.01.2017

не слушай его, маядеточка, всё в одну строчку делается. 

uint16_t src = 65530;

uint16_t swapped = (src<<8) | (src>>8);

sadman41
Онлайн
Зарегистрирован: 19.10.2016

DetSimen пишет:

не слушай его, маядеточка, всё в одну строчку делается. 

uint16_t src = 65530;

uint16_t swapped = (src<<8) | (src>>8);

А биты в байте перевернуть так же смогёшь? ;)

DIYMan
DIYMan аватар
Offline
Зарегистрирован: 23.11.2015

По поводу битовых операций - в своё время наткнулся на отличную статью: https://graphics.stanford.edu/~seander/bithacks.html Там есть ВСЁ, и ещё чуть-чуть. Рекомендую.

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

DIYMan, отличный материал! Только давать его ТС (который путает биты и байты) - это жирный троллинг :-)

DetSimen
DetSimen аватар
Онлайн
Зарегистрирован: 25.01.2017

sadman41 пишет:

А биты в байте перевернуть так же смогёшь? ;)

в одну строчку - нет, не смогу. 

template<typename T>
T Reverse(T ASrc) {
	T result = 0;
	for (uint8_t i = 0; i < sizeof(T); i++) {
		result <<= 1;
		result |= (ASrc & 0x01);
		ASrc >>= 1;
	}
	return result;
}

 

b707
Offline
Зарегистрирован: 26.05.2017

sadman41 пишет:

А биты в байте перевернуть так же смогёшь? ;)

unsigned char reverse(unsigned char b) {
   b = (b & 0xF0) >> 4 | (b & 0x0F) << 4;
   b = (b & 0xCC) >> 2 | (b & 0x33) << 2;
   b = (b & 0xAA) >> 1 | (b & 0x55) << 1;
   return b;
}

я где-то в форуме уже выкладывал этот код, только найти не могу :)

freeman86
Offline
Зарегистрирован: 07.09.2016

Спасибо за помощь! Не сочтите за наглость, а как тоже самое с помощью указателей сделать? :-)

DetSimen
DetSimen аватар
Онлайн
Зарегистрирован: 25.01.2017

freeman86 пишет:

Спасибо за помощь! Не сочтите за наглость, а как тоже самое с помощью указателей сделать? :-)

А это в лекциях посмотри, у тебя записано должно быть

b707
Offline
Зарегистрирован: 26.05.2017

freeman86 пишет:

Спасибо за помощь! Не сочтите за наглость, а как тоже самое с помощью указателей сделать? :-)

 

uint16_t B =65530;
uint8_t* ptr_H = (uint8_t*) &B;   //  указатель на старший байт
uint8_t* ptr_L = ptr_H + 1;  //  указатель на младший байт
uint16_t B2 = (uint16_t) (*ptr_L << 8 ) |  *ptr_H;   // поменять местами и собрать обратно uint16

 

DetSimen
DetSimen аватар
Онлайн
Зарегистрирован: 25.01.2017

Филин, ты ж видишь, задание учебное.  Зачем потакаешь ленивой жопе?

b707
Offline
Зарегистрирован: 26.05.2017

DetSimen пишет:

Филин, ты ж видишь, задание учебное. 

сам учусь :)

сноси :)

freeman86
Offline
Зарегистрирован: 07.09.2016

Это не учеба. Это для работы. 

На форуме я давно, но не пользовался побитовыми операциями в своих скетчах и указателями тоже. И вообще в основном Python изучал.

DetSimen
DetSimen аватар
Онлайн
Зарегистрирован: 25.01.2017

freeman86 пишет:

Это не учеба. Это для работы. 

На форуме я давно, но не пользовался побитовыми операциями в своих скетчах и указателями тоже. И вообще в основном Python изучал.

вот теперь бери Кернигана и Ритчи  и изучай Си "для работы".  

DetSimen
DetSimen аватар
Онлайн
Зарегистрирован: 25.01.2017

b707 пишет:

сноси :)

У мня прав нет. 

b707
Offline
Зарегистрирован: 26.05.2017

DetSimen пишет:

У мня прав нет. 

убрал под спойлер. Там кода-то пара строк, даже если это учебное задание - этого явно будет мало, так что ТС придется и своей головой поработать

freeman86
Offline
Зарегистрирован: 07.09.2016

Спасибо!

Вопрос  по поводу этой строчки: uint8_t* ptr_H = (uint8_t*) &B;

что значит запись (uint8_t*) ?

uint8_t* ptr_L = ptr_H + 1;  Что дает прибавление  единицы к указателю, в котором хранится адрес начала байта? 

b707
Offline
Зарегистрирован: 26.05.2017

freeman86 пишет:

что значит запись (uint8_t*) ?

приведение типа от указателя на uint16_t к типу "указатель на uint8_t"

Цитата:
uint8_t* ptr_L = ptr_H + 1;  Что дает прибавление  единицы к указателю, в котором хранится адрес начала байта? 

очевидно, адрес следующего байта :) 

ЗЫ В последнем ответе есть неточность, какая - найдите сами, а то я и правда вам все разжевываю, даж неприлично

DetSimen
DetSimen аватар
Онлайн
Зарегистрирован: 25.01.2017

freeman86 пишет:

Спасибо!

Вопрос  по поводу этой строчки: uint8_t* ptr_H = (uint8_t*) &B;

что значит запись (uint8_t*) ?

uint8_t* ptr_L = ptr_H + 1;  Что дает прибавление  единицы к указателю, в котором хранится адрес начала байта? 

в библии по Си есть ответы на этот и многие другие вопросы.  Если действительно для работы надо, а не "завтра здавать", думаю, разберёсси. 

freeman86
Offline
Зарегистрирован: 07.09.2016

Спасибо, нашел неточность. Только вчера начал разбираться с побитовыми операциями и указателями :)

Еще вопрос по этой записи: B2 = (*ptr_H << 8 ) | *ptr_L;   если бы стоял плюс, то все понятно, но тут стоит или.

Если исходить из такого примера:

byte b1 = B10110010;   //B10110010
byte b2 = B11100111;   //B11100111
byte result = b1 | b2; //B11110111

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

В оригинале 1111111111011100

При сохранении в B2 = 11011100 | 11111111 получится  1111111111111111 разве нет?

 
DetSimen
DetSimen аватар
Онлайн
Зарегистрирован: 25.01.2017

freeman86 пишет:

При сохранении в B2 = 11011100 | 11111111 получится  1111111111111111 разве нет?

 
При сохранении в B2 = 0b11011100 | 0b11111111 получится  0b11111111
а вот если B2 = (0b11111111<<8) | 0b11011100 то получится  0b1111111111011100
b707
Offline
Зарегистрирован: 26.05.2017

freeman86 пишет:

При сохранении в B2 = 11011100 | 11111111 получится  1111111111111111 разве нет?

нет.
первая ошибка в том, что при операции "или" двух 8битных переменных никак не может получится 16-битная
 
Так что  при 11011100 | 11111111 получится  11111111
 
freeman86
Offline
Зарегистрирован: 07.09.2016

Наверное я не так выразился. Вот скетч, он работает и делает то, что надо, благодаря вашим подсказкам ) 

Вот что получается на выводе: 

Оригинальное значение: 1111111111011100

Старший бит: 11011100. Чтение начинается справа, так ведь?
Младший бит: 11111111
Перевернутое значение: 1101110011111111
Получается тут uint16_t B2 = (*ptr_H << 8 ) | *ptr_L;  сначала сохраняется то, что в скобках, а потом в след за ним сохраняется в следующий байт?  Результат этого значения (*ptr_H << 8 ) после сдвига будет 1101110000000000, и потом уже с оставшимися нулями происходит операция или ? 00000000 | 11111111?
 
void setup() {
 Serial.begin(9600);
}

void loop() {
  uint16_t B = 65500;
  uint8_t* ptr_H = (uint8_t*) &B;
  uint8_t* ptr_L = ptr_H + 1;
  uint16_t B2 = (*ptr_H << 8 ) | *ptr_L;
   
   Serial.println(B, BIN);
   Serial.println(*ptr_H, BIN);
   Serial.println(*ptr_L, BIN);
   Serial.println(B2, BIN);
}

 

DetSimen
DetSimen аватар
Онлайн
Зарегистрирован: 25.01.2017

Птваюмать.  Мы тебе весь первый курс программирования пересказывать будем?  

b707
Offline
Зарегистрирован: 26.05.2017

freeman86 пишет:

Старший бит: 11011100. Чтение начинается справа, так ведь?
Младший бит: 11111111

не бит, а байт. Старший байт слева.

Я начиная думать. что Дед был прав, когда предлагал вам не давать готового, а гнать ссаными тряпками в библиотеку за учебниками. По мере продвижения по теме все очевиднее становится. что думать самостоятельно вы не хотите, иначе не задавали бы вопросов. ответы на которые очевидны из кода

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

b707 пишет:

не бит, а байт.

Так то, что ТС не видит разницы было очевидно ещё утром (см. мой пост #7). А собсна чё мы хотим, он же честно признался:

freeman86 пишет:

в основном Python изучал.

Хотя, судя по плавающим отступам в коде, насчёт питона он пошутил. Там так не пишут :-)

wdrakula
wdrakula аватар
Offline
Зарегистрирован: 15.03.2016

ЕвгенийП пишет:

Так то, что ТС не видит разницы было очевидно ещё утром (см. мой пост #7). А собсна чё мы хотим, он же честно признался:

freeman86 пишет:

в основном Python изучал.

Некоторые на Python баллон катят? Или я чот не понял???!!! Может укажешь чё получше из современного и ПОПУлярного? ;))) Все, что придумывают специалисты по языкам - в течении года оказывается в Питоне, ты ж не станешь спорить? И каша не получается, удается сохранить некую логику. В отличии от JS, куда тоже напихано всё что родила научная мысль, но там уже нет начальной концепции... просто каша из всего, где про топор забыли. Как-то так.

Но фраза "Питон изучал" сделала мой день. Я когда только прочитал - думал простебаться в ответ.... ну к примеру попросив построить какое-нить простенькое замыкание... ну чуть сложнее "умножить на 5". Ну раз уж человек столько лет Питон изучал... Потом лень стало.

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

wdrakula пишет:

Некоторые на Python баллон катят?

А чё, последнюю фразу поста ниасилил дочитать? :-)))

Это баллон не на питон, а на 20 языков на уровне выше университетского :-)