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 in msp430fg4618/f2013 experimenter's board

Other Parts Discussed in Thread: MSP430FG4618, MSP430F2013

  I tried interfacing the inbuilt thermometer with the msp430fg4618 in the experimenter's board. 

I connected the jumpers in PWR2 and then H1- 1 2 and 3 4 pins. I tried displaying the temperature in the lcd but I don't get anything. I am very sure that nothing is wrong in the additional functions that I have written apart from main() as those functions worked perfectly with other programs. Also when I touched some places in msp430f2013 then I get 0 degree celcius in the lcd.

Just see the main() part.

Here's the code

#include <msp430fg4618.h> //
#include <intrinsics.h> // Intrinsic functions
#include <stdint.h> // Integers of defined sizes
#define SLAVE_ADDRESS 0x48 // I2C address of thermometer
//#define LED P5OUT_bit.P5OUT_1 // Output pin for LED (active high)
// Pin is output low by default


#define LCDDIGITS 7 // Number of digits in display
#define LCDMEMS 11 // LCD memories used (3-13)
// Pointer to LCD memory used: allows use of array LCDMem[]
uint8_t * const LCDMem = (uint8_t *) &LCDM3;
// LCD segment definitions (SoftBaugh SBLCDA4)
#define SEG_A BIT0 // AAAA
#define SEG_B BIT1 // F B
#define SEG_C BIT2 // F B
#define SEG_D BIT3 // GGGG
#define SEG_E BIT6 // E C
#define SEG_F BIT4 // E C
#define SEG_G BIT5 // DDDD
#define SEG_H BIT7 // colon, point etc
// Patterns for hexadecimal characters
const uint8_t LCDHexChar[] = {
SEG_A | SEG_B | SEG_C | SEG_D | SEG_E | SEG_F, // "0"
SEG_B | SEG_C, // "1"
SEG_A | SEG_B | SEG_D | SEG_E | SEG_G, // "2"
SEG_A | SEG_B | SEG_C | SEG_D | SEG_G, // "3"
SEG_B | SEG_C | SEG_F | SEG_G, // "4"
SEG_A | SEG_C | SEG_D | SEG_F | SEG_G, // "5"
SEG_A | SEG_C | SEG_D | SEG_E | SEG_F | SEG_G, // "6"
SEG_A | SEG_B | SEG_C, // "7"
SEG_A | SEG_B | SEG_C | SEG_D | SEG_E | SEG_F | SEG_G, // "8"
SEG_A | SEG_B | SEG_C | SEG_D | SEG_F | SEG_G, // "9"
SEG_A | SEG_B | SEG_C | SEG_E | SEG_F | SEG_G, // "A"
SEG_C | SEG_D | SEG_E | SEG_F | SEG_G, // "b"
SEG_A | SEG_D | SEG_E | SEG_F, // "C"
SEG_B | SEG_C | SEG_D | SEG_E | SEG_G, // "d"
SEG_A | SEG_D | SEG_E | SEG_F | SEG_G, // "E"
SEG_A | SEG_E | SEG_F | SEG_G, // "F"
};
// More useful patterns
const uint8_t LCDhexChar = SEG_C | SEG_E | SEG_F | SEG_G;
const uint8_t LCDAMChar = SEG_A | SEG_B | SEG_C | SEG_E | SEG_F | SEG_G;
const uint8_t LCDPMChar = SEG_A | SEG_B | SEG_E | SEG_F | SEG_G;
const uint8_t LCDMinusChar = SEG_G;
const uint8_t LCDCChar = SEG_A | SEG_D | SEG_E | SEG_F;
const uint8_t LCDEChar = SEG_A | SEG_D | SEG_E | SEG_F | SEG_G;
const uint8_t LCDHChar = SEG_B | SEG_C | SEG_E | SEG_F | SEG_G;
const uint8_t LCDhChar = SEG_C | SEG_E | SEG_F | SEG_G;
const uint8_t LCDLChar = SEG_D | SEG_E | SEG_F;
const uint8_t LCDOChar = SEG_A | SEG_B | SEG_C | SEG_D | SEG_E | SEG_F;
const uint8_t LCDoChar = SEG_C | SEG_D | SEG_E | SEG_G;
const uint8_t LCDrChar = SEG_E | SEG_G;
const uint8_t LCDdegChar = SEG_A | SEG_B | SEG_F | SEG_G;
const uint8_t LCDBlankChar = 0;
// Segments of "digit 10", half-digit on right plus special symbols
#define ONESEG BIT3 // '1' (only one logical segment)
#define DOLLARSEG BIT4 // '$'
#define ERRORSEG BIT5 // 'E' marker
#define MINUSSEG BIT6 // '-' marker
#define MEMSEG BIT7 // 'M' marker
//----------------------------------------------------------------------
// Initialize SBLCDA4
//----------------------------------------------------------------------
void LCDInit (void)
{
int i;
for(i = 0; i < LCDMEMS; ++i) { // Clear LCD memory used
LCDMem[i] = 0;
}
P5SEL = BIT4|BIT3|BIT2; // Select COM[3:1] function
LCDAPCTL0 = LCDS4|LCDS8|LCDS12|LCDS16|LCDS20|LCDS24;
// Enable LCD segs 4-27 (4-25 used)
LCDAVCTL0 = 0; // No charge pump, everything internal
LCDACTL = LCDFREQ_128 | LCD4MUX | LCDSON | LCDON;
// ACLK/128, 4mux, segments on, LCD_A on
}
//----------------------------------------------------------------------
// Display word in hexadecimal, 4 digits followed by 'h' (or 'H')
//----------------------------------------------------------------------

