我正在Sparkfun红板Turbo(处理器samd21g18)和旧的arduino uno(处理器mega16u2)上都使用I2C运行ADXL345。我在两块板上都使用的库和草图相同,不同之处在于串行端口已更改为SerialUSB以容纳该红板。
问题似乎是,uno将xyz寄存器(寄存器0x32-0x37中的每个轴2个字节)解释为16位二进制补码(根据数据表),而红板则不然。 Uno的输出正确,而redboard输出不正确的都是正整数输出。
下图在ADXL345的相同相对位置的左侧显示了红板的输出,在右侧显示了uno的输出。
我相信令人反感的代码在以下库代码中。
/*********************** READING ACCELERATION ***********************/
/* Reads Acceleration into Three Variables: x, y and z */
void ADXL345::readAccel(int *xyz){
readAccel(xyz, xyz + 1, xyz + 2);
}
void ADXL345::readAccel(int *x, int *y, int *z) {
readFrom(ADXL345_DATAX0, ADXL345_TO_READ, _buff); // Read Accel Data from ADXL345
// Each Axis @ All g Ranges: 10 Bit Resolution (2 Bytes)
*x = (((int)_buff[1]) << 8) | _buff[0];
*y = (((int)_buff[3]) << 8) | _buff[2];
*z = (((int)_buff[5]) << 8) | _buff[4];
}
草图代码如下:
#include <SparkFun_ADXL345.h>
/*********** COMMUNICATION SELECTION ***********/
/* Comment Out The One You Are Not Using */
//ADXL345 adxl = ADXL345(10); // USE FOR SPI COMMUNICATION, ADXL345(CS_PIN);
ADXL345 adxl = ADXL345(); // USE FOR I2C COMMUNICATION
/****************** INTERRUPT ******************/
/* Uncomment If Attaching Interrupt */
//int interruptPin = 2; // Setup pin 2 to be the interrupt pin (for most Arduino Boards)
/******************** SETUP ********************/
/* Configure ADXL345 Settings */
void setup(){
SerialUSB.begin(9600); // Start the SerialUSB terminal
SerialUSB.println("SparkFun ADXL345 Accelerometer Hook Up Guide Example");
SerialUSB.println();
adxl.powerOn(); // Power on the ADXL345
adxl.setRangeSetting(2); // Give the range settings
// Accepted values are 2g, 4g, 8g or 16g
// Higher Values = Wider Measurement Range
// Lower Values = Greater Sensitivity
}
/****************** MAIN CODE ******************/
/* Accelerometer Readings and Interrupt */
void loop(){
// Accelerometer Readings
int x,y,z;
adxl.readAccel(&x, &y, &z); // Read the accelerometer values and store them in variables declared above x,y,z
// Output Results to SerialUSB
/* UNCOMMENT TO VIEW X Y Z ACCELEROMETER VALUES */
SerialUSB.print(x);
SerialUSB.print(", ");
SerialUSB.print(y);
SerialUSB.print(", ");
SerialUSB.println(z);
adxl.printAllRegister();
delay(10);
}
声明.b文件头中的_buff []的代码:
private:
void writeTo(byte address, byte val);
void writeToI2C(byte address, byte val);
void writeToSPI(byte address, byte val);
void readFrom(byte address, int num, byte buff[]);
void readFromI2C(byte address, int num, byte buff[]);
void readFromSPI(byte address, int num, byte buff[]);
void setRegisterBit(byte regAdress, int bitPos, bool state);
bool getRegisterBit(byte regAdress, int bitPos);
byte _buff[6] ; // 6 Bytes Buffer
int _CS = 10;
bool I2C = true;
unsigned long SPIfreq = 5000000;
我认为需要修改红板库,以读取输出寄存器0x32-0x37,作为16位二进制补码。我是此编程环境的新手,因此感谢您的帮助。
谢谢-杰里
我从Sparkfun董事会笔记(https://www.sparkfun.com/products/14812)中怀疑,问题在于Redboard Turbo是32位处理器,具有32位int而不是16位int。在这样的处理器上,存储在int中的所有16位值都是正数。
为了测试我的理论,请在您的Redboard Turbo上运行以下草图:
void setup() {
Serial.begin(9600);
while (!Serial) {}
Serial.print("sizeof(int) = ");
Serial.println(sizeof(int));
}
void loop() {
}
在我的Arduino Uno上-16位环境-输出表明int是两个字节(16位)
sizeof(int) = 2
如果您的Redboard Turbo而是打印,则>
sizeof(int) = 4
然后其int为4字节(32位)。
我怀疑该库不是为32位处理器编写的,在Redboard Turbo上可能会显示一些问题。要修复特定的readAccel()函数,请将其重写以将16位数字符号扩展为32位:
int16_t i16; // the 16-bit result, signed. i16 = (int16_t) ((((uint16_t)_buff[1]) << 8) | _buff[0]); *x = (int) i16; i16 = (int16_t) ((((uint16_t)_buff[3]) << 8) | _buff[2]); *y = (int) i16; i16 = (int16_t) ((((uint16_t)_buff[5]) << 8) | _buff[4]); *z = (int) i16;
顺便说一句,在上面对readAccel()的重写中,我已经使用uint16_t来确保字节移位发生在无符号值上,因为左移有符号数会在某些处理器上产生意外的结果。