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.

MSP430F5438A: How to communicate I2C using one MSP430?

Part Number: MSP430F5438A

Hi, everyone.

I'm new to the I2C protocol, and have no experience programming for it.

I have read I2C communication in MSP430 Microcontroller basics book by David.john. Also i have looked CCS example code.

However i havn't been able to make a connection with my MCU. 

My Board is MSP-TS430PZ5x100 using MSP430F5438A.

I want to communicate I2C using my board. So i have set USCI_B0 as master and transmission, and I set USCI_B1 as slave and wrote a code to receive it.

but My code started repeating itself in 21 lines.

 

void USCI_B_I2C_masterSendSingleByte (uint16_t baseAddress,
    uint8_t txData
    )
{
    //Store current TXIE status
    uint8_t txieStatus = HWREG8(baseAddress + OFS_UCBxIE) & UCTXIE;

    //Disable transmit interrupt enable
    HWREG8(baseAddress + OFS_UCBxIE) &= ~(UCTXIE);

    //Send start condition.
    HWREG8(baseAddress + OFS_UCBxCTL1) |= UCTR + UCTXSTT;

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

    //Send single byte data.
    HWREG8(baseAddress + OFS_UCBxTXBUF) = txData;

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

    //Send stop condition.
    HWREG8(baseAddress + OFS_UCBxCTL1) |= UCTXSTP;

    //Clear transmit interrupt flag before enabling interrupt again
    HWREG8(baseAddress + OFS_UCBxIFG) &= ~(UCTXIFG);

    //Reinstate transmit interrupt enable
    HWREG8(baseAddress + OFS_UCBxIE) |= txieStatus;
}

This is my Code using driverlib.h.

#include <MSP430.h>
#include <MSP430F5xx_6xx/driverlib.h>

uint8_t transmitData = 0x52;
uint8_t receiveData;
/**
 * main.c
 */
void main(void)
{
	WDT_A_hold(WDT_A_BASE);// stop watchdog timer

	initGPIO();
	initClock();
	initI2C();

	while(1)
	{
		USCI_B_I2C_masterSendSingleByte(USCI_B0_BASE, transmitData);

		while(USCI_B_I2C_isBusBusy(USCI_B0_BASE));

		__delay_cycles(50);

		transmitData++;
	}
}
#pragma vector = USCI_B1_VECTOR
__interrupt void USCI_B1_ISR(void)
{
	switch(__even_in_range(UCB1IV, 0x0C)){
		case 0x0C:
			receiveData = USCI_B_I2C_slaveGetData(USCI_B1_BASE);
			break;
	default: //__never_executed();
	break;
	}
}

#include <MSP430F5xx_6xx/driverlib.h>


uint32_t myACLK, mySMCLK, myMCLK;


void initGPIO(void)
{
	//Configurate oscillator 
	GPIO_setAsPeripheralModuleFunctionInputPin(GPIO_PORT_P7, GPIO_PIN0 + GPIO_PIN1);

	//Configurate I2C
	GPIO_setAsPeripheralModuleFunctionInputPin(GPIO_PORT_P3, GPIO_PIN1 + GPIO_PIN2 + GPIO_PIN6 + GPIO_PIN7);
}

	

void initClock(void)
{
	PMM_setVCore(PMM_CORE_LEVEL_3);

	UCS_setExternalClockSource(XT1CLK_HZ, XT2CLK_HZ);
	UCS_turnOnLFXT1(XT1DRIVE_0, XCAP_3);

	UCS_initClockSignal(UCS_ACLK, UCS_XT1CLK_SELECT, UCS_CLOCK_DIVIDER_1);

	//Configurate FLL
	/*
	UCS_initClockSignal(UCS_FLLREF, UCS_XT1CLK_SELECT, UCS_CLOCK_DIVIDER_1);
	UCS_initFLL(DESIREDMCLK_KHZ, MCLKXT1CLKRATIO);
	*/
	myACLK = UCS_getACLK();
	mySMCLK = UCS_getSMCLK();
	myMCLK = UCS_getMCLK();
}

void initI2C(void)
{
	USCI_B_I2C_initMasterParam I2cParam0 = {0,};
	I2cParam0.selectClockSource = USCI_B_I2C_CLOCKSOURCE_SMCLK;
	I2cParam0.i2cClk = UCS_getSMCLK();
	I2cParam0.dataRate = USCI_B_I2C_SET_DATA_RATE_400KBPS;

	USCI_B_I2C_initMaster(USCI_B0_BASE, &I2cParam0);
	USCI_B_I2C_initSlave(USCI_B1_BASE, SLAVEADDRESS);

	USCI_B_I2C_setSlaveAddress(USCI_B0_BASE, SLAVEADDRESS);

	USCI_B_I2C_setMode(USCI_B0_BASE, USCI_B_I2C_TRANSMIT_MODE);
	USCI_B_I2C_setMode(USCI_B1_BASE, USCI_B_I2C_RECEIVE_MODE);

	USCI_B_I2C_enable(USCI_B0_BASE);
	USCI_B_I2C_enable(USCI_B1_BASE);

	USCI_B_I2C_clearInterrupt(USCI_B0_BASE, USCI_B_I2C_TRANSMIT_INTERRUPT);
	USCI_B_I2C_clearInterrupt(USCI_B1_BASE, USCI_B_I2C_RECEIVE_INTERRUPT);

	USCI_B_I2C_enableInterrupt(USCI_B0_BASE, USCI_B_I2C_TRANSMIT_INTERRUPT);
	USCI_B_I2C_enableInterrupt(USCI_B1_BASE, USCI_B_I2C_RECEIVE_INTERRUPT);
}

I take a picture about I2C SCL and SDA at USCI_B_I2C_masterSendSingleByte. (Yello is SCL, Sky blue is SDA)

Where am i missing? 

Thanks.

  • What the scope shows is the Slave side stretching the clock, since you haven't fetched its Rx byte. a NACK since the Slave SCL isn't connected. Places to look:

    1) I don't see where you enable interrupts (GIE). Add this somewhere in main():

    > __enable_interrupt(); // GIE=1

    2) In your Slave ISR:

    >  case 0x0C:

    This is the IV code for Transmit (TXIFG) not Receive (RXIFG) [Ref User Guide (SLAU208Q) Table 38-14]. Try:

    >  case 0x0A:   // RXIFG: Received something from Master

    You may eventually need a TXIFG case as well, but not in your current experiment

    3) Unsolicited:

    >  USCI_B_I2C_enableInterrupt(USCI_B0_BASE, USCI_B_I2C_TRANSMIT_INTERRUPT);

    You don't need to enable TXIE for the master when you're using masterSendSingleByte(). It's not causing trouble now, but it might eventually.

    [Edit: According to data sheet (SLAS655H) Table 9-45, UCB1SCL isn't on P3.6, but rather on P5.4 [Ref Table 9-49], so now I think you're getting a NACK, which masterSendSingleByte doesn't deal with very well. So in addition to (1)-(3) above, you should probably move to P5.4 and add:

    >  GPIO_setAsPeripheralModuleFunctionInputPin(GPIO_PORT_P5, GPIO_PIN4);  // UCB1SCL is over here

    ]

  • Your suggestion helped me!

    I missed Global Interrupt and  UCB1SCL(P5.4). I misktook UCA1CLK(P3.6) for  UCB1SCL. and I have changed 0x0C to 0x0A..

**Attention** This is a public forum