Jump to content
43oh

Interface MSP430 and MPU6050


Recommended Posts

MPU6050 are accelerometer and gyroscope sensor , cheap and very useful.But there aren't a lot of library codes available for MSP430.Here is the library,include initialing and reading MPU6050.I had convert this library from AVR's library.

 

Use for : MSP430x2xx ,other MSP430 must redefine some register of I2C Module or rewrite "I2C_USCI.h" function

Link Download: Code MSP430 and MPU6050

 

I2C_USCI Library use for MPU6050 Library:

////////////////////////////////////////////////////////////////////
// LIBRARY CONTROL I2C USCI MODULE
// Write by : PHAM VAN THUAN	DTVT07-K55
// Email:	terran991992@gmail.com
// Blog :	http://thuanbk55.blogspot.com/
// .................................................................
// USE FOR MSP430
//******************************************************************/


#ifndef I2C_USCI_H
#define I2C_USCI_H

// Address 
#define MPU6050_ADDRESS	0x68
#define BQ32000_ADDRESS	0x68
#define DS1307_ADDRESS	0x68
#define LM92_ADDRESS	0x48
/******************************************************************************\
*					Prototype  						       *
\******************************************************************************/
void I2C_USCI_Init(unsigned char addr);	//Init I2C
void I2C_USCI_Set_Address(unsigned char addr);	//Change Slave's  Address
unsigned char I2C_USCI_Read_Byte(unsigned char address);	//Read 1 byte
//Read many Byte
unsigned char I2C_USCI_Read_Word(unsigned char Addr_Data,unsigned char *Data, unsigned char Length);
//Write 1 Byte
unsigned char I2C_USCI_Write_Byte(unsigned char address, unsigned char Data);
/******************************************************************************\
*					Function                            *
\******************************************************************************/


void I2C_USCI_Init(unsigned char addr)
{
	P1SEL |= BIT6 + BIT7;                     // Assign I2C pins to USCI_B0
	P1SEL2|= BIT6 + BIT7;                     // Assign I2C pins to USCI_B0
	UCB0CTL1 |= UCSWRST;                      // Enable SW reset
	UCB0CTL0 = UCMST+UCMODE_3+UCSYNC;         // I2C Master, synchronous mode
  	UCB0CTL1 = UCSSEL_2+UCSWRST;              // Use SMCLK, keep SW reset
	UCB0BR0 = 40;                             // fSCL = SMCLK/40 = ~400kHz
	UCB0BR1 = 0;
	UCB0I2CSA = addr;                         // Set slave address
	UCB0CTL1 &= ~UCSWRST;                     // Clear SW reset, resume operation
}

void I2C_USCI_Set_Address(unsigned char addr)
{
  	UCB0CTL1 |= UCSWRST;    
  	UCB0I2CSA = addr;                     		// Set slave address
  	UCB0CTL1 &= ~UCSWRST;                 		// Clear SW reset, resume operation 	
}

unsigned char I2C_USCI_Read_Byte(unsigned char address)
{ 	
	while (UCB0CTL1 & UCTXSTP);       
	UCB0CTL1 |= UCTR + UCTXSTT;             	// I2C TX,START

	while (!(IFG2&UCB0TXIFG));				
	UCB0TXBUF = address;                     

	while (!(IFG2&UCB0TXIFG));				

	UCB0CTL1 &= ~UCTR;                      // I2C RX
	UCB0CTL1 |= UCTXSTT;                    // I2C RESTART
	IFG2 &= ~UCB0TXIFG;                     

	while (UCB0CTL1 & UCTXSTT);             
	UCB0CTL1 |= UCTXSTP;                   
	return UCB0RXBUF;
}

unsigned char I2C_USCI_Read_Word(unsigned char Addr_Data,unsigned char *Data, unsigned char Length)
{ 	
	unsigned char i=0;
	while (UCB0CTL1 & UCTXSTP);             // Loop until I2C STT is sent
	UCB0CTL1 |= UCTR + UCTXSTT;             // I2C TX, start condition

	while (!(IFG2&UCB0TXIFG));
	IFG2 &= ~UCB0TXIFG;                     // Clear USCI_B0 TX int flag
	if(UCB0STAT & UCNACKIFG) return UCB0STAT;	
	UCB0TXBUF = Addr_Data;                      	

	while (!(IFG2&UCB0TXIFG));
	if(UCB0STAT & UCNACKIFG) return UCB0STAT;	

	UCB0CTL1 &= ~UCTR;                      // I2C RX
	UCB0CTL1 |= UCTXSTT;                    // I2C start condition
	IFG2 &= ~UCB0TXIFG;                     // Clear USCI_B0 TX int flag
	while (UCB0CTL1 & UCTXSTT);             // Loop until I2C STT is sent
	for(i=0;i<(Length-1);i++)
	{
		while (!(IFG2&UCB0RXIFG));
		IFG2 &= ~UCB0TXIFG;                     // Clear USCI_B0 TX int flag
		Data[i] = UCB0RXBUF;
	}
	while (!(IFG2&UCB0RXIFG));
	IFG2 &= ~UCB0TXIFG;                     // Clear USCI_B0 TX int flag
	UCB0CTL1 |= UCTXSTP;                    // I2C stop condition after 1st TX
	Data[Length-1] = UCB0RXBUF;
	IFG2 &= ~UCB0TXIFG;                     // Clear USCI_B0 TX int flag
	return 0;
}

