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.

CCS/MSP430FR2355: Problem in generating clock pulse in I2C and setting the TxIFG flag

Part Number: MSP430FR2355

Tool/software: Code Composer Studio

I am working on  msp430fr2355 to communicate with veml6040(colour sensor) using i2c. I installed driver library provided in ccs resource explorer. I have written a program. But it is not working. the TxIFG0 flag is not being set. and the control is being stuck in a loop while polling for TxIFG flag. I even checked the output of SDA and SCL pins using logic analyzer. But there was nothing. the clock itself is not being generated by SCL. Below is my code. Can someone tell if something is wrong with it. 

uint8_t RL;
uint8_t RH;
uint16_t t = 0;

EUSCI_B_I2C_initMasterParam i2cParam = {
EUSCI_B_I2C_CLOCKSOURCE_SMCLK,
1000000,
EUSCI_B_I2C_SET_DATA_RATE_100KBPS,
5,
EUSCI_B_I2C_NO_AUTO_STOP
};

int main(void)
{

EUSCI_B_I2C_initMasterParam* pmaster;
pmaster = &master;

EUSCI_B_I2C_initMaster(EUSCI_B1_BASE, pmaster);
EUSCI_B_I2C_setSlaveAddress(EUSCI_B1_BASE, 0x10);

P4SEL1 |= 0xC0;      //Assigning pins 4.6 and 4.7 to I2C

EUSCI_B_I2C_enable(EUSCI_B1_BASE);

EUSCI_B_I2C_masterSendMultiByteStart(EUSCI_B1_BASE, 0xA5);

EUSCI_B_I2C_masterSendMultiByteFinish(EUSCI_B1_BASE, 0xA5);

EUSCI_B_I2C_masterSendMultiByteStart(EUSCI_B1_BASE, 0x08);

EUSCI_B_I2C_masterReceiveStart(EUSCI_B1_BASE);

RL = EUSCI_B_I2C_masterReceiveMultiByteNext(EUSCI_B1_BASE);

RH = EUSCI_B_I2C_masterReceiveMultiByteFinish(EUSCI_B1_BASE);

P1OUT = 0x00;
return 0;
}

 

when I run it. It is being Stuck in this loop :