uint32_t UintToBCD (uint16_t UIntValue)
{
uint32_t converted;
uint8_t i;

converted = 0;
for (i = 0; i < 16; ++i) {
converted = __bcd_add_long (converted, converted);
if ((UIntValue & BITF) != 0) {
converted = __bcd_add_long (converted, 1);
}
UIntValue <<= 1;
}
return converted;
}


void DisplayHex (uint16_t HexValue)
{
uint8_t i; // Index for LCD array

LCDMem[0] = LCDhChar; // 'h' for hexadecimal on right
for (i = 1; i <= 4; ++i) { // Display 4 hex digits
LCDMem[i] = LCDHexChar[HexValue & 0x000F];
HexValue >>= 4; // Move next nibble into position
}
while (i < LCDDIGITS) { // Clear more significant digits
LCDMem[i++] = LCDBlankChar; // of numerical display
}
}
//----------------------------------------------------------------------
// Display unsigned, 16-bit integer (uint16_t)
// Convert to BCD and display
// Leading zeros suppressed; BCD value does not exceed 5 digits
//----------------------------------------------------------------------
void DisplayUint (uint16_t UintValue)
{
uint8_t i; // Index for LCD array
uint32_t BCDValue; // Value converted bin to BCD

BCDValue = UintToBCD (UintValue); // Convert binary to BCD
i = 0; // Index for LCD memories
do { // Store pattern for next digit
LCDMem[i++] = LCDHexChar[BCDValue & 0x000F];
BCDValue >>= 4; // Move next nibble down
} while (BCDValue > 0); // (Always display first digit)
while (i < LCDDIGITS) { // Clear more significant digits
LCDMem[i++] = LCDBlankChar; // of numerical display
}
}
//----------------------------------------------------------------------
// Display unsigned, 32-bit integer (uint32_t) up to 19,999,999
// Convert to BCD if it fits and display with leading zeros suppressed
//----------------------------------------------------------------------
void DisplayUlint (uint32_t UlintValue)
{
uint8_t i; // Index for LCD array
uint32_t BCDValue; // Value converted bin to BCD

if (UlintValue <= 9999999) {
BCDValue = UlintToBCD (UlintValue); // Convert binary to BCD
i = 0; // Index for LCD memories
do { // Store pattern for next digit
LCDMem[i++] = LCDHexChar[BCDValue & 0x000F];
BCDValue >>= 4; // Move next nibble down
} while (BCDValue > 0); // (Always display first digit)
while (i < LCDDIGITS) { // Clear more significant digits
LCDMem[i++] = LCDBlankChar; // of numerical display
}
LCDMem[10] = LCDBlankChar; // Special segment for "1"
} else if (UlintValue <= 19999999) { // Needs special treatment
BCDValue = UlintToBCD (UlintValue); // Convert binary to BCD
for (i = 0; i < LCDDIGITS; ++i) {
LCDMem[i] = LCDHexChar[BCDValue & 0x000F];
BCDValue >>= 4; // Move next nibble down
}
LCDMem[10] = ONESEG; // Special segment for "1"
} else {
LCDMem[10] = LCDBlankChar; // Special segment for "1"
}
}
//----------------------------------------------------------------------
// Display signed, 16-bit integer (int16_t)
// Strip sign, convert unsigned value to BCD and display
// Leading zeros suppressed; BCD value does not exceed 5 digits
//----------------------------------------------------------------------
void DisplayInt (int16_t IntValue)
{
uint8_t i; // Index for LCD array
uint32_t BCDValue; // Value converted bin to BCD
enum {plus, minus} sign;

if (IntValue >= 0) { // Keep track of sign
sign = plus;
} else {
sign = minus;
IntValue = -IntValue; // Conversion needs IntValue>=0
}
BCDValue = UintToBCD (IntValue); // Convert binary to BCD
i = 0; // Index for LCD memories
do { // Store pattern for next digit
LCDMem[i++] = LCDHexChar[BCDValue & 0x000F];
BCDValue >>= 4; // Move next nibble down
} while (BCDValue > 0); // (Always display first digit)
if (sign == minus) {
LCDMem[i++] = LCDMinusChar; // Prepend minus sign
}
while (i < LCDDIGITS) { // Clear more significant digits
LCDMem[i++] = LCDBlankChar; // of numerical display
}
}
//----------------------------------------------------------------------
// Display temperature (-99.9 to 999.9 deg C) to 0.1 degree celsius
// Leave far right character blank to get decimal point in correct place
//----------------------------------------------------------------------
void DisplayDeciCels (int16_t Temperature)
{
uint8_t i; // Index for LCD array
uint32_t BCDValue; // Value converted bin to BCD
enum {plus, minus} sign;

if (Temperature >= 0) { // Keep track of sign
sign = plus;
if (Temperature > 9999) { // Bring value within range;
Temperature = 9999; // only 4 characters available
} // to show positive values
} else {
sign = minus;
Temperature = -Temperature; // Conversion needs value >= 0
if (Temperature > 999) { // Only 3 characters available
Temperature = 999; // to show negative values
}
} // (lose one for - sign)
BCDValue = UintToBCD (Temperature); // Convert binary to BCD
i = 0; // Index for LCD memories
LCDMem[i++] = LCDBlankChar; // Leave rightmost space blank
LCDMem[i++] = LCDCChar; // Show 'C'
LCDMem[i++] = LCDdegChar; // Show degree sign
// Least significant digit is tenths with decimal point
LCDMem[i++] = LCDHexChar[BCDValue & 0x000F] | SEG_H;
BCDValue >>= 4; // Move next nibble down
do { // Store pattern for next digit
LCDMem[i++] = LCDHexChar[BCDValue & 0x000F];
BCDValue >>= 4; // Move next nibble down
} while (BCDValue > 0); // (Always display units digit)
if (sign == minus) {
LCDMem[i++] = LCDMinusChar; // Prepend minus sign
}
while (i < LCDDIGITS) { // Clear more significant digits
LCDMem[i++] = LCDBlankChar; // of numerical display
}
}
//----------------------------------------------------------------------
// Display temperature (-99.99 to 999.99 deg C) to 0.01 degree celsius
//----------------------------------------------------------------------
void DisplayCentiCels (int16_t Temperature)
{
uint8_t i; // Index for LCD array
uint32_t BCDValue; // Value converted bin to BCD
enum {plus, minus} sign;

if (Temperature >= 0) { // Keep track of sign
sign = plus; // Value always fits on display
} else {
sign = minus;
Temperature = -Temperature; // Conversion needs value >= 0
if (Temperature > 9999) { // Only 4 characters available
Temperature = 9999; // to show negative values
}
} // (lose one for - sign)
BCDValue = UintToBCD (Temperature); // Convert binary to BCD
i = 0; // Index for LCD memories
LCDMem[i++] = LCDCChar; // Show 'C'
LCDMem[i++] = LCDdegChar; // Show degree sign
LCDMem[i++] = LCDHexChar[BCDValue & 0x000F]; // Hundredths
BCDValue >>= 4; // Move next nibble down
// Next significant digit is tenths with decimal point
LCDMem[i++] = LCDHexChar[BCDValue & 0x000F] | SEG_H;
BCDValue >>= 4; // Move next nibble down
do { // Store pattern for next digit
LCDMem[i++] = LCDHexChar[BCDValue & 0x000F];
BCDValue >>= 4; // Move next nibble down
} while (BCDValue > 0); // (Always display units digit)
if (sign == minus) {
LCDMem[i++] = LCDMinusChar; // Prepend minus sign
}
while (i < LCDDIGITS) { // Clear more significant digits
LCDMem[i++] = LCDBlankChar; // of numerical display
}
}
//----------------------------------------------------------------------
// Display line of hyphens ----- across LCD to show that it is alive
//----------------------------------------------------------------------
void DisplayLine (void)
{
uint8_t i; // Index for LCD array

for (i = 0; i < LCDDIGITS; ++i) { // Step through digits
LCDMem[i] = LCDMinusChar; // of numerical display
}
}

