_Murphy_ 6 Posted January 15, 2013 Share Posted January 15, 2013 Over the past week I have been attempting to get my MSP430g2553 to act as the master and talk to an MPU-6050 which is the slave. I have so far only been able to get it to receive an ACK to the slave, and the code indicates that it is present and listening. My attempts at writing and reading from the slave have produced no results. Does anyone have any advice or recommendations on how to proceed with this? Quote Link to post Share on other sites
mbeals 74 Posted January 15, 2013 Share Posted January 15, 2013 It would help if you could post some code to look at. Quote Link to post Share on other sites
_Murphy_ 6 Posted January 15, 2013 Author Share Posted January 15, 2013 Ok. This is the code I have so far. I currently can verify that it is working up to the if statement that checks if the slave is present. I also have included an attachment of the Read sequence that is in the data sheet. All comments are welcome. #include "msp430g2553.h" #include "TI_USCI_I2C_master.h" #define MPU6050_I2C_ADDRESS 0x68 // Confirmed correct address + communication #define prescale 0x14 // 400kHz #define MPU6050_PWR_MGMT_1 0x6B // Power management register: write 0x00 to wake the device #define MPU6050_ACCEL_XOUT_H 0x3B // Read #define MPU6050_ACCEL_YOUT_H 0x3D // Read #define MPU6050_ACCEL_YOUT_L 0x3E // Read #define MPU6050_ACCEL_ZOUT_H 0x3F // Read #define MPU6050_ACCEL_ZOUT_L 0x40 // Read #define MPU6050_TEMP_OUT_H 0x41 // Read #define MPU6050_TEMP_OUT_L 0x42 // Read #define MPU6050_GYRO_XOUT_H 0x43 // Read #define MPU6050_GYRO_XOUT_L 0x44 // Read #define MPU6050_GYRO_YOUT_H 0x45 // Read #define MPU6050_GYRO_YOUT_L 0x46 // Read #define MPU6050_GYRO_ZOUT_H 0x47 // Read #define MPU6050_GYRO_ZOUT_L 0x48 // Read #define MPU6050_AD_R 0xD1 #define MPU6050_AD_W 0xD0 unsigned char timercounter; unsigned char array[20] = { MPU6050_PWR_MGMT_1, 0x0}; unsigned char array2[20] = { MPU6050_AD_W, MPU6050_GYRO_XOUT_L}; unsigned char store[40] = { 0}; void main(void) { WDTCTL = WDTPW + WDTHOLD; // Stop watchdog timer. This line of code is needed at the beginning of most MSP430 projects. // This line of code turns off the watchdog timer, which can reset the device after a certain period of time. BCSCTL1 = CALBC1_8MHZ; // Set clock calibration to 8 MHz DCOCTL = CALDCO_8MHZ; // Internal oscillator to 8 MHz _EINT(); /* initialization of the I2C with the slave */ TI_USCI_I2C_transmitinit(MPU6050_I2C_ADDRESS,prescale); // init transmitting with USCI while ( TI_USCI_I2C_notready() ); // wait for bus to be free if ( TI_USCI_I2C_slave_present(MPU6050_I2C_ADDRESS) ) // Allow communication if slave was present at address { TI_USCI_I2C_transmitinit(MPU6050_I2C_ADDRESS,prescale); // Start initialization of the transmission using slave address and frequency using USCI while ( TI_USCI_I2C_notready() ); // wait for bus to be free TI_USCI_I2C_transmit(4,array); // start transmitting while ( TI_USCI_I2C_notready() ); // wait for bus to be free between each different connection TI_USCI_I2C_transmitinit(MPU6050_I2C_ADDRESS,prescale); // Start initialization of the transmission using slave address and frequency using USCI while ( TI_USCI_I2C_notready() ); // wait for bus to be free TI_USCI_I2C_transmit(4,array2); // start transmitting while ( TI_USCI_I2C_notready() ); // wait for bus to be free between each different connection TI_USCI_I2C_receiveinit(MPU6050_I2C_ADDRESS,prescale); // Start initialization of the receiving using slave address and frequency using USCI while ( TI_USCI_I2C_notready() ); // wait for bus to be free TI_USCI_I2C_receive(2,store); } LPM3; } Quote Link to post Share on other sites
ucfknight 1 Posted January 21, 2013 Share Posted January 21, 2013 Hi Murphy! I've been trying to do the exact same thing for the past week with little progress. I Tried using the library provided by TI, but I never got it to read anything from the MPU. I took it upon myself to write the interrupt routines myself and so far I get a response, but sometimes it appears to be valid data, then others garbage. Here is the code I wrote. Can anyone spot where the error is? or have a working library to interface these two devices? #include <msp430g2553.h> // General Boolean /////////////// #define False 0 #define True 1 /////////////////////////////////// // I2C MPU definitions //////// #define MPU_A 0x68 // MPU 6050 Slave Address #define PWR_MGMT_1 0x6B // Power Management 1 Register Address #define SMPLRT_DIV 0x19 // Sample Rate Divider Register Address #define CONFIG 0x1A // Configuration Register Addres #define GYRO_CONFIG 0x1B // Gyroscope Configuration Register Address #define ACCEL_CONFIG 0x1C // Accelerometer Configuration Register Address #define INT_ENABLE 0x38 // Interrupt Enable Register Address #define INT_PIN_CFG 0x37 // Interrupt Pin Configuration Register Address //////////////////////////////// // UART definitions ////////////////////// #define TXBUF UCA0TXBUF // UART Transfer Buffer #define RXBUF UCA0RXBUF // UART Receive Buffer /////////////////////////////////////////// // Function Prototypes // I2C void InitializeI2c(void); void InitializeMpu(void); void InitializeInt(void); void WriteI2c(char MpuReg, char Data); void ReadI2c(char MpuReg, char *Field, char ByteCnt); ////////////////////////////////////////////////////// // UART void SendUart(char *Data); void InitializeUart(void); ////////////////////////// // ASCii void ConvertAscii(char* String); //////////////////////////////// // Global Variables // I2C char I2c_Tx; char AddSent; char Register; char ByteSent; char RepStart; char ReadWriteN; char *I2c_Rx_Field; signed char I2cByteCnt; /////////////////////// // UART char *UartTxStr; char RxBuffer[14]; char UartRxFlag = False; char *UartRxStr = RxBuffer; /////////////////////////// // ASCii char AsciiStr[12]; ////////////////// /* * main.c */ void main(void) { //char Accel_T_Gyro[14]; char RX[14]; char Interrupt; WDTCTL = WDTPW + WDTHOLD; //DCOCTL = CALDCO_8MHZ; //BCSCTL1 = CALBC1_8MHZ; InitializeInt(); //InitializeUart(); InitializeI2c(); InitializeMpu(); for(;{ LPM0; ReadI2c(0x3A,&Interrupt,1); if(Interrupt == 0x01) ReadI2c(0x42,RX,14); //LPM0; } } ////////////////////////////////////////// // InitializeInt Enables P1.3 Interrupt / // - Hi/Lo Edge Trigger / ////////////////////////////////////////// void InitializeInt(void) { P1IE |= BIT3; // P1.5 interrupt enabled P1IES |= BIT3; // P1.5 Hi/lo edge P1IFG &= ~BIT3; } ////////////////////////////////////////////////////////// // InitializeI2c sets up UCB0 module for I2C operations / // - P1.6 = SCL / // - P1.7 = SDA / // - Transfer Rate = 100kHz / ////////////////////////////////////////////////////////// void InitializeI2c(void) { P1SEL |= BIT6 + BIT7; // p1.6 SCL p1.7 SDA P1SEL2 |= BIT6 + BIT7; UCB0CTL1 |= UCSWRST; // ensure SWRST high before configuration UCB0CTL0 = UCMST + UCMODE_3 + UCSYNC; // Master, I^2C, Synchronous UCB0CTL1 = UCSSEL_2 + UCSWRST; // SMCLK, keep SWRST high UCB0BR0 = 12; UCB0BR1 = 0; UCB0I2CSA = MPU_A; UCB0CTL1 &= ~UCSWRST; UCB0I2CIE = UCNACKIE; IFG2 &= ~(UCB0TXIFG + UCB0RXIFG); IE2 |= UCB0TXIE + UCB0RXIE; } ////////////////////////////////////////////////////// // InitializeMpu sets up the MPU-6050 for Operation / // - Resets Device / // - Sample Rate = 10 / // - Accell Full Range / // - Gyro Full Range / // - Data Ready Int Enable / ////////////////////////////////////////////////////// void InitializeMpu(void) { WriteI2c(PWR_MGMT_1, 0x80); // Reset MPU __enable_interrupt(); // Wait for MPU to Reset TACCR0 = 2000; TACCTL0 |= CCIE; TA0CTL = TASSEL_2 + MC_1; // SMCLK, up mode LPM0; // Enter low power mode TACCTL0 &= ~CCIE; __disable_interrupt(); // Done with Reset WriteI2c(PWR_MGMT_1, 0x00); //WriteI2c(INT_PIN_CFG,0x80); WriteI2c(SMPLRT_DIV, 99); // Sample Rate Divider = 50 //WriteI2c(CONFIG, 0x06); WriteI2c(GYRO_CONFIG, 0x18); // Gyro Full Range WriteI2c(ACCEL_CONFIG, 0x18); // Accel Full Range WriteI2c(INT_ENABLE, 0x01); // Enable Data Ready Interrupt } /////////////////////////////////////////////////////////////////////////// // WriteI2c Writes a single Byte to the Internal Register Address MpuReg / // / // Parameters: / // - MpuReg = Internal Register Address / // - Data = Byte to be written to MpuReg / /////////////////////////////////////////////////////////////////////////// void WriteI2c(char MpuReg, char Data) { // Reset variables prior to Start of Transmission AddSent = False; ReadWriteN = False; ByteSent = False; I2c_Tx = Data; // Load Byte to be written to MPU Register = MpuReg; // Load Internal Register Address UCB0CTL1 |= UCTR + UCTXSTT; // send I2C start condition __bis_SR_register(CPUOFF + GIE); } //////////////////////////////////////////////////////////////////////////////////////////////////////// // Read I2c Reads a user specified number of Bytes and stores them in the String pointed to by *Field / // / // Parameters: / // - MpuReg = Internal Register Address to be Read / // - *Field = Pointer to Storage String / // - ByteCnt = Number of Bytes to be Read / //////////////////////////////////////////////////////////////////////////////////////////////////////// void ReadI2c(char MpuReg, char *Field, char ByteCnt) { // Reset variables prior to Start of Transmission RepStart = False; AddSent = False; ReadWriteN = True; I2cByteCnt = ByteCnt; // Load number of byte to be read to Global variable I2c_Rx_Field = Field; // Copy pointer for String to be Read Register = MpuReg; // Load Internal Register Address UCB0CTL1 |= UCTR + UCTXSTT; // send I2C start condition __bis_SR_register(CPUOFF + GIE); } /////////////////////////////////////////////////////////////// // InitializeUart sets up the UCA0 module for UART operation / // - P1.1 = RX / // - P1.2 = TX / // - SMLCK source / // - 9600 Baud / /////////////////////////////////////////////////////////////// void InitializeUart(void) { // UART SET UP P1.2 UCA0TXD P1.1 UCA0RXD P1SEL = BIT1 + BIT2; P1SEL2 = BIT1 + BIT2; UCA0CTL1 |= UCSSEL_2; // select SMCLK as source UCA0BR0 = 104; // 1MHz/9600 ~ 104.16667 UCA0BR1 = 0; UCA0MCTL = UCBRS0; // second stage modulation= 1 round((N-int(N))*8) UCA0CTL1 &= ~UCSWRST; IE2 |= UCA0RXIE; } /////////////////////////////////////////////////////////////// // SendUart sends a Null terminated String over the UART bus / // / // Parameters: / // - *Data = Pointer to the Start of String to be sent / /////////////////////////////////////////////////////////////// void SendUart(char *Data) { UartTxStr = Data; TXBUF = *UartTxStr++; IE2 |= UCA0TXIE; __bis_SR_register(CPUOFF + GIE); } ////////////////////////////////////////////////////////////////////////////////////////////////////////////// // ConverAscii Converts a Null terminated string of Hex Values and outputs a string of its Ascii equivalent / // / // Parameters: / // - *String = Pointer to beginning of String to be converted / ////////////////////////////////////////////////////////////////////////////////////////////////////////////// void ConvertAscii(char* String) { char* Str = String; char Binary; char Ascii; char i = 0; while(*Str != '\0'){ Str++; i++; } Str = String; char Length = i; for(i = 0;i < Length;i++) { Binary = *Str; Binary &= 0xF0; Binary = Binary>>4; if(Binary < 10) Ascii = Binary + 0x30; else Ascii = Binary + 0x37; AsciiStr[i++] = Ascii; Binary = *Str++; Binary &= 0x0F; if(Binary < 10) Ascii = Binary + 0x30; else Ascii = Binary + 0x37; AsciiStr[i] = Ascii; } AsciiStr[i++] = 0x20; AsciiStr[i] = '\0'; } ///////////////////////////////////////////////// // / // ISR / ///////////////////////////////////////////////// // USCIAB0RX Interrupt Service Routine #pragma vector = USCIAB0RX_VECTOR __interrupt void USCIAB0RX_ISR(void) { if (UCB0STAT & UCNACKIFG) { // send STOP if slave sends NACK UCB0CTL1 |= UCTXSTP; UCB0STAT &= ~UCNACKIFG; } else { *UartRxStr = RXBUF; if(*UartRxStr == '\0') { UartRxStr = RxBuffer; UartRxFlag = True; } else UartRxStr++; } } // USCIAB0TX Interrupt Service Routine #pragma vector = USCIAB0TX_VECTOR __interrupt void USCIAB0TX_ISR(void){ static unsigned char Index = 0; // Check Interrupt Source // If UCA0TXIE then UART Mode if(IE2 & UCA0TXIE) { if(*UartTxStr == '\0') { IE2 &= ~UCA0TXIE; __bic_SR_register_on_exit(CPUOFF); } else TXBUF = *UartTxStr++; } // Else I2C Mode else{ // If ReadWriteN = True // Read Operation if (ReadWriteN) { // Check if Internal Register Address and Repeated Start have been sent // If True Start to Read UCB0RXBUF if(RepStart == True && AddSent == True) { // If Index is not equal to last byte to read // Keep reading if(Index != I2cByteCnt-1) { *I2c_Rx_Field++ = UCB0RXBUF; Index++; } // Else Read Last byte and send stop condition else { *I2c_Rx_Field = UCB0RXBUF; UCB0CTL1 |= UCTXSTP; // send stop condition while(UCB0CTL1 & UCTXSTP); IFG2 &= ~UCB0RXIFG; Index = 0; __bic_SR_register_on_exit(CPUOFF); } } // Send the Register address Followed by the Repeated Start else { // If Register Address has not been sent. Send Register Address if(AddSent == False) { UCB0TXBUF = Register; AddSent = True; } // If Register Address have been sent. Send Repeated Start. else { IFG2 &= ~UCB0TXIFG; UCB0CTL1 &= ~UCTR; UCB0CTL1 |= UCTXSTT; RepStart = True; } } } // If ReadWriteN = False // Write Operation else { // Check if Register Address has been sent // If True Start Writing to UCB0TXBUF if(AddSent == True) { // Check if Data has been Written to UCB0TXBUF // If True the send STOP condition if(ByteSent == True) { UCB0CTL1 |= UCTXSTP; // send stop condition IFG2 &= ~UCB0TXIFG; // clear Tx flag __bic_SR_register_on_exit(CPUOFF); } // Else Write Data to UCB0TXBUF else { UCB0TXBUF = I2c_Tx; ByteSent = True; } } // If Register Address has not been sent. Send it else { UCB0TXBUF = Register; AddSent = True; } } } } // Timer A0 Interrupt Service Routine #pragma vector = TIMER0_A0_VECTOR __interrupt void TIMER_A0(void){ LPM0_EXIT; } // Port 1 Interrupt Service Routine #pragma vector=PORT1_VECTOR __interrupt void Port_1(void){ LPM0_EXIT; P1IFG &= ~BIT3; //P1IE &= ~BIT3; } Quote Link to post Share on other sites
_Murphy_ 6 Posted January 22, 2013 Author Share Posted January 22, 2013 The I2C code I have has been re-written and it may function correctly now. Once I complete testing on it I will know for sure. If I can verify my code to be working I will post it on this topic. Coli 1 Quote Link to post Share on other sites
Phaelz 0 Posted February 2, 2013 Share Posted February 2, 2013 Have you managed to get it working? I used the same library of you two and I'm getting confused because sometimes it works, sometimes not... Quote Link to post Share on other sites
ucfknight 1 Posted February 3, 2013 Share Posted February 3, 2013 Hello Phaelz, I managed to get it working with the msp430, and recently with the Stellaris (much easier thanks the driverlib). Anyways, if you post your email I will send you my msp430 code which used the grace plug in. Also, as a general note I've found that the debug circuit doesn't do well with any type of external communication. My suggestion is just use either the run to line command, or the reset button itself. (don't step through) arvinasokan 1 Quote Link to post Share on other sites
jjlima 0 Posted February 7, 2013 Share Posted February 7, 2013 Hi ucfknight, I'm having the same problem. Could you send me msp430 code? My email is jhefrei22@hotmail.com Quote Link to post Share on other sites
_Murphy_ 6 Posted February 9, 2013 Author Share Posted February 9, 2013 I haven't been able to verify if the code I have works since It isn't displaying values correctly in the debugger. Quote Link to post Share on other sites
_Murphy_ 6 Posted February 9, 2013 Author Share Posted February 9, 2013 What I currently am using I have based it off of another persons code. It is able to compile but after stepping through the debugger I am not 100% certain that the IMU code is working properly. If anyone who may be in the process of doing something similar to this is able to improve upon this code or has another approach please post it. Attached Files: main.c I2C_MSP430.c I2C_MSP430.h MPU6050.h MSP430_MPU6050.c MSP430_MPU6050.h manhviking 1 Quote Link to post Share on other sites
jjlima 0 Posted February 12, 2013 Share Posted February 12, 2013 Does anyone know how to activate the DMP? Quote Link to post Share on other sites
_Murphy_ 6 Posted February 12, 2013 Author Share Posted February 12, 2013 I was able to get my code to work once I added some printf code to debug it. Thank you for posting that code though. Quote Link to post Share on other sites
AMPS 0 Posted March 22, 2013 Share Posted March 22, 2013 What I currently am using I have based it off of another persons code. It is able to compile but after stepping through the debugger I am not 100% certain that the IMU code is working properly. I m trying to interface with ds1307 .please let me know how can interface with g2553 kit. If anyone who may be in the process of doing something similar to this is able to improve upon this code or has another approach please post it. Attached Files: main.c I2C_MSP430.c I2C_MSP430.h MPU6050.h MSP430_MPU6050.c MSP430_MPU6050.h Quote Link to post Share on other sites
_Murphy_ 6 Posted April 25, 2013 Author Share Posted April 25, 2013 Since you asked for more code via a Private message. I will share the project I used to test that the I2C was working using the MPU-6050. It has a printf script in it that someone on this forum created. MSP430_MPU6050.rar Just import this code and connect an MPU-6050 and you should be able to verify that your I2C lines are working through the printf. jefinkt, stingx666, GMX and 1 other 4 Quote Link to post Share on other sites
bluehash 1,581 Posted April 25, 2013 Share Posted April 25, 2013 Since you asked for more code via a Private message. I will share the project I used to test that the I2C was working using the MPU-6050. It has a printf script in it that someone on this forum created. MSP430_MPU6050.rar Just import this code and connect an MPU-6050 and you should be able to verify that your I2C lines are working through the printf. Thanks for sharing. jefinkt 1 Quote Link to post Share on other sites
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.