Needing high level advice please. Been playing with alternatives for 2 days now... basically my ISR Port1 is acknowledging the Interrupt on P1.1 but the darn thing remains asleep (it seems).
My goal is to read the 9150 Gyros at set time intervals for an accurate calculation of angle and let the 9250 interrupt line drive the ship (plenty of time to do everything else in between, removed for now but still no luck).
I used the MSP430 ISR to set a flag (assuming it wakes up), then immediately read the sensor data which should clear the interrupt (as configured with the motion sensor). I have no trouble reading (verified) or writing for sensor data. Just need the 9250 to wake then do a read.
No expert here, so thanks in advance for any thoughts to try!
CC430F513x <-> Invensense 9250
P1.1 <-> INT
P1.2 <-> CLK (10K to Vcc)
P1.3 <-> SDA (10K to Vcc)
int main( void ) {
WDTCTL = WDTPW + WDTHOLD; // Stop watchdog timer to prevent time out
HAL::SetVCore(2);
accel->configAccelerometer(); // Configure Port Maps
msp430_i2c_write (MPU9250_ADDRESS, PWR_MGMT_1, 1, &InitCMP0); // 00 6B Wake up!
__delay_cycles(100);
msp430_i2c_write (MPU9250_ADDRESS, PWR_MGMT_1, 1, &InitCMP1); // 01 Stable PLL Clock Source
__delay_cycles(200);
msp430_i2c_write (MPU9250_ADDRESS, CONFIG, 1, &InitCMP3); // 03 DLPF_CFG = bits 2:0 = 011; 1K Hz internally
msp430_i2c_write (MPU9250_ADDRESS, GYRO_CONFIG, 1, &InitCMP3); // 03 Set accelerometer rate to 1 kHz and bandwidth to 41 Hz
msp430_i2c_write (MPU9250_ADDRESS, SMPLRT_DIV, 1, &InitCMP3); // 0x07 is very slow sampling for now
msp430_i2c_write (MPU9250_ADDRESS, INT_PIN_CFG, 1, &InitCMP30); // 10 INT_Status is cleared on any read of the device
// Also tried 0x00 requiring Int_Status read, and 70 w/o pullup, no luck…
msp430_i2c_write (MPU9250_ADDRESS, INT_ENABLE, 1, &InitCMP11); // 11 Raw Ready Enable and FIFO to Interrupt (just to force the INT line to fire)
msp430_i2c_read (MPU9250_ADDRESS, INT_STATUS, 1, &IntStatus); // clears Interrupt, actually any read does depending on settings... tried them all.
ReadMotion (); // Read Accelerometers and Gyros
while (true) {
P1IFG &= ~0x01; // P1.1 IFG cleared
P1IE |= BIT1; // P1.1 interrupt enabled
__bis_SR_register(LPM0_bits + GIE); // LPM4 stops all clocks, saves 300uA during deep sleep
if (IntFlag == 1){
ReadMotion (); // Read Accelerometers and Gyros ******************* This never gets executed, in fact no lines are executed past the LPM0 line above no matter what I put there. *****************
IntFlag = 0;
}
}
}
// Port 1 Interrupt
#pragma vector=PORT1_VECTOR
__interrupt void Port_1(void) {
switch(__even_in_range(P1IV, 0x06)){
case 0x00: break; // pin 0
case 0x02: P1IFG &= ~0x01; // P1-Pin 1 // ********************** This executes, but constantly, but no code follow-through in main... so it appears ;)
break;
case 0x04: break; // pin 2
case 0x06: break; // pin 3
default: break;
}}
// This USCI works fine... can read/write 9250, verified.
#pragma vector = USCI_B0_VECTOR
__interrupt void USCI_B0_ISR(void)
{
switch(__even_in_range(UCB0IV,12)) {
case 4: /* NAK interrupt. */
i2c.state = STATE_WAITING;
UCB0CTL1 |= UCTXSTP;
NoAck = 4;
break;
case 10: /* RX interrupt. */
NoAck = 0;
UCB0IFG &= ~UCRXIFG;
if (–i2c.length) {
/* If only one byte left, prepare stop signal. */
if (i2c.length == 1)
UCB0CTL1 |= UCTXSTP;
} else
i2c.state = STATE_WAITING;
/* Read RXBUF last because we don’t want to release SCL until we’re
* sure we’re ready.
*/
*i2c.data++ = UCB0RXBUF;
break;
case 12: /* TX interrupt. */
UCB0IFG &= ~UCTXIFG;
switch (i2c.state) {
case STATE_WRITING:
if (!i2c.slave_reg_written) {
i2c.slave_reg_written = 1;
UCB0TXBUF = i2c.slave_reg;
} else if (i2c.length) {
/* Send next byte, increment pointer. */
char next = i2c.data[0];
i2c.data++;
i2c.length–;
/* Writing to TXBUF must always be the final operation. */
UCB0TXBUF = next;
} else {
i2c.state = STATE_WAITING;
UCB0CTL1 |= UCTXSTP;
//UCB0IFG &= ~UCTXIFG; // clear after all done
}
break;
case STATE_READING:
if (!i2c.slave_reg_written) {
i2c.slave_reg_written = 1;
UCB0TXBUF = i2c.slave_reg;
} else {
/* Repeated start, switch to RX mode. */
UCB0CTL1 &= ~UCTR;
UCB0CTL1 |= UCTXSTT;
/* If single byte, prepare stop signal immediately. */
if (i2c.length == 1) {
/* Well, not IMMEDIATELY. First we need to make sure
* the start signal got sent.
*/
while (UCB0CTL1 & UCTXSTT);
UCB0CTL1 |= UCTXSTP;
}
}
break;
case STATE_WAITING:
default:
break;
}
break;
case 0: /* No interrupt. */
case 2: /* Arbitration lost interrupt. */
case 6: /* Start condition interrupt. */
case 8: /* Stop condition interrupt. */
default:
break;
}
__bic_SR_register_on_exit(LPM0_bits); // maybe I'm putting it back to sleep here? Again?
}
void Accelerometer::configAccelerometer( void )
{
// Disable all interrupts
PMAPPWD = 0x02D52; // Get write-access to port mapping regs
P2SEL |= 0x01; // Enable A/D channel A0
/* Initialize ADC12_A */
ADC12CTL0 = ADC12ON+ADC12SHT0_8+ADC12MSC; // Turn on ADC12, set sampling time
// Need this to be 12 bits for accuracy
ADC12CTL2 &= ~0x30; // Clear out only bits 4 and 5
ADC12CTL2 |= 0x20; // Set only bit 5 (put in 12-bit mode)
ADC12CTL1 = ADC12SHP+ADC12CONSEQ_0; // Use sampling timer, Single Channel converted once
ADC12CTL0 |= ADC12ENC; // Enable conversions ENC = 1
// 9250 Interrupt on Port 1.1 input
P1DIR &= ~BIT1; // for the motion interrupt on P1.1 input to CPU
P1IES &= ~BIT1; // P1.1 Lo/Hi edge
P1IFG &= ~BIT1; // P1.1 IFG cleared
// 9250 Data and Clock to I2C
P1MAP3 = PM_UCB0SDA; // Map UCB0SDA to P1.3
P1MAP2 = PM_UCB0SCL; // Map UCB0SCL to P1.2
P1SEL |= BIT2 + BIT3; // Select P1.2 & P1.3 to I2C function
UCB0CTL1 |= UCSWRST; // Enable SW reset
UCB0CTL0 = UCMST + UCMODE_3 + UCSYNC; // I2C Master, synchronous mode
UCB0CTL1 = UCSSEL_2 + UCSWRST; // Use SMCLK, keep SW reset
UCB0BR0 = 12; // fSCL = SMCLK/12 = ~100kHz
UCB0BR1 = 0;
UCB0CTL1 &= ~UCSWRST; // Clear SW reset, resume operation
UCB0IE |= UCTXIE + UCRXIE + UCNACKIE; // Enable TX/RX interrupt, monitor for NACK (No Acknowledge)
PMAPPWD = 0; // Lock port mapping registers
return;
}