I2C (inter IC) was invented by Philips Semiconductor (now named NXP). It is typically used to attach low-speed peripherals to processors/micro-controllers.
Since 2006, no licensing fees are required to implement I2C protocol, but fees are still required to obtain I2C addresses, allocated by NXP.
I2C bus (SDA, SCL)
- both outputting and inputting signals on the wire are possible (it can sense the voltage level of the wire).
- open-drain, or open-collector
- masters and slaves can only drive these lines low, or leave them open;
- each line requires a pull-up resistor on it, to pull the line up to VCC, if no I2C device is pulling it down.
more on pull-up resistor:
- without a pull-up resistor, he device is not able to generate the I2C start condition.
- sometimes, there is no external pull-up, but an internal pull-up can be enabled.
- lack of pull-up will not damage either IC, as PNP transistor is being used.
- resistor selection: start with 4.7K, and adjust down if necessary.
- note: a small resistor might be too weak for I2C pull up (it might still work, depending on the I2 speed, etc).
I2C bus transaction
- Usually, the slaves are in the idle condition, monitoring the SDA and SCLK lines for the start condition and the correct transmitted address.
- the clock signal is always generated by the current bus master.
- start condition: a high to low transition on SDA while SCL remains high, then pulls the SCL low.
- Following the start condition, the address bits are transferred from MSB down to LSB.
- A logic 0 on the LSB of the first byte means a “write”; a logic 1 means a “read”.
- The first 8 clock cycles are used for slave address, then the 9th is for slave ACK.
- The slave, if it recognizes its address, it responds by pulling the data line low during the ninth clock pulse – this is known as an acknowledge bit.
- A data transfer is terminated by a stop condition: a low to high transition on SDA, while SCL is high.
example #1: (the slave 0x70 doesn’t respond)
# irecv -n/dev/i2c0 -a0x70 -l1 // 0111 0000 –> 1110 0001 DCMD_I2C_SENDRECV, send STOP.
example #2 (the slave 0x6c works well)
# irecv -n/dev/i2c4 -a0x6c -l1 // 0110 1100 –> 1101 1001 DCMD_I2C_SENDRECV, send STOP, too.
Data recvd: 15h // 0001 0101