I2C Communication with USI Module

From Texas Instruments Wiki
Jump to: navigation, search

The USI (Universal Serial Interface) module which can be found in several MSP430 devices can be used either as SPI or I2C interface. Altough there is already an application report implementing a USI I2C library, this guide is intended to give a deeper explanation on how the USI module works, together with tips and tricks working with the USI module.

USI Module I2C Registers

As stated in the User's Guide documentation, the USI (Universal Serial Interface) module is configured if the following configuration is set:

  • USII2C = 1
  • USICKPL = 1
  • USICKPH = 0
  • USILSB and USI16B cleared
  • USIPE6 and USIPE7 set to enable SCL and SDA port function

For I2C mode, the following registers and bit fields play important role on establising the I2C communication:

  • The 16 bit serial register (USISR) containing the input/output data - however in I2C mode, the USISR is used only 8 bit wide (USISRL).
  • The USIOE bit of USICTL0 register controls the input/output direction of the shift register USISRL
  • The USICNTx bits of USICNT register determines how many bit(s) shall be transmitted/received. If USIMST bit of USICTL0 is set (i.e. node is acting as I2C master), setting the USICNTx with a value greater than zero will directly cause the clock signals generated on the SCL line, with the number of clock signals corresponds to the USICNTx bits value.
  • The USIGE bit of USICTL0 register which can be used together with USIOE bit to bypass the MSB value of USISR into the SDA line
  • Two interrupt flags of USI module in I2C mode:
    • USIIFG (activated by USIIE) indicating that the USICNTx is decremented to zero
    • USISTTIFG (activated by USISTTIE) indicating that a start signal has been received

Basic Operations

Basic Transmission and Reception Process

The transmission and reception process can be done basically in the following steps:

  • Setting the input(reception)/output(transmission) direction by resetting/setting the USIOE bit
  • For transmission, writing the data to be transmitted into USISRL register
  • Setting the number of bits to be transmitted/received in USICNTx bits of USICNT register (NOTE: USICNT register contains other bits than USICNTx, therefore it is necessary to mask the value before setting the USICNTx bits)

The following code snippet shows how the I2C reception can be done:

USICTL0 &= ~USIOE; // set SDA as input USICNT = (USICNT & 0xE0) + NUM_OF_BYTE;

The NUM_OF_BYTE is usually 8 for receiving a data byte or 1 for receiving (N)ACK bit. If the node acts as I2C master, the SCL signal will be generated (as many as the USICNTx bits value) as soon as the USICNTx bit is written and the content of SDA line will be shifted into the USISRL register. If the node acts as I2C slave, the USI module waits for incoming SCL signal before shifting in the data inside USIRL.

The following code snippet shows how the I2C transmission can be done:

USICTL0 |= USIOE; // set SDA as output USISRL = DATA_BYTE_TO_BE_SENT; USICNT = (USICNT & 0xE0) + NUM_OF_BYTE;

The NUM_OF_BYTE is usually 8 for sending a data byte or 1 for sending (N)ACK bit. If the node acts as I2C master, the SCL signal will be generated (as many as the USICNTx bits value) as soon as the USICNTx bit is written and the USISRL register content will be also shifted out along the clock signal at SCL line. If the node acts as I2C slave, the USI module waits for incoming SCL signal before shifting out the data inside USIRL.

Generating START/STOP condition - Setting SDA Line without SCL signal

In I2C protocol, a START condition which marks the start of an I2C packet is defined as a HIGH to LOW transission of SDA line while SCL line is held HIGH. On the other side the STOP condition is defined as LOW to HIGH transission of SDA line while SCL is held HIGH.

As mentioned above, usually the content of USISRL register corresponding to the value SDA lin, will not be outputted with any transmission/reception of clock signal on SCL line. However for example to generate START and STOP signal, it should be possible to output the MSB value of USISRL register without any clock signal on SCL line. This can be done by setting USIGE and USIOE bits of USICTL0 register to bypass the MSB value into the SDA line. The following code shows an example on generating START condition:

  1. define FORCING_SDA_HIGH() \
       {                            \
         USISRL = 0xFF;             \
         USICTL0 |= USIGE;          \
         USICTL0 &= ~(USIGE+USIOE); \
       }
  1. define FORCING_SDA_LOW() \
       {                         \
         USISRL = 0x00;          \
         USICTL0 |= USIGE+USIOE; \
         USICTL0 &= ~USIGE;      \
       }

// function to generate I2C START condition void i2c_usi_mst_gen_start(void) {

 // make sure SDA line is in HIGH level
 FORCING_SDA_HIGH();
 // small delay
 DELAY(DELAY_START_CYCLES);
 // pull down SDA to create START condition
 FORCING_SDA_LOW();

}

// function to generate I2C STOP condition void i2c_usi_mst_gen_stop(void) {

 USICTL0 |= USIOE;
 USISRL = 0x00;
 USICNT = 1;
 // wait for USIIFG is set
 i2c_usi_mst_wait_usi_cnt_flag();
 FORCING_SDA_HIGH();

}

Generating RESTART/REPEATED START condition

Generating repeated condition using the USI module can be done such as follows:

// function to generate I2C REPEATED START condition void i2c_usi_mst_gen_repeated_start(void) {

 USICTL0 |= USIOE;
 USISRL = 0xFF;
 USICNT = 1;
 // wait for USIIFG is set
 i2c_usi_mst_wait_usi_cnt_flag();
 // small delay
 DELAY(DELAY_START_CYCLES);
 // pull down SDA to create START condition
 FORCING_SDA_LOW();
 // small delay
 DELAY(DELAY_START_CYCLES);

}

USI module Example

The following example code shows a small implementation of I2C communication between MSP430G2452 as I2C master and CMA3000D-01 accelerometer as I2C slave. The example demonstrates the typical single byte memory read from the slave address with repeated start as shown below (in this case the DOUTZ register - address 0x08 - from the CMA3000D-01):

USI example comm.PNG

The source code along the project files for CCS v5.1 can be found as follows: File:USI Example.zip.

The following images show the I2C packet dump result of the example code above: Usi i2c master cma3000 slave dump.PNG