Как обрабатывать 20-битные данные датчика
У меня есть датчик ускорения (ADXL355), который возвращает 20-битные данные в трех байтах, отформатированные как дополнение 2s:
- acc3 (биты 19-12) в байтовом регистре 3 (сопоставлен битам 7-0)
- acc2 (биты 11-4) в байтовом регистре 2 (сопоставлен битам 7-0)
- acc1 (биты 3-0) в байтовом регистре 1 (сопоставляется битам 7-4, пока 3-0 не используются)
значение ускорения берется как 32 - разрядное целое число со знаком из вышеуказанных 3 регистров следующим образом :
int32_t acc32 = ((uint32_t)acc3 << 12) | ((uint16_t)acc2 << 4) | (acc1 >> 4);
if (acc32 & (1UL << 19)) acc32 -= 1UL << 20;
Затем я провожу некоторый статистический анализ значений ускорения, чтобы вычислить обрезку смещения как 32-битное целое число со знаком.
int32 off32;
Это смещение должно быть записано обратно в датчик в виде 16 - битного дополнительного значения 2s следующим образом :
- старший байт смещения (биты 15-8)
- младший байт смещения (биты 7-0)
В техническом описании указано, что "Значение битов смещения 15-0 соответствует значению битов ускорения 19-4".
Я нашел это довольно сложным, поэтому я спрашиваю, как преобразовать это подписанное 32-битное целое число со смещением в 16-битное целое число со смещением, которое соответствует приведенной выше спецификации.
У меня была такая идея, но я не знаю, правильна ли она:
int16_t off16[i] = (int16_t)(off32[i] / 16);
sendSPI((uint8_t)(off16 >> 8));
sendSPI((uint8_t)off16);
Любой комментарий должен быть высоко оценен!
1 ответ
Лучший ответ:
За исключением нижнего индекса [i]
, который выглядит подозрительно, то, что вы сделали
, кажется мне совершенно правильным. Теперь, если я начну придираться, я могу предложить:
- используйте битовый сдвиг, так как это намного дешевле, чем деление
- округлять до ближайшего, а не до нуля или минус бесконечности.
Это дает:
int16_t off16 = (off32 + 8) >> 4;
Обратите внимание, что битовый сдвиг ведет себя как деление, которое округляется в сторону −∞ (обычное деление округляется до нуля). Добавление 8 приводит к округлению до ближайшего, с округлением связей в большую сторону.
- устаревшее преобразование из строковой константы в 'char*'
- Можно ли измерить скорость акселерометром? Насколько точно?
- Как запрограммировать ардуино на чистом C/C++?
- Количество элементов в массиве char
- В чем разница между акселерометром, гироскопом и датчиком магнитометра?
- Регистры ввода-вывода SAM3X8E (Arduino Due)
- как быстро loop() работает в Arduino
- Arduino: как получить тип платы в коде
Большое спасибо за ваш ответ! Да, подстрочного [i] там быть не должно! Что касается битового сдвига, я не был уверен, работает ли он как деление в целых числах со знаком, поэтому вместо этого я выбрал деление., @Vassilis Papanikolaou