去年电赛备赛期间,学的STM32标准库,那一整个繁琐直接给我劝退了,当时学习MPU6050时就非常痛苦,代码也看不懂,无非抄来抄去,然后就是编译,改错,编译无穷尽也。最近参考野火的MPU6050代码,将其移植到了MSP430f5529之上,今天分享出来。
1.重要性MPU6050模块对于不论平衡车还是四旋翼无人机的开发都是非常重要的一个模块,除此之外,对于四轮小车的转弯闭环控制也是至关重要的,因此备战电赛控制类这是一个不可避开的模块。该模块包含陀螺仪和加速度传感器,可以解算出其x,y,z三个方向的角度和各个方向的角速度,使用十分方便,此次并未采用官方的DMP库。
2.代码废话不多说,直接上代码,调用即可。
#include "driverlib.h"
#include "mpu6050.h"
void ByteWrite6050(unsigned char REG_Address,unsigned char REG_data);
unsigned char ByteRead6050(unsigned char REG_Address);
int Get6050Data(unsigned char REG_Address);
void InitMPU6050();
float Mpu6050AccelAngle(char dir);
float Mpu6050GyroAngle(char dir);
///开启信号
void IIC_start()
{
SDA_OUT;
SCL_OUT;
SCL_HIGH;
SDA_HIGH;
__delay_cycles(10);
SDA_LOW;
__delay_cycles(10);
SCL_LOW;
}
///停止信号
void IIC_stop()
{
SDA_OUT;
SCL_OUT;
SDA_LOW;
SCL_HIGH;
__delay_cycles(10);
SDA_HIGH;
__delay_cycles(10);
}
//发送应答信号(MCU=>||)
void SendACK(unsigned char ack)
{
SDA_OUT;
SCL_OUT;
if(ack==1)
{
SDA_HIGH;
}
else if(ack==0)
{
SDA_LOW;
}
else
return;
SCL_HIGH;
__delay_cycles(10);
SCL_LOW;
__delay_cycles(10);
}
接收应答信号(||=>MCU)
unsigned char IIC_testACK()
{
unsigned char a;
SCL_OUT;
SDA_IN;
//GPIO_setAsInputPinWithPullUpResistor (GPIO_PORT_P8, GPIO_PIN2);
SCL_HIGH;
__delay_cycles(10);
if(GPIO_getInputPinValue (GPIO_PORT_P8, GPIO_PIN2)==1)
{
a=1;
}
else
{
a=0;
}
SCL_LOW;
__delay_cycles(10);
SDA_OUT;
return a;
}
///向IIC总线发送数据(MCU=>||)
void IIC_writebyte(unsigned char IIC_byte)
{
unsigned char i;
SDA_OUT;
SCL_OUT;
// SCL_LOW;
for (i=0; i<8; i++) //8位计数器
{
if((IIC_byte<
SDA_HIGH;
}
else
{
SDA_LOW;
}
__delay_cycles(10);
SCL_HIGH;
__delay_cycles(10);
SCL_LOW;
// __delay_cycles(10);
// IIC_byte<<=1;
}
IIC_testACK();
}
IIC接收一个字节(||——>MCU)
unsigned char IIC_readebyte(void)
{
unsigned char i,k=0;
SDA_IN;
GPIO_setAsInputPinWithPullUpResistor (GPIO_PORT_P8, GPIO_PIN2);
SCL_OUT;
SCL_LOW;
__delay_cycles(100);
for(i=0;i<8;i++)
{
SCL_HIGH;
k=k<<1;
if(SDA)
k|=1;
SCL_LOW;
__delay_cycles(100);
}
SDA_OUT;
__delay_cycles(100);
return k;
}
/
float Mpu6050AccelAngle(char dir)
{
float accel_agle; // 测量的倾角值
float result; // 测量值缓存变量
result = (float)Get6050Data(dir); // 测量当前方向的加速度值,转换为浮点数
accel_agle = (result + MPU6050_ZERO_ACCELL)/16384; // 去除零点偏移,计算得到角度(弧度)
accel_agle = accel_agle*1.2*180/3.14; //弧度转换为度
return accel_agle; // 返回测量值
}
float Mpu6050GyroAngle(char dir)
{
float gyro_angle;
gyro_angle = (float)Get6050Data(dir); // 检测陀螺仪的当前值
gyro_angle = -(gyro_angle + MPU6050_ZERO_GYRO)/16.4; //去除零点偏移,计算角速度值,负号为方向处理
return gyro_angle; // 返回测量值
}
#ifndef MPU6050_H_ #define MPU6050_H_ / #define ACCEL_XOUT_H 0x3B #define ACCEL_XOUT_L 0x3C #define ACCEL_XOUT ACCEL_XOUT_H // X轴读取地址,高位为起始位 #define ACCEL_YOUT_H 0x3D #define ACCEL_YOUT_L 0x3E #define ACCEL_YOUT ACCEL_YOUT_H // Y轴读取地址,高位为起始位 #define ACCEL_ZOUT_H 0x3F #define ACCEL_ZOUT_L 0x40 #define ACCEL_ZOUT ACCEL_ZOUT_H // Z轴读取地址,高位为起始位 #define TEMP_OUT_H 0x41 #define TEMP_OUT_L 0x42 #define TEMP_OUT TEMP_OUT_H // 温度传感器读取地址,高位为起始位 // /陀螺仪相关寄存器// // #define GYRO_XOUT_H 0x43 #define GYRO_XOUT_L 0x44 #define GYRO_XOUT GYRO_XOUT_H // 陀螺仪X轴读取地址,高位为起始位 #define GYRO_YOUT_H 0x45 #define GYRO_YOUT_L 0x46 #define GYRO_YOUT GYRO_YOUT_H // 陀螺仪Y轴读取地址,高位为起始位 #define GYRO_ZOUT_H 0x47 #define GYRO_ZOUT_L 0x48 #define GYRO_ZOUT GYRO_ZOUT_H // 陀螺仪Z轴读取地址,高位为起始位 /// 其它寄存器/ // #define PWR_MGMT_1 0x6B //电源管理 #define WHO_AM_I 0x75 //6位iic地址,最后一位A0控制 // ///iic地址设置 / #define SlaveAddress 0xD0 //A0接地,若接3.3v则0xD1 extern void ByteWrite6050(unsigned char REG_Address,unsigned char REG_data); extern unsigned char ByteRead6050(unsigned char REG_Address); extern int Get6050Data(unsigned char REG_Address); extern void InitMPU6050(); extern float Mpu6050AccelAngle(char dir); extern float Mpu6050GyroAngle(char dir); #define SCL_HIGH P1OUT|=BIT2 #define SCL_LOW P1OUT&=~BIT2 #define SDA_HIGH P1OUT|=BIT3 #define SDA_LOW P1OUT&=~BIT3 #define SDA_OUT P1DIR|=BIT3 #define SDA_IN P1DIR&=~BIT3 #define SCL_OUT P1DIR|=BIT2 #define SDA P1IN&BIT3 void IIC_start();//开始 void IIC_stop();//停止 void SendACK(unsigned char ack);//向iic发送标志 void IIC_writebyte(unsigned char IIC_byte);///接收iic标志 unsigned char IIC_testACK();///发送数据 unsigned char IIC_readebyte();///接收数据 #endif
直接根据自己的需求更改模拟IIC的SCL和SDA引脚即可
需要注意的是IIC时序中的延时,以上代码是在主频为16MHZ的条件下完成的。



