PDA

View Full Version : Unexpected extra I2C cycle on Teensy 3.1



danjulio
03-18-2014, 06:27 PM
I am seeing an extra, unexpected, I2C cycle on Teensy 3.1. I expect two cycles:

Write Register Address: 2 bytes [I2C device address + Write] + [device register address]
Read Register Data: 2 bytes [I2C device address + Read] + [data from device]

after the Read Register Data I see another Write Register Address cycle. Why is this occurring? Am I doing something wrong or is there an issue in the Wire Library?

I've included both a test program below and screen shot from my scope. This test is an access to an accelerometer chip where we continue the cycle, however I also see the same behavior when accessing a temperature chip (tmp102) where we do not continue the cycle.



/*
* Teensy I2C Wire Library test program
*
* Execute a very simple I2C operation for verification using an oscilloscope
*
* This test program reads the ID ("Who Am I") register in a MMA8452 accelerometer
* chip. The I2C access of this register consists of writing the ID register
* address to the chip and then performing an I2C read to get the value.
*
*/
#include <Wire.h>

// I2C address of the accelerometer
#define MMA8452_ADDRESS 0x1D

// Accelerometer ID Register address
#define ID_REG_ADDR 0x0D

// Expected ID Register value
#define ACCEL_ID 0x2A

void setup() {
uint8_t regVal;

Serial.begin(115200);
Wire.begin();

delay(5000); // Allow the user to open the serial monitor & trigger the scope

// Execute one access to the acceleromter to read the ID Register
if (ReadAccelReg(MMA8452_ADDRESS, ID_REG_ADDR, &regVal)) {
if (regVal == ACCEL_ID) {
Serial.println("Successfully read ID Register");
} else {
Serial.printf("Got unexpected value from ID register: 0x%x\n", regVal);
}
} else {
Serial.println("Register access failed");
}
}

void loop() {
}

/* ************************************************** ***************************
* ReadAccelReg - Read a register in a MMA8452 accelerometer
*
* On entry: a contains the I2C address of the accelerometer
* reg contains the address of the register to read
* *d contains a pointer to a uint8_t variable to receive the register value
*
* On exit: *d may be updated with the register value
************************************************** ************************** */
boolean ReadAccelReg(uint8_t a, uint8_t reg, uint8_t* d) {
uint8_t n, s;

// Reset the register pointer
Wire.beginTransmission(a);
n = Wire.write(reg);
s = Wire.endTransmission(false); // Do not release the bus for the subsequent read

if (n != 1) {
Wire.endTransmission(true); // Force release of the bus
return false;
} else if (s != 0) {
Wire.endTransmission(true);
return false;
}

// Read the register value
n = Wire.requestFrom(a, (uint8_t) 1);
s = Wire.endTransmission();

if (n != 1) {
return false;
} else if (s != 0) {
return false;
}

// Success: finally get the data
*d = Wire.read();

return true;
}




1657

Jp3141
03-18-2014, 08:21 PM
I don't think you need the Wire.endTransmission() after the wire.requestFrom() lines.

I use something like this:

int readI2C_Register(int Slave_Register) {
Wire.beginTransmission(I2CAddress); // Select address
Wire.write(Slave_Register); // sends one byte
Wire.endTransmission(false); // stop transmitting, with repeated start
Wire.requestFrom(I2CAddress, 1); // request 1 byte
// delayMicroseconds(10);
while(! Wire.available());
return Wire.read();
}

danjulio
03-18-2014, 08:36 PM
Yup. That's it Jp3141. Thanks. Dunno what I was thinking since the documentation is pretty clear.