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.

MSP430G2102: CCS/MSP430G2102 controller as a slave device transmit and receive data form the master device on wake up from the lpm4 mode. Problem is that after getting the USISRL data 0xAA i can disable the pin, but that pin is constantly remain high inste

Part Number: MSP430G2102
Other Parts Discussed in Thread: CC1310,

Hi,

Here i am using MSP430G2102 microcontroller as a slave device and CC1310 TI chip as a master device.

TI chip is wake based on gpio high/low. Here we have used LPM4 mode.

Device gets wake up on getting interrupt of any key press (P1.1, P1.2 P1.3,P1.4,P1.5).and device than transmit the data of key press to the master device.

Master device send the NACK on receiving the key press data and master than send the data 0xAA to the msp430 slave device. Once the MSP430 slave device receives the 0xAA it disables the gpio(Port Pin P1.0) which cuts the power of master TI CC1310 chip.

But here the problem i am facing in else part of switch case 10 is that though in debug mode msp430 device received the 0xAA but than also the pin P1.0 is sometimes getting high and remain permanent high  instead of low by this statement (P1OUT &= ~BIT1). 

here please find the i2c slave transmit receive code for your reference, and please inform me for the below query.

1) In switch case 10 else part though the msp430 device getting 0xAA but the  line  (P1OUT &= ~BIT1) do not make pin low permanently but sometimes it remain high permanently . can u please let me know why this happen? and what is the problem in my code.

2) is i am handling the low power mode 4 correctly in my attached code?

3) Provide me the solution so that everytime while getting 0xAA my gpio pin P1.0 get disable which is right now remain most of time high. 

4) Is my I2c routine in code okay?

Code:


#include <msp430.h>

char flag=0;
char Slave_Tx = 1;
char SLV_Data = 0; // Variable for transmitted data
char SLV_Addr = 0x90; // Address is 0x48<<1 for R/W
int I2C_State = 0; // State variable
int i=0;


void i2c_init(void)
{
USICTL0 = USIPE6 + USIPE7 + USISWRST; // Port & USI mode setup
USICTL1 = USII2C + USIIE + USISTTIE; // Enable I2C mode & USI interrupts
USICKCTL = USICKPL; // Setup clock polarity
USICNT |= USIIFGCC; // Disable automatic clear control
USICTL0 &= ~USISWRST; // Enable USI
USICTL1 &= ~USIIFG; // Clear pending flag
__enable_interrupt();
}

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

if (CALBC1_1MHZ == 0xFF) // If calibration constants erased
{
while (1); // do not load, trap CPU!!
}

DCOCTL = 0; // Select lowest DCOx and MODx settings*/
BCSCTL1 = CALBC1_1MHZ; // Set DCO
DCOCTL = CALDCO_1MHZ;

P1DIR |= (BIT7 + BIT6 + BIT0); // Set P1.0 to output direction
P1DIR &= ~(BIT1 + BIT2 + BIT3 + BIT4 + BIT5);
P1OUT |= (BIT7 + BIT6);
P1OUT &= ~BIT0;

P1IES |= (BIT1 + BIT2 + BIT3 + BIT4 + BIT5); // P1.1 Hi/lo edge
P1IFG &= ~(BIT1 + BIT2 + BIT3 + BIT4 + BIT5); // IFG cleared
P1IE |= (BIT1 + BIT2 + BIT3 + BIT4 + BIT5); // interrupt enabled

i2c_init();

while(1)
{
if(flag==1)
{
P1OUT |= BIT0;
}
else
{
P1DIR |= BIT0;
P1OUT &= ~BIT0;
__bis_SR_register(LPM4_bits + GIE);
}

 }
}

