51单片机驱动程序 MPU6050

 MPU6050.h

#ifndef _MPU6050_H_
#define _MPU6050_H_

#include "reg52.h"
#include  // _nop_();
#include 
#include 

#define uchar unsigned char
#define uint unsigned int


//****************************************
// 定义51单片机端口
//****************************************
sbit    SCL=P1^0;			//IIC时钟引脚定义
sbit    SDA=P1^1;			//IIC数据引脚定义

//偏移量
#define TYPE_ACCEL      0
//角速度
#define TYPE_GYRO       1
//角度
#define TYPE_ANGLE      2


/*================================================================
【名 称】InitMPU6050
【功 能】初始化MPU6050
【参 数】无
【备 注】程序运行前进行初始化
================================================================*/
void InitMPU6050();											

/*================================================================
【名 称】Get_Mpu6050_Data
【功 能】获取偏移量-角速度-角度
【参 数】X_Dat Y_Dat Z_Dat 传入变量地址,函数走完后你传入的参数里就有值了
         Type 获取哪种数据  传入宏定义 TYPE_ACCEL  TYPE_GYRO  TYPE_ANGLE
【备 注】数据有正负请注意  前三个参数 如果你传入的不是指针地址 
         就在你想传入的参数前加一个&(取址符)
================================================================*/
void Get_Mpu6050_Data(int *X_Dat, int *Y_Dat, int *Z_Dat, uchar Type);

 

#include "MPU6050.h"


//****************************************
// 定义MPU6050内部地址
//****************************************
#define	SMPLRT_DIV		0x19	//陀螺仪采样率,典型值:0x07(125Hz)
#define	CONFIG			  0x1A	//低通滤波频率,典型值:0x06(5Hz)
#define	GYRO_CONFIG		0x1B	//陀螺仪自检及测量范围,典型值:0x18(不自检,2000deg/s)
#define	ACCEL_CONFIG	0x1C	//加速计自检、测量范围及高通滤波频率,典型值:0x01(不自检,2G,5Hz)
#define	ACCEL_XOUT_H	0x3B
#define	ACCEL_XOUT_L	0x3C
#define	ACCEL_YOUT_H	0x3D
#define	ACCEL_YOUT_L	0x3E
#define	ACCEL_ZOUT_H	0x3F
#define	ACCEL_ZOUT_L	0x40
#define	TEMP_OUT_H		0x41
#define	TEMP_OUT_L		0x42
#define	GYRO_XOUT_H		0x43
#define	GYRO_XOUT_L		0x44	
#define	GYRO_YOUT_H		0x45
#define	GYRO_YOUT_L		0x46
#define	GYRO_ZOUT_H		0x47
#define	GYRO_ZOUT_L		0x48
#define	PWR_MGMT_1		0x6B	//电源管理,典型值:0x00(正常启用)
#define	WHO_AM_I		  0x75	//IIC地址寄存器(默认数值0x68,只读)
#define	SlaveAddress	0xD0	//IIC写入时的地址字节数据,+1为读取



//**************************************************************************************************
void  Delay5us();
//********************************MPU6050操作函数***************************************************
void  I2C_Start();
void  I2C_Stop();
void  I2C_SendACK(bit ack);
bit   I2C_RecvACK();
void  I2C_SendByte(uchar dat);
uchar I2C_RecvByte();
void  I2C_ReadPage();
void  I2C_WritePage();

uchar Single_ReadI2C(uchar REG_Address);						//读取I2C数据
void  Single_WriteI2C(uchar REG_Address,uchar REG_data);	    //向I2C写入数据
int GetData(uchar REG_Address);