//----------------------------------------------------------------------
// Display "HELLO" on LCD (need a less clumsy routine?)
//----------------------------------------------------------------------
void DisplayHello (void)
{
uint8_t i; // Index for LCD array

LCDMem[0] = LCDOChar;
LCDMem[1] = LCDLChar;
LCDMem[2] = LCDLChar;
LCDMem[3] = LCDEChar;
LCDMem[4] = LCDHChar;
for (i = 5; i < LCDDIGITS; ++i) { // Step through digits
LCDMem[i] = LCDBlankChar; // of numerical display
}
}
//----------------------------------------------------------------------
// Initialize ports for board: pins are outputs driven low by default
// Many of these will be overwritten by LCD initialization later
//----------------------------------------------------------------------
void PortsInit (void)
{
// Port 1: 0 = SW1, 1 = SW2, others used for Chipcon (not placed)
P1OUT = 0;
P1DIR = 0xFF & ~(BIT0|BIT1); // P1.0,1 input, others output
// Port 2: 1 = LED2, 2 = LED1, 3 = mic power, 4 = UCA0TXD, 5 = UCA0RXD
P2OUT = 0;
P2DIR = 0xFF & ~BIT5; // P2.5 must be input
// Port 3: 0-3 = comms with F2013, 5 = buzzer (active low)
P3OUT = BIT1 | BIT2 | BIT5; // F2013 might tie 1,2 high;
P3DIR = 0xFF; // P3.5 high for buzzer off
// Port 4: 2-5 used for Chipcon (not placed)
P4OUT = 0;
P4DIR = 0xFF;
// Port 5: 1 = LED4, 2-4 = COM1-3 for LCD
P5OUT = 0;
P5DIR = 0xFF;
// Port 6: All except 6 used for opamp external components
P6OUT = 0;
P6DIR = 0xFF;
// Port 7: 4-7 = LCD segments
P7OUT = 0;
P7DIR = 0xFF;
// Port 8: LCD segments
P8OUT = 0;
P8DIR = 0xFF;
// Port 9: LCD segments
P9OUT = 0;
P9DIR = 0xFF;
// Port 10: 0-5 = LCD segments
P10OUT = 0;
P10DIR = 0xFF;
}


