Чтение значений из регистра подчиненного

Я пытаюсь подключить MPU6050 к arduino. Нашел простой код онлайн, но с небольшим количеством проблем в его интерпретации.

// MPU-6050 Short Example Sketch
// By Arduino User JohnChi
// August 17, 2014
// Public Domain
#include<Wire.h>
const int MPU=0x68;  // I2C address of the MPU-6050
int16_t AcX,AcY,AcZ,Tmp,GyX,GyY,GyZ;
void setup(){
Wire.begin();
Wire.beginTransmission(MPU);
Wire.write(0x6B);  // PWR_MGMT_1 register
Wire.write(0);     // set to zero (wakes up the MPU-6050)
Wire.endTransmission(true);
Serial.begin(9600);
}
void loop(){
Wire.beginTransmission(MPU);
Wire.write(0x3B);  // starting with register 0x3B (ACCEL_XOUT_H)
Wire.endTransmission(false);
Wire.requestFrom(MPU,14,true);  // request a total of 14 registers
AcX=Wire.read()<<8|Wire.read();  // 0x3B (ACCEL_XOUT_H) & 0x3C     (ACCEL_XOUT_L)     
AcY=Wire.read()<<8|Wire.read();  // 0x3D (ACCEL_YOUT_H) & 0x3E (ACCEL_YOUT_L)
AcZ=Wire.read()<<8|Wire.read();  // 0x3F (ACCEL_ZOUT_H) & 0x40 (ACCEL_ZOUT_L)
Tmp=Wire.read()<<8|Wire.read();  // 0x41 (TEMP_OUT_H) & 0x42 (TEMP_OUT_L)
GyX=Wire.read()<<8|Wire.read();  // 0x43 (GYRO_XOUT_H) & 0x44 (GYRO_XOUT_L)
GyY=Wire.read()<<8|Wire.read();  // 0x45 (GYRO_YOUT_H) & 0x46 (GYRO_YOUT_L)
GyZ=Wire.read()<<8|Wire.read();  // 0x47 (GYRO_ZOUT_H) & 0x48 (GYRO_ZOUT_L)
Serial.print("AcX = "); Serial.print(AcX);
Serial.print(" | AcY = "); Serial.print(AcY);
Serial.print(" | AcZ = "); Serial.print(AcZ);
Serial.print(" | Tmp = "); Serial.print(Tmp/340.00+36.53);  //equation for   temperature in degrees C from datasheet
Serial.print(" | GyX = "); Serial.print(GyX);
Serial.print(" | GyY = "); Serial.print(GyY);
Serial.print(" | GyZ = "); Serial.println(GyZ);
delay(3330); 
}

Теперь есть несколько вещей, которые я хочу задать относительно этого кода: 1. Здесь мы указали, что данные из регистра 3B подчиненного устройства должны быть первыми, и мастер получит в общей сложности 14 байтов. В этом случае 14 регистров непрерывны ( см. таблицу данных ). Теперь, как я должен читать значения, если меня интересуют регистры, которые не являются непрерывными, скажем, альтернатива?

2. AcX=Wire.read()<<8|Wire.read();

Эта строка берет первые 8 бит и последние 8 бит и формирует 16-битное число. Но почему нам нужно перенести первые 8-битные байты на 8 мест влево. Пожалуйста, объясните, как именно эта линия работает?

2 голоса | спросил Abhishek Tyagi 10 J0000006Europe/Moscow 2015, 18:59:27

1 ответ


2

Для чтения неисследованных байтов «обычным» способом было бы сделать однобайтовый запрос и однобайтное чтение для каждого байта, который вы хотите. Однако, если требуемые вами байты достаточно близки (например, вы хотите каждый другой байт), это было бы быстрее делать непрерывное чтение и просто игнорировать байты, которые вы делаете не хочу. Например:.

 byte data1 = Wire.read();  // read first byte
Wire.read();               // read and ignore second byte
byte data3 = Wire.read();  // read third byte

По вопросу о значении Wire.read()<<8|Wire.read();:

  1. Wire.read() возвращает 16-разрядное целое число, где 8 наиболее значимых биты равны нулю, а 8 младших битов содержат фактические данные. В двоичном коде это что-то вроде 00000000xxxxxxxx, где x являются битами данных.
  2. <<8 означает «сдвиг влево на восемь позиций», где отсутствующие биты заменяются нулями. Таким образом, Wire.read()<<8 есть xxxxxxxx00000000 в двоичном формате.
  3. Второй вызов Wire.read() возвращает еще одно 16-разрядное целое число в form 00000000yyyyyyyy.
  4. Вертикальная строка | является побитовым или оператором: каждый бит слева операнд или соответствующий бит правого операнда дать один бит результата: x or 0 is x, 0 or y есть y.
  5. Затем все выражение дает xxxxxxxxyyyyyyyy, где xxxxxxxx происходит от первого Wire.read() и yyyyyyyy от второй.

Проблема здесь в том, что «первый» и «второй» Wire.read() в предложение выше относится к позиции вызова в строке, а не к фактический порядок, в котором выполняются вызовы. Таким образом, вам может повезти и получить правильный порядок байтов ... или нет. Вместо этого вы должны сделать один прочитайте за оператор, если вы хотите контролировать порядок байтов. Для MSB сначала:

 AcX = Wire.read() << 8;  // read most significant byte first
AcX |= Wire.read();      // then least significant byte

И для LSB сначала:

 AcX = Wire.read();        // read least significant byte first
AcX |= Wire.read() << 8;  // then most significant byte
ответил Edgar Bonet 10 J0000006Europe/Moscow 2015, 21:08:23

Похожие вопросы

Популярные теги

security × 330linux × 316macos × 2827 × 268performance × 244command-line × 241sql-server × 235joomla-3.x × 222java × 189c++ × 186windows × 180cisco × 168bash × 158c# × 142gmail × 139arduino-uno × 139javascript × 134ssh × 133seo × 132mysql × 132