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.

MSP430I2041: MSP430i2041 with EMDC and CCS and read result over I2C

Part Number: MSP430I2041
Other Parts Discussed in Thread: TIDM-3OUTSMTSTRP, , MSP-ISO, UNIFLASH, MSP430F67791, MSP430G2553

Hi.

My name Dung.

I have project with MSP430i2041 EVM 1 Voltage (990K-2.4K - 220VAC max 250V), 3 Current (CT 1000.1, R = 6.8R max 80A), my design the same TIDM-3OUTSMTSTRP and use CT, not include Relay.

I have some question. On the EMDC when creat project why TI calculator approximately real value.

When I calib for MSP430i2041 by EMDC use KIT MSP430F5529LP, if only connect 3 CT to EVM, can read result to EMDC, when I connect 1V 3C to EVM it cannot connect to EMDC. I don't know why (I don't use MSP-ISO).

  • Dung,

    Did you review my feedback to your questions in your previous thread?

    MSP430I2041: Error when I use on Uniflash load image file

    Regards,

    James

  • Hi James. I have view your feedback. I will comback, thread. I thing that error when use Uniflash to load Image. I thing it have complete. If it continouos thread MSP430I2041: Error when I use on Uniflash load image file , this thread is close.

  • Hi Dung,

    If you haven't marked the other thread resolved, please do so. You can copy your EMDC-related questions and my answers into this thread, and then we can continue here.

    Regards,

    James

  • Hi James.

    Other thread I don't have question. This thread I have error when I connect HID to calibration value on KIT MSP430i2041 (EVM). 

    EVM 1 Voltage (990K-2.4K - 220VAC max 250V), 3 Current (CT 1000.1, Rshunt = 6.8R max 80A), my design the same TIDM-3OUTSMTSTRP and use CT, not include Relay.

    When I calibration for MSP430i2041 by EMDC use KIT MSP430F5529LP, if only connect 3 CT (have current thought CT) to EVM, can read result to EMDC (have data result) and add Voltage to EVM it cannot connect to EMDC (no receiver data result on EMDC). I don't know why it can't read data. I don't use MSP-ISO.

    Regards.

  • When I calibration for MSP430i2041 by EMDC use KIT MSP430F5529LP, if only connect 3 CT (have current thought CT) to EVM, can read result to EMDC (have data result) and add Voltage to EVM it cannot connect to EMDC (no receiver data result on EMDC). I don't know why it can't read data. I don't use MSP-ISO.

    Be careful not using the MSP-ISO. If AC line gets connected to the board ground rather than AC neutral, and you're not using MSP-ISO, your PC could get damaged and you could get shocked.

    You're saying that when you connect AC voltage to your board, the communication stops? This could be a power supply issue. How's the board powered? Battery? AC-to-DC power? F5529 LP? Make sure there's no power supply conflicts.

    Make sure your board is powered before or while you are apply voltages to any pins (e.g. connecting sensors, connecting UART pins).

    EVM 1 Voltage (990K-2.4K - 220VAC max 250V), 3 Current (CT 1000.1, Rshunt = 6.8R max 80A), my design the same TIDM-3OUTSMTSTRP and use CT, not include Relay.

    I created this same project in EMDC and had no trouble connecting to the i20xx to view results or calibrate the board.

    • Created new EMDC project with 1V and 3C sensors
    • Configured library based on TIDM-3OUTSMTSTRP
    • Saved EMDC project
    • Generated code
    • Imported code into CCS
    • Programmed i20xx
    • Closed CCS
    • Hooked up i20xx to F5529 LP (HID bridge)
    • Opened MCU in EMDC
    • Clicked Connect
    • Uncalibrated results were shown
    • Started calibration mode without any issues

    Here are some screenshots from my side.

    Regards,

    James

  • Your project run as the same my project Slight smile

    You're saying that when you connect AC voltage to your board, the communication stops? This could be a power supply issue. How's the board powered? Battery? AC-to-DC power? F5529 LP? Make sure there's no power supply conflicts.

    I have test with power from 5529LP and AC-to-DC Power, AC-to-DC module the same TIDM-3OUTSMTSTRP. I have carefully connect Neutral to 0V of EVM. Can you test calibration help me on TIDM-3OUTSMTSTRP. What is your connect?

    When I calibration, I connect TX, RX, GND to P3.4, P3.3 and GND of 5529LP board. Data result when not apply Voltage.

    And if I apply Voltage to EVM, I wait 5 min data not update.

  • I would divide and conquer this issue. I don't think it's an EMDC issue but a power supply issue. Without hooking anything up to AC, use the F5529 LP or a bench supply to power your board. The EMDC communication should work, and you should be able to enter the calibration mode. If that works, it indicates that your power supply is causing the device to stop communicating when AC is connected and you can start debugging that rather than the communication.

  • Now, I can't work on the i2041 for my project, because I don't understand why it can't be calibration. I switched to another IC for EVM, because i don't have time for test. If in future I have time maybe I can test and use it. MSP430i2401 and msp430F67791 I am sorry it don't work for my project. I have more time for it but it is not as expected.

    Thank you so much, James.

  • Hi James.

    The TI have solution for customer to design EVM. Why TI don't integration example calib value calculator in Code flow value of customer designed.

  • Hi Dung,

    The manual calibration process is complex and requires an accurate test source to apply precise voltages, currents and phase angles to the board. The EMDC GUI still requires a test source but will easily perform the calibration process. Then, you can use the applied calibration factors in your final design by either updating those factors in your CCS project or sending them over UART from a host MCU or processor in the system.

    For more details about the calibration calculations, refer to the following thread.

    MSP430i2041: Need EMDC calibration factor calculation details

    Regards,

    James

  • Hi, Jame.

    I thing when read full result Voltage mode Common ( 1V 3 CT), in EMDC mcu is >80%, but real when apply Voltage i thing MCU is overload => I can't read result and calibration it.  Then i readl Vrms, Irms, V Peak, I Peak, Active Power, Active Energy. I can calibration it.

    Now a read result over I2C, but it not read data. i use esp8266 on arduino.

    Start i write 55 AA 06 04 01 01 01 07 00, when read i write 55 AA 06 04 80 00 01 0D 00 ( VRMS PHASE A). result is 0189040E, when i change read Irms PhaseA and V, I of other Phase the same result.

    I don't understand. maybe wrong write I2C?  I Read mode Device 0x0A is '0' => IDLE in evm_start()

    byte evm_config(uint8_t device,uint8_t cmdRW, uint8_t cmdValue)
    { // 55 AA 06 04 CMD_CONFIG_MODE cmdRW cmdValue crcl crch
      byte byte_in,error;
      prepare_evm_write(CMD_CONFIG_MODE,cmdRW,cmdValue,6);
    
      Wire.beginTransmission(device);
      Serial.print(" Device: "); Serial.print(device,HEX); Serial.print(" "); 
      for(byte i=0;i<9;i++) {
        Wire.write(evm_write_message[i]);  
        if(cmdRW==CMD_WRITE)Serial.print(evm_write_message[i],HEX);
      }
      error = Wire.endTransmission();//Wire.endTransmission();
      if(cmdRW==CMD_READ){
        Wire.requestFrom(device, 1);
        byte_in = Wire.read();
        Serial.print(byte_in,HEX);
      }
      Serial.println(" ");
      return error;
    }
    void evm_start(){
      if(evm_config(i2041a,CMD_WRITE,CMD_MODE_ACTIVE)==0) Serial.println("Start Phase A - Ok. ");
      else Serial.println("Start Phase A - error. ");
      if(evm_config(i2041b,CMD_WRITE,CMD_MODE_ACTIVE)==0) Serial.println("Start Phase B - Ok. ");
      else Serial.println("Start Phase B - error. ");
      if(evm_config(i2041c,CMD_WRITE,CMD_MODE_ACTIVE)==0) Serial.println("Start Phase C - Ok. ");
      else Serial.println("Start Phase C - error. ");
       Serial.print("Read mode Device A");  evm_config(i2041a,CMD_READ,CMD_READ);
       Serial.print("Read mode Device B");  evm_config(i2041b,CMD_READ,CMD_READ);
       Serial.print("Read mode Device C");  evm_config(i2041c,CMD_READ,CMD_READ);
    }

  • Hi Dung,

    I thing when read full result Voltage mode Common ( 1V 3 CT), in EMDC mcu is >80%, but real when apply Voltage i thing MCU is overload => I can't read result and calibration it.  Then i readl Vrms, Irms, V Peak, I Peak, Active Power, Active Energy. I can calibration it.

    I'm sorry, but I don't understand this. Are you saying that you can read the values when no voltage is applied but you cannot read values when voltage is applied? That shouldn't matter unless there's a power supply conflict. If you're using the MSP-ISO, make sure you're not using the isolated power supply for 3V3 if your board already has an AC/DC to 3V3 supply.

    Start i write 55 AA 06 04 01 01 01 07 00, when read i write 55 AA 06 04 80 00 01 0D 00 ( VRMS PHASE A). result is 0189040E, when i change read Irms PhaseA and V, I of other Phase the same result.

    For these commands, you can check the protocol in the latest EMDC Technology Guide (v1.40 as of today). Make sure you're changing the Phase ID byte in the command.

    I don't understand. maybe wrong write I2C?  I Read mode Device 0x0A is '0' => IDLE in evm_start()

    I'm not sure about the Arduino code. Perhaps you could post that on an Arduino forum. I would also recommend just using one of our I2C code examples from TI Resource Explorer on the i20xx with dummy data to get the I2C communication working separately from the EMDC project. Then, you can work on integrating the I2C code into your EMDC project when it's working.

  • Hi James.

    I'm sorry, but I don't understand this.

    When I creat new project EVM with all parameter (0x80-0x8B) in mode 1V 3 CT, data result can connect with EMDC when AC voltage don't connect. When I connect AC Voltage to EVM => can't read result to calibration by EMDC.

    If I creat project with VRMS, IRMS, Vpeak, Ipeak, Active power, Energy Power mode 1V 3 CT, I can calibration EVM over EMDC.

    I'm not sure about the Arduino code. Perhaps you could post that on an Arduino forum. I would also recommend just using one of our I2C code examples from TI Resource Explorer on the i20xx with dummy data to get the I2C communication working separately from the EMDC project. Then, you can work on integrating the I2C code into your EMDC project when it's working.

    Can you send to me example project Communication I2C between MSP430F5529LP with EVM MSP430i2041. After read result over I2C 5529LP send data debug to PC by UART. I want test I2C read data is Ok with MSP430Fxx. Please help me.

    My project need send data to Server over Wifi Internet. 

      

    Thank you so much.

  • When I creat new project EVM with all parameter (0x80-0x8B) in mode 1V 3 CT, data result can connect with EMDC when AC voltage don't connect. When I connect AC Voltage to EVM => can't read result to calibration by EMDC.

    If I creat project with VRMS, IRMS, Vpeak, Ipeak, Active power, Energy Power mode 1V 3 CT, I can calibration EVM over EMDC.

    The EMDC code programmed on the EVM must match the EMDC project. If they don't the communication may not work correctly.

    Can you send to me example project Communication I2C between MSP430F5529LP with EVM MSP430i2041. After read result over I2C 5529LP send data debug to PC by UART. I want test I2C read data is Ok with MSP430Fxx. Please help me.

    Check out my earlier comments. I'd recommend starting with the I2C code examples in TI Resource Explorer (inside CCS or at dev.ti.com). Like I mentioned earlier, you'll want to split this effort up and make incremental progress.

  • You did the I2C communication in measurement with the i2041. Structure to write read data with i2041 like. Can you write a sample code to initialize the i2041 to operate and read measured voltage or current data?

    Can you send to me example code to read data from i2041 in this application.

    What is address of VRMS, IRMS, and other data when i want read?

    Usually, i read and write to Eeprom, form for write (SlaveAdd, Address & read or write, data write or data to read).

  • You did the I2C communication in measurement with the i2041.

    I'm not sure what you mean.

    Can you send to me example code to read data from i2041 in this application.

    You can find i20xx I2C example code in TI Resource explorer inside CCS or at dev.ti.com.

    What is address of VRMS, IRMS, and other data when i want read?

    These are just variables stored in RAM that you can use with I2C to send the data to a host.

  • Hi James Evans.

    I use I2C to read result EVM from i2041. I write on MSP430G2553. MSP430G2553 is mater I2C will read data evm of multi device i2041 (add 0x0A). but my code read result only 00 FF FF FF FF FF FF FF FF FF FF . Please check for me, i have send I2C_Master_Write(SLAVE_ADDR, MasterType0, TYPE_0_LENGTH);  // {0x55,0xAA,0x06,0x04,0x01,0x01,0x01,0x07,0x00};   before read data   {0x55,0xAA,0x07,0x04,0x80,0x00,0x00,0x00,0x84,0x00};

    //******************************************************************************
    //   MSP430G2xx3 Demo - USCI_B0, I2C Master multiple byte TX/RX
    //
    //   Description: I2C master communicates to I2C slave sending and receiving
    //   3 different messages of different length. I2C master will enter LPM0 mode
    //   while waiting for the messages to be sent/receiving using I2C interrupt.
    //   ACLK = NA, MCLK = SMCLK = DCO 16MHz.
    //
    //
    //                   MSP430G2553
    //                 -----------------
    //            /|\ |             P2.6|--- XIN
    //             |  |                 |   |
    //             ---|RST              |   32kHz
    //                |                 |   |
    //                |             P2.7|--- XOUT
    //                |             P1.1|<------- Receive Data (UCA0RXD)
    //                |             P1.2|-------> Transmit Data (UCA0TXD)
    //                |             P1.6|<------- Receive Data (UCB0SCL)
    //                |             P1.7|-------> Transmit Data (UCB0SDA)
    //
    //   Nima Eskandari
    //   Texas Instruments Inc.
    //   April 2017
    //   Built with CCS V7.0
    //******************************************************************************
    
    #include <msp430.h>
    #include <stdint.h>
    #include <stdbool.h>
    
    
    //******************************************************************************
    // UART Initialization *********************************************************
    //******************************************************************************
    
    #define SMCLK_11500     0
    #define SMCLK_9600      1
    #define ACLK_9600       2
    
    #define UART_MODE       SMCLK_11500
    
    //******************************************************************************
    // I2C Initialization **********************************************************
    //******************************************************************************
    
    #define SLAVE_ADDR  0x0A
    
    /* CMD_TYPE_X_SLAVE are example commands the master sends to the slave.
     * The slave will send example SlaveTypeX buffers in response.
     *
     * CMD_TYPE_X_MASTER are example commands the master sends to the slave.
     * The slave will initialize itself to receive MasterTypeX example buffers.
     * */
    
    #define SLAVE_ADDR  0x0A
    
    #define TYPE_0_LENGTH   9
    #define TYPE_1_LENGTH   10
    #define TYPE_2_LENGTH   10
    
    #define MAX_BUFFER_SIZE     20
    // 00010100 0 0 01010101 10101010
    uint8_t MasterType0 [TYPE_0_LENGTH] = {0x55,0xAA,0x06,0x04,0x01,0x01,0x01,0x07,0x00};
    uint8_t MasterType1 [TYPE_1_LENGTH] = {0x55,0xAA,0x07,0x04,0x80,0x00,0x00,0x00,0x84,0x00};
    uint8_t MasterType2 [TYPE_2_LENGTH] = {0x55,0xAA,0x07,0x04,0x80,0x00,0x01,0x00,0x85,0x00};
    
    #define SLAVE_READ0   11
    #define SLAVE_READ1   15
    
    uint8_t SlaveRead0 [SLAVE_READ0] = {0};
    
    //******************************************************************************
    // General I2C State Machine ***************************************************
    //******************************************************************************
    
    
    typedef enum I2C_ModeEnum{
        IDLE_MODE,
        NACK_MODE,
        TX_REG_ADDRESS_MODE,
        RX_REG_ADDRESS_MODE,
        TX_DATA_MODE,
        RX_DATA_MODE,
        SWITCH_TO_RX_MODE,
        SWITCH_TO_TX_MODE,
        TIMEOUT_MODE
    } I2C_Mode;
    
    
    /* Used to track the state of the software state machine*/
    I2C_Mode MasterMode = IDLE_MODE;
    
    /* The Register Address/Command to use*/
    uint8_t TransmitRegAddr = 0;
    
    /* ReceiveBuffer: Buffer used to receive data in the ISR
     * RXByteCtr: Number of bytes left to receive
     * ReceiveIndex: The index of the next byte to be received in ReceiveBuffer
     * TransmitBuffer: Buffer used to transmit data in the ISR
     * TXByteCtr: Number of bytes left to transfer
     * TransmitIndex: The index of the next byte to be transmitted in TransmitBuffer
     * */
    uint8_t ReceiveBuffer[MAX_BUFFER_SIZE] = {0};
    uint8_t RXByteCtr = 0;
    uint8_t ReceiveIndex = 0;
    uint8_t TransmitBuffer[MAX_BUFFER_SIZE] = {0};
    uint8_t TXByteCtr = 0;
    uint8_t TransmitIndex = 0;
    
    /* I2C Write and Read Functions */
    
    /* For slave device with dev_addr, writes the data specified in *reg_data
     *
     * dev_addr: The slave device address.
     *           Example: SLAVE_ADDR
     * reg_addr: The register or command to send to the slave.
     *           Example: CMD_TYPE_0_MASTER
     * *reg_data: The buffer to write
     *           Example: MasterType0
     * count: The length of *reg_data
     *           Example: TYPE_0_LENGTH
     *  */
    I2C_Mode I2C_Master_WriteReg(uint8_t dev_addr, uint8_t reg_addr, uint8_t *reg_data, uint8_t count);
    
    /* For slave device with dev_addr, read the data specified in slaves reg_addr.
     * The received data is available in ReceiveBuffer
     *
     * dev_addr: The slave device address.
     *           Example: SLAVE_ADDR
     * reg_addr: The register or command to send to the slave.
     *           Example: CMD_TYPE_0_SLAVE
     * count: The length of data to read
     *           Example: TYPE_0_LENGTH
     *  */
    I2C_Mode I2C_Master_ReadReg(uint8_t dev_addr, uint8_t reg_addr, uint8_t count);
    void CopyArray(uint8_t *source, uint8_t *dest, uint8_t count);
    
    I2C_Mode I2C_Master_Read(uint8_t dev_addr, uint8_t count)
    {
        /* Initialize state machine */
        MasterMode = RX_DATA_MODE;
    //    TransmitRegAddr = reg_addr;
        RXByteCtr = count;
        TXByteCtr = 0;
        ReceiveIndex = 0;
        TransmitIndex = 0;
    
        /* Initialize slave address and interrupts */
        UCB0I2CSA = dev_addr;
        IE2 |= UCB0RXIE;              // Enable RX interrupt
        IE2 &= ~UCB0TXIE;             // Disable TX interrupt
        UCB0CTL1 &= ~UCTR;            // Switch to receiver
        MasterMode = RX_DATA_MODE;    // State state is to receive data
        UCB0CTL1 |= UCTXSTT;          // Send repeated start
    
    //    IFG2 &= ~(UCB0TXIFG + UCB0RXIFG);       // Clear any pending interrupts
    //    IE2 &= ~UCB0RXIE;                       // Disable RX interrupt
    //    IE2 |= UCB0TXIE;                        // Enable TX interrupt
    
    //    UCB0CTL1 |= UCTR + UCTXSTT;             // I2C TX, start condition
    //    __bis_SR_register(CPUOFF + GIE);              // Enter LPM0 w/ interrupts
        __bis_SR_register( GIE);              // Enter LPM0 w/ interrupts
    
        return MasterMode;
    }
    
    
    I2C_Mode I2C_Master_Write(uint8_t dev_addr, uint8_t *reg_data, uint8_t count)
    {
        /* Initialize state machine */
        MasterMode = TX_DATA_MODE;
    //    TransmitRegAddr = reg_addr;
    
        //Copy register data to TransmitBuffer
        CopyArray(reg_data, TransmitBuffer, count);
    
        TXByteCtr = count;
        RXByteCtr = 0;
        ReceiveIndex = 0;
        TransmitIndex = 0;
    
        /* Initialize slave address and interrupts */
        UCB0I2CSA = dev_addr;
        IFG2 &= ~(UCB0TXIFG + UCB0RXIFG);       // Clear any pending interrupts
        IE2 &= ~UCB0RXIE;                       // Disable RX interrupt
        IE2 |= UCB0TXIE;                        // Enable TX interrupt
    
        UCB0CTL1 |= UCTR + UCTXSTT;             // I2C TX, start condition
        __bis_SR_register(GIE);              // Enter LPM0 w/ interrupts
    //    __bis_SR_register(CPUOFF + GIE);              // Enter LPM0 w/ interrupts
    
        return MasterMode;
    }
    
    I2C_Mode I2C_Master_ReadReg(uint8_t dev_addr, uint8_t reg_addr, uint8_t count)
    {
        /* Initialize state machine */
        MasterMode = TX_REG_ADDRESS_MODE;
        TransmitRegAddr = reg_addr;
        RXByteCtr = count;
        TXByteCtr = 0;
        ReceiveIndex = 0;
        TransmitIndex = 0;
    
        /* Initialize slave address and interrupts */
        UCB0I2CSA = dev_addr;
        IFG2 &= ~(UCB0TXIFG + UCB0RXIFG);       // Clear any pending interrupts
        IE2 &= ~UCB0RXIE;                       // Disable RX interrupt
        IE2 |= UCB0TXIE;                        // Enable TX interrupt
    
        UCB0CTL1 |= UCTR + UCTXSTT;             // I2C TX, start condition
        __bis_SR_register(CPUOFF + GIE);              // Enter LPM0 w/ interrupts
    
        return MasterMode;
    
    }
    
    
    I2C_Mode I2C_Master_WriteReg(uint8_t dev_addr, uint8_t reg_addr, uint8_t *reg_data, uint8_t count)
    {
        /* Initialize state machine */
        MasterMode = TX_REG_ADDRESS_MODE;
        TransmitRegAddr = reg_addr;
    
        //Copy register data to TransmitBuffer
        CopyArray(reg_data, TransmitBuffer, count);
    
        TXByteCtr = count;
        RXByteCtr = 0;
        ReceiveIndex = 0;
        TransmitIndex = 0;
    
        /* Initialize slave address and interrupts */
        UCB0I2CSA = dev_addr;
        IFG2 &= ~(UCB0TXIFG + UCB0RXIFG);       // Clear any pending interrupts
        IE2 &= ~UCB0RXIE;                       // Disable RX interrupt
        IE2 |= UCB0TXIE;                        // Enable TX interrupt
    
        UCB0CTL1 |= UCTR + UCTXSTT;             // I2C TX, start condition
        __bis_SR_register(CPUOFF + GIE);              // Enter LPM0 w/ interrupts
    
        return MasterMode;
    }
    
    void CopyArray(uint8_t *source, uint8_t *dest, uint8_t count)
    {
        uint8_t copyIndex = 0;
        for (copyIndex = 0; copyIndex < count; copyIndex++)
        {
            dest[copyIndex] = source[copyIndex];
        }
    }
    
    //******************************************************************************
    // UART Configtion *************************************************************
    //******************************************************************************
    
    void putcUART(uint8_t data)
    {
        while (!(IFG2&UCA0TXIFG));                // USCI_A0 TX buffer ready?
        UCA0TXBUF = data;
    }
    
    void putsUART(uint8_t *data)
    {
        while (*data)
        {
            putcUART(*data);
            data++;
        }
    }
    void initUART()
    {
    #if UART_MODE == SMCLK_11500
        UCA0CTL1 |= UCSSEL_2;                     // SMCLK
        UCA0BR0 = 138;                            // 16MHz 115200
        UCA0BR1 = 0;                              // 16MHz 115200
        UCA0MCTL = UCBRS_7;                       // Modulation UCBRSx = 7
        UCA0CTL1 &= ~UCSWRST;                     // **Initialize USCI state machine**
        IFG2 &= ~(UCA0RXIFG);
        IE2 |= UCA0RXIE;                          // Enable USCI_A0 RX interrupt
    #elif UART_MODE == SMCLK_9600
        UCA0CTL1 |= UCSSEL_2;                     // SMCLK
        UCA0BR0 = 104;                            // 16MHz 9600
        UCA0BR1 = 0;                              // 16MHz 9600
        UCA0MCTL = UCBRS_0 + UCOS16 + UCBRF_3;    // Modulation UCBRSx = 0
        UCA0CTL1 &= ~UCSWRST;                     // **Initialize USCI state machine**
        IFG2 &= ~(UCA0RXIFG);
        IE2 |= UCA0RXIE;                          // Enable USCI_A0 RX interrupt
    #elif UART_MODE == ACLK_9600
        UCA0CTL1 |= UCSSEL_1;                     // ACLK
        UCA0BR0 = 3;                              // 32768Hz 9600
        UCA0BR1 = 0;                              // 32768Hz 9600
        UCA0MCTL = UCBRS_3;                       // Modulation UCBRSx = 3
        UCA0CTL1 &= ~UCSWRST;                     // **Initialize USCI state machine**
        IFG2 &= ~(UCA0RXIFG);
        IE2 |= UCA0RXIE;                          // Enable USCI_A0 RX interrupt
    #else
        #error "Select UART Baud Rate of 115200 or 9600"
    #endif
    }
    
    //******************************************************************************
    // Device Initialization *******************************************************
    //******************************************************************************
    
    void initClockTo16MHz()
    {
        if (CALBC1_16MHZ==0xFF)                  // If calibration constant erased
        {
            while(1);                               // do not load, trap CPU!!
        }
        DCOCTL = 0;                               // Select lowest DCOx and MODx settings
        BCSCTL1 = CALBC1_16MHZ;                    // Set DCO
        DCOCTL = CALDCO_16MHZ;
    }
    
    void initGPIO()
    {
    //    P1DIR |= BIT0 + BIT1 + BIT2 + BIT3 + BIT4;
    //    P1OUT &= ~(BIT0 + BIT1 + BIT2 + BIT3 + BIT4);
    //
    //    P1SEL |= BIT6 + BIT7;                     // Assign I2C pins to USCI_B0
    //    P1SEL2|= BIT6 + BIT7;                     // Assign I2C pins to USCI_B0
    
        P1DIR |= BIT0;// + BIT3 + BIT4;
        P1OUT &= ~(BIT0);// + BIT3 + BIT4);
    
        // P1.1 = RXD, P1.2=TXD, P1.6 = SCL, P1.7 = SDA;
        P1SEL |= BIT1 + BIT2 + BIT6 + BIT7;                     // Assign I2C pins to USCI_B0
        P1SEL2|= BIT1 + BIT2 + BIT6 + BIT7;                     // Assign I2C pins to USCI_B0
    }
    
    void initI2C()
    {
        UCB0CTL1 |= UCSWRST;                      // Enable SW reset
        UCB0CTL0 = UCMST + UCMODE_3 + UCSYNC;     // I2C Master, synchronous mode
        UCB0CTL1 = UCSSEL_2 + UCSWRST;            // Use SMCLK, keep SW reset
        UCB0BR0 = 40;                            // fSCL = SMCLK/40 = ~400kHz
        UCB0BR1 = 0;
        UCB0I2CSA = SLAVE_ADDR;                   // Slave Address
        UCB0CTL1 &= ~UCSWRST;                     // Clear SW reset, resume operation
        UCB0I2CIE |= UCNACKIE;
    }
    
    
    //******************************************************************************
    // Main ************************************************************************
    // Send and receive three messages containing the example commands *************
    //******************************************************************************
    
    int main(void) {
        long i;
        WDTCTL = WDTPW + WDTHOLD;                 // Stop WDT
    
        initClockTo16MHz();
        initGPIO();
        initUART();
        initI2C();
        //putcUART('A');
        //putsUART("Hello A");
        I2C_Master_Write(SLAVE_ADDR, MasterType0, TYPE_0_LENGTH);
        I2C_Master_Write(SLAVE_ADDR, MasterType0, TYPE_0_LENGTH);
        I2C_Master_Write(SLAVE_ADDR, MasterType0, TYPE_0_LENGTH);
        //putsUART(" 1 ");
        I2C_Master_Write(SLAVE_ADDR, MasterType2, TYPE_1_LENGTH);
       // putsUART(" 2 ");
        I2C_Master_Read(SLAVE_ADDR, SLAVE_READ0);
        CopyArray(ReceiveBuffer, SlaveRead0, SLAVE_READ0); //uint8_t SlaveRead0 [SALVE_READ0] = {0};
        //putsUART("\n Send Data:");
        for(i=0;i<11;i++){
            putcUART(ReceiveBuffer[i]);
        }
    //    I2C_Master_WriteReg(SLAVE_ADDR, CMD_TYPE_0_MASTER, MasterType0, TYPE_0_LENGTH);
    //    I2C_Master_WriteReg(SLAVE_ADDR, CMD_TYPE_1_MASTER, MasterType1, TYPE_1_LENGTH);
    //    I2C_Master_WriteReg(SLAVE_ADDR, CMD_TYPE_2_MASTER, MasterType2, TYPE_2_LENGTH);
    //
    //    I2C_Master_ReadReg(SLAVE_ADDR, CMD_TYPE_0_SLAVE, TYPE_0_LENGTH);
    //    CopyArray(ReceiveBuffer, SlaveType0, TYPE_0_LENGTH);
    //
    //    I2C_Master_ReadReg(SLAVE_ADDR, CMD_TYPE_1_SLAVE, TYPE_1_LENGTH);
    //    CopyArray(ReceiveBuffer, SlaveType1, TYPE_1_LENGTH);
    //
    //    I2C_Master_ReadReg(SLAVE_ADDR, CMD_TYPE_2_SLAVE, TYPE_2_LENGTH);
    //    CopyArray(ReceiveBuffer, SlaveType2, TYPE_2_LENGTH);
    
        //__bis_SR_register(LPM0_bits + GIE);
        while(1)
        {
               //putsUART(" 1 ");
               I2C_Master_Write(SLAVE_ADDR, MasterType1, TYPE_1_LENGTH);
              // putsUART(" 2 ");
               I2C_Master_Read(SLAVE_ADDR, SLAVE_READ0);
               CopyArray(ReceiveBuffer, SlaveRead0, SLAVE_READ0); //uint8_t SlaveRead0 [SALVE_READ0] = {0};
               //putsUART("\n Send Data:");
               for(i=0;i<11;i++){
                   putcUART(ReceiveBuffer[i]);
               }
    //           for(i=0;i<100000;i++){
    //
    //                      }
    
        }
    }
    
    //******************************************************************************
    // I2C Interrupt For Received and Transmitted Data******************************
    //******************************************************************************
    
    #if defined(__TI_COMPILER_VERSION__) || defined(__IAR_SYSTEMS_ICC__)
    #pragma vector = USCIAB0TX_VECTOR
    __interrupt void USCIAB0TX_ISR(void)
    #elif defined(__GNUC__)
    void __attribute__ ((interrupt(USCIAB0TX_VECTOR))) USCIAB0TX_ISR (void)
    #else
    #error Compiler not supported!
    #endif
    {
      if (IFG2 & UCB0RXIFG)                 // Receive Data Interrupt
      {
          //Must read from UCB0RXBUF
          uint8_t rx_val = UCB0RXBUF;
    
          if (RXByteCtr)
          {
              ReceiveBuffer[ReceiveIndex++] = rx_val;
              RXByteCtr--;
          }
    
          if (RXByteCtr == 1)
          {
              UCB0CTL1 |= UCTXSTP+UCTXNACK;
    
          }
          else if (RXByteCtr == 0)
          {
              IE2 &= ~UCB0RXIE;
              MasterMode = IDLE_MODE;
              __bic_SR_register_on_exit(CPUOFF);      // Exit LPM0
          }
      }
      else if (IFG2 & UCB0TXIFG)            // Transmit Data Interrupt
      {
          switch (MasterMode)
          {
              case TX_REG_ADDRESS_MODE:
                  UCB0TXBUF = TransmitRegAddr;
                  if (RXByteCtr)
                      MasterMode = SWITCH_TO_RX_MODE;   // Need to start receiving now
                  else
                      MasterMode = TX_DATA_MODE;        // Continue to transmision with the data in Transmit Buffer
                  break;
    
              case SWITCH_TO_RX_MODE:
                  IE2 |= UCB0RXIE;              // Enable RX interrupt
                  IE2 &= ~UCB0TXIE;             // Disable TX interrupt
                  UCB0CTL1 &= ~UCTR;            // Switch to receiver
                  MasterMode = RX_DATA_MODE;    // State state is to receive data
                  UCB0CTL1 |= UCTXSTT;          // Send repeated start
                  if (RXByteCtr == 1)
                  {
                      //Must send stop since this is the N-1 byte
                      while((UCB0CTL1 & UCTXSTT));
                      UCB0CTL1 |= UCTXSTP;      // Send stop condition
                  }
                  break;
    
              case TX_DATA_MODE:
                  if (TXByteCtr)
                  {
                      UCB0TXBUF = TransmitBuffer[TransmitIndex++];
                      TXByteCtr--;
                  }
                  else
                  {
                      //Done with transmission
                      UCB0CTL1 |= UCTXSTP;     // Send stop condition
                      MasterMode = IDLE_MODE;
                      IE2 &= ~UCB0TXIE;                       // disable TX interrupt
                      //__bic_SR_register_on_exit(CPUOFF);      // Exit LPM0
                  }
                  break;
    
              default:
                  __no_operation();
                  break;
          }
      }
    }
    
    
    //******************************************************************************
    // I2C Interrupt For Start, Restart, Nack, Stop ********************************
    //******************************************************************************
    
    #if defined(__TI_COMPILER_VERSION__) || defined(__IAR_SYSTEMS_ICC__)
    #pragma vector = USCIAB0RX_VECTOR  // USCIAB0TX_VECTOR
    __interrupt void USCIAB0RX_ISR(void)
    #elif defined(__GNUC__)
    void __attribute__ ((interrupt(USCIAB0RX_VECTOR))) USCIAB0RX_ISR (void)
    #else
    #error Compiler not supported!
    #endif
    {
        if (IFG2 & UCA0RXIFG)
        {
            uint8_t rx_val = UCA0RXBUF; //Must read UCxxRXBUF to clear the flag
            putcUART(rx_val);
        }
        if (UCB0STAT & UCNACKIFG)
        {
            UCB0STAT &= ~UCNACKIFG;             // Clear NACK Flags
        }
        if (UCB0STAT & UCSTPIFG)                        //Stop or NACK Interrupt
        {
            UCB0STAT &=
                ~(UCSTTIFG + UCSTPIFG + UCNACKIFG);     //Clear START/STOP/NACK Flags
        }
        if (UCB0STAT & UCSTTIFG)
        {
            UCB0STAT &= ~(UCSTTIFG);                    //Clear START Flags
        }
    }
    
     

    I have read your write on https://e2e.ti.com/support/microcontrollers/msp-low-power-microcontrollers-group/msp430/f/msp-low-power-microcontroller-forum/844030/ccs-msp430i2040-emdc-i2c-communication-with-evm430-i2040s/3121142?tisearch=e2e-sitesearch&keymatch=msp430i2041%2520i2c#3121142  18/10/2019  4:32 PM. Please you can send to me project you write read data over i2c ok.

    Thank so much.

  • This thread should contain details about making changes to use I2C.

    MSP430I2040: Interfacing the MSP430i2040S Sub metering EVM on I2C

  • Hi James. 

    I write code with f5529. My project  read evmi2041 (multi device) over I2C and send to PC by UART, now i have connect one device EVM, but data result not true. Please check for me

    //******************************************************************************
    //   MSP430F552x Demo - USCI_B0, I2C Master multiple byte TX/RX
    //
    //   Description: I2C master communicates to I2C slave sending and receiving
    //   messages of different length. I2C master will enter LPM0 mode
    //   while waiting for the messages to be sent/receiving using I2C interrupt.
    //   ACLK = NA, MCLK = SMCLK = DCO 16MHz.
    //
    //                                     /|\ /|\
    //                   MSP430F5529       4.7k |
    //                 -----------------    |  4.7k
    //            /|\ |             P3.1|---+---|-- I2C Clock (UCB0SCL)
    //             |  |                 |       |
    //             ---|RST          P3.0|-------+-- I2C Data (UCB0SDA)
    //                |                 |
    //                |             P3.3|-------+-- UART TX (UCA0 TXD)
    //                |                 |
    //                |             P3.4|-------+-- UART RX (UCA0 RXD)
    //                |                 |
    //                |                 |
    //
    //   Texas Instruments Inc.
    //   June 2019
    //   Built with CCS V9.x
    //******************************************************************************
    
    #include <msp430.h>
    #include <stdint.h>
    #include <stdbool.h>
    
    char update;
    
    //******************************************************************************
    // UART Initialization *********************************************************
    //******************************************************************************
    
    #define SMCLK_11500     0
    #define SMCLK_9600      1
    #define ACLK_9600       2
    
    #define UART_MODE       SMCLK_115200
    const char hex_digits[] = "0123456789ABCDEF";
    void initUART()
    {
        // Configure USCI_A0 for UART mode
        UCA0CTLW0 = UCSWRST;                      // Put eUSCI in reset
    #if UART_MODE == SMCLK_115200
    
        UCA0CTLW0 |= UCSSEL__SMCLK;               // CLK = SMCLK
        // Baud Rate calculation
        // 16000000/(16*115200) = 8.6805
        // Fractional portion = 0.6805
        // Use Table 24-5 in Family User Guide
        UCA0BR0 = 8;                               // 16000000/16/9600
        UCA0BR1 = 0x00;
        UCA0MCTL |= UCOS16 | UCBRF_11 | UCBRS_0;
    
    #elif UART_MODE == SMCLK_9600
    
        UCA0CTLW0 |= UCSSEL__SMCLK;               // CLK = SMCLK
        // Baud Rate calculation
        // 16000000/(16*9600) = 104.1667
        // Fractional portion = 0.1667
        // Use Table 24-5 in Family User Guide
        UCA0BR0 = 104;                            // 16000000/16/9600
        UCA0BR1 = 0x00;
        UCA0MCTL |= UCOS16 | UCBRF_3 | UCBRS_0;
    
    #elif UART_MODE == ACLK_9600
    
        UCA0CTLW0 |= UCSSEL__ACLK;               // CLK = ACLK
        // Baud Rate calculation
        // 32768/(9600) = 3.4133
        // Fractional portion = 0.4133
        // Use Table 24-5 in Family User Guide
        UCA0BR0 = 3;                             // 32768/9600
        UCA0BR1 = 0x00;
        UCA0MCTL |= UCBRS_3;    //0x0300 is UCBRSx = 0x03
    
    #else
        # error "Please specify baud rate to 115200 or 9600"
    #endif
    
        UCA0CTLW0 &= ~UCSWRST;                    // Initialize eUSCI
        UCA0IE |= UCRXIE;                         // Enable USCI_A0 RX interrupt
    }
    
    //******************************************************************************
    // Device Initialization *******************************************************
    //******************************************************************************
    
    void putcUART(uint8_t data)
    {
        while (!(UCA0IFG & UCTXIFG));             // USCI_A0 TX buffer ready?
            UCA0TXBUF = data;                  // TX -> RXed character
    }
    void putsUART(uint8_t *data)
    {
        while (*data)
        {
            putcUART(*data);
            data++;
        }
    }
    
    void putHexUART(uint8_t c)
    {   //uint8_t c;
        putcUART(hex_digits[c >> 4]);
        putcUART(hex_digits[c & 15]);
    }
    void putsHexPC(uint8_t *buff, uint8_t len)
    {
        uint8_t i;
        for(i=0;i<len;i++)   {
            putHexUART(buff[i]);
            putcUART(' ');
        }
    }
    
    
    //******************************************************************************
    // Example Commands ************************************************************
    //******************************************************************************
    
    #define SLAVE_ADDR  0x0A
    
    #define MAX_BUFFER_SIZE     50
    
    
    // CMD 0x01 = Configure Mode
    #define CMD_01_MASTER      0x01
    // send 2 bytes of payload
    #define CMD_01_LENGTH   2
    // Payload[0] = 0x01: Write, [1] = 0x01: Active
    uint8_t MasterCMD01Payload [CMD_01_LENGTH] = { 0x01, 0x01};
    
    #define RESPONSE_SLAVE_LENGTH  15
    
    //******************************************************************************
    // General I2C State Machine ***************************************************
    //******************************************************************************
    
    typedef enum I2C_ModeEnum{
        IDLE_MODE,
        NACK_MODE,
        TX_DATA_MODE,
        RX_DATA_MODE,
        TIMEOUT_MODE,
        ERROR_MODE
    } I2C_Mode;
    
    /* Used to track the state of the software state machine*/
    I2C_Mode MasterMode = IDLE_MODE;
    
    /* ReceiveBuffer: Buffer used to receive data in the ISR
     * RXByteCtr: Number of bytes left to receive
     * ReceiveIndex: The index of the next byte to be received in ReceiveBuffer
     * TransmitBuffer: Buffer used to transmit data in the ISR
     * TXByteCtr: Number of bytes left to transfer
     * TransmitIndex: The index of the next byte to be transmitted in TransmitBuffer
     * */
    uint8_t ReceiveBuffer[MAX_BUFFER_SIZE] = {0};
    uint8_t RXByteCtr = 0;
    uint8_t ReceiveIndex = 0;
    uint8_t TransmitBuffer[MAX_BUFFER_SIZE] = {0};
    uint8_t TXByteCtr = 0;
    uint8_t TransmitIndex = 0;
    
    /* I2C Write and Read Functions */
    
    I2C_Mode I2C_Master_ReadDataBlocking(uint8_t dev_addr, uint8_t count);
    void CopyArray_wCRC(uint8_t *source, uint8_t *dest, uint8_t count, uint16_t *CRC);
    I2C_Mode I2C_Master_WriteCmdBlocking(uint8_t dev_addr, uint8_t cmd, uint8_t *payload, uint8_t count);
    
    
    I2C_Mode I2C_Master_ReadDataBlocking(uint8_t dev_addr, uint8_t count)
    {
    
        if (count > MAX_BUFFER_SIZE)
        {
            return ERROR_MODE;
        }
    
        /* Initialize state machine */
        RXByteCtr = count;
        TXByteCtr = 0;
        ReceiveIndex = 0;
        TransmitIndex = 0;
    
        /* Initialize slave address and interrupts */
        UCB0I2CSA = dev_addr;
        UCB0IFG &= ~(UCTXIFG + UCRXIFG);       // Clear any pending interrupts
        UCB0IE |= UCRXIE;                       // Enable RX interrupt
        UCB0IE &= ~UCTXIE;                      // Disable TX interrupt
    
        __disable_interrupt();
        MasterMode = RX_DATA_MODE;
        UCB0CTL1 &= ~UCTR;
        UCB0CTL1 |= UCTXSTT;             // I2C RX, start condition
        while (MasterMode == RX_DATA_MODE)
        {
            __bis_SR_register(LPM0_bits + GIE);              // Enter LPM0 w/ interrupts
            __disable_interrupt();
        }
    
        return MasterMode;
    
    }
    I2C_Mode I2C_Master_Write_cmd(uint8_t dev_addr,uint8_t command)
    {
        uint16_t total_count=10;
        uint8_t CRC_Calc = command+4;
    
        // If size is OK, fill buffer
        TransmitBuffer[0] = 0x55;   // header
        TransmitBuffer[1] = 0xAA;   // header
        TransmitBuffer[2] = 0x07;   // packet length (ID, CMD, payload, checksum)
        TransmitBuffer[3] = 0x04;    // Design Center ID
        TransmitBuffer[4] = command;    // command
        TransmitBuffer[5] = 0x00;    //
        TransmitBuffer[6] = 0x00;    //
        TransmitBuffer[7] = 0x00;    //
        TransmitBuffer[8] = CRC_Calc;    // CRC
        TransmitBuffer[9] = 0x00;    // CRC
    
        putsHexPC(TransmitBuffer,total_count);
        TXByteCtr = total_count;
        RXByteCtr = 0;
        ReceiveIndex = 0;
        TransmitIndex = 0;
    
        /* Initialize slave address and interrupts */
        UCB0I2CSA = dev_addr;
        UCB0IFG &= ~(UCTXIFG + UCRXIFG);       // Clear any pending interrupts
        UCB0IE &= ~UCRXIE;                       // Disable RX interrupt
        UCB0IE |= UCTXIE;                        // Enable TX interrupt
    
        __disable_interrupt();
        /* Initialize state machine */
        MasterMode = TX_DATA_MODE;
        UCB0CTL1 |=  UCTR | UCTXSTT;             // I2C RX, start condition
        while(MasterMode == TX_DATA_MODE)
        {
            __bis_SR_register(LPM0_bits + GIE);              // Enter LPM0 w/ interrupts
            __disable_interrupt();
        }
    
        return MasterMode;
    }
    
    I2C_Mode I2C_Master_Write_Config(uint8_t dev_addr)
    {
        uint16_t total_count=9;
    
        // If size is OK, fill buffer
        TransmitBuffer[0] = 0x55;   // header
        TransmitBuffer[1] = 0xAA;   // header
        TransmitBuffer[2] = 0x06;   // packet length (ID, CMD, payload, checksum)
        TransmitBuffer[3] = 0x04;   // Design Center ID
        TransmitBuffer[4] = 0x01;   // command
        TransmitBuffer[5] = 0x01;   // Write
        TransmitBuffer[6] = 0x01;   // Active
        TransmitBuffer[7] = 0x07;   // CRC
        TransmitBuffer[8] = 0x00;   // CRC
    
        putsHexPC(TransmitBuffer,total_count);
        TXByteCtr = total_count;
        RXByteCtr = 0;
        ReceiveIndex = 0;
        TransmitIndex = 0;
    
        /* Initialize slave address and interrupts */
        UCB0I2CSA = dev_addr;
        UCB0IFG &= ~(UCTXIFG + UCRXIFG);       // Clear any pending interrupts
        UCB0IE &= ~UCRXIE;                       // Disable RX interrupt
        UCB0IE |= UCTXIE;                        // Enable TX interrupt
    
        __disable_interrupt();
        /* Initialize state machine */
        MasterMode = TX_DATA_MODE;
        UCB0CTL1 |=  UCTR | UCTXSTT;             // I2C RX, start condition
        while(MasterMode == TX_DATA_MODE)
        {
            __bis_SR_register(LPM0_bits + GIE);              // Enter LPM0 w/ interrupts
            __disable_interrupt();
        }
    
        return MasterMode;
    }
    
    I2C_Mode I2C_Master_WriteCmdBlocking(uint8_t dev_addr, uint8_t cmd, uint8_t *payload, uint8_t count)
    {
        uint16_t total_count;
        uint16_t CRC_Calc = 0x00;
    
    
        //Total count is header (2 bytes) + length (1 byte) + DC ID (1 Byte) + CMD (1 byte) + payload (count) + checksum (2 bytes)
        total_count = 7 + count;
    
        if (total_count > MAX_BUFFER_SIZE)
        {
            return ERROR_MODE;
        }
    
        // If size is OK, fill buffer
        TransmitBuffer[0] = 0x55;   // header
        TransmitBuffer[1] = 0xAA;   // header
        TransmitBuffer[2] = count+4;   // packet length (ID, CMD, payload, checksum)
        TransmitBuffer[3] = 0x04;    // Design Center ID
        TransmitBuffer[4] = cmd;    // command
    
        CRC_Calc = TransmitBuffer[3] + TransmitBuffer[4];
    
        //Copy register data to TransmitBuffer
        CopyArray_wCRC(payload, &TransmitBuffer[5], count, &CRC_Calc);
    
        putsHexPC(TransmitBuffer,total_count);
        TXByteCtr = total_count;
        RXByteCtr = 0;
        ReceiveIndex = 0;
        TransmitIndex = 0;
    
        /* Initialize slave address and interrupts */
        UCB0I2CSA = dev_addr;
        UCB0IFG &= ~(UCTXIFG + UCRXIFG);       // Clear any pending interrupts
        UCB0IE &= ~UCRXIE;                       // Disable RX interrupt
        UCB0IE |= UCTXIE;                        // Enable TX interrupt
    
        __disable_interrupt();
        /* Initialize state machine */
        MasterMode = TX_DATA_MODE;
        UCB0CTL1 |=  UCTR | UCTXSTT;             // I2C RX, start condition
        while(MasterMode == TX_DATA_MODE)
        {
            __bis_SR_register(LPM0_bits + GIE);              // Enter LPM0 w/ interrupts
            __disable_interrupt();
        }
    
        return MasterMode;
    }
    void CopyArray_wCRC(uint8_t *source, uint8_t *dest, uint8_t count, uint16_t *CRC)
    {
        uint8_t copyIndex = 0;
        for (copyIndex = 0; copyIndex < count; copyIndex++)
        {
            dest[copyIndex] = source[copyIndex];
            *CRC += source[copyIndex];
        }
    
        dest[copyIndex++] = (*CRC & 0xFF);   // Store LSB CRC
        dest[copyIndex] = (*CRC >> 8);   // Store MSB CRC
    }
    
    //******************************************************************************
    // Device Initialization *******************************************************
    //******************************************************************************
    
    void initClockTo16MHz()
    {
        UCSCTL3 |= SELREF_2;                      // Set DCO FLL reference = REFO
        UCSCTL4 |= SELA_2;                        // Set ACLK = REFO
        __bis_SR_register(SCG0);                  // Disable the FLL control loop
        UCSCTL0 = 0x0000;                         // Set lowest possible DCOx, MODx
        UCSCTL1 = DCORSEL_5;                      // Select DCO range 16MHz operation
        UCSCTL2 = FLLD_0 + 487;                   // Set DCO Multiplier for 16MHz
                                                  // (N + 1) * FLLRef = Fdco
                                                  // (487 + 1) * 32768 = 16MHz
                                                  // Set FLL Div = fDCOCLK
        __bic_SR_register(SCG0);                  // Enable the FLL control loop
    
        // Worst-case settling time for the DCO when the DCO range bits have been
        // changed is n x 32 x 32 x f_MCLK / f_FLL_reference. See UCS chapter in 5xx
        // UG for optimization.
        // 32 x 32 x 16 MHz / 32,768 Hz = 500000 = MCLK cycles for DCO to settle
        __delay_cycles(500000);//
        // Loop until XT1,XT2 & DCO fault flag is cleared
        do
        {
            UCSCTL7 &= ~(XT2OFFG + XT1LFOFFG + DCOFFG); // Clear XT2,XT1,DCO fault flags
            SFRIFG1 &= ~OFIFG;                          // Clear fault flags
        }while (SFRIFG1&OFIFG);                         // Test oscillator fault flag
    }
    
    uint16_t setVCoreUp(uint8_t level){
        uint32_t PMMRIE_backup, SVSMHCTL_backup, SVSMLCTL_backup;
    
        //The code flow for increasing the Vcore has been altered to work around
        //the erratum FLASH37.
        //Please refer to the Errata sheet to know if a specific device is affected
        //DO NOT ALTER THIS FUNCTION
    
        //Open PMM registers for write access
        PMMCTL0_H = 0xA5;
    
        //Disable dedicated Interrupts
        //Backup all registers
        PMMRIE_backup = PMMRIE;
        PMMRIE &= ~(SVMHVLRPE | SVSHPE | SVMLVLRPE |
                    SVSLPE | SVMHVLRIE | SVMHIE |
                    SVSMHDLYIE | SVMLVLRIE | SVMLIE |
                    SVSMLDLYIE
                    );
        SVSMHCTL_backup = SVSMHCTL;
        SVSMLCTL_backup = SVSMLCTL;
    
        //Clear flags
        PMMIFG = 0;
    
        //Set SVM highside to new level and check if a VCore increase is possible
        SVSMHCTL = SVMHE | SVSHE | (SVSMHRRL0 * level);
    
        //Wait until SVM highside is settled
        while((PMMIFG & SVSMHDLYIFG) == 0)
        {
            ;
        }
    
        //Clear flag
        PMMIFG &= ~SVSMHDLYIFG;
    
        //Check if a VCore increase is possible
        if((PMMIFG & SVMHIFG) == SVMHIFG)
        {
            //-> Vcc is too low for a Vcore increase
            //recover the previous settings
            PMMIFG &= ~SVSMHDLYIFG;
            SVSMHCTL = SVSMHCTL_backup;
    
            //Wait until SVM highside is settled
            while((PMMIFG & SVSMHDLYIFG) == 0)
            {
                ;
            }
    
            //Clear all Flags
            PMMIFG &= ~(SVMHVLRIFG | SVMHIFG | SVSMHDLYIFG |
                         SVMLVLRIFG | SVMLIFG |
                         SVSMLDLYIFG
                         );
    
            //Restore PMM interrupt enable register
            PMMRIE = PMMRIE_backup;
            //Lock PMM registers for write access
            PMMCTL0_H = 0x00;
            //return: voltage not set
            return false;
        }
    
        //Set also SVS highside to new level
        //Vcc is high enough for a Vcore increase
        SVSMHCTL |= (SVSHRVL0 * level);
    
        //Wait until SVM highside is settled
        while((PMMIFG & SVSMHDLYIFG) == 0)
        {
            ;
        }
    
        //Clear flag
        PMMIFG &= ~SVSMHDLYIFG;
    
        //Set VCore to new level
        PMMCTL0_L = PMMCOREV0 * level;
    
        //Set SVM, SVS low side to new level
        SVSMLCTL = SVMLE | (SVSMLRRL0 * level) |
                   SVSLE | (SVSLRVL0 * level);
    
        //Wait until SVM, SVS low side is settled
        while((PMMIFG & SVSMLDLYIFG) == 0)
        {
            ;
        }
    
        //Clear flag
        PMMIFG &= ~SVSMLDLYIFG;
        //SVS, SVM core and high side are now set to protect for the new core level
    
        //Restore Low side settings
        //Clear all other bits _except_ level settings
        SVSMLCTL &= (SVSLRVL0 + SVSLRVL1 + SVSMLRRL0 +
                     SVSMLRRL1 + SVSMLRRL2
                     );
    
        //Clear level settings in the backup register,keep all other bits
        SVSMLCTL_backup &=
            ~(SVSLRVL0 + SVSLRVL1 + SVSMLRRL0 + SVSMLRRL1 + SVSMLRRL2);
    
        //Restore low-side SVS monitor settings
        SVSMLCTL |= SVSMLCTL_backup;
    
        //Restore High side settings
        //Clear all other bits except level settings
        SVSMHCTL &= (SVSHRVL0 + SVSHRVL1 +
                     SVSMHRRL0 + SVSMHRRL1 +
                     SVSMHRRL2
                     );
    
        //Clear level settings in the backup register,keep all other bits
        SVSMHCTL_backup &=
            ~(SVSHRVL0 + SVSHRVL1 + SVSMHRRL0 + SVSMHRRL1 + SVSMHRRL2);
    
        //Restore backup
        SVSMHCTL |= SVSMHCTL_backup;
    
        //Wait until high side, low side settled
        while(((PMMIFG & SVSMLDLYIFG) == 0) &&
              ((PMMIFG & SVSMHDLYIFG) == 0))
        {
            ;
        }
    
        //Clear all Flags
        PMMIFG &= ~(SVMHVLRIFG | SVMHIFG | SVSMHDLYIFG |
                    SVMLVLRIFG | SVMLIFG | SVSMLDLYIFG
                    );
    
        //Restore PMM interrupt enable register
        PMMRIE = PMMRIE_backup;
    
        //Lock PMM registers for write access
        PMMCTL0_H = 0x00;
    
        return true;
    }
    
    bool increaseVCoreToLevel2()
    {
        uint8_t level = 2;
        uint8_t actlevel;
        bool status = true;
    
        //Set Mask for Max. level
        level &= PMMCOREV_3;
    
        //Get actual VCore
        actlevel = PMMCTL0 & PMMCOREV_3;
    
        //step by step increase or decrease
        while((level != actlevel) && (status == true))
        {
            if(level > actlevel)
            {
                status = setVCoreUp(++actlevel);
            }
            else
            {
                status = false;
            }
        }
    
        return (status);
    }
    
    void initGPIO()
    {
        //LEDs
        P1OUT = 0x00;                             // P1 setup for LED & reset output
        P1DIR |= BIT0;
    
        P4DIR |= BIT7;
        P4OUT &= ~(BIT7);
    
        //I2C Pins
        P3SEL |= BIT0 + BIT1 + BIT3 + BIT4;                     // P3.0,1 option select
        // P3.4,5 = USCI_A0 TXD/RXD
    
    }
    
    void initGPIO_UART()
    {
    //    P3SEL = BIT3 + BIT4;                        // P3.4,5 = USCI_A0 TXD/RXD
    //    P5SEL |= BIT4+BIT5;                         // Select XT1
    }
    
    void initI2C()
    {
        UCB0CTL1 |= UCSWRST;                      // Enable SW reset
        UCB0CTL0 = UCMST + UCMODE_3 + UCSYNC;     // I2C Master, synchronous mode
        UCB0CTL1 = UCSSEL_2 + UCSWRST;            // Use SMCLK, keep SW reset
        UCB0BR0 = 160;                            // fSCL = SMCLK/160 = ~100kHz
        UCB0BR1 = 0;
        UCB0I2CSA = SLAVE_ADDR;                   // Slave Address is 048h
        UCB0CTL1 &= ~UCSWRST;                     // Clear SW reset, resume operation
        UCB0IE |= UCNACKIE;
    }
    
    //******************************************************************************
    // Main ************************************************************************
    // Send and receive three messages containing the example commands *************
    //******************************************************************************
    
    int main(void) {
        uint8_t i,cnt;
        WDTCTL = WDTPW | WDTHOLD;                 // Stop watchdog timer
    
        increaseVCoreToLevel2();
        initClockTo16MHz();
        initGPIO();initGPIO_UART();
        initI2C();
        initUART();
    
        putsUART("Hello ");
        putsUART("\nConfig: ");
    //    __bis_SR_register(LPM0_bits + GIE);       // Since SMCLK is source, enter LPM0, interrupts enabled
    //    I2C_Master_WriteCmdBlocking(SLAVE_ADDR, CMD_01_MASTER, MasterCMD01Payload, CMD_01_LENGTH);
        I2C_Master_Write_Config(SLAVE_ADDR);
    
        while (1)
        {
            cnt++;
            if(cnt>4)cnt=0;
            putsUART("\nCmd  Read: ");
            I2C_Master_Write_cmd(SLAVE_ADDR,0x80+cnt);
            __delay_cycles(1000000);
            I2C_Master_ReadDataBlocking(SLAVE_ADDR, RESPONSE_SLAVE_LENGTH);
            putsUART("\nData Read: ");
            for(i=0;i<15;i++)   {
                putHexUART(ReceiveBuffer[i]);
                putcUART(' ');
            }
            // Check response in Receive buffer
        }
    }
    
    //******************************************************************************
    // I2C Interrupt ***************************************************************
    //******************************************************************************
    
    #if defined(__TI_COMPILER_VERSION__) || defined(__IAR_SYSTEMS_ICC__)
    #pragma vector=USCI_B0_VECTOR
    __interrupt void USCI_B0_ISR(void)
    #elif defined(__GNUC__)
    void __attribute__ ((interrupt(USCI_B0_VECTOR))) USCI_B0_ISR (void)
    #else
    #error Compiler not supported!
    #endif
    {
      //Must read from UCB0RXBUF
      uint8_t rx_val = 0;
    
      switch(__even_in_range(UCB0IV,0xC))
      {
        case USCI_NONE:break;                             // Vector 0 - no interrupt
        case USCI_I2C_UCALIFG:break;                      // Interrupt Vector: I2C Mode: UCALIFG
        case USCI_I2C_UCNACKIFG:break;                    // Interrupt Vector: I2C Mode: UCNACKIFG
        case USCI_I2C_UCSTTIFG:break;                     // Interrupt Vector: I2C Mode: UCSTTIFG
        case USCI_I2C_UCSTPIFG:break;                     // Interrupt Vector: I2C Mode: UCSTPIFG
        case USCI_I2C_UCRXIFG:
            rx_val = UCB0RXBUF;
            if (RXByteCtr)
            {
              ReceiveBuffer[ReceiveIndex++] = rx_val;
              RXByteCtr--;
            }
    
            if (RXByteCtr == 1)
            {
              UCB0CTL1 |= UCTXSTP;
            }
            else if (RXByteCtr == 0)
            {
              UCB0IE &= ~UCRXIE;
              MasterMode = IDLE_MODE;
              update=1;
              __bic_SR_register_on_exit(CPUOFF);      // Exit LPM0
            }
            break;                      // Interrupt Vector: I2C Mode: UCRXIFG
        case USCI_I2C_UCTXIFG:
              if (TXByteCtr)
              {
                  UCB0TXBUF = TransmitBuffer[TransmitIndex++];
                  TXByteCtr--;
              }
              else
              {
                  //Done with transmission
                  UCB0CTL1 |= UCTXSTP;     // Send stop condition
                  MasterMode = IDLE_MODE;
                  UCB0IE &= ~UCTXIE;                       // disable TX interrupt
                  __bic_SR_register_on_exit(CPUOFF);      // Exit LPM0
              }
            break;                      // Interrupt Vector: I2C Mode: UCTXIFG
        default: break;
      }
    }
    
    //******************************************************************************
    // UART RX Interrupt ***********************************************************
    //******************************************************************************
    
    #if defined(__TI_COMPILER_VERSION__) || defined(__IAR_SYSTEMS_ICC__)
    #pragma vector=USCI_A0_VECTOR
    __interrupt void USCI_A0_ISR(void)
    #elif defined(__GNUC__)
    void __attribute__ ((interrupt(USCI_A0_VECTOR))) USCI_A0_ISR (void)
    #else
    #error Compiler not supported!
    #endif
    {
      switch(__even_in_range(UCA0IV,4))
      {
      case 0:break;                             // Vector 0 - no interrupt
      case 2:                                   // Vector 2 - RXIFG
        while (!(UCA0IFG & UCTXIFG));             // USCI_A0 TX buffer ready?
        UCA0TXBUF = UCA0RXBUF;                  // TX -> RXed character
        break;
      case 4:break;                             // Vector 4 - TXIFG
      default: break;
      }
    }
    

    Data read result.

  • Are you connected to AC voltage? If you're not, that could be why the results are zero. Also, check your function in 'emDCCommandHandlers.c'. It should look something like this for VRMS. Your data read packets seem to be longer than necessary.

    void CommandHandler_transmitVRMS(Packet_t *packet,
                                     uint8_t phaseID,
                                     uint8_t *vrms)
    {
        packet->length = 8;
        packet->payload[0] = COMMAND_HANDLER_EM_GUI_ID_BYTE;
        packet->payload[1] = COMMAND_HANDLER_VRMS_ID;
        packet->payload[2] = COMMAND_HANDLER_WRITE_CMD;
        packet->payload[3] = phaseID;
        packet->payload[4] = vrms[0];
        packet->payload[5] = vrms[1];
        packet->payload[6] = vrms[2];
        packet->payload[7] = vrms[3];
    
        Comm_writePacket(packet);
    }
  • I want read VRMS result, i have sent to device command of VRMS, but result i read not VRMS. In command read is 0x89. You can viewer value of command I send to device change from 0x80 - 0x84, but read result comback have command 0x89.

    I thing have problem is code or connect. I have connect F5529LP 4 wire (3.3V SDA, SCL, GND). Can you help me check my code in my write 20-05-2021.

    How long after write command to slave device, I can read data result. In project EVM need to use Request PIN? Do you have code example read data result from i204x over I2C. Can you send to me by reply or send to email dungnv@lctech.vn.

    Thank you so much.

  • I'd recommend digging into the code and see why the return command is wrong. Perhaps the command that's sent from the F5529 is incorrect.

**Attention** This is a public forum