void main (void)
{
volatile uint16_t i; // Loop counter to stabilize FLL+
int16_t Temperature; // Value received over I2C
WDTCTL = WDTPW | WDTHOLD; // Stop watchdog timer
FLL_CTL0 = XCAP14PF; // 14pF load caps; 1MHz default
do { // Wait until FLL has locked
for (i = 0x2700; i > 0; --i) { // One loop should be enough
} // Delay for FLL+ to lock

//IFG1_bit.OFIFG = 0; // Attempt to clear osc fault flag

IFG1&=~OFIFG;
} while (IFG1 & OFIFG != 0); // Repeat if not yet clear
PortsInit (); // Initialize ports
LCDInit (); // Initialize SBLCDA4
DisplayHello (); // Display HELLO on LCD
P3SEL = BIT1 | BIT2; // Route pins to USCI_B for I2C
// 7-bit addresses (default), single master , master mode , I2C , synch
UCB0CTL0 = UCMST | UCMODE_3 | UCSYNC;
// Clock from SMCLK , receiver (default), hold in reset

UCB0CTL1 = UCSSEL_2 | UCSWRST;
UCB0BR1 = 0; // Upper byte of divider word
UCB0BR0 = 10; // Clock = SMCLK / 10 = 100 KHz
UCB0I2COA = 0; // Ignore genl call; own address = 0
UCB0CTL1 &= ~UCSWRST; // Release from reset
// Set up basic timer for interrupts at 2Hz (500ms)

// I can't find "BT_ADLY_500" anywhere in the family user guide.
BTCTL = BTHOLD | BT_ADLY_500; // Hold , period = 500ms from ACLK
BTCNT2 = 0; // Clear counter
BTCTL &= ~BTHOLD; // Start basic timer

//IE2_bit.BTIE = 1; // Enable basic timer interrupts

IE2|= BTIE;
for (;;) { // Transfers triggered by BT
__low_power_mode_3 (); // Wait for BT (needs only ACLK)

//LED = 1; // Show start of activity

P5OUT= BIT1;
UCB0I2CSA = SLAVE_ADDRESS; // Slave to be addressed
UCB0CTL1 |= UCTXSTT; // Send Start and slave address
while (( UCB0CTL1 & UCTXSTT) != 0) {
} // Wait for address to be sent
if (( UCB0STAT & UCNACKIFG) != 0) { // Address NOT acknowledged?
UCB0CTL1 |= UCTXSTP; // Send Stop condition and finish
} else { // Address acknowledged: receive
while (IFG2 & UCB0RXIFG == 0) {
} // Wait for first byte
Temperature = UCB0RXBUF << 8; // MSB of temperature
UCB0CTL1 |= UCTXSTP; // Send Stop condition after byte
while (IFG2 & UCB0RXIFG == 0) {
} // Wait for second byte
Temperature |= UCB0RXBUF; // LSB of temperature
DisplayCentiCels (Temperature); // Display temp to 0.01oC
}
P5OUT &= ~BIT1; // Show end of activity
}
}
// ----------------------------------------------------------------------
// ISR for basic timer: return to main routine
// ----------------------------------------------------------------------
#pragma vector = BASICTIMER_VECTOR
__interrupt void BASICTIMER_ISR (void) // Acknowledged automatically
{
__low_power_mode_off_on_exit(); // Return to start new I2C message
}

  • Sorry, I didn't really read through all the code since it is too long and unformatted and my office hours are olmost over. But a few things I noticed:

    Venkatraman Natarajan said:
    do { // Wait until FLL has locked
    for (i = 0x2700; i > 0; --i) { // One loop should be enough


    The loop probably won't do what you think it does. YOu define di as volatile to disable optimization. However, the compiler knows for sure that volatile is nonsese since it is a local variable which is generated under compiler ocntrol. Nobody knows how/where it is generated except the current function, and you never pass a reference to anyone, so the compiler knows for sure that it cannot be altered by someone else or have side-effects. Sio th evolatile is simply ignored, and the loop might be optimized away.

    Besides this, the theoretical maximum locking time for the FLL is 30 reference clock cycles = 30/32768s = ~1ms. Since you run on default frequency,, which is somewher ein the 1.1MHz range, a loop of ~350 would be enough :)
    However, the FLL requires a watch crystal on XT1. And the watch crystal may require way more than 1ms to stabilize else the FLL will adjust into the wrong direction. Worst case, it will never stabilize, running the CPU on lowest frequency for the default DCO setting. But even if it comes up properly, still ~30-100ms have to be expected. Much more than the 0x2700 you use (which gives <30ms on 1.1MHz)

    So you need to reorder the code: first wait for the crystal to be stable, then wait for the FLL to lock.

    It's all not critical, though, unless a stable, stabilized frequency is crucial for your applicaiton from the beginning.

    Venkatraman Natarajan said:
    // I can't find "BT_ADLY_500" anywhere in the family user guide.

    It's not there. It is a "convenience define" that combines different settings: It configures the basic timer to use ACLK for a delay of 500ms, I think. If you look into the header files, you'll find the exact combination of bits and can look up their meaning in the users guide.

    What about the pullup resistors ont eh two I2C signals? AFAIK, the usual communication between the two processors on this board works using SPI which doesn't need pullups. For I2C, you need external pullups (the internal, even if activated, are too weak for a reliable conenction).
    YOur statement that you see something appearing if you touch the board supports this as possible cause for your problem.

**Attention** This is a public forum