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.
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".
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.Ilmars said:16 MHz clock can't be default because it is no supported at low supply voltages.
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.
**Attention** This is a public forum