unsigned char I2C_USCI_Write_Byte(unsigned char address, unsigned char data)
{
	while (UCB0CTL1 & UCTXSTP);          
	UCB0CTL1 |= UCTR + UCTXSTT;          

	while (!(IFG2&UCB0TXIFG));				
	if(UCB0STAT & UCNACKIFG) return UCB0STAT;	
	UCB0TXBUF = address;				


	while (!(IFG2&UCB0TXIFG));			
	if(UCB0STAT & UCNACKIFG) return UCB0STAT;	
	UCB0TXBUF = data;					

	while (!(IFG2&UCB0TXIFG));				
	if(UCB0STAT & UCNACKIFG) return UCB0STAT;	
	UCB0CTL1 |= UCTXSTP;                    
	IFG2 &= ~UCB0TXIFG;                  
	return 0;
} 
#endif	/* I2C_USCI */

MSP430 vs MPU6050.rar

Link to post
Share on other sites
  • 3 months later...
  • 2 weeks later...
  • 5 months later...

Thank you for sharing this code!

Which pins from MPU6050 do you use on this project? Just SCL and SDA? Or do you use the INT pin as well?
What is the easiest way to read the values you get from the MPU?

Somehow the code get stucked on the Setup_MPU6050(); routine,

 

 

Thank you

Link to post
Share on other sites
  • 8 months later...

This is a little late to the topic, but hopefully it will help the next time it comes up in a search...

 

The key to success with the MPU-6050 module that I got from Amazon (about $4 US) was to use a 5V source for the board's Vcc.  It has a 3.3V regulator on board to convert the 5V from Arduino to 3.3V required, and the LaunchPad's 3.3V Vcc was not enough.  The module also contains pull-up resistors for SCL and SDA, and 330-Ohm resistors on the SCL and SDA lines as well.  I was able to connect the LaunchPad GND, SCL (P1.6) and SDA (P1.7) directly to the module, but powered the module separately with a 5V source, and it worked fine.

 

I adapted some code from the TI examples that use the USCIAB0TX_VECTOR interrupt service routine when UCB0RXIFG or UCB0TXIFG is set.

 

Mike

/*
 * I2C_Accel_MPU6050
 *
 * Version 1:  Read raw accelerometer X, Y and Z data continuously
 *
 *  P1.6					UCB0SCL
 *	P1.7					UCB0SDA
 *
 * MPU-6050 Accelerometer & Gyro
 * NOTE:  Default state of the MPU-6050 is SLEEP mode.
 *        Wake up by writing 0x00 to the PWR_MGMT_1 register
 * NOTE:  No-name version from Amazon has a 5V to 3.3V regulator, and Vcc MUST be 5V !!!
 *        10-kOhm pull-up resistors are included on the board
 *        330-Ohm resistors are included in series on SCL and SDA
 *                (safe to connect P1.6 & P1.7 directly to SCL and SDA)
 *
 * Slave address: 	0x68 (AD0=0) or 0x69 (AD0=1)
 *
 * Z-data buffer addresses:
 * 					0x3B ACCEL_XOUT_H R ACCEL_XOUT[15:8]
 * 					0x3C ACCEL_XOUT_L R ACCEL_XOUT[ 7:0]
 * 					0x3D ACCEL_YOUT_H R ACCEL_YOUT[15:8]
 * 					0x3E ACCEL_YOUT_L R ACCEL_YOUT[ 7:0]
 * 					0x3F ACCEL_ZOUT_H R ACCEL_ZOUT[15:8]
 * 					0x40 ACCEL_ZOUT_L R ACCEL_ZOUT[ 7:0]
 *
 * pins not used: 	INT (interrupt for data ready in the 1024-byte FIFO bufer)
 * 				  	XCL, XDA (external clock and data lines for MPU-6050 I2C bus)
 *
 * Reading the raw values: disable sleep mode
 * 					0x6B PWR_MGMT_1 --> set to 0
 *
 */
#include <msp430.h> 

/*
 * main.c
 */

unsigned char RX_Data[6];
unsigned char TX_Data[2];
unsigned char RX_ByteCtr;
unsigned char TX_ByteCtr;

int xAccel;
int yAccel;
int zAccel;

unsigned char slaveAddress = 0x68;	// Set slave address for MPU-6050
					// 0x68 for ADD pin=0
					// 0x69 for ADD pin=1

const unsigned char PWR_MGMT_1   = 0x6B;	// MPU-6050 register address
const unsigned char ACCEL_XOUT_H = 0x3B;	// MPU-6050 register address
const unsigned char ACCEL_XOUT_L = 0x3C;	// MPU-6050 register address
const unsigned char ACCEL_YOUT_H = 0x3D;	// MPU-6050 register address
const unsigned char ACCEL_YOUT_L = 0x3E;	// MPU-6050 register address
const unsigned char ACCEL_ZOUT_H = 0x3F;	// MPU-6050 register address
const unsigned char ACCEL_ZOUT_L = 0x40;	// MPU-6050 register address

