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.

MSP432P401R: In I2C master, how to "send one byte to slave, repeat start, and read one byte" by interrupt method?

Part Number: MSP432P401R

I try the MAP_I2C_masterSendSingleByte(), and MAP_I2C_masterReceiveSingleByte(), but there is a stop in between, and I prefer to use interrupt routine, which can catch the NACK status.

I would like to monitor the SCL and SDA lines stuck low condition, where can I find line status from registers?

  • Hi,
    To clarify - is this the sequence you are trying to implement?

    1. Master I2C TX 1 byte
    2. Master send Restart
    3. Master I2C RX 1 byte

    If yes, you would use the following API sequence:

    1. MAP_I2C_masterSendMultiByteStart - this API will send out the first start condition, followed by a single byte without sending the STOP.
    At the end of the transaction, the TX interrupt is enabled

    2. Use the transmit interrupt service routine to send the restart condition & setup the state machine to receive a single byte by using the following API

    API call: MAP_I2C_masterReceiveSingleByte()

    To poll the SCL line you can directly use the bit - UCSCLLOW in the UCBxSTAT register or the UCBBUSY bit. Refer to section 24.4.4 in the technical reference manual : www.ti.com/.../slau356g.pdf

    As an option you can use the function
    uint8_t I2C_isBusBusy()

    Hope this helps.

    -Priya
  • Hi Priya:
    I followed you suggestion, and tested it.
    from my scope and I2C sniffer, it looked like:
    [start], write one-byte, [stop]; [start], read two-byte, [stop];
    Any suggestion in my codes?
    Thanks.
    -Philip

    /* DriverLib Includes */
    #include <ti/devices/msp432p4xx/driverlib/driverlib.h>

    /* Standard Includes */
    #include <stdint.h>
    #include <stdbool.h>

    /* Slave Address */
    #define SLAVE_ADDRESS_1 0x50

    /* Statics */
    static volatile uint8_t RXData[256];
    static volatile uint32_t xferIndex, txIndex;
    static volatile uint32_t numOfRecBytes;

    /* I2C Master Configuration Parameter */
    const eUSCI_I2C_MasterConfig i2cConfig =
    {
    EUSCI_B_I2C_CLOCKSOURCE_SMCLK, // SMCLK Clock Source
    3000000, // SMCLK = 3MHz
    EUSCI_B_I2C_SET_DATA_RATE_100KBPS, // Desired I2C Clock of 100khz
    0, // No byte counter threshold
    EUSCI_B_I2C_NO_AUTO_STOP // No Autostop
    };

    int main(void)
    {
    uint32_t i;
    /* Disabling the Watchdog */
    MAP_WDT_A_holdTimer();
    xferIndex = 0;

    MAP_GPIO_setAsPeripheralModuleFunctionInputPin(GPIO_PORT_P1, GPIO_PIN6 + GPIO_PIN7, GPIO_PRIMARY_MODULE_FUNCTION);

    MAP_I2C_initMaster(EUSCI_B0_BASE, &i2cConfig);
    MAP_I2C_setSlaveAddress(EUSCI_B0_BASE,SLAVE_ADDRESS_1);

    /* Clearing interrupts for I2C and enabling the module */
    MAP_I2C_enableModule(EUSCI_B0_BASE);
    MAP_I2C_clearInterruptFlag(EUSCI_B0_BASE, EUSCI_B_I2C_RECEIVE_INTERRUPT0 | EUSCI_B_I2C_TRANSMIT_INTERRUPT0);

    MAP_Interrupt_enableInterrupt(INT_EUSCIB0);
    /* Enabling master interrupts */
    MAP_Interrupt_enableMaster();

    while (1)
    {
    MAP_I2C_setMode(EUSCI_B0_BASE, EUSCI_B_I2C_TRANSMIT_MODE);
    MAP_I2C_enableInterrupt(EUSCI_B0_BASE, EUSCI_B_I2C_TRANSMIT_INTERRUPT0|EUSCI_B_I2C_NAK_INTERRUPT);
    MAP_I2C_masterSendMultiByteStart(EUSCI_B0_BASE, 0x55); // No Interrupt in it. I2C_masterSendSingleByteWithTimeout
    for (i=0; i< 100; i++);
    for (i=0; i< 500000; i++); // long delay to check scope
    }
    }

    /******************************************************************************
    * The USCI_B0 data ISR RX vector is used to move received data from the I2C
    * master to the MSP432 memory.
    ******************************************************************************/
    void EUSCIB0_IRQHandler(void)
    {
    uint_fast16_t status;

    status = MAP_I2C_getEnabledInterruptStatus(EUSCI_B0_BASE);
    MAP_I2C_clearInterruptFlag(EUSCI_B0_BASE, status);

    /* RXIFG */
    if (status & EUSCI_B_I2C_RECEIVE_INTERRUPT0)
    {
    RXData[xferIndex++] = UCB0RXBUF;
    EUSCI_B0->CTLW0 |= EUSCI_B_CTLW0_TXSTP ;
    MAP_I2C_disableInterrupt(EUSCI_B0_BASE, EUSCI_B_I2C_RECEIVE_INTERRUPT0);
    } else
    /* TXIFG */
    if (status & EUSCI_B_I2C_TRANSMIT_INTERRUPT0) //
    {
    MAP_I2C_disableInterrupt(EUSCI_B0_BASE, EUSCI_B_I2C_TRANSMIT_INTERRUPT0);
    MAP_I2C_enableInterrupt( EUSCI_B0_BASE, EUSCI_B_I2C_RECEIVE_INTERRUPT0);
    MAP_I2C_masterReceiveSingleByte(EUSCI_B0_BASE); //
    } else /* NACK */
    if (status & EUSCI_B_I2C_NAK_INTERRUPT)
    {
    EUSCI_B0->CTLW0 |= EUSCI_B_CTLW0_TXSTP;
    MAP_I2C_disableInterrupt(EUSCI_B0_BASE, EUSCI_B_I2C_NAK_INTERRUPT);
    }
    }
  • Hello,

    I did some testing for this scenario and discovered some caveats.

    The transaction attempted is Master TX 1 byte, Restart, Master RX 1 byte.

    First when it comes to the master TX, you have two available flags, one when the start + address is sent & the other is TXIFG.

    The important thing to note about TXIFG is that it is NOT set when the byte is transmitted on the bus.

    Instead TXIFG is set when the data byte moves from the TXBUF to the transmit shift register in preparation to be sent out.

    This means that after TXIFG is set, we still have 9 I2C CLOCKS before the actual data byte is sent.

    If the I2C is running at 100KHz & the CPU is at 3MHz (default) , this is about 300 CPU cycles.

    The application needs to delay these 300 cycles before sending the restart or the transaction may stall or result in a stop.

    In order to keep this timing tight, in my example I have used an inline delay with no interrupts.

    However it is also possible to enabled TXIFG, delay 300 cycles in the ISR and then send the restart.

    I assume this is not preferable since ISRs could be blocking.

    Second when it comes to the RX of one byte, there seems to be a timing issue with the API "Masterreceivesinglebyte".

    I was also unable to create a successful one byte read with this API.

    However I managed to do so by using direct register access code & altering the sequence.

    My guess is that the I2C transactions/ state machine being slower than MCLK is causing this.

    Since I got my example to work, successfully transmitting, then receiving one byte, I've attached it to this post.

    I've also filed a bug against the API & will come back to post here if there are further updates.

    I am marking this thread resolved, feel free to let me know if you have additional questions.

    PS: The test setup is 2x MSP432 LPs , one as master and the other as slave.

    Regards,

    Priya

    master_onebyte.c
    Fullscreen
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    /* --COPYRIGHT--,BSD
    * Copyright (c) 2017, Texas Instruments Incorporated
    * All rights reserved.
    *
    * Redistribution and use in source and binary forms, with or without
    * modification, are permitted provided that the following conditions
    * are met:
    *
    * * Redistributions of source code must retain the above copyright
    * notice, this list of conditions and the following disclaimer.
    *
    * * Redistributions in binary form must reproduce the above copyright
    * notice, this list of conditions and the following disclaimer in the
    * documentation and/or other materials provided with the distribution.
    *
    * * Neither the name of Texas Instruments Incorporated nor the names of
    * its contributors may be used to endorse or promote products derived
    * from this software without specific prior written permission.
    *
    * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
    * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
    * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
    * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
    * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
    * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
    * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
    * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
    * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
    * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
    * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
    * --/COPYRIGHT--*/
    /******************************************************************************
    * MSP432 I2C - EUSCI_B0 I2C Master TX 1 bytes to MSP432 Slave
    * and reads one byte back following a repeated start
    *
    * Description: This demo connects two MSP432 's via the I2C bus. The master
    * transmits to the slave. This is the MASTER CODE.
    * _________________________________________________________
    * | Start | | Start | | |
    * | 0x48Addr | 0x04 | 0x48Addr | <1 Byte Read> | Stop |
    * | W | | R | | |
    * |__________|______|__________|___________________|_______|
    *
    * ACLK = n/a, MCLK = HSMCLK = SMCLK = BRCLK = default DCO = ~3.0MHz
    *
    * /|\ /|\
    * MSP432P4111 10k 10k MSP432P4111
    * slave | | master
    * ----------------- | | -----------------
    * | P1.6/UCB0SDA|<-|----+->|P1.6/UCB0SDA |
    * | | | | |
    * | | | | |
    * | P1.7/UCB0SCL|<-+------>|P1.7/UCB0SCL |
    * | | | |
    *
    *****************************************************************************/
    /* DriverLib Defines */
    #include <ti/devices/msp432p4xx/driverlib/driverlib.h>
    /* Slave Address for I2C Slave */
    #define SLAVE_ADDRESS 0x48
    #define NUM_OF_REC_BYTES 1
    /* Variables */
    const uint8_t TXData[] = {0x41,0x42};
    unsigned char RXData=0;
    XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

    slave_onebyte.c.c
    Fullscreen
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    /* --COPYRIGHT--,BSD,BSD
    * Copyright (c) 2017, Texas Instruments Incorporated
    * All rights reserved.
    *
    * Redistribution and use in source and binary forms, with or without
    * modification, are permitted provided that the following conditions
    * are met:
    *
    * * Redistributions of source code must retain the above copyright
    * notice, this list of conditions and the following disclaimer.
    *
    * * Redistributions in binary form must reproduce the above copyright
    * notice, this list of conditions and the following disclaimer in the
    * documentation and/or other materials provided with the distribution.
    *
    * * Neither the name of Texas Instruments Incorporated nor the names of
    * its contributors may be used to endorse or promote products derived
    * from this software without specific prior written permission.
    *
    * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
    * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
    * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
    * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
    * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
    * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
    * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
    * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
    * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
    * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
    * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
    * --/COPYRIGHT--*/
    /******************************************************************************
    * MSP432 I2C - EUSCI_B0 I2C Slave
    *
    * Description: This demo connects two MSP432 's via the I2C bus.
    * _________________________________________________________
    * | Start | | Start | | |
    * | 0x48Addr | 0x04 | 0x48Addr | <1 Byte Read> | Stop |
    * | W | | R | | |
    * |__________|______|__________|___________________|_______|
    *
    * ACLK = n/a, MCLK = HSMCLK = SMCLK = BRCLK = default DCO = ~3.0MHz
    *
    * /|\ /|\
    * MSP432P4111 10k 10k MSP432P4111
    * slave | | master
    * ----------------- | | -----------------
    * | P1.6/UCB0SDA|<-|----+->|P1.6/UCB0SDA |
    * | | | | |
    * | | | | |
    * | P1.7/UCB0SCL|<-+------>|P1.7/UCB0SCL |
    * | | | |
    *
    *****************************************************************************/
    /* DriverLib Includes */
    #include <ti/devices/msp432p4xx/driverlib/driverlib.h>
    /* Standard Defines */
    #include <stdint.h>
    #include <stdbool.h>
    #include <string.h>
    /* Application Defines */
    #define SLAVE_ADDRESS 0x48
    #define NUM_OF_RX_BYTES 1
    #define NUM_OF_TX_BYTES 10
    XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

  • thanks. delay works for me.

**Attention** This is a public forum