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.

Problem with I2C Driverlib. MSP430FR5969

Other Parts Discussed in Thread: MSP430FR5969

#include "driverlib.h"

const uint16_t baseAddress = __MSP430_BASEADDRESS_EUSCI_B0__;
const uint8_t slaveAddress = 00000001;

//P1.6 SDA P1.7 SCLK

int main(void) {

WDT_A_hold(WDT_A_BASE);

GPIO_setAsPeripheralModuleFunctionInputPin(GPIO_PORT_P1, GPIO_PIN6 + GPIO_PIN7, GPIO_SECONDARY_MODULE_FUNCTION);

EUSCI_B_I2C_initMasterParam master_init = {EUSCI_B_I2C_CLOCKSOURCE_SMCLK,
CS_getSMCLK(),
EUSCI_B_I2C_SET_DATA_RATE_400KBPS,
1, //byteCounterThreshold
EUSCI_B_I2C_NO_AUTO_STOP
};

EUSCI_B_I2C_initMasterParam *master_init_ptr = &master_init;

EUSCI_B_I2C_initMaster(baseAddress, master_init_ptr);

EUSCI_B_I2C_setSlaveAddress(baseAddress, slaveAddress);

EUSCI_B_I2C_setMode(baseAddress, EUSCI_B_I2C_TRANSMIT_MODE);

EUSCI_B_I2C_enable(baseAddress);

//EUSCI_B_I2C_enableInterrupt(baseAddress, mask);

while (1) {

EUSCI_B_I2C_masterSendSingleByte(baseAddress, 0x55);

__delay_cycles(50);
} // end while
return (0);

Above is my code. I am attempting to network together a group of 4 MSP430s. Currently I can't even get the master to send the start signal. The code gets stuck in EUSCI_B_I2C_masterSendSingleByte(baseAddress, 0x55), specifically line 249 

//Poll for transmit interrupt flag.

while (!(HWREG16(baseAddress + OFS_UCBxIFG) & UCTXIFG));

This is directly after the send start condition line 

//Send start condition.
HWREG16(baseAddress + OFS_UCBxCTLW0) |= UCTR + UCTXSTT;

Seems to me that the UCTXIFG flag is supposed to be set but it is not getting set. Also I am monitoring both lines with a logic analyzer and after the send start condition line is executed no actually start condition is sent. SDA remains high. I am powering the lines with 3V and using Im using the MSP430FR5969 development boards. Please advise.

  • Also just to add I'm using 4.7k pull-up resistors.
  • So I've managed to solve this problem, it was due to not unlocking the pins from the reset state which is done with the following line of code.

    PM5CTL0 &= ~LOCKLPM5; 

    But now I have another problem. The masterSendSingleByte() function never actually moves on to send the byte of data. It only sends the address. I have the code set up to repeat this function over and over again for testing purposes. I've attached a screenshot of the oscope screen. The slave address is 0010001. I can see the start condition is sent, then the address and then the 0 bit indicating a write to the slave but there is no acknowledge from the slave neither does the master send the actual data byte. Not sure why this is happening.  

    Master Code 

    #include "driverlib.h"
    
    const uint16_t baseAddress = __MSP430_BASEADDRESS_EUSCI_B0__;
    const uint8_t slaveAddress = 0b0010001;
    
    //P1.6 SDA P1.7 SCLK
    
    int main(void) {
    
        uint8_t txData = 0x00;
    
        WDT_A_hold(WDT_A_BASE);
    
        GPIO_setAsPeripheralModuleFunctionInputPin(GPIO_PORT_P1, GPIO_PIN6 + GPIO_PIN7, GPIO_SECONDARY_MODULE_FUNCTION);
    
        PM5CTL0 &= ~LOCKLPM5; //unlock pins
    
        EUSCI_B_I2C_initMasterParam master_init = {EUSCI_B_I2C_CLOCKSOURCE_SMCLK,
        			     	 	 	 	 	 	 CS_getSMCLK(),
    											 EUSCI_B_I2C_SET_DATA_RATE_100KBPS,
    											 10,
    											 EUSCI_B_I2C_NO_AUTO_STOP
        										 };
    
        	EUSCI_B_I2C_initMasterParam *master_init_ptr = &master_init;
    
        	EUSCI_B_I2C_initMaster(baseAddress, master_init_ptr);
    
        	EUSCI_B_I2C_setSlaveAddress(baseAddress, slaveAddress);
    
        	EUSCI_B_I2C_setMode(baseAddress, EUSCI_B_I2C_TRANSMIT_MODE);
    
        	EUSCI_B_I2C_enable(baseAddress);
    
        	//EUSCI_B_I2C_enableInterrupt(baseAddress, mask);
    
    while (1) {
    
    	EUSCI_B_I2C_masterSendSingleByte(baseAddress, txData);
    
        __delay_cycles(50);
    	}
    
    	return (0);
    }
    

    Slave code 

    #include "driverlib.h"
    
    const uint16_t baseAddress = 0x0640;
    const uint8_t slaveAddress = 0b0010001;
    
    int main(void) {
    
    	int i = 0;
    
    	WDT_A_hold(WDT_A_BASE);
    
    	GPIO_setAsPeripheralModuleFunctionInputPin(GPIO_PORT_P1, GPIO_PIN6 + GPIO_PIN7,
    												GPIO_SECONDARY_MODULE_FUNCTION);
    
    	PM5CTL0 &= ~LOCKLPM5;
    
        EUSCI_B_I2C_initSlaveParam slave_init = {slaveAddress, EUSCI_B_I2C_OWN_ADDRESS_OFFSET0 /*0x00, can change later*/, EUSCI_B_I2C_OWN_ADDRESS_ENABLE};
        EUSCI_B_I2C_initSlaveParam *slave_init_ptr = &slave_init;
        EUSCI_B_I2C_initSlave(baseAddress, slave_init_ptr);
    
        EUSCI_B_I2C_setMode(baseAddress, EUSCI_B_I2C_RECEIVE_MODE);
    
        EUSCI_B_I2C_enable(baseAddress);
    
        while(1);
    
    
        return (0);
    }

  •  Forgot to attach the Oscope screen, SDA is CH0 and SCL is CH1

  • User's Guide section 23.3.5.1.2 (I²C Slave Receiver Mode) says:

    If the slave receives data from the master, the eUSCI_B module is automatically configured as a receiver and UCTR is cleared. After the first data byte is received, the receive interrupt flag UCRXIFG0 is set. The eUSCI_B module automatically acknowledges the received data and can receive the next data byte.

    If the previous data was not read from the receive buffer UCBxRXBUF at the end of a reception, the bus is stalled by holding SCL low.

    Your slave is too lazy; I guess only the very first byte got ACKed.

  • Hi Brenton,

    I think Clemens is right here - If that is truly your whole slave code, then I don't see anywhere that your slave is ever reading out the received data - basically the I2C hardware thinks that your slave code is busy doing something else so it is stalling the line - the only way it knows you're ready to move on is by the code reading the buffer. I think you should either enable your receive interrupt in your slave code and read out the UCBxRXBUF in the ISR, or simply alter your while(1) loop to constantly poll for the receive flag to be set and then read out the data into a variable. The act of reading the data out will allow the I2C hardware state machine on the slave to progress and allow the communication to advance.

    Regards,
    Katie
  • Besides the said, your scope shoot looks suspicious. Your clock pulses are triangles rather than rectangles. With 100kHz clock speed, you should have nice, clean, steep rectangles, even (or especially) with the limited resolution of your scope. It's possible that the slave just can't decipher what it sees on the bus.
    Since falling and rising times are equal, it can't be just a too-small pull-up. It rather looks like a huge capacitance on the signal lines. Or your scope probe wreaks havoc on the signal (In which case I wouldn't trust anything I see on the screen).

**Attention** This is a public forum