void i2cInit(void);
void i2cWrite(unsigned char);
void i2cRead(unsigned char);

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

	// Set clock speed (default = 1 MHz)
	BCSCTL1 = CALBC1_1MHZ;	 				// Basic Clock System CTL (1,8,12 16_MHZ available)
	DCOCTL  = CALDCO_1MHZ;	 				// Digitally-Controlled Oscillator CTL

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

	// Initialize the I2C state machine
	i2cInit();
	
	// Wake up the MPU-6050
	slaveAddress = 0x68;					// MPU-6050 address
	TX_Data[1] = 0x6B;						// address of PWR_MGMT_1 register
	TX_Data[0] = 0x00;						// set register to zero (wakes up the MPU-6050)
	TX_ByteCtr = 2;
	i2cWrite(slaveAddress);

	while (1)
	{
		// Point to the ACCEL_ZOUT_H register in the MPU-6050
		slaveAddress = 0x68;					// MPU-6050 address
		TX_Data[0] = 0x3B;					// register address
		TX_ByteCtr = 1;
		i2cWrite(slaveAddress);

		// Read the two bytes of data and store them in zAccel
		slaveAddress = 0x68;					// MPU-6050 address
		RX_ByteCtr = 6;
		i2cRead(slaveAddress);
		xAccel  = RX_Data[5] << 8;				// MSB
		xAccel |= RX_Data[4];					// LSB
		yAccel  = RX_Data[3] << 8;				// MSB
		yAccel |= RX_Data[2];					// LSB
		zAccel  = RX_Data[1] << 8;				// MSB
		zAccel |= RX_Data[0];					// LSB

		// do something with the data

		__no_operation();                       // Set breakpoint >>here<< and read

	}
}

//*********************************************************************************************
void i2cInit(void)
{
	// set up I2C module
	UCB0CTL1 |= UCSWRST;				// Enable SW reset
	UCB0CTL0 = UCMST + UCMODE_3 + UCSYNC;	        // I2C Master, synchronous mode
	UCB0CTL1 = UCSSEL_2 + UCSWRST;			// Use SMCLK, keep SW reset
	UCB0BR0 = 10;					// fSCL = SMCLK/12 = ~100kHz
	UCB0BR1 = 0;
	UCB0CTL1 &= ~UCSWRST;				// Clear SW reset, resume operation
}

//*********************************************************************************************
void i2cWrite(unsigned char address)
{
	__disable_interrupt();
	UCB0I2CSA = address;				// Load slave address
	IE2 |= UCB0TXIE;				// Enable TX interrupt
	while(UCB0CTL1 & UCTXSTP);			// Ensure stop condition sent
	UCB0CTL1 |= UCTR + UCTXSTT;			// TX mode and START condition
	__bis_SR_register(CPUOFF + GIE);		// sleep until UCB0TXIFG is set ...
}

//*********************************************************************************************
void i2cRead(unsigned char address)
{
	__disable_interrupt();
	UCB0I2CSA = address;				// Load slave address
	IE2 |= UCB0RXIE;				// Enable RX interrupt
	while(UCB0CTL1 & UCTXSTP);			// Ensure stop condition sent
	UCB0CTL1 &= ~UCTR;				// RX mode
	UCB0CTL1 |= UCTXSTT;				// Start Condition
	__bis_SR_register(CPUOFF + GIE);		// sleep until UCB0RXIFG is set ...
}

/**********************************************************************************************/
// USCIAB0TX_ISR
#pragma vector = USCIAB0TX_VECTOR
__interrupt void USCIAB0TX_ISR(void)
{
	if(UCB0CTL1 & UCTR)					// TX mode (UCTR == 1)
	{
		if (TX_ByteCtr)				        // TRUE if more bytes remain
		{
			TX_ByteCtr--;				// Decrement TX byte counter
			UCB0TXBUF = TX_Data[TX_ByteCtr];	// Load TX buffer
		}
		else						// no more bytes to send
		{
			UCB0CTL1 |= UCTXSTP;			// I2C stop condition
			IFG2 &= ~UCB0TXIFG;			// Clear USCI_B0 TX int flag
			__bic_SR_register_on_exit(CPUOFF);	// Exit LPM0
		}
	}
	else // (UCTR == 0)					// RX mode
	{
		RX_ByteCtr--;				        // Decrement RX byte counter
		if (RX_ByteCtr)				        // RxByteCtr != 0
		{
			RX_Data[RX_ByteCtr] = UCB0RXBUF;	// Get received byte
			if (RX_ByteCtr == 1)			// Only one byte left?
			UCB0CTL1 |= UCTXSTP;			// Generate I2C stop condition
		}
		else						// RxByteCtr == 0
		{
			RX_Data[RX_ByteCtr] = UCB0RXBUF;	// Get final received byte
			__bic_SR_register_on_exit(CPUOFF);	// Exit LPM0
		}
	}
}

Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...