//Poll for transmit interrupt flag.
while (!(HWREG16(baseAddress + OFS_UCBxIFG) & UCTXIFG)) ;

  • Hello Pavan,

    I think you are missing the setMode API. Chapter 14The Driverlib User's guide lays out the APIs and order required to initialize the I2C. User's Guide can be found here: dev.ti.com/.../node

    This is what it says for I2C Master Mode:

    "To drive the master module, the APIs need to be invoked in the following order:
    -EUSCI_B_I2C_initMaster
    -EUSCI_B_I2C_setSlaveAddress
    -EUSCI_B_I2C_setMode
    -EUSCI_B_I2C_enable
    -EUSCI_B_I2C_enableInterrupt ( if interrupts are being used ) This may be followed by the
    APIs for transmit or receive as required"


    Thanks,
    JD
  • Hello JD,

    I tried the pattern you suggested, but i am still getting the the same problem.

    i am stuck in this loop:
    //Poll for transmit interrupt flag.
    while (!(HWREG16(baseAddress + OFS_UCBxIFG) & UCTXIFG)) ;

    When i check the UCB1IFG register, the transmit flag(UCTXIFG) is not getting set.

    I don't know why. Can u suggest something else.
  • > P4SEL1 |= 0xC0; //Assigning pins 4.6 and 4.7 to I2C

    The P4SELx setting for I2C [Ref data sheet (SLASEC4B) Table 6-66] is specified as "01", which means SEL1=0, SEL0=1. (DriverLib calls this "primary".) Try instead:

    > P4SEL0 |= 0xC0; //Assigning pins 4.6 and 4.7 to I2C
    -------------------------
    Unsolicited: What does command code 0xA5 do? I don't see it in VEML6040 data sheet Table 1.
  • I tried using P4SEL0 |=  0xC0;.   But it is still not working.

    Actually it is not A5.  It is 0x00,  It is Command code for configuration register.

    This is my code :

    #include <msp430.h>
    #include "driverlib.h"

    uint8_t RL;
    uint8_t RH;
    uint16_t t = 0;
    uint16_t i = 0;
    EUSCI_B_I2C_initMasterParam master = {
    EUSCI_B_I2C_CLOCKSOURCE_SMCLK,
    1000000,
    EUSCI_B_I2C_SET_DATA_RATE_100KBPS,
    5,
    EUSCI_B_I2C_NO_AUTO_STOP
    };

    int main(void)
    {
    // stop watchdog timer

    P1DIR = 0x01;
    P1OUT = 0x01;        // LED on

    P4SEL0 |= BIT6 | BIT7;

    EUSCI_B_I2C_initMasterParam* pmaster;

    pmaster = &master;

    EUSCI_B_I2C_disable(EUSCI_B1_BASE);

    EUSCI_B_I2C_initMaster(EUSCI_B1_BASE, pmaster);
    EUSCI_B_I2C_setSlaveAddress(EUSCI_B1_BASE, 0x10);

    EUSCI_B_I2C_setMode(EUSCI_B1_BASE, EUSCI_B_I2C_TRANSMIT_MODE);

    P4SEL1 |= 0xC0;
    EUSCI_B_I2C_enable(EUSCI_B1_BASE);

    i = UCB1CTLW0;
    //EUSCI_B_I2C_setMode(EUSCI_B1_BASE, EUSCI_B_I2C_TRANSMIT_MODE);

    EUSCI_B_I2C_masterSendMultiByteStart(EUSCI_B1_BASE, 0x00);             // command code for configuration register

    EUSCI_B_I2C_masterSendMultiByteFinish(EUSCI_B1_BASE, 0x00);         // value to be written into configuration register

    EUSCI_B_I2C_masterSendMultiByteStart(EUSCI_B1_BASE, 0x08);           // command code for red register

    //EUSCI_B_I2C_setMode(EUSCI_B1_BASE, EUSCI_B_I2C_RECEIVE_MODE);

    EUSCI_B_I2C_masterReceiveStart(EUSCI_B1_BASE);       // start receiving data from Red register

    RL = EUSCI_B_I2C_masterReceiveMultiByteNext(EUSCI_B1_BASE);        // LSB(low byte) of red register

    RH = EUSCI_B_I2C_masterReceiveMultiByteFinish(EUSCI_B1_BASE);     //MSB(high byte) of red register

    P1OUT = 0x00;      // LED off
    return 0;
    }

       

  • > P4SEL1 |= 0xC0;
    This (along with the setting up at the top) sets the SEL bits to 11, not 01. Remove this line of code.
  • I have tried what you said but I am still getting the same problem.
    I have connected the digital scope to pins 4.6(SDA) and 4.7(SCL) but I still cannot see any clock pulse.
    I am using I2C 1 (UCB1SDA and UCB1SCL).
    Do I need to connect external pullup registers to SDA and SCL pins ?
  • What target (VEML6040) board are you using? Many/most breakout boards have pullups as needed; if those are installed, you don't need additional pullups.

    What Do you see on the scope? 0V? 3V? Floating?

    What values does the debugger see in P4SEL0/1?
  • I am using MSP430FR2355 TI launchpad Kit.
    www.ti.com/.../slau680.pdf

    Most of the times I see 0V on both SDA and SCL. Sometimes, i see 3.3V. But there is no clock generated.

    The P4SEL0/1 values are 0xC0.
  • Do I need to use external pullup resistors for I2C pins ?
  • > P4SEL1 |= 0xC0;
    Remove this line of code.
    ------------------------------------------------------------------------
    > Do I need to use external pullup resistors for I2C pins ?
    What target (VEML6040) board are you using? Many/most breakout boards have pullups as needed; if those are installed, you don't need additional pullups.
  • P4SEL1 |= 0xC0;
    i removed this line of code and tried . I am still getting the same problem.

    I am using MSP430FR2355 TI launchpad Kit.
    www.ti.com/.../slau680.pdf

    Can you please tell me if I need to use pullup resistors for i2c pins.
  • www.ti.com/.../slau680.pdf
    this is the user guide for MSP430FR2355.
  • I think you also need to add:
    > PM5CTL0 &= ~LOCKLPM5; // Engage GPIOs
    probably up near the beginning of main.
    -----------------------
    > Can you please tell me if I need to use pullup resistors for i2c pins.

    External pullups are required for I2C pins.

    The external pullups are Not present on the Launchpad.

    If your VEML6040 chip is mounted on a separate (commercial "breakout") board, there May be external pullups already installed on that board. Check the schematic or visually inspect it.

    If your VEML6040 chip is just hanging on wires, then you need to Add external pullups. I have had success on some Launchpads by connecting the pullups using the connectors on the underside.
  • > PM5CTL0 &= ~LOCKLPM5; // Engage GPIOs

    I have added this statement. But I am still getting the same problem. The clock is not being generated on the SCL pin. 

    I even connected pullup resistors between SCL SDA pins and 3.3V. I tried with both 9.2K and 4.7K resistors.

    I am uploading the picture  of the scope when I run the code.  I am also uploading the code.

    5100.main.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
    #include <msp430.h>
    #include "driverlib.h"
    uint8_t RL;
    uint8_t RH;
    uint16_t t = 0;
    uint16_t i = 0;
    EUSCI_B_I2C_initMasterParam master = {
    EUSCI_B_I2C_CLOCKSOURCE_SMCLK,
    1000000,
    EUSCI_B_I2C_SET_DATA_RATE_100KBPS,
    5,
    EUSCI_B_I2C_NO_AUTO_STOP
    };
    int main(void)
    {
    WDTCTL = WDTPW | WDTHOLD; // stop watchdog timer
    PM5CTL0 &= ~LOCKLPM5; //Engage GPIOs
    P1DIR = 0x01;
    P1OUT = 0x01; // LED on
    //P4DIR = 0x00;
    //P4SEL1 |= 0xC0;
    P4SEL0 |= 0xC0;
    P4REN |= 0xC0;
    //P4OUT |= 0xC0;
    // EUSCI_B_I2C_remapPins(EUSCI_B1_BASE, EUSCI_B_I2C_REMAP_PINS_TRUE);
    EUSCI_B_I2C_initMasterParam* pmaster;
    pmaster = &master;
    //EUSCI_B_I2C_disable(EUSCI_B1_BASE);
    EUSCI_B_I2C_initMaster(EUSCI_B1_BASE, pmaster);
    EUSCI_B_I2C_setSlaveAddress(EUSCI_B1_BASE, 0x10);
    //EUSCI_B_I2C_setMode(EUSCI_B1_BASE, EUSCI_B_I2C_TRANSMIT_MODE);
    P4SEL1 |= 0xC0;
    EUSCI_B_I2C_enable(EUSCI_B1_BASE);
    //__delay_cycles(10000);
    //EUSCI_B_I2C_setMode(EUSCI_B1_BASE, EUSCI_B_I2C_TRANSMIT_MODE);
    //EUSCI_B_I2C_masterSendMultiByteStart(EUSCI_B1_BASE, 0x00); // command code for configuration register
    EUSCI_B_I2C_masterSendSingleByte(EUSCI_B1_BASE, 0x00);
    EUSCI_B_I2C_masterSendMultiByteFinish(EUSCI_B1_BASE, 0x00); // value to be written into configuration register
    EUSCI_B_I2C_masterSendMultiByteStart(EUSCI_B1_BASE, 0x08); // command code for red register
    //EUSCI_B_I2C_setMode(EUSCI_B1_BASE, EUSCI_B_I2C_RECEIVE_MODE);
    EUSCI_B_I2C_masterReceiveStart(EUSCI_B1_BASE); // start receiving data from Red register
    RL = EUSCI_B_I2C_masterReceiveMultiByteNext(EUSCI_B1_BASE); // LSB(low byte) of red register
    RH = EUSCI_B_I2C_masterReceiveMultiByteFinish(EUSCI_B1_BASE); //MS(high byte) of red register
    XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

  • > P4SEL1 |= 0xC0;
    This line of code is still there. You need to remove it.
  • I commented it out.
    Ok, I removed it and tried again.
    I am getting the same problem.
    The clock is not being generated.
  • I pasted line 45 from the .c file you posted. It was not a comment. Try searching for "P4SEL1" -- there should be no references to that name in this program.
    -------------------
    > P4REN |= 0xC0;
    > //P4OUT |= 0xC0;
    If you want to use the internal pullups (P4REN) you need to set the corresponding P4OUT bits to get them to pull in the right direction. You should un-comment the second line here, or -- since you have external pullups -- don't set P4REN at all.
  • Yes, Now I am getting the pulse. I have enabled the internal pullup and set the corresponding P4OUT bits. I uncommented that //P4OUT |= 0xC0; statement.

    But, I am getting the clock only once after I power up the board. I am not getting another time.
    If the remove the power and then plug it back, then I am able to see the clock signal.

    Thanks for your help.
  • Please explain "once":
    1) Only one clock pulse (ever)?
    2) Only one transaction?
    3) All transactions, but only once?

    For (2): You appear to be doing a "MultiByteFinish" on a transaction you didn't "MultiByteStart"

    For (3): Your program does two transactions, then quits. Maybe you should enclose some of the transactions in a while(1) loop (maybe with a delay in between).

    When you pause your program, where is it executing? (Be sure to check the stack traceback to know who called whom.)
  • I am getting all the pulses but only once.
    If I run my code again it does not work.
    It works when I unplug the USB and plug it back.
    Moreover, it does not work when I debug and run it.
    It works only if i flash it onto the board.

  • A couple of observations:

    1) In my copy of the driverlib source (3.80.06.03) masterReceiveMultiByteNext doesn't have a guard for RXIFG, so it probably is reading the RXBUF too early, which throws the sequence off. Unless there's a note I've missed, I don't see how one can use this function the way the driverlib user manual suggests.

    2) veml6040 data sheet Fig 4 suggests that it expects an ACK from the master, even for the last byte (rather unusual), and your trace further suggests that it ignores a NACK in master-receiver mode.

    Taken together, I suspect the sequence you're using is (a) not reading the correct bytes and (b) leaving the veml6040 hanging (with SDA held low) waiting for more clocks when no more will be supplied.

    I suggest you replace the calls to masterReceiveMultiByteNext and masterReceiveMultiByteFinish (both) with calls to EUSCI_B_I2C_masterReceiveSingle, then follow them with a call to EUSCI_B_I2C_masterReceiveMultiByteStop. This should (a) read and ack both bytes in sequence and (b) only then send a stop for the veml6040.

    I defer to the driverlib folks to say whether masterReceiveMultiByteNext is functioning as intended.
    --------------------------------------------
    Unsolicited: The veml6040 data sheet "Basic Characteristics" table (p. 3) says that it only draws 200uA, which is low enough to power from a GPIO. You might consider connecting its Vdd pin to a spare GPIO, and toggle the GPIO at startup to power-cycle it out of this mode. (I don't see a "startup time" specification, so you should probably delay for maybe a millisecond or so to let it power up.)
  • Ok I will try that.

    I am using CCS.

    My problem is that, if I debug and run the code, it is not working i.e. no clock is being generated.

    It is working only if I flash it on to the board and then remove the USB and plug it back.

    When I run it like this I cannot see variables that I am using to receive the data from the slave.

    Can you suggest something for that.

  • I offered a hypothesis -- that the code sequence you're using is causing the sensor to hang -- and an alternate code sequence which (if I'm correct) will keep it from hanging.

    I also offered you a workaround (GPIO-powering the sensor) which should clear the hang condition if it persists.

    I'm not sure what else you're looking for.

**Attention** This is a public forum