//************************************************************************************************
//延时5微秒(STC90C52RC@12M)
//不同的工作环境,需要调整此函数
//注意当改用1T的MCU时,请调整此延时函数
//************************************************************************************************
void Delay5us()
{
	_nop_();_nop_();_nop_();_nop_();
	_nop_();_nop_();_nop_();_nop_();
	_nop_();_nop_();_nop_();_nop_();
	_nop_();_nop_();_nop_();_nop_();
	_nop_();_nop_();_nop_();_nop_();
	_nop_();_nop_();_nop_();_nop_();
}
//*************************************************************************************************
//I2C起始信号
//*************************************************************************************************
void I2C_Start()
{
    SDA = 1;                    //拉高数据线
    SCL = 1;                    //拉高时钟线
    Delay5us();                 //延时
    SDA = 0;                    //产生下降沿
    Delay5us();                 //延时
    SCL = 0;                    //拉低时钟线
}
//*************************************************************************************************
//I2C停止信号
//*************************************************************************************************
void I2C_Stop()
{
    SDA = 0;                    //拉低数据线
    SCL = 1;                    //拉高时钟线
    Delay5us();                 //延时
    SDA = 1;                    //产生上升沿
    Delay5us();                 //延时
}
//**************************************************************************************************
//I2C发送应答信号
//入口参数:ack (0:ACK 1:NAK)
//**************************************************************************************************
void I2C_SendACK(bit ack)
{
    SDA = ack;                  //写应答信号
    SCL = 1;                    //拉高时钟线
    Delay5us();                 //延时
    SCL = 0;                    //拉低时钟线
    Delay5us();                 //延时
}
//****************************************************************************************************
//I2C接收应答信号
//****************************************************************************************************
bit I2C_RecvACK()
{
    SCL = 1;                    //拉高时钟线
    Delay5us();                 //延时
    CY = SDA;                   //读应答信号
    SCL = 0;                    //拉低时钟线
    Delay5us();                 //延时
    return CY;
}
//*****************************************************************************************************
//向I2C总线发送一个字节数据
//*****************************************************************************************************
void I2C_SendByte(uchar dat)
{
    uchar i;
    for (i=0; i<8; i++)         //8位计数器
    {
        dat <<= 1;              //移出数据的最高位
        SDA = CY;               //送数据口
        SCL = 1;                //拉高时钟线
        Delay5us();             //延时
        SCL = 0;                //拉低时钟线
        Delay5us();             //延时
    }
    I2C_RecvACK();
}
//*****************************************************************************************************
//从I2C总线接收一个字节数据
//******************************************************************************************************
uchar I2C_RecvByte()
{
    uchar i;
    uchar dat = 0;
    SDA = 1;                    //使能内部上拉,准备读取数据,
    for (i=0; i<8; i++)         //8位计数器
    {
        dat <<= 1;
        SCL = 1;                //拉高时钟线
        Delay5us();             //延时
        dat |= SDA;             //读数据               
        SCL = 0;                //拉低时钟线
        Delay5us();             //延时
    }
    return dat;
}
//*****************************************************************************************************
//向I2C设备写入一个字节数据
//*****************************************************************************************************
void Single_WriteI2C(uchar REG_Address,uchar REG_data)
{
    I2C_Start();                  //起始信号
    I2C_SendByte(SlaveAddress);   //发送设备地址+写信号
    I2C_SendByte(REG_Address);    //内部寄存器地址,
    I2C_SendByte(REG_data);       //内部寄存器数据,
    I2C_Stop();                   //发送停止信号
}
//*******************************************************************************************************
//从I2C设备读取一个字节数据
//*******************************************************************************************************
uchar Single_ReadI2C(uchar REG_Address)
{
	uchar REG_data;
	I2C_Start();                   //起始信号
	I2C_SendByte(SlaveAddress);    //发送设备地址+写信号
	I2C_SendByte(REG_Address);     //发送存储单元地址,从0开始	
	I2C_Start();                   //起始信号
	I2C_SendByte(SlaveAddress+1);  //发送设备地址+读信号
	REG_data=I2C_RecvByte();       //读出寄存器数据
	I2C_SendACK(1);                //接收应答信号
	I2C_Stop();                    //停止信号
	return REG_data;
}
//******************************************************************************************************
//初始化MPU6050
//******************************************************************************************************
void InitMPU6050()
{
	Single_WriteI2C(PWR_MGMT_1, 0x00);	//解除休眠状态
	Single_WriteI2C(SMPLRT_DIV, 0x07);
	Single_WriteI2C(CONFIG, 0x06);
	Single_WriteI2C(GYRO_CONFIG, 0x18);
	Single_WriteI2C(ACCEL_CONFIG, 0x01);
}
//******************************************************************************************************
//合成数据
//******************************************************************************************************
int GetData(uchar REG_Address)
{
	uchar H,L;
	H=Single_ReadI2C(REG_Address);
	L=Single_ReadI2C(REG_Address+1);
	return ((H<<8)+L);   //合成数据
}

void Get_Mpu6050_Data(int *X_Dat, int *Y_Dat, int *Z_Dat, uchar Type)
{
  float res = 0;
  switch(Type)
  {
    //偏移量  也就是加速度计 的分量
    case TYPE_ACCEL:
    {
      *X_Dat = GetData(ACCEL_XOUT_H);
      *Y_Dat = GetData(ACCEL_YOUT_H);
      *Z_Dat = GetData(ACCEL_ZOUT_H);
      break;
    }
    //运动速度   也就是角速度  
    case TYPE_GYRO:
    {
      *X_Dat = GetData(GYRO_XOUT_H);
      *Y_Dat = GetData(GYRO_YOUT_H);
      *Z_Dat = GetData(GYRO_ZOUT_H);
      break;
    }
    //角度  
    case TYPE_ANGLE:
    {
      float Accel_ax;
      float Accel_ay;
      float Accel_az;
      float res;
      Accel_ax = GetData(ACCEL_XOUT_H);
      Accel_ay = GetData(ACCEL_YOUT_H);
      Accel_az = GetData(ACCEL_ZOUT_H);
            
      res = Accel_ax/sqrt((Accel_az*Accel_az+Accel_ay*Accel_ay));
      res = atan(res)*180/3.14;
      *X_Dat = res;
      
			res = Accel_ay/sqrt((Accel_az*Accel_az+Accel_ax*Accel_ax));
			res = atan(res)*180/3.14;
      *Y_Dat = res;
      
      res = sqrt((Accel_ax*Accel_ax+Accel_ay*Accel_ay))/Accel_az;
      res = atan(res)*180/3.14;
      *Z_Dat = res;
      
      break;
    }

    default:
      break;
  }
}
	InitMPU6050();

 

你可能感兴趣的:(51单片机程序,51单片机,嵌入式硬件,单片机)