Saturday, October 18, 2014

2-Wire Interface

2-Wire Interface, popularly known as I2C is one of the methods used to communicate with other hardware, like a sensor or any other controller on the board, which supports I2C. As most of us know and as the title hints, I2C needs only 2 lines/wires to communicate. SDA(data line) and SCL(clock line). The speed of I2C communication(bit rate) depends on devices, ranged from 100-kHz till 5-MHz.

All I2C devices are 7 bit addressable. That means, maximum of 128 devices can be connected to those SDA and SCL lines (I2C bus). I2C devices can be connected to I2C bus in 4 mode of communication: Master Transmit, Master Receive, Slave Transmit and Slave Receive. Any device connected to I2C bus, can be a master (that means taking control of that bus), rest of the connected devices will become slaves. When more more than one device tries to take control of the I2C bus, bus arbitration decides which device will be master. When multiple devices are trying to become master, SCL line of I2C bus is High, when all connected master's SCL is High and is Low when all connected master's SCL is Low.

If master wants to broadcast data to all the connected I2C devices, then master has to use the address 0x00, which is known as general call. When master wants to communicate to one particular device, then master has to use that device's address. Once Slave has been addressed by any master, it will either sends the data or receives the data from the master. Slave will always have the freedom to hold the SCL line until interrupt has been served, which is known as clock stretching. Once the I2C communication started, it's master's responsibility to stop the I2C communication. Master has the freedom to do a repeated start without freeing the I2C bus.

I2C specifications are:
+ Start condition - SDA line transition from High to Low when clock is high.
+ Stop condition - SDA line transition from Low to High when clock is high.
+ Data will be of 9 bits length. 8 bits of address or data, and one bit is for acknowledgement for byte reception.
+ When master transmit slave's address. It has to send the slave's 7 bit address from bits 7:1 and 0th bit will Read/Write bit (1- read, 0 for write).

Steps for writing I2C communication code:

  1. Go through the I2C or Two Wire Interface(TWI) part of datasheet (click here for Atmega644P).
  2. Assign the self address for device.
  3. Initialize the bit rate register based on the speed in which communication has to happen.
  4. Enable the I2C communication, Enable the interrupt, Enable the acknowledgement.
  5. If Device has to be configured as Master, then set the Start Condition bit. (In some controllers, you can start the communication by setting the Start Condition bit and Interrupt flag reset bit).
  6. Write a ISR, for interrupt handling. In ISR, monitor Status register, and based on the value in the status register, take an appropriate action and reset the interrupt flag.
  7. In master mode, when there is a interrupt for successful transmission of start condition, slave's address has to be updated in the data register (7:1 bit) and 0th bit indicating the direction of transfer (1 for read and 0 for write).
  8. When Device wants to receive or transmit more than one byte of data, a buffer has to be maintained. For transmitting data, buffer has to filled before(in master transmit) and/or during the communication (in slave transmit).
  9. When configured as slave mode, device has to wait until the direction is know. like:

Note: Disabling the acknowledgement in slave mode is one of the way for device to avoid all I2C communication.

Click here for I2C driver code for Atmega644P. With that, any I2C device with known address can be connected and communicated. The demo of I2C driver testing can be found in below links: