This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

Simple custom I2C interface controller from MSP430 Master to a digital camera

Other Parts Discussed in Thread: TMP100, PCF8574, DAC8571, MSP430F5438A, ENERGIA

HI,

Are there 'tutorials for dummys' regarding I2C interface?

A camera I am trying to control has a 'similar' I2C interface except it uses 16 bit registers instead of 8 bits and thus 16 bit data transfers.

Seeing only examples with constant variables and no comments on what is happening does not help much.

Thanks

  • Hi Dan!


    What do you mean by "custom" I²C interface?

    Wether the registers are 16 bit or 8 bit does not matter. I don't know any hardware that can only send 16 bits. Normally everything is based on bytewise transfers. To send 16 bits you just send two times 8 bits in series. The USI module of some MSPs can send 16 bit at once, but they can also send 8 (or even 7) bit of data. It is all about configuration.

    There are a lot examples. Which processor do you want to use?

    Here are the code examples for the ever popular G2553 which has an USCI:

    The code examples contain the following programs concerning the I²C interface:

    • msp430g2xx3_uscib0_i2c_01.c                USCI_B0 I2C Master to TMP100, Set P1.0 if Temp > 28C
    • msp430g2xx3_uscib0_i2c_02.c                USCI_B0 I2C Master Interface to PCF8574, Read/Write
    • msp430g2xx3_uscib0_i2c_03.c                USCI_B0 I2C Master Interface to DAC8571, Write
    • msp430g2xx3_uscib0_i2c_04.c                USCI_B0 I2C Master RX single bytes from MSP430 Slave
    • msp430g2xx3_uscib0_i2c_05.c                USCI_B0 I2C Slave TX single bytes to MSP430 Master
    • msp430g2xx3_uscib0_i2c_06.c                USCI_B0 I2C Master TX single bytes to MSP430 Slave
    • msp430g2xx3_uscib0_i2c_07.c                USCI_B0 I2C Slave RX single bytes from MSP430 Master
    • msp430g2xx3_uscib0_i2c_08.c                USCI_B0 I2C Master TX multiple bytes to MSP430 Slave
    • msp430g2xx3_uscib0_i2c_09.c                USCI_B0 I2C Slave RX multiple bytes from MSP430 Master
    • msp430g2xx3_uscib0_i2c_10.c                USCI_B0 I2C Master RX multiple bytes from MSP430 Slave
    • msp430g2xx3_uscib0_i2c_11.c                USCI_B0 I2C Slave TX multiple bytes to MSP430 Master
    • msp430g2xx3_uscib0_i2c_12.c                USCI_B0 I2C Master TX/RX multiple bytes from MSP430 Slave with a repeated start in between TX and RX operations.
    • msp430g2xx3_uscib0_i2c_13.c                USCI_B0 I2C Slave RX/TX multiple bytes to MSP430 Master

    Enough to get started.

    Dennis

  • The I2C-bus is specified for -and only- 8-bit data transfer. The Serial Communication Interface (USI/USCI) in I2C mode will always use 8-bit data transfers.
    9 or more bits needs to be sent as a stream of bytes.
  • Leo is right! Just had a look in the user's guide - even the chapter of the USI module that can handle 16 bit transfers says that USI16B has to be cleared for I²C which means 8 bits only. And this makes sense, of course, because you have to handle the (N)ACK from the other side.

    Dennis

  • By 'custom' I mean modify the I2C driver do try to do specifically what we want.

    So I can send two bytes separately as long as I get an (N)/ACK from the other side each time?

    I am using the TrxEB that has an F5438A. Presumably the G2553 is the LaunchPad board.

    Thanks,
    Dan
  • Dan,


    I²C is I²C - I don't think you have to modify anything to get it working. Just configure the USCI of the MSP430F5438A for I²C operation.

    Samples for doing this with your MSP430F5438A can be found here:

    • msp430x54xA_uscib0_i2c_04.c           USCI_B0 I2C Master RX single bytes from MSP430 Master
    • msp430x54xA_uscib0_i2c_05.c           USCI_B0 I2C Slave TX single bytes to MSP430 Slave
    • msp430x54xA_uscib0_i2c_06.c           USCI_B0 I2C Master TX single bytes to MSP430 Slave
    • msp430x54xA_uscib0_i2c_07.c           USCI_B0 I2C Slave RX single bytes from MSP430 Master
    • msp430x54xA_uscib0_i2c_08.c           USCI_B0 I2C Master TX multiple bytes to MSP430 Slave
    • msp430x54xA_uscib0_i2c_09.c           USCI_B0 I2C Slave RX multiple bytes from MSP430 Master
    • msp430x54xA_uscib0_i2c_10.c           USCI_B0 I2C Master RX multiple bytes from MSP430 Slave
    • msp430x54xA_uscib0_i2c_11.c           USCI_B0 I2C Slave TX multiple bytes to MSP430 Master
    • msp430x54xA_uscib0_i2c_12.c           USCI B0 I2C Master TX/RX multiple bytes to/from MSP430 Slave Repeated Start
    • msp430x54xA_uscib0_i2c_13.c           USCI B0 I2C Slave RX/TX multiple bytes from/to MSP430 Master Repeated Start

    You can send as many bytes as you want, but the I²C interface has a (N)ACK between every byte.

    Dennis

  • Great, thanks.

    How important is the SLAVE_ADDRESS? I understand it is not necessary for one master and one slave. The camera does have a device address number, I think.

    Also, is there a user manual for the 'constants' that are used in some of the examples I have seen? Looks like there is an example that uses sub-routine calls instead, such as USCI_B_I2C_enable(USCI_B0_BASE, USCI_B_I2C_TRANSMIT_MODE), but of course still more constants.

    Dan
  • There is always an address, even with only one slave connected. This slave address is given by the slave itself. It will respond only when beeing addressed. Where are your examples from? Those sub-routines maybe come from Energia? Not sure, have never used it. I prefer writing everything myself. And those "constants" you are mentioning are definitions/macros. They are easier to read expressions for registers, bits in registers or actions on registers.

    Just an example:

    #define LED_ON (P1OUT |= 0x01)
    
    void main( void )
    {
      ...
      LED_ON;
      ...
    }

    Same for individual bits or bit fields in a register - what is easier to read?

    UCA0CTL1 |= UCSWRST;

    or

    UCA0CTL1 |= 0x01;

    Both is the same, but the first one lets you know that it is the software reset bit - the 0x01 only tells you that it is bit 0, but who knows all the bits in a register?

    The reason for the possibility of using UCSWRST is a definition in the header file of the processor you will include in your project which simply says:

    #define UCSWRST 0x01

    In your case these expressions will define registers and bits of them.

    Dennis

  • The slave address is hard-coded into the slave. Since I2C is a bus with addressing, addressing is always required, no matter how many slaves are really there. Unless a slave is explicitly addressed, it remains passive.

    I2C is a transaction-based bus protocol. A transaction starts with a start condition followed by the address of the target slave and a direction bit. Then the addressed slave acknowledges its presence (if present). Then the master begins sending or receiving data, depending on the previously declared direction. When sending data, the slave acknowledges the reception of each byte. If the slave doe snot acknowledges a byte or the master doesn't want to send more, the transaction is ended with a stop condition. then the next transfer can start (in case of a read transfer, the master will continue to read until satisfied (the slave may send dummy data or just ignore superfluous reads).

    This is how I2C works.

    You need to
    - set up the port logic
    - configure the clock system (the master requires a clock signal, but since I2C passes the clock to the slave, it doesn't need to be precise)
    - configure the USCI hardware for I2C, mainly the final clock speed which has to be in the allowed (for master) and supported (by slave) range, derived from the clock system clock signal

    For each transfer, you'll have to
    - declare a slave address and transfer direction
    - start a transfer
    - provide (or accept) the data
    - end the transfer.

    The library functions help you dealing with all this. But since they are generic, they will need some additional information to adapt to your specific situation (e.g. which USCI do you use, as some MSPs have multiple, on which port pins are the USCI signals, as this varies from MSP to MSP etc.)
    A description of the library functions should come with the library. Either in the header files or in the code files or as separate documentation (I don't use it, so I don't know).

    If you use the forum search, you will also find lots of threads about I2C. With further explanations as well as code.
  • Thanks everyone,
    I was able to send a two byte address a byte at a time and get the return status I was looking for as a start. Everyone's comment were helpful.

    I used the Energia Wire (I2C) library examples. The code I created below is based on the example master receive routine, which means the camera is behaving the same way.

    Dan
    ------------------
    void setup()
    {
    Wire.begin(); // join i2c bus (address optional for master)
    Serial.begin(9600); // start serial output to terminal on PC.
    }

    byte statusb1 = 0;
    byte statusb2 = 2;

    void loop()
    {
    Wire.beginTransmission(42); // 0x2A
    Wire.write(statusb1); // First byte of 2-byte address
    Wire.write(statusb2); // Second byte of 2-byte address
    Wire.endTransmission(); // stop transmittion

    delay(100); // experiment with delay

    Wire.requestFrom(42, 2);

    while(Wire.available()) // slave should include a 2 for a status value.
    {
    byte return1 = Wire.read(); // read most significant byte
    byte return2 = Wire.read(); // read 2nd byte
    Serial.print(return1);
    Serial.print(return2);
    }

    delay(100);
    }
    -------------------------

**Attention** This is a public forum