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.

Communicating with a raspberry pi via i2c

Other Parts Discussed in Thread: MSP430G2553, ENERGIA

Hi everyone,

I am trying to set up a MSP430G2553 as a slave to relay ADC information to a raspberry pi. Here's the relevant part of my code:

 

#include <msp430.h>

volatile int i = 0;

volatile int bytectr = 0;

volatile int output[3] = {0};

volatile int RXData = 0;

volatile int reg = 0;

volatile int VAR_INPUT[34];

void getadc();

void inttoarray();

int main(void)

{

WDTCTL = WDTPW + WDTHOLD;                 // Stop WDT

//BCSCTL1 = CALBC1_1MHZ;                  // Set range

//DCOCTL = CALDCO_1MHZ;        // SMCLK = DCO = 1MHz

P1SEL |= BIT6 + BIT7;                     // Assign I2C pins to USCI_B0

P1SEL2|= BIT6 + BIT7;                     // Assign I2C pins to USCI_B0

//P1DIR |= BIT0;

//P1OUT &= ~BIT0;

UCB0CTL1 |= UCSWRST;                      // Enable SW reset

UCB0CTL0 = UCMODE_3 + UCSYNC; // I2C Slave, synchronous mode

UCB0I2COA = 0x48;                         // Own Address is 048h

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

UCB0I2CIE |= UCSTPIE + UCSTTIE;           // Enable STT and STP interrupt

IE2 |= UCB0TXIE;                          // Enable RX interrupt

//__enable_interrupt();

while (1)

{

  __bis_SR_register(CPUOFF + GIE);        // Enter LPM0 w/ interrupts

}

}

void inttoarray()

{

VAR_INPUT[0] = reg;

if(reg == 0)

VAR_INPUT[0] = 8;

VAR_INPUT[1] = RXData / 256;

RXData -= VAR_INPUT[1] * 256;

VAR_INPUT[2] = RXData;

}

 

#pragma vector = USCIAB0TX_VECTOR

__interrupt void USCIAB0TX_ISR(void)

{

//VAR_INPUT[0] = 0x11;

//VAR_INPUT[1] = 0x22;

//VAR_INPUT[2] = 0x33;

//VAR_INPUT[3] = 0x44;

while((IFG2 & UCB0TXIFG) == 0);

UCB0TXBUF = VAR_INPUT[i];

i++;

}

 

#pragma vector = USCIAB0RX_VECTOR// Received start bit

__interrupt void USCIAB0RX_ISR(void)

{

//UCB0TXBUF = 0x44;

//__delay_cycles(1000);

if(UCB0CTL1 & UCTR) //data requested

{

// if(UCB0STAT & UCSTTIFG)

// {

//getadc();  //<- ideally I would like this here

// }

i = 0;

bytectr = 0;

UCB0STAT &= ~(UCSTPIFG + UCSTTIFG);       // Clear interrupt flags

if (bytectr != 0)                            // Check TX byte counter

__bic_SR_register_on_exit(CPUOFF);      // Exit LPM0 if data was 

}

else

{

  reg = UCB0RXBUF;

UCB0STAT &= ~UCSTPIFG; // Clear start condition int flag

  if(reg == 8)

  reg = 0; //use 0 internally

  bytectr = 3;

  getadc();

  __bic_SR_register_on_exit(CPUOFF);        // Exit LPM0

  //  TXData++;                                 // Increment data

}

}

void getadc()

{

ADC10CTL0 &= ~ENC; // Disable ADC

ADC10CTL1 = (reg *0x1000u) + ADC10DIV_3;        // Temp Sensor ADC10CLK/4

ADC10CTL0 = ADC10ON | ADC10SHT_0 | SREF_0;                                                        // reference generator ON/ADC10 ON

ADC10CTL0 |= ENC + ADC10SC;                     // Sampling and conversion start

while ( ADC10CTL1 & ADC10BUSY );                // Wait for ADC to complete

RXData = ADC10MEM;

inttoarray();

}

Here is what the master sends:

START (transmit)

REGISTER_BYTE

STOP

START (receive)

(I would ideally like to call getadc() here)

RECIEVED_BYTE_1

RECIEVED_BYTE_2

RECIEVED_BYTE_3

STOP

 

The code works fine with a MSP430 as the master(unless my master has issues as well) but not with the Pi. The Pi appears to send the register byte correctly but it seems to cut off the first bit of the first byte of RECIEVED_BYTE_1 with the rest of the transmission being lost. I noticed that when I comment out getadc(), the pi will receive any bytes I send it. I'm new to i2c and find this very confusing. Any help would be really appreciated.

 

  • It is possible that the PI does not support clock stretching. The USCI will hold the clock line low if the software doesn't read the RXBUF register in time or didn'T stuff somehting to TXBUF. If teh MSP is the master, it detects this and waits for the slave. But if the PI doesn't, communication will be hosed.

  • I figured it out, it turns out that the default calibration settings were too slow. So, I added this:

      BCSCTL1 = CALBC1_16MHZ;                   

      DCOCTL = CALDCO_16MHZ;

    I'm not sure why this isn't the default. Anyways thanks for your reply.

  • 16 MHz clock can't be default because it is no supported at low supply voltages. It also means that after start-up it's wise idea to put some delay before setting DCO to high frequency - hopefully supply reached it's nominal voltage. Remember that output of every supply starts from 0V and it usually is not "instantly on".

  • Ilmars said:
    16 MHz clock can't be default because it is no supported at low supply voltages.

    Also, 16MHz (or 25, which is the maximum on some MSPs) would mean maximum power consumption. Which isn't a suitable default for a low-power device.

  • Sorry to reply to a 2 year old post. Hope someone is still watching :-)

    I'm using Energia to program my MSP430, I have seen other places where I can set magic variables like these in the setup() function, so that is what I tried and the compiler didn't complain but it also doesn't seem to make any difference.  Do I need an external crystal for this clock speed to work?

    With or without these magic variables, the MSP430 slave is visible at the correct I2C address when I run "sudo i2cdetect -y 1" on the raspberry pi.I can see the MSP430 startup messages on the serial monitor so I know it is running. I have checked and rechecked the connections. I've tried both with and without external pullup resistors. I am using the Wire library and I have tried both an onReceive() function and also just looking for Wire.available() > 0 in my main loop. No matter what I have tried, I don't receive any data from the raspberry pi as an I2C master.

  • >but it also doesn't seem to make any difference
    Then verify that CPU clock speed is changed indeed - by using something like LED flashing code with __delay_cycles() loop.

    >Do I need an external crystal for this clock speed to work?
    No. When/if you read datasheet of msp430g2553 - you will be surprised how far from reaching 16MHz with external resonator you are.

    > No matter what I have tried, I don't receive any data from the raspberry pi as an I2C master.
    It could be very, very long way to go if you just try everything while it works. Better use some step by step approach of finding what's wrong with your i2c communications. Use debugger to see where's your problem. Scope would help alot too.

**Attention** This is a public forum