Туговат на понимание работы с байтовыми операциями, прошу помочь
- Войдите на сайт для отправки комментариев
Доброе время всем! Купил температурный датчик DS18B20. Скачал библиотечку, запустил тестовую прогу, получаю с датчика температуру, все ок. Но хочу разобратся как это все работает. Скачал даташит на него, читаю и пытаюсь сопоставить сс тем что в коде примера прописано, понимаю, что не хватает знаний С+...
Вот кусочек кода который хочу разобрать:
int16_t raw = (data[1] << 8) | data[0]; byte cfg = (data[4] & 0x60); if (cfg == 0x00) raw = raw & ~7; else if (cfg == 0x20) raw = raw & ~3; raw = (raw & 0xFFF0) + 12 - data[6];
Как понять эту операцию "cfg=(data[4] & 0x60)", вот эту "raw = raw & ~7"
В массиве data находится значение к примеру (01 D6 01 4B 46 7F FF C 10 E9)
Здесь: data[1] << 8) | data[0] я понял только первую часть, это значение D6 (1101 0110) смещаем влево на 8 бит, т.е получаем такую штуку наверное (1101 0110 0000 0000), а вот что происходит в этой части
"| data[0]" не понимаю...
И еще здесь
raw = (raw & 0xFFF0) + 12 - data[6];
(raw & 0xFFF0) - какая операция?
+12 - прибавляем 12 в hex системе?
Побитовые операции (и другие) можно посмотреть здесь:
http://atmel.ucoz.ru/publ/spravochnik_po_jazyku/1-1-0-1
+12 в десятичном виде, в шестнадцатиричном виде будет +0x12
Почитал, пробую пройти самостоятельно алгоритм и где-то туплю.. Вот что получилось у меня
Полный код:
В массиве data = 01 08 02 4B 46 7F FF 0C 10 98
Высчитываю эту строку
Получаем data[1]=08(h) = 1000(b), добавляем 8 бит справа, получаем 1000 0000 0000(b), это 800(h) или 2048(dec)
Иду дальше - type_s =0, тогда
Data[4]=46(h) = 01000110(b), число 60(h) = 01100000(b), умножаем побитово, получаем 01000000(b) =40 (h)
Иду дальше
Вот тут загвоздка... ~1 это значит инверсия 1, т.е равно 0, вроде так? тогда не понимаю команду "800(h) & ~1", по сути умножить на 0??? Вот тут я и завис ))) поясните как решается эта строка плиз )
P.S. знаю что в raw должен остаться резульат 208(h)
Как показал опыт, похоже расшифровка значения температуры только в этой строке:
raw = (data[1] << 8) | data[0];
Осталось правильно ее понять )) при том что Data[1]=08(h), а Data[0]=01(h) число должно получится 208(h)
8(h) = 1000(b)
1(h) = 0001(b)
208(h) = 0010 0000 1000(b)
где тут логика ))
Дописал код:
celsius1 = (data[1] << 8);
Serial.print(celsius1); получаю 512(dec), 200(h), 1000000000(b), вот тут я полностью потерялся... ведь функция <<8 должна добавить 8 нулей к значению 1000(b) ? а тут 6 нолей получается.. какой-то не польный байт даж... что я пропустил?
Жееесть какая!!! В data[1] хранится 1h, а в Data[0] хранится 8h!!! (выявил тем же print() )... тогда получается что 1(h) << 8 добавляет к 1 - 8 нулей, 100000000(b), и сравнивает с числом 1000(b)...
0001 0000 0000
0000 0000 1000
---------------------
0001 0000 1000 =108(h) а где еще 100(h)? ))
При data[1]=08(h) и data[0]=01(h) операция raw = (data[1] << 8) | data[0] даёт 0801(h) или 0x0801.
Русскоязычное описание датчика DS18B20 здесь:
http://masterkit.ru/zip/ds18b20-rus.pdf
Вот кусочек кода который хочу разобрать:
Как понять эту операцию "cfg=(data[4] & 0x60)", вот эту "raw = raw & ~7"
В массиве data находится значение к примеру (01 D6 01 4B 46 7F FF C 10 E9)
raw = (data[1] << 8) | data[0] = 0xD601
cfg = (data[4] & 0x60) = 0x40
raw = raw & ~7 = raw & 0xFFF8 = 0xD600
Я такие расчёты на калькуляторе делаю. http://www.hexelon.com/kalkulator/index_en.php
Такие расчеты и в уме просто делаются, и на windows'ком калькуляторе можно сделать. Главное понимать!
Можно делать в уме, и на windows'ком калькуляторе, но придется заново рассчитывать при внесении изменений.
Предпочитаю калькуляторы которые поддерживают Ctrl+C и Ctrl+V, это экономит время.
Предпочитаю калькуляторы которые поддерживают Ctrl+C и Ctrl+V, это экономит время.
Windows'кий калькулятор поддерживает Ctrl+C и Ctrl+V, а также работает с разными системами счисления и позволяет переводить числа из одной системы в другую.
Да, проверил сейчас, поддерживает. Но неполноценно. Можно копировать и вставлять только последнее число. А заменять числа в начале расчёта никак.
Да калькулятором то я и считаю, но нужно понимать что происходит, т.к. этот калькулятор нужно вписать в код программы)))
Вот кусочек кода который хочу разобрать:
Как понять эту операцию "cfg=(data[4] & 0x60)", вот эту "raw = raw & ~7"
В массиве data находится значение к примеру (01 D6 01 4B 46 7F FF C 10 E9)
raw = (data[1] << 8) | data[0] = 0xD601
cfg = (data[4] & 0x60) = 0x40
raw = raw & ~7 = raw & 0xFFF8 = 0xD600
Я так понял что это на калькуляторе посчитано? как первую строку получили?
raw = (data[1] << 8) | data[0] = 0xD601 ? При том, что в Data[0]=8h а в Data[1] = 1h
В массиве data находится значение к примеру (01 D6 01 4B 46 7F FF C 10 E9)
raw = (data[1] << 8) | data[0] = 0xD601
Я так понял что это на калькуляторе посчитано? как первую строку получили?
raw = (data[1] << 8) | data[0] = 0xD601 ? При том, что в Data[0]=8h а в Data[1] = 1h
Слабо свои собственные записи прочитать?
В массиве data находится значение к примеру (01 D6 ...
Теперь понял )) но это не верное, результат вычислений дает совсем другой ответ... он явно не соединяет эти два байта... при (01 08..) - получается 208(h) в этой строке... там еще какая-то операция, типа побитовое умножение.. но когда я его делаю на бумаге, у меня между разярядами не хватает одного нуля... не пойму от куда он берется в этом алгоритме..
прикол опять нашел ) Если представить число 01D6 то это 470(dec), что является верным.. 470/16=29,37 градуса цельсия... тогда не понимаю, что происходит с байтам data = (01 08 ... ).... здесь не выходит 32.50 градуса... 208(h)=520(dec)/16 = 32.50