26.6.2.4 I2C Host Operation
The I2C Host is byte-oriented and interrupt based. The number of interrupts generated is kept at a minimum by automatic handling of most incidents. The software driver complexity and code size are reduced by auto-triggering of operations, and a Special Smart mode, which can be enabled by the Smart Mode Enable bit in the Control B register (CTRLB.SMEN).
Host Clock Generation
- Standard mode (Sm) up to 100 kHz
- Fast mode (Fm) up to 400 kHz
Clock Generation (Standard-Mode, Fast-Mode, and Fast-Mode Plus)
In I2C Sm and Fm mode, the Host clock (SCL) frequency is determined as described in this section:
The low (TLOW) and high (THIGH) times are determined by the Baud Rate register (BAUD), while the rise (TRISE) and fall (TFALL) times are determined by the bus topology. Because of the wired-AND logic of the bus, TFALL will be considered as part of TLOW. Similarly, TRISE will be in a state between TLOW and THIGH until a high state has been detected.
- TLOW – Low period of SCL clock
- TSU;STO – Set-up time for stop condition
- TBUF – Bus free time between stop and start conditions
- THD;STA – Hold time (repeated) start condition
- TSU;STA – Set-up time for repeated start condition
- THIGH is timed using the SCL high time count from BAUD.BAUD
- TRISE is determined by the bus impedance; for internal pull-ups. Refer to Electrical Characteristics.
- TFALL is determined by the open-drain current limit and bus impedance; can typically be regarded as zero. Refer to Electrical Characteristics for details.
The SCL frequency is given by:
When BAUD.BAUDLOW is zero, the BAUD.BAUD value is used to time both SCL high and SCL low. In this case the following formula will give the SCL frequency:
When BAUD.BAUDLOW is non-zero, the following formula determines the SCL frequency:
The following formulas can determine the SCL TLOW and THIGH times:
Transmitting Address Packets
The I2C Host starts a bus transaction by writing the I2C Client address to ADDR.ADDR and the direction bit, as described in Principle of Operation. If the bus is busy, the I2C Host will wait until the bus becomes idle before continuing the operation. When the bus is idle, the I2C Host will issue a start condition on the bus. The I2C Host will then transmit an address packet using the address written to ADDR.ADDR. After the address packet has been transmitted by the I2C Host, one of four cases will arise according to arbitration and transfer direction.
Case 1: Arbitration lost or bus error during address packet transmission
If arbitration was lost during transmission of the address packet, the Host on Bus bit in the Interrupt Flag Status and Clear register (INTFLAG.MB) and the Arbitration Lost bit in the Status register (STATUS.ARBLOST) are both set. Serial data output to SDA is disabled, and the SCL is released, which disables clock stretching. In effect the I2C Host is no longer allowed to execute any operation on the bus until the bus is idle again. A bus error will behave similarly to the arbitration lost condition. In this case, the MB interrupt flag and Host Bus Error bit in the Status register (STATUS.BUSERR) are both set in addition to STATUS.ARBLOST.
The Host Received Not Acknowledge bit in the Status register (STATUS.RXNACK) will always contain the last successfully received acknowledge or not acknowledge indication.
In this case, software will typically inform the application code of the condition and then clear the interrupt flag before exiting the interrupt routine. No other flags have to be cleared at this moment, because all flags will be cleared automatically the next time the ADDR.ADDR register is written.
Case 2: Address packet transmit complete – No ACK received
If there is no I2C Client device responding to the address packet, then the INTFLAG.MB interrupt flag and STATUS.RXNACK will be set. The clock hold is active at this point, preventing further activity on the bus.
The missing ACK response can indicate that the I2C Client is busy with other tasks or sleeping. Therefore, it is not able to respond. In this event, the next step can be either issuing a stop condition (recommended) or resending the address packet by a repeated start condition. When using SMBus logic, the Client must ACK the address. If there is no response, it means that the Client is not available on the bus.
Case 3: Address packet transmit complete – Write packet, Host on Bus set
If the I2C Host receives an acknowledge response from the I2C Client, INTFLAG.MB will be set and STATUS.RXNACK will be cleared. The clock hold is active at this point, preventing further activity on the bus.
- Initiate a data transmit operation by writing the data byte to be transmitted into DATA.DATA.
- Transmit a new address packet by writing ADDR.ADDR. A repeated start condition will automatically be inserted before the address packet.
- Issue a stop condition, consequently terminating the transaction.
Case 4: Address packet transmit complete – Read packet, Client on Bus set
If the I2C Host receives an ACK from the I2C Client, the I2C Host proceeds to receive the next byte of data from the I2C Client. When the first data byte is received, the Client on Bus bit in the Interrupt Flag register (INTFLAG.SB) will be set and STATUS.RXNACK will be cleared. The clock hold is active at this point, preventing further activity on the bus.
- Let the I2C Host continue to read data by acknowledging the data received. ACK can be sent by software, or automatically in smart mode.
- Transmit a new address packet.
- Terminate the transaction by issuing a stop condition.
Transmitting Data Packets
When an address packet with direction Host Write (see Figure 26-3) was transmitted successfully , INTFLAG.MB will be set. The I2C Host will start transmitting data via the I2C bus by writing to DATA.DATA, and monitor continuously for packet collisions.
If a collision is detected, the I2C Host will lose arbitration and STATUS.ARBLOST will be set. If the transmit was successful, the I2C Host will receive an ACK bit from the I2C Client, and STATUS.RXNACK will be cleared. INTFLAG.MB will be set in both cases, regardless of arbitration outcome.
It is recommended to read STATUS.ARBLOST and handle the arbitration lost condition in the beginning of the I2C Host on Bus interrupt. This can be done as there is no difference between handling address and data packet arbitration.
STATUS.RXNACK must be checked for each data packet transmitted before the next data packet transmission can commence. The I2C Host is not allowed to continue transmitting data packets if a NACK is received from the I2C Client.
Receiving Data Packets
When INTFLAG.SB is set, the I2C Host will already have received one data packet. The I2C Host must respond by sending either an ACK or NACK. Sending a NACK may be unsuccessful when arbitration is lost during the transmission. In this case, a lost arbitration will prevent setting INTFLAG.SB. Instead, INTFLAG.MB will indicate a change in arbitration. Handling of lost arbitration is the same as for data bit transmission.