//******************************************************
// USI interrupt service routine
//******************************************************
#if defined(__TI_COMPILER_VERSION__) || defined(__IAR_SYSTEMS_ICC__)
#pragma vector = USI_VECTOR
__interrupt void USI_TXRX(void)
#elif defined(__GNUC__)
void __attribute__ ((interrupt(USI_VECTOR))) USI_TXRX (void)
#else
#error Compiler not supported!
#endif
{
if (USICTL1 & USISTTIFG) // Start entry?
{
I2C_State = 2; // Enter 1st state on start
}

switch (I2C_State)
{
case 0: //Idle, should not get here
break;

case 2: //RX Addres
USICNT = (USICNT & 0xE0) + 0x08; // Bit counter = 8, RX Address
USICTL1 &= ~USISTTIFG; // Clear start flag
I2C_State = 4; // Go to next state: check address
break;

case 4: // Process Address and send (N)Ack
if (USISRL & 0x01) // If read...
SLV_Addr++; // Save R/W bit
USICTL0 |= USIOE; // SDA = output
if (USISRL == SLV_Addr) // Address match?
{
USISRL = 0x00; // Send Ack
I2C_State = 8; // Go to next state: TX data
}
else
{
USISRL = 0xFF; // Send NAck
I2C_State = 6; // Go to next state: prep for next Start
flag=0;
}
USICNT |= 0x01; // Bit counter = 1, send (N)Ack bit
break;

case 6: // Prep for Start condition
USICTL0 &= ~USIOE; // SDA = input
SLV_Addr = 0x90; // Reset slave address
I2C_State = 0; // Reset state machine
break;

case 8: // Send Data byte
if (Slave_Tx)
{
USICTL0 |= USIOE; // SDA = output
USISRL = SLV_Data; // Send data byte
}
else
{
USICTL0 &= ~USIOE; // SDA = input
}
USICNT |= 0x08; // Bit counter = 8, RX data
I2C_State = 10; // Go to next state: Test data and (N)Ack
break;

case 10: // Receive Data (N)Ack
if (Slave_Tx)
{
USICTL0 &= ~USIOE; // SDA = input
USICNT |= 0x01; // Bit counter = 1, receive (N)Ack
I2C_State = 12; // Go to next state: check (N)Ack
}
else
{
// Check Data & TX (N)Ack
USICTL0 |= USIOE; // SDA = output

if (USISRL == 0xAA) // If data valid...
{
USISRL = 0x00; // Send Ack
Slave_Tx = 1;
flag=0;
}
else
{
USISRL = 0xFF; // Send NAck
}
USICNT |= 0x01; // Bit counter = 1, send (N)Ack bit
I2C_State = 6; // Go to next state: prep for next Start
}
break;

case 12: // Process Data Ack/NAck
if (USISRL & 0x01) // If Nack received...
{
Slave_Tx = 0;
}

// Prep for Start condition
USICTL0 &= ~USIOE; // SDA = input
SLV_Addr = 0x90; // Reset slave address
I2C_State = 0; // Reset state machine
break;
}

USICTL1 &= ~USIIFG; // Clear pending flags
}

// Port 1 interrupt service routine
#if defined(__TI_COMPILER_VERSION__) || defined(__IAR_SYSTEMS_ICC__)
#pragma vector=PORT1_VECTOR
__interrupt void Port_1(void)
#elif defined(__GNUC__)
void __attribute__ ((interrupt(PORT1_VECTOR))) Port_1 (void)
#else
#error Compiler not supported!
#endif
{
if (P1IFG & BIT1)
{
SLV_Data = 1;
P1IFG &= ~BIT1; // P1.1 IFG cleared
}

if (P1IFG & BIT2)
{
SLV_Data = 2;
P1IFG &= ~BIT2; // P1.2 IFG cleared
}

if (P1IFG & BIT3)
{
SLV_Data = 3;
P1IFG &= ~BIT3; // Reset Port1 interrupt flag
}

if (P1IFG & BIT4)
{
SLV_Data = 4; // Save the state of the switch 4
P1IFG &= ~BIT4; // P1.4 IFG cleared
}

if (P1IFG & BIT5)
{
SLV_Data = 5; // Save the state of the switch 5
P1IFG &= ~BIT5; // P1.5 IFG cleared
}

flag=1;
__bic_SR_register_on_exit(LPM4_bits);

}

Waiting fo your reply.

Thanks 

  • Hello,

    I wasn't able to review the I2C code, but what is P1.1 connected to?  Also, it looks like P1.1 is configured as an input, is this correct.  If it's an input, you can't force the pin low by clearing the OUT register because it's being driven by something externally. 

    Thanks,

    JD

  • Hi,

    Here P1.1 is a switch and P1.0 is the LDO pin used to on or off the supply of TI pin. It is bymistake written wrong statment (ie. P1OUT &= ~BIT1)only in above thread  instead of P1OUT &= ~BIT0. But in the i2c code attached it is correct only P1OUT &= ~BIT0. So here P1.0 i have configured as a output direction and it is not going low on giving P1OUT &= ~BIT0 statement randomly in release mode. Can u please let me know why uch behaviour occurs did i am doing any mistake

  • After you receive the 0xAA, you set flag=0 but I don't see where you wake up main to look at the flag. This looks like the kind of race that could produce the symptom you describe. 

    Unsolicited: "flag" should be declared "volatile". If you haven't run into this yet, you will eventually.

  • Hi,

    MSP430 device will be wake up every time on getting the interrupt of PORT 1 ISR routine where the flag becomes 1 and command " __bic_SR_register_on_exit(LPM4_bits);"use which will make the msp430 device to exit from the LPM4 mode. 

    I will test my code by declaring the flag as a volatile and give u the update as per your suggestion.

    But in the meanwhile time can u check and please let me know is there any other thing to be take care in my code rather than flag.

    Because as i have take the msp430 slave code form the library examples itself but some times i am getting the address ack issue sometimes the finally 0xAA not getting, some random behaviour is occuring so. sometimes working fine also. So what small thing  is missing in my attached code to take care so that code will work every time fine.

    Thanks for your kind reply

  • This code does a wakeup when it sets flag=1, but I don't see anything which does a wakeup when it sets flag=0. I suggest you add something like:

    > __bic_SR_register_on_exit(LPM4_bits);

    after you set flag=0.