The Inter Integrated Circuit (I2C) module is a serial interface primarily intended for communication with other peripheral or microcontroller devices. Examples of the peripheral devices are: serial EEPROM memories, shift registers, display drivers, serial AD converters, etc. In the dsPIC30F family of devices the I2C module can operate in the following systems:
The I2C module contains independent I2C master logic and I2C slave logic each generating interrupts based on their events. In multi-master systems, the software is simply partitioned into master controller and slave controller. When the master logic is active, the slave logic remains active also, detecting the state of the bus and potentially receiving messages from itself or from other I2C devices. No messages are lost during multi-master bus arbitration. In a multi-master system, bus collision conflicts with other masters in the system are detected and the module provides a method to terminate and then restart the messages.
The I2C module contains a baud-rate generator. The baud-rate generator does not consume other timer resources in the device. The speed of operation of the module may be standard or fast and it may detect 7-bit and 10-bit addresses.
The I2C module may be configured to operate in the following modes:
A standard I2C interface makes use of two pins, SCL (clock line) and SDA (data line).
The configuration of the I2C module is performed by using the following registers: I2CRV (8 bits), I2CTRN (8 bits), I2CBRG (9 bits), I2CON (16 bits), and I2CADD (10 bits). Functional block diagram of the I2C module is shown in Fig. 12-1.
The I2CCON and I2CSTAT are 16-bit control and status registers, respectively. The content of the I2CCON control register may be read or written and so is the content of the 10 higher bits of the I2CSTAT status register. The lower 6 bits of the status register are read only.
The I2CRSR shift register performs parallel-series conversion of data. Data to be transmitted are written in the I2CTRN buffer register, whereas received data are read from the I2CRCV buffer register. Address of a slave device on the I2C bus is written in the I2CADD register. The control bit A10M (I2CCON<10>) denotes whether the 7-bit or 10-bit addressing is used. Baud-rate is defined by the I2CBRG register, i.e. it holds the baud-rate generator reload value for the I2C module baud-rate generator.
NOTE: In receive operation the shift register I2CRSR and the buffer register I2CRCV create a double-buffered receiver, i.e. when a complete message is received by the I2CRSR register, the byte transfers to the I2CRCV register and the interrupt request for the I2C module is generated. While transmitting a message the transmit buffer is not double-buffered.
Fig. 12-1 Functional block diagram of I2C module
The 10-bit I2CADD register holds the slave device address. If the control bit A10M (I2CCON<10>) is cleared, address in the I2CADD is interpreted as a 7-bit address. When an address from a master device is received, only 7 lower bits are compared against the register I2CADD. If the control bit ADD10 (I2CCON<10>) is set, the value of the received address is compared in two cycles. At first, the 8 higher bits of the address are compared with the value '11110 A9 A8' (where A9 and A8 are two most significant bits of the device address held in the I2CADD register). If coincidence occurs, the lower 8 bits of the register I2CADD are compared with the 8 lower bits of the received address.
The segments of an address usable in a standard I2C communication are specified by the standard I2C protocol. Table 12-1 shows the ranges of I2C addresses supported by the family of dsPIC30F devices together with the corresponding applications.
| Address | Description |
|---|---|
| 0x00 | General call address or starting byte |
| 0x01 – 0x03 | Range of reserved addresses |
| 0x04 – 0x77 | Range of valid 7-bit addresses |
| 0x78 – 0x7B | Range of valid 10-bit addresses |
| 0x7C – 0x7F | Range of reserved addresses |
Table 12-1 Standard I2C addresses supported by the family of dsPIC30F devices
When in the slave mode, after setting the I2CEN (I2CCON<15>) enable bit, the slave function will begin to monitor the I2C bus to detect a START event. Upon deteting a START event, 8 bits are loaded to the I2CRSR shift register and the receved address is compared with the one from the I2CADD register. In the 7-bit address slave mode (A10M = 0) the bits I2CADD<6:0> are compared with the I2CRSR<7:1> bits. The bit I2CRSR<0> is ignored. The bits loaded to the shift register are sampled by the rising edge of SCL the clock.
If an address match occurs, the slave sends an ACKNOWLEDGE of the 9-bit message, and an interrupt of the I2C module is generated (the flag SI2CIF is set) on the falling edge od the ninth bit (ACK – acknowledegement). The address detection is of no influence neither on the content of the receive buffer register I2CRCV nor on the value of the bit RBF (I2CSTAT<1>) which indicates that there is a new value in the receive buffer register.
A typical standard I2C message consists of the START bit, address bits, R/W bit, acknowledge bit, data bits (eg. in an I2C communication with the EEPROM memory within data bits are the location address bits and the contents bits which are read out or written in), and STOP bit.
A slave device transmit process is carried out as follows. Upon reception of the address part of the message containing the R/W bit, the device enters the transmit mode. It sends the ACKNOWLEDGE bit (ACK) and keeps the SCL clock signal low until the message byte is written to the transmit buffer I2CTRN. Then, the SCL clock signal is released, the bit SCLREL is set (I2CCON<12>), and the 8-bit message is sent from the I2CRSR shift register. The bits are sent on the falling edge of the SCL clock so that the SDA pin data are valid when the SCL closk is high. The interrupt request is generated on the falling edge of the ninth clock period irrespective of the status of the ACKLOWLEDGE (ACK) bit of the master device.
The receive sequence of a slave device comprises the following steps. Upon receiving the address part of the message which contains the R/W bit cleared, the slave device is initiated for the receive mode. The incoming bits at the pin SDA are sampled on the rising edge of the SCL clock signal. After receiving 8 bits, if the receive buffer register I2CRCV is not full or the flag RBF (I2CSTAT<1>) is not cleared or the overflow status bit (I2COV (I2CSTAT<6>) of the receive buffer register I2CRCV is not set, the received bits contained by the shift register are transferred to the receive buffer register I2CRCV. Upon completion of the data transfer, the ACKNOWLEDGE bit ACK is generated as the ninth bit. If the flag RBF (I2CSTAT<1>) is set, the ACKNOWLEDGE bit ACK is not sent, but the interrupt request for the I2C is generated. In the case of the receive buffer overflow, the content of the shift register I2CRSR is not transferred to the receive buffer I2CRCV.
Attention!
The status overflow bit of the receive buffer I2COV (I2CSTAT<6>) is hardware set, but the user can clear it by the software. If the bit I2COV (I2CSTAT<6>) is not cleared, the I2C module will operate irregularly, i.e. a recevied message is written to the receive buffer register I2CRCV if RBF was cleared, but the bit acknowledge ACK is not sent to the master device.
The basic process of receiving and transmitting messages in the slave mode with 10-bit addressing is the same as in the slave mode with 7-bit addressing, the only difference is that the method of comparing addresses is much more complicated. The I2C standard specifies that after the START bit, any slave devise has to be addressed by two bytes. The control bit A10M (I2CCON<10>) is set meaning that a 10-bit address is in the I2CADD regsiter. After the START bit, the received data in the shift register I2CRSR<7:1> are compared with the expression '11110 A9 A8' containing two most significant bits of the device address, A9 and A8. If the result of the comparison is positive and the received R/W bit is cleared, an interrupt request is generated. At the same time the bit ADD10 (I2CSTAT<8>), which denotes partial match of the sent address and the slave address, is cleared. If the sent address and the slave address do not match or if the received R/W bit is set, the status bit ADD10 is cleared and the I2C is returned to the IDLE state. If there is partial match with the upper part of the address of the slave device, the lower part of the address is received and compared with the lower part of the address register I2CADD (I2CADD<7:0>). If a full match occurs, an interrupt request for the I2C module is generated and the status bit ADD10 (I2CSTAT<8>), indicating a full match of the 10-bit addresses, is set. If a full match does not occur, the status bit ADD (I2CSTAT<8>) is cleared and the module returns to the IDLE state.
In the case when a full match of all 10 bits is detected, the master device may send the part of the message defining whether the slave is to receive data or trasmit data to the master. If the master repeats the START bit, the upper address bit is cleared and the R/W bit is set in order to avoid that the STOP bit is generated, and the master performs initialization of the slave device for the operation transmit data. The synchronization of the read and transmit data to the master is performed in the slave device by stretching the SCL clock signal.
Whenever the slave device is to transmit data to the master, in both 7-bit or 10-bit addressing, stretching of the clock signal SCL is implemented by inserting the SCLREL (I2CCON<12>) bit on the falling edge of the ninth period of the clock. In the case when the transmit buffer is empty, the status bit TBF (I2CSTAT<0>) is cleared. Stretching of the SCL clock signal in the slave mode at data transmition is always performed irrespective of the state of the STREN (I2CON<6>) control bit which enables stretching of the SCL clock. This is not the case in the slave mode at data reception. The clock synchronization occurs after the ninth period of the SCL clock. Then, the slave device samples the value of the ACK acknowledgement bit (active low) and checks the value of the TBF status bit. If the ACK is low (the acknlowledge ACK bit active) and the TBF (I2CSTAT<0>) status bit is cleared, the SCLREL (I2CCON<12>) bit is cleared automatically. Setting the SCLREL (I2CCON<12>) bit low causes setting the external SCL line low. By the interrupt routine the user has to set the bit SCLREL (I2CCON<12>) before the slave device starts transmitting the message to the master. In this way the user is given the chance that in the interrupt routine writes data to be transferred to the I2CTRN transmit buffer register before the master device initiates a new transmit sequence.
Attention!
If the user writes data to be transferred to the I2CTRN transmit buffer register and sets the TBF bit before the falling edge of the ninth period of the SCL clock, the SCLREL (I2CCON<12>) bit will not be cleared and stretching of the SCL clock signal will not occur. Also, it shoud be noted that the SCLREL (I2CCON<12>) bit can be set by the software irrespective of the TBF bit.
In essence, the STREN (I2CON<6>) control bit primarily serves for enabling stertching of the SCL clock signal during reception in the slave mode. When the STREN (I2CON<6>) bit is set, the pin of the SCL clock signal is kept low at the end of each receive sequence in the slave mode. Stretching of the clock signal is performed after the ninth period of the SCL clock signal during a receive sequence. On the falling edge of the ninth period of the SCL clock signal the value of the ACK ACKNOWLEDGE bit (active low) is sampled and the value of the TBF status bit is checked. If the ACK is low (bit ACK active) and the RBF (I2CSTAT<1>) status bit set, the SCLREL (I2CCON<12>) bit is cleared automatically. Setting the SCLREL (I2CCON<12>) bit low causes setting the external SCL line low. By the interrupt routine the user has to set the bit SCLREL (I2CCON<12>) before the slave device starts receiving data from the master. In this way the user is given the chance that in the interrupt routine reads out received data from the I2CRCV receive buffer before the master device initiates a new receive sequence. This prevents the overflow of the I2CRCV receive buffer register.
Attention!
If the user reads out received data from the I2CRCV receive buffer register and clears the RBF bit before the falling edge of the ninth period of the SCL clock signal, the SCLREL (I2CCON<12>) bit will not be cleared and no stretching of the SCL clock signal will occur. Also, the SCLREL (I2CCON<12>) bit can be set by the software irrespective of the RBF bit. Clearing the RBF bit by the user has to be done carefully during the interrupt routine to avoid overflow of the I2CRCV receive buffer register.
A master device differs from a slave device in that it generates the system SCL serial clock, and START and STOP bits. Each data transfer is ended by a STOP bit or by the repeated START bit. A repeated START bit also means the beginning of a new data transfer, but the I2C bus is still busy by the current communication session.
In the master mode serial data are transferred via the SDA pin in synchronism with the SCL clock signal. The firstbyte to be sent contains the 7-bit address of the slave (the device for whom the message is intended) and one bit for data direction R/W. In the case of data transmit the R/W bit is cleared (logic zero). The STARTand STOP bits are sent in order to recognize the beginning and end of a communication session, i.e. of a data transfer.
In the master mode when receiving data, the 7-bit address of the slave (the device for whom the message is intended)and one bit for data direction R/W are sent first. In the case of data receive the R/W bit is set (logic one). Serial data are transmitted or received via pin SDA in synchronism with the SCL clock signal. Serial data are received 8 bits per cycle and each cycle is ended by sending the ACKNOWLEDGE ACK bit. The START and STOP bits are sent in order to recognize the beginning and end of a communication session.
In the master mode the transmission of a 7-bit address or of the second part of a 10-bit address is performed by writing the desired value to the transmit buffer register I2CTRN. The user writes the desired value to the transmit buffer register only when the I2C module is in the WAIT state. By writing data to the transmit buffer register I2CTRN, the status flag TBF (I2CSTAT<0>) is set and the baud-rate generator is enabled to start counting and start data transmission. Each data bit or address bit from the shift register is sent to the SDA pin on the falling edge of the SCL clock signal. When the device is transmitting data, the transmit status flag TRSTAT (I2CSTAT<14>) is set.
The reception in the master mode is enabled by setting, using the software, the RCEN (I2CCON<11>) control bit. In order to set the RCEN (I2CCON<11>) control bit, the I2C module has to be in the IDLE state. If this is not observed, the receive enable control bit RCEN (I2CCON<11>) will be ignored. The baud-rate generator starts counting and when it reaches the preset count it is reset, then the state of the SCL clock signal is changed, the ACKNOWLEGDE ACK bit is set, and the value of the SDA line is sampled on the rising edge of the clock signal and transferred to the shift register I2CRSR.
In the master mode of the I2C module the value of the baud rate is defined by the preset value of the baud-rate counter BRG in the I2CBRG register. The baud-rate counter counts down from the preset value to zero. When zero is reached, the preset value BRG is written to the counter again. In the case when the clock arbitration occurs, writing the preset value BRG to the baud-rate counter is performed when the pin SCL is high.
According to the I2C standard, the frequency of the clock signal FSCK is 100kHz or 400kHz. The user has the optionofspecifying the baud rate up to 1MHz. The following expression defines in the I2CBRG register the value of the desired baud rate:

The arbitration of the clock signal is performed each time when the master device releases the SCL pin (the SCL pin is set high) during reception, transmission, or the repeated START state or STOP state. When the master device releases the SCL pin, the baud-rate generator does not operate. The preset value BRG is written each time the SCL pin is set high while the baud-rate generator does not operate. Then, the baud-rate counter starts counting and generates the SCL clock signal.
The I2C module can generate two interrupts by setting the flag bits MI2CIF (IFS0<14> - I2C master interrupt flag) for a master interrupt request and SI2CIF (IFS0<13> - I2C slave interrupt flag) for a slave interrupt request. An I2C master interrupt request MI2CIF (IFS0<14>) is generated on completion a master message event (transmission or reception). A slave interrupt request SI2CIF (IFS0<13>) is generated when a message intended for a slave device is detected.
In the case of the fast mode (400kHz), the standard I2C communication interface requires the slope control on pins SDA and SCL. The control bit DISSLW allows that, if desired, the slope control is skipped in order to allow baud rates up to 1MHz.
By setting the control bit IPMIEN the use of the Intelligent peripheral management interface (IPMI) support is enabled which allows that the I2C module covers all defined addresses.
All devices on the I2C bus are addressed by using the general call address. When the general call address is used, all device on the I2C bus which receive a message with this address should (at least theoretically) confirm the reception by the ACKNOWLDGE ACK bit. In essence, the general call address is one of the addresses reserved by the I2C protocol. These are usually all '0' with the direction bit R/W=0.
In order to enable the recognition of the general call address, the control bit GCEN (I2CCON<15>) which enables general call address has to be set.
When the microcontroller enters SLEEP state, all clock sources are off, consequently the baud-rate generator stops operating and stays low (logic zero). If entering the SLEEP state occurs during transmission of a message, the current transmission is interrupted and the transmitted data are lost. Similarly, if entering the SLEEP state occurs during reception of a message, the current reception is interrupted and the received psrt of the message is lost.
In the IDLE state the I2C module may continue operating if the control bit I2CSIDL (I2CCON<13>) is not set. If the bit I2CSIDL (I2CCON<13>) is set, the I2C module behaves like in the SLEEP state.
Example:
This example shows how to use the specialized I2C library of the mikroPascal compiler for dsPIC microcontrollers which allows easy initialization of the I2C module, writing, and reading data from the transmit and receive buffers of the I2C module, respectively. Specifically, the example shows the method of connecting the I2C module to the serial I2C EEPROM memory 24C02.
program I2CEEPROM;
var dAddr : word;
begin
ADPCFG := 0xFFFF;
PORTB := 0;
TRISB := 0;
dAddr := 0x02;
I2c_Init(0x000186A0);
I2c_Start(); // issue I2C start signal
I2c_Write(0xA2); // send byte via I2C (command to 24cO2)
I2c_Write(dAddr); // send byte (address of EEPROM location)
I2c_Write(0xF5); // send data (data to be written)
I2c_Stop();
Delay_ms(100);
I2c_Start(); // issue I2C start signal
I2c_Write(0xA2); // send byte via I2C (device address + W)
I2c_Write(0x02); // send byte (data address)
I2c_Restart(); // issue I2C signal repeated start
I2c_Write(0xA3); // send byte (device address + R)
PORTB := I2c_Read(1); // Read the data (NOT acknowledge)
I2c_Stop();
end.
The procedure I2C_Init initializes the I2C module, i.e. baud-rate. The procedure I2C_Start sets the conditions for START of the communication session on the I2C bus (defines the beginning of the message). The procedures I2C_Write and I2C_Read enable that a microcontroller of the family dsPIC30F as a master can write or read from a peripheral having the I2C interface. In addition to these procedures, also significant is the procedure I2C_Stop setting the state at the end of the I2C communication session (defines the end of the message). The I2C library of the mikroPascal compiler for dsPIC microcontrollers contains also the procedures I2C_Repeated_Start and I2C_Is_Idle generating the state of a repeated start and the state of waiting of the I2C module, respectively. Fig. 12-2 shows the connection of a microcontroller of the family dsPIC30F to a serial I2C EEPROM memory 24C02.
Fig. 12-2 Interconnection between a dsPIC30F device and a serial I2C EEPROM memory 24C02
Fig. 12-3a Pinout of the dsPIC30F4013 device
Fig. 12-3b Pinout of the dsPIC30F6014A device
Finally, a description of the I2C module registers of the dsPIC30F4013 device is presented.
| name | ADR | 15 | 14 | 13 | 12 | 11 | 10 | 9 |
|---|---|---|---|---|---|---|---|---|
| I2CRCV | 0x0200 | - | - | - | - | - | - | - |
| I2CTRN | 0x0202 | - | - | - | - | - | - | - |
| I2CBRG | 0x0204 | - | - | - | - | - | - | - |
| I2CCON | 0x0206 | I2CEN | - | I2CSIDL | SCLREL | IPMIEN | A10M | DISSLW |
| I2CSTAT | 0x0208 | ACKSTAT | TRSTAT | - | - | - | - | GCSTAT |
Table 12-2 Description of I2C registers
| 8 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 | Reset State |
|---|---|---|---|---|---|---|---|---|---|
| - | Receive buffer register | 0x0000 | |||||||
| - | Transmit buffer register | 0x00FF | |||||||
| Baud-rate generator preset register | 0x0000 | ||||||||
| SMEN | GCEN | STREN | ACKDT | ACKEN | RCEN | PEN | RSEN | SEN | 0x0000 |
| ADD10 | IWCOL | I2COV | D_A | P | S | R_W | RBF | TBF | 0x0000 |
| Address register | |||||||||
(Table 12-2 continued)
I2CEN – I2C enable bit
(I2CEN = 0 I2C module disabled, I2CEN = 1 I2C module enabled and the SDA
and SCL pins configured as serial port pins)
I2CSIDL – STOP in IDLE mode bit (I2CSIDL = 0 continue module operation,
I2CSIDL = 1 discontinue module operation)
SCREL – SCL pin release control bit (SCREL = 0 hold SCL clock low
(clock stretch in slave mode), SCREL = 1 release SCL clock)
IPMIEN – Intelligent peripheral management interface enable bit
(IPMIEN = 0 IPMI mode not enabled, IPMIEN = 1 enable IPMI support mode)
A10M – 10-bit slave address bit
(A10M = 0 I2CADD is a 7-bit address, I2CADD = 1 I2CADD is a 10-bit address)
DISSLW – Disable slew rate control bit
(DISSLW = 0 slew rate control enabled, DISSLW = 1 slew rate control disabled)
SMEN – SMBus input levels bit
(SMEN = 0 disable SMBus input thresholds, SMEN = 1 enable I/O pin
thresholds compliant with SMBus specification)
GCEN – General call enable bit (when operating as I2C slave)
(GCEN = 0 general call address disabled, GCEN = 1 enable
interrupt when a general call address is received in the I2CRSR)
STREN – SCL clock stretch enable bit (when operating as I2C slave)
(STREN = 0 disable software or receive clock stretching,
STREN = 1 enable software or receive clock stretching)
ACKDT – Acknowledge data bit (when operating as I2C master, during master receive)
(ACKDT = 0 send NACK during Acknowledge, ACKDT = 1 send ACK during Acknowledge)
ACKEN – Acknowledge sequence enable bit (when operating as I2C master, during master receive)
(ACKEN = 0 acknowledge sequence not in progress, ACKEN = 1 initiate acknowledge
sequence on SDA and SCL pins and transmit ACKDT data bit)
RCEN – Receive enable bit (when operating as I2C master)
(RCEN = 0 receive sequence not in progress, RCEN = 1 enable receive mode for I2C)
PEN – STOP condition enable bit (when operating as I2C master)
(PEN = 0 STOP condition not in progress,
PEN = 1 initiate STOP condition on SDA and SCL pins)
RSEN – Repeated START condition enable bit (when operating as I2C master)
(RSEN = 0 repeated START condition not in progress,
RSEN = 1 initiate repeated START condition on SDA and SCL pins)
SEN – START condition enabled bit (when operating as I2C master)
(SEN = 0 START condition not in propgress,
SEN = 1 initiate START condition on SDA and SCL pins)
ACKSTAT – Acknowledge status bit (when operating as I2C master)
(ACKSTAT = 0 ACK received from slave,
ACKSTAT = 1 NACK received from slave)
TRSTAT – Transmit status bit (when operating as I2C master)
(TRSTAT = 0 master transmit is not in progress,
TRSTAT = 1 master transmit is in progress (8 bits + ACK))
BCL – Master bus collision detect bit (BCL = 0 no collision,
BCL = 1 a bus collision has been detected during a master operation)
GCSTAT – General call status bit (GCSTAT = 0 general call address was not received,
GCSTAT = 1 general call address was received)
ADD10 – 10-bit address status bit
(ADD10 = 0 10-bit address was not matched, ADD10 = 1 10-bit address was matched)
IWCOL – Write collision detect bit
(IWCOL = 0 no collision, IWCOL = 1 an attempt to write the I2CTRN register failed
because the I2C module is busy)
I2COV – Receive overflow flag bit (I2COV = 0 no overflow, I2COV = 1 a byte was received while
the I2CRCV register is still holding the previous byte)
D_A – Data/address bit (when operating as I2C slave)
(D_A = 0 indicates that the last byte received was device address,
D_A = 1 indicates that the last byte received was data)
P – STOP bit
(P = 0 STOP bit was not detected last,
P = 1 indicates that a STOP bit has been detected last)
S – START bit (S = 0 START bit was not detected last,
S = 1 indicates that a START, or repeated START, bit has been detected last)
R_W – Read/write bit information (when operating as I2C slave)
(R_W = 0 write – indicates data transfer is input to slave,
R_W = 1 read - indicates data transfer is output from slave)
RBF – Receive buffer full status bit (RBF = 0 receive not complete,
I2CRCV is empty, RBF = 1 receive complete, I2CRCV is full)
TBF – Transmit buffer full status bit (TBF = 0 transmit complete,
I2CTRN is empty, TBF = 1 transmit in progress, I2CTRN is full)