Приведение типа указателей
- Войдите на сайт для отправки комментариев
Доброго времени суток.
В общем, такая проблема: мне кажется, что приведение типа указателей работает не совсем корректно. В чем суть - как я понимаю,указатель ссылается на старший байт многобайтной переменной, и, если указатель int16_t* привести к однобайтному uint8_t*, то почему-то он будет ссылаться на младший бит, внимание, ПРЕДЫДУЩЕЙ переменной (как будто ptr[-1]). Привожу пример кода:
int16_t _data[7]; IMU.readRawData(_data);
Это - "библиотечная" функция для считывания данных из акселерометра/гироскопа наподобие MPU6050, только в данном случае - MPU9250 (в плане считывания данных ничем не отличается). IMU - объект специального класса, а функция readRawData выглядит следующим образом:
bool MPU9250::readRawData(int16_t *_rawData) { return burstRead(MPU9250_ACCEL_XOUT_H, 14, (uint8_t*)_rawData); }
Причем функция burstRead:
bool MPU9250::burstRead(uint8_t _reg, uint8_t _quantity, uint8_t* _data) { Wire.beginTransmission(_deviceAddress); Wire.write(_reg); bool _transmissionResult = !Wire.endTransmission(); Wire.requestFrom(_deviceAddress, _quantity); for(uint8_t i = 0; i < _quantity; i++) _data[i] = Wire.read(); return _transmissionResult; }
побайтово записывает в предоставленый массив данные (байты), считанные из регистров устройства. Устройство проверил - с "обычным" кодом работает отлично. Лично я "грешу" на приведение типа указателей в функции readRawData, либо на личное незнание их принципа работы... По крайней мере, в интернете найти об этом информацию не удалось.
Пробовал эту функцию переписать так:
bool MPU9250::readRawData(int16_t *_rawData) { return burstRead(MPU9250_ACCEL_XOUT_H, 14, (uint8_t*)_rawData - 1); }
и так:
bool MPU9250::readRawData(int16_t *_rawData) { return burstRead(MPU9250_ACCEL_XOUT_H, 14, (uint8_t*)_rawData + 1); }
и если в первом варианте с вычитанием единицы он худо-бедно показывает какие-то вменяемые данные, но со смещением (вроде того, что ось гироскопа по иксу показывает данные с оси игрек и т.п.), то во втором случае, с прибавлением единицы, выводит -1. На основании этого делаю вывод, что "приведенный" указатель ссылается на предыдущую переменную, которой в массиве нет.
Заранее благодарю за любую информацию.
1. Вы неправильно понимаете: в многобайтовой переменной первым идет младший байт (так же, как и на Intel).
2. Давайте отделять мух от котлет, если хотите разбираться в приведении типа, забудьте об акселерометре и используйте обычные массивы. Если хотите разбираться с акселерометром, так и пишите (и, думаю, тему надо было создавать в аппаратном разделе).
Да кстати, я совсем забыл, что существуют такие системы, как little/big endian. Тогда ясно.
Насчет акселерометра - вообще не суть, это я для примера привел. На его месте вполне могло быть другое устройство, ну или просто побайтная передача данных.
Хорошо, значит, указатель ссылается на младший байт. Значит, нужно просто менять местами эти байты, чтобы отображались корректные данные? Сейчас попробую.
Но тогда вопрос - почему работает такая запись:
Ведь считываемые регистры данных расположены в порядке от старшего к младшему, и получается, что первый прочитанный байт смещается влево...
Возьмем тупо целое число 0x1234 и запишем его в массив data[0]=0x1234; Элемент data[0] занимает в памяти 2 байта. В памяти число 0x1234 запишется как 0x34, затем 0x12.
Это понятно?
Да, сначала записывается младший байт, а затем старший, с большей "разрядностью". Но как это изменит то, что "смещаемые" влево, казалось бы, старшие байты вдруг оказываются младшими?
Нужно отделять мух от котлет. Разделяй этот процесс на части. Т.е. сначала мы формируем целое значение, считывал данные по байтам. Первое чтение Wire.read() дает нам старший байт, второе - младший. Сначала собираем целое значение. Предположим мы считали сначала 0x12, затем 0x34. Собираем целое и получаем 0x1234. Далее его записываем в data[0], но это я уже писал выше.
Поскольку ты еще учишься, не морочь себе голову и не смешивай два процесса, формирование целого и запись его в память.
Да, сначала записывается младший байт, а затем старший, с большей "разрядностью". Но как это изменит то, что "смещаемые" влево, казалось бы, старшие байты вдруг оказываются младшими?
Зачем тебе это знать, как хранится в памяти многобайтовое число? Цель какая?
Спасибо, так и сделал, сейчас все работает корректно. Но все-таки я не понимаю - почему первый вызов Wire.read(), смещенный влево, оказывается вдруг младшим байтом? Или это все же второй вызов?
Спасибо, так и сделал, сейчас все работает корректно. Но все-таки я не понимаю - почему первый вызов Wire.read(), смещенный влево, оказывается вдруг младшим байтом? Или это все же второй вызов?
Кто тебе сказал, что старший байт становится младшим?
Есть многобайтные переменные, которые в разных устройствах хранятся по-разному. К примеру, тот же MPU9250 имеет встроенный магнитометр, у которого хранение байтов - прямо противоположное, т.е. сначала записывается младший, а за ним старший байт. Ну и, все-таки хотелось бы разобраться, как записывать данные "побайтово" в многобайтные переменные, даже если формат записи в регистрах устройства такой же, как и в памяти контроллера.
Спасибо, так и сделал, сейчас все работает корректно. Но все-таки я не понимаю - почему первый вызов Wire.read(), смещенный влево, оказывается вдруг младшим байтом? Или это все же второй вызов?
Потому что так написано в даташите. Сначала в регистрах идет старший байт, за ним - младший. Вот я и думаю, почему первый вызов Wire.read(), который, казалось бы, должен считать старший байт и сместить его влево, почему-то считывает младший байт?
Famouspilot, в регистре не может быть "сначала" и "потом".
Внутри регистра нет адресации.
Порядок может быть (и есть) в памяти, где:
1. Существует адресация.
2. Длина минимально адресуемого элемента меньше длины рассматриваемого объекта.
Так что весьма маловероятно, что в дэйташите может быть написанео нечто, напоминающее Ваше утверждение.
Да, прошу прощения, под "регистрами" я имел в виду регистры ведомого I2C устройства.
Ну да, для ведомого устройства такая организация достаточно характерна. Мне даже довелось иметь дело с устройством, минимально адресуемый элемент которого имел длину 2 бита (т.е. на байт приходилось 4 последовательных адреса).
Ну да, для ведомого устройства такая организация достаточно характерна. Мне даже довелось иметь дело с устройством, минимально адресуемый элемент которого имел длину 2 бита (т.е. на байт приходилось 4 последовательных адреса).
Не побоюсь спросить, что это за интересное устройство было?
Не побоюсь спросить, что это за интересное устройство было?
Вообще-то не I2C.
Микросхема управляемого фильтра max261. Там режим фильтра задается 32 разрядами. Протокола обмена нет, есть, как и положено, 3 параллельных шины: данных, адреса и управления. Вот по количеству расходуемых контактов и была проведена оптимизация.
Шина управления, в общем-то, без вариантов: для мультиплексирования адреса слишком короткий сам адрес.
А вот сумму шины данных и шины адреса можно попробовать пооптимизировать. Очевидно, для 32 разрядов можно:
- 32 данных, 0 адреса, всего: 32,
- 16 данных, 1 адреса, всего: 17,
- 8 данных, 2 адреса, всего: 10,
- 4 данных, 3 адреса, всего: 7,
- 2 данных, 4 адреса, всего: 6,
- 1 данных, 5 адреса, всего: 6.
Т.е. по общему количеству контактов два равноправных варианта, но первый из них вдвое эффективнее с точки зрения времени необходимого для установки режима работы.
Я пытался помочь, но дальше без меня. Еще раз говорю, автор, определись с задачей и не смешивай всё в одну кучу.
Вот преобразование к 16-ти битам из rawdata. Взято из Вашей, ишаком долбаной, библиотеки от акселерометра.
Перестаньте размножать людям мозг своей тупостью.
В регистрах данные лежат в ИНВЕРСНОМ, Вашу ять, порядке. Старший байт, потом младший.
Чтобы получтить целое, 16-ти битное, нужно их поменять местам. Что и сделано в библиотеке.
=================
Каждое ...удло считает своим долгом объявить, что компилятор, контроллер, стандарт языка, китайцы-призводители и Господь Б..г - ошибаются!
Нет мля, ошибка - она в ДНК!
Вот преобразование к 16-ти битам из rawdata. Взято из Вашей, ишаком долбаной, библиотеки от акселерометра.
Да, спасибо, в моей *Ишаком долбаной* библиотеке проблемы подобного рода исправлены. А тупость... Ну знаете ли, все когда-то начинали задавать тупые вопросы. Я еще не такой ТСарь и Б-г программирования, как Вы.