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 getting the F2617 to send over I2C

Other Parts Discussed in Thread: MSP430F2617

I'm trying to interface an F2617 with an AD5242 digital potentiometer http://www.analog.com/static/imported-files/data_sheets/AD5241_5242.pdf

The code hangs on line 40: while (UCB0CTL1 & UCTXSTT);

If I comment that line out, it instead hangs on line 43: while ((IFG2 & UCB0TXIFG) == 0);

Pull-up resistors are 10kohm on both lines

I can program the AD5242 just fine from an AVR Mega32, so its not faulty.

I've been trying several I2C examples as well as writing my own code from the datasheets info, and have tried the the Launchpad/G2553 as well, with no success.

Does someone have working I2C master-slave/device code that they can share?

Can anyone see what I'm doing wrong? 

The code (also attached):

#include "msp430f2617.h"

#define I2C_MASTER_ADDRESS 0x007F // 7-bit addressing, MSB is "respond to general calls"
// I2C pot address: b010.11xx = 0x2C or 0x2D or 0x2E or 0x2F
#define I2C_POTMETER_ADDRESS 0x2C // 7-bit addressing, do not include write-bit
#define I2C_POTMETER_INSTRUCTION 0x00 // RADC1, no reset, no shutdown, no logic pin outputs
#define I2C_POTMETER_TAPS (int)255

/*
	USCI module is configured as an synchronous mode I2C master in a single-master enviroment.
	Both master and slave use 7-bit addressing. Master does not respond to general calls.
	Clock used is SMCLK/12 = 1.2GHz/12 = 100kHz. Master is configured as transmitter.
	P3.1 = SDA I2C data
	P3.2 = SCL I2C clock
*/
void I2C_init()
{
	UCB0CTL1 |= UCSWRST;					// Enable USCI SW reset
	UCB0CTL0 = UCMST + UCMODE_3 + UCSYNC;	// Single I2C master, synchronous mode, 7-bit addressing (both master and slave)
	UCB0CTL1 = UCSSEL_2 + UCTR + UCSWRST;	// Use SMCLK, transmitter mode, keep SW reset
	UCB0BR0 = 12;							// fSCL = SMCLK/12 = ~100kHz
	UCB0BR1 = 0;
	UCB0I2COA = I2C_MASTER_ADDRESS;			// Master address, MSB = 0 to not respond to general calls
	UCB0I2CSA = I2C_POTMETER_ADDRESS;		// Slave address
	P3SEL |= BIT1 + BIT2;					// Assign I2C pins to USCI_B0 (secondary peripheral module)
//	P3SEL2 |= BIT1 + BIT2;					// Assign I2C pins to USCI_B0 (secondary peripheral module)
	UCB0CTL1 &= ~UCSWRST;					// Clear USCI SW reset, resume operation
	IE2 |= UCB0TXIE;						// Enable TX interrupt
}

/*
	The digital potmeter is written over I2C. Default is to write a new potmeter tap value.
*/
void I2C_write_pot_value(int value)
{
	if (value > I2C_POTMETER_TAPS)
		value = I2C_POTMETER_TAPS;
	while (UCB0CTL1 & UCTXSTP);             // Ensure stop condition got sent
	UCB0CTL1 |= UCTR + UCTXSTT;				// Switch to I2C transmit mode, send START condition
	while (UCB0CTL1 & UCTXSTT);				// Wait for slave to acknowledges the address
	while ((IFG2 & UCB0TXIFG) == 0);		// Wait for transmit buffer to clear
	UCB0TXBUF = I2C_POTMETER_INSTRUCTION;	// Send instruction
	while ((IFG2 & UCB0TXIFG) == 0);		// Wait for transmit buffer to clear
	UCB0TXBUF = value;						// Send data
	while ((IFG2 & UCB0TXIFG) == 0);		// Wait for transmit buffer to clear
	UCB0CTL1 |= UCTR + UCTXSTP;				// Send STOP condition
}

int I2C_read_pot_value(void)
{
	return 0;
}

void main(void)
{
	WDTCTL = WDTPW + WDTHOLD;				// Stop WDT

	I2C_init();

	while(1)
	{
		I2C_write_pot_value(1);
	}
}

#include "msp430f2617.h"

#define I2C_MASTER_ADDRESS 0x007F // 7-bit addressing, MSB is "respond to general calls"

// I2C pot address: b010.11xx = 0x2C or 0x2D or 0x2E or 0x2F

#define I2C_POTMETER_ADDRESS 0x2C // 7-bit addressing, do not include write-bit

#define I2C_POTMETER_INSTRUCTION 0x00 // RADC1, no reset, no shutdown, no logic pin outputs

#define I2C_POTMETER_TAPS (int)255

/*

USCI module is configured as an synchronous mode I2C master in a single-master enviroment.

Both master and slave use 7-bit addressing. Master does not respond to general calls.

Clock used is SMCLK/12 = 1.2GHz/12 = 100kHz. Master is configured as transmitter.

P3.1 = SDA I2C data

P3.2 = SCL I2C clock

*/

void I2C_init()

{

UCB0CTL1 |= UCSWRST; // Enable USCI SW reset

UCB0CTL0 = UCMST + UCMODE_3 + UCSYNC; // Single I2C master, synchronous mode, 7-bit addressing (both master and slave)

UCB0CTL1 = UCSSEL_2 + UCTR + UCSWRST; // Use SMCLK, transmitter mode, keep SW reset

UCB0BR0 = 12; // fSCL = SMCLK/12 = ~100kHz

UCB0BR1 = 0;

UCB0I2COA = I2C_MASTER_ADDRESS; // Master address, MSB = 0 to not respond to general calls

UCB0I2CSA = I2C_POTMETER_ADDRESS; // Slave address

P3SEL |= BIT1 + BIT2; // Assign I2C pins to USCI_B0 (secondary peripheral module)

// P3SEL2 |= BIT1 + BIT2; // Assign I2C pins to USCI_B0 (secondary peripheral module)

UCB0CTL1 &= ~UCSWRST; // Clear USCI SW reset, resume operation

IE2 |= UCB0TXIE; // Enable TX interrupt

}

/*

The digital potmeter is written over I2C. Default is to write a new potmeter tap value.

*/

void I2C_write_pot_value(int value)

{

if (value > I2C_POTMETER_TAPS)

value = I2C_POTMETER_TAPS;

while (UCB0CTL1 & UCTXSTP);             // Ensure stop condition got sent

UCB0CTL1 |= UCTR + UCTXSTT; // Switch to I2C transmit mode, send START condition

while (UCB0CTL1 & UCTXSTT); // Wait for slave to acknowledges the address

while ((IFG2 & UCB0TXIFG) == 0); // Wait for transmit buffer to clear

UCB0TXBUF = I2C_POTMETER_INSTRUCTION; // Send instruction

while ((IFG2 & UCB0TXIFG) == 0); // Wait for transmit buffer to clear

UCB0TXBUF = value; // Send data

while ((IFG2 & UCB0TXIFG) == 0); // Wait for transmit buffer to clear

UCB0CTL1 |= UCTR + UCTXSTP; // Send STOP condition

}

int I2C_read_pot_value(void)

{

return 0;

}

void main(void)

{

WDTCTL = WDTPW + WDTHOLD; // Stop WDT

I2C_init();

while(1)

{

I2C_write_pot_value(1);

}

}

  • Problem solved :)

    Turns out that 10kohm pull-ups when the IC supply is only 3V is just too high. It worked fine with 5,6kohm pull-ups instead.

  • On 100kHz and with only 2 peers, 10k should be fine. So maybe you have large parasitic capacitances on your connection. Or bad soldering (high resistance) on one of the chip pins.
    Well, 5,6k woN't hurt except for the higher current consumption.

  • The soldering is fine, but the IC _is_ connected to the MSP430 through 5-10 centimeter wires, so that might be it.

    Though I suspect that the reason is simply that a 2,7-5,5V supply range IC operated at 3V will require smaller pull-up resistor values to operate properly. Its just a digital potmeter after all, so my guess is that there is no internal stepping up those 3V.

  • Jacob Jorvang said:
    the IC _is_ connected to the MSP430 through 5-10 centimeter wires

    That's not much. The resistance should be negligible. I've had much longer traces in the past. Still capacitance might be the reason.

    Jacob Jorvang said:
    a 2,7-5,5V supply range IC operated at 3V will require smaller pull-up resistor values to operate properl

    Well, shouldn't. If the slave is CMOS technology, then it typically needs 70% VCC, to detect the signal as high, but does not draw significant current.

    At VCC=3V and R=5.6k, you have a voltage drop of 0.9V (worst case) with 160µA (90µA on 10k). Quite much for even a handful of CMOS inputs. But with some capacitance, you'll have a low-pass filter. A (very rough) estimation gives something in the magnitude of ~47pF as limit for 10k and 100kHz. more for lower R or lower frequency. Maybe you really have that much capacitance.

  • I agree that it could be stray capacitance, and that it would have to be a lot. Since my current hardware setup is a bunch of wires with crimped connecters, connecting between target board and vero board, I'm not going to spend a lot of time on it though. Eventually a proper prototype will be made, where I will try 10kohm pull-ups first.

    In any case, thanks for your help :-)

**Attention** This is a public forum