发新帖我要提问
123
返回列表
打印
[STM32F4]

STM32F4_MPU6050六轴传感器详解

[复制链接]
楼主: kqh11a
手机看帖
扫描二维码
随时随地手机跟帖
41
kqh11a|  楼主 | 2023-6-29 18:53 | 只看该作者 回帖奖励 |倒序浏览
MyMPU6050.c

#include "stm32f4xx.h"               
#include "MyMPU6050.h"
#include "delay.h"
#include "usart.h"


//初始化MPU6050
//返回值:0,成功
//    其他,错误代码
u8 MPU6050_Init(void)
{
        //该步骤严格按读取MPU6050姿态的步骤进行
        u8 res;
        IIC_Init();
    //#define MPU_PWR_MGMT1_REG                0X6B        //电源管理寄存器1
        MPU6050_Write_Byte(MPU_PWR_MGMT1_REG,0X80);        //复位MPU6050  通过对电源管理寄存器1的位7写1来实现
    //位7 DEVICE_RESET:该位设置1,重启内部寄存器到默认值。复位完成后该位自动清0。
    delay_ms(100);
        MPU6050_Write_Byte(MPU_PWR_MGMT1_REG,0X00);        //唤醒MPU6050  通过使电源管理寄存器1清0,进入正常工作模式
    //设置角速度传感器(陀螺仪)和加速度传感器的满量程范围
    //设置两个传感器的满量程范围(FSR),分别通过陀螺仪配置寄存器(0X1B)和加速度传感器配置寄存器(0X1C)设置。
    //我们一般设置陀螺仪的满量程范围为2000dps,加速度传感器的满量程范围为2g。
        MPU6050_Set_Gyro_Fsr(3);                                        //陀螺仪传感器,±2000dps
        MPU6050_Set_Accel_Fsr(0);                                        //加速度传感器,±2g
        MPU6050_Set_Rate(50);                                                //设置采样率50Hz
    //设置其他参数,其中包括关闭中断、关闭AUX IIC接口、禁止FIFO、设置陀螺仪采样率和设置数字低通滤波器(DLPF)
        MPU6050_Write_Byte(MPU_INT_EN_REG,0X00);        //关闭所有中断  将中断使能寄存器的所有位写入0,关闭所有中断
        MPU6050_Write_Byte(MPU_USER_CTRL_REG,0X00);        //I2C主模式关闭 也就是MPU6050充当主机,通过IIC和磁力传感器进行通讯,实现九轴传感器
        MPU6050_Write_Byte(MPU_FIFO_EN_REG,0X00);        //关闭FIFO  将FIFO使能寄存器的所有位写入0,来关闭FIFO
        MPU6050_Write_Byte(MPU_INTBP_CFG_REG,0X80);        //INT引脚低电平有效
        res=MPU6050_Read_Byte(MPU_DEVICE_ID_REG);   //通过读取WHO_AM_I寄存器获取MPU6050的ID
        if(res==MPU_Address)//器件ID正确   //判断ID是否是0X68
        {
        //配置系统时钟源并使能角速度传感器和加速度传感器
                MPU6050_Write_Byte(MPU_PWR_MGMT1_REG,0X01);        //设置CLKSEL,PLL X轴为参考 通过设置电源管理寄存器1的最低位,设置系统时钟为001
                MPU6050_Write_Byte(MPU_PWR_MGMT2_REG,0X00);        //加速度与陀螺仪都工作  通过设置电源管理寄存器2的所有位为0来使能加速度计和陀螺仪,设置为1则加速度计和陀螺仪的X,Y,Z轴进入待机模式
                MPU6050_Set_Rate(50);                                                //设置采样率为50Hz
        }
    else
        return 1; //ID错误
        return 0;
}
//设置MPU6050的陀螺仪传感器满量程范围
//FS_SEL:0,±250dps;1,±500dps;2,±1000dps;3,±2000dps
//返回值:0,设置成功
//                其他,设置失败
u8 MPU6050_Set_Gyro_Fsr(u8 FS_SEL)
{
        return MPU6050_Write_Byte(MPU_GYRO_CFG_REG,FS_SEL<<3); //设置陀螺仪配置寄存器的位3和位4,这里选择量程3,±2000dps,所以配置为3即可
}
//设置MPU6050加速度传感器满量程范围
//AFS_SEL::0,±2g;1,±4g;2,±8g;3,±16g
//返回值:0,设置成功
//    其他,设置失败
u8 MPU6050_Set_Accel_Fsr(u8 AFS_SEL)
{
        return MPU6050_Write_Byte(MPU_ACCEL_CFG_REG,AFS_SEL<<3); //配置加速度传感器配置寄存器的位3和位4,所以需要左移三位,这里设置0,±2g;
}
//设置MPU6050的数字低通滤波器
//PinLv:数字低通滤波频率
//返回值:0,设置成功
//    其他,设置失败
u8 MPU6050_Set_LPF(u16 PinLv)
{
        u8 Data=0;
        if(PinLv>=188)  //这里解释一下,为什么分别设置数字低通滤波频率为188 98 42 20 10 并且得到的低通滤波频率为1 2 3 4 5 6
                                        //首先设置MPU6050的数字低通滤波器其实质是设置配置寄存器的低3位,根据官方MPU6050寄存器手册
                Data=1;     //当设置的数字低通滤波器频率大于188Hz时,配置寄存器的低三位写入001,也就是1
        else if(PinLv>=98)
                Data=2;                //当设置的数字低通滤波器频率大于98Hz时,配置寄存器的低三位写入010,也就是2
        else if(PinLv>=42)
                Data=3;                //当设置的数字低通滤波器频率大于42Hz时,配置寄存器的低三位写入011,也就是3
        else if(PinLv>=20)
                Data=4;                //当设置的数字低通滤波器频率大于20Hz时,配置寄存器的低三位写入100,也就是4
        else if(PinLv>=10)
                Data=5;                //当设置的数字低通滤波器频率大于10Hz时,配置寄存器的低三位写入101,也就是5
        else
                Data=6;                //其他情况下均写入111,表示6
        return MPU6050_Write_Byte(MPU_CFG_REG,Data);  //通过写配置寄存器的第三位即可设置数字低通滤波器
    //#define MPU_CFG_REG                                0X1A        //配置寄存器
}
//设置MPU6050采样率
//Rate:4~1000Hz
//返回值:0,设置成功
//    其他,设置失败
u8 MPU6050_Set_Rate(u16 Rate) //这里一定要假设MPU6050的输出频率为1Khz,输出频率可以是1Khz或者8Khz,其值和数字低通滤波器的设置有关,当数字低通滤波器的低三位写入0或者7时,为8Khz,其余均是1Khz
{
        u8 Data;  //定义Data是采样率分频寄存器写入的8位数值
        if(Rate>1000) //设置范围
                Rate=1000;
        if(Rate<4)    //设置范围
                Rate=4;
        Data=1000/Rate-1;  //采样频率 = 陀螺仪输出频率 / (1+SMPLRT_DIV)  其中SMPLRT_DIV就是Data,寄存器中写入的值
        //采样频率 = 陀螺仪输出频率 / (1+Data) 其中输出频率是1Khz
        Data=MPU6050_Write_Byte(MPU_SAMPLE_RATE_REG,Data); //设置数字低通滤波器
        return MPU6050_Set_LPF(Rate/2); //自动设置数字低通滤波器为采样频率的一半
}
//得到温度值
//返回值:温度值(扩大了100倍)
short MPU6050_Get_Temperature(void)
{
        u8 Buffer[2]; //温度的值是由两个八位寄存器读取的,所以定义一个存储两字节大小的数组
        short raw;  //短整型16位
        float temperature;
        MPU6050_Read_Len(MPU_Address,MPU_TEMP_OUTH_REG,2,Buffer);
        raw=((u16)Buffer[0]<<8)|Buffer[1]; //16位温度值需要两个8位进行或运算
        temperature=36.53+((double)raw)/340; //Temperature = 36.53 + regval/340 ,计算温度的公式 其中regval是从0X41和0X42寄存器读出的值
        return temperature*100;
}
//得到陀螺仪原始值
//GX,GY,GZ:陀螺仪X,Y,Z轴的原始读数
//返回值:0,成功
//    其他,错误代码
u8 MPU6050_Get_Gyroscope(short *GX,short *GY,short *GZ)
{
        u8 Buffer[6];
        u8 res;
        res=MPU6050_Read_Len(MPU_Address,MPU_GYRO_XOUTH_REG,6,Buffer);//读陀螺仪的原始值是通过读6个陀螺仪数据输出寄存器,这些寄存器都是8位的,每两个寄存器拼接成一个16位的原始数据
        if(res==0)//返回值为0,表示读成功
        {
                *GX=((u16)Buffer[0]<<8)|Buffer[1];//因为先读的是寄存器的高8位
                *GY=((u16)Buffer[2]<<8)|Buffer[3];
                *GZ=((u16)Buffer[4]<<8)|Buffer[5];
        }
        return res;
}
//得到加速度计原始值
//AX,AY,AZ:加速度计X,Y,Z轴的原始读数
//返回值:0,成功
//    其他,错误代码
u8 MPU6050_Get_Accelerometer(short *AX,short *AY,short *AZ)
{
        u8 Buffer[6];
        u8 res;
        res=MPU6050_Read_Len(MPU_Address,MPU_ACCEL_XOUTH_REG,6,Buffer);//读加速度计的原始值是通过读6个加速度数据输出寄存器,这些寄存器都是8位的,每两个寄存器拼接成一个16位的原始数据
        if(res==0)//返回值为0,表示读成功
        {
                *AX=((u16)Buffer[0]<<8)|Buffer[1];//因为先读的是寄存器高8位
                *AY=((u16)Buffer[2]<<8)|Buffer[3];
                *AZ=((u16)Buffer[4]<<8)|Buffer[5];
        }
        return res;
}
//IIC连续写
//Address:器件地址
//Register:寄存器地址
//Length:要写入的长度
//Buffer:数据区
//返回值:0,正常
//                其他,错误代码
u8 MPU6050_Write_Len(u8 Address,u8 Register,u8 Length,u8 *Buffer)
{
        u8 i;
        IIC_Start(); //发送起始信号
        IIC_Send_Byte((Address<<1)|0); //主机向从机发送器件地址,也就是主机想要和从机的哪块地址进行通讯,地址最低位是读写位
        //IIC发送的从机地址是7位,最低位是R/W:主从写方向位,(Address<<1)|0表示左移一位再把最低位置0,也就表示主机写数据到从机
        if(IIC_Wait_Ack()) //等待从机应答,IIC_Wait_Ack该函数的返回值若为1,则表示没有接收到从机的应答信号,IIC通讯结束
        {
                IIC_Stop();
                return 1;
        }
        IIC_Send_Byte(Register); //跳过if判断语句就意味着从机接收到了主机的信号,主机发送寄存器地址
        IIC_Wait_Ack(); //等待从机应答
        for(i=0;i<Length;i++)
        {
                IIC_Send_Byte(Buffer[i]);//通过循环一位一位的发送数据,发送Length字节长的数据
                if(IIC_Wait_Ack())//IIC时序规定每发送一位,从机都要应答一次
                {
                        IIC_Stop();
                        return 1;
                }
        }
        IIC_Stop(); //发送完毕,IIC通讯结束
        return 0;
}
//IIC连续读
//Address:器件地址
//Register:要读取的寄存器地址
//Length:要读取的长度
//Buffer:读取到的数据存储区
//返回值:0,正常
//                其他,错误代码
u8 MPU6050_Read_Len(u8 Address,u8 Register,u8 Length,u8 *Buffer)
{
        IIC_Start(); //发送起始信号
        IIC_Send_Byte((Address<<1)|0); //主机向从机发送器件地址,也就是主机想要和从机的哪块地址进行通讯
        //IIC发送的从机地址是7位,最低位是R/W:主从写方向位,(Address<<1)|0表示左移一位再把最低位置0,也就表示主机写数据到从机
        if(IIC_Wait_Ack()) //等待从机应答,IIC_Wait_Ack该函数的返回值若为1,则表示没有接收到从机的应答信号,IIC通讯结束
        {
                IIC_Stop();
                return 1;
        }
        IIC_Send_Byte(Register); //跳过if判断语句就意味着从机接收到了主机的信号,主机发送寄存器地址
        IIC_Wait_Ack(); //等待从机应答
        IIC_Start(); //发送起始信号
        IIC_Send_Byte((Address<<1)|1); //主机向从机发送器件地址,也就是主机想要和从机的哪块地址进行通讯
        //IIC发送的从机地址是7位,最低位是R/W:主从写方向位,(Address<<1)|1表示左移一位再把最低位置1,也就表示主机从从机中读数据
        IIC_Wait_Ack(); //等待从机应答
        while(Length)
        {
                if(Length==1)//如果只写入了一个节长的数据,那么发送NAck
                {
                        *Buffer=IIC_Read_Byte(0); //不产生应答
                }
                else
                        *Buffer=IIC_Read_Byte(1);//产生应答
                Length--;
                Buffer++;
        }
        IIC_Stop();
        return 0;
}
//IIC写一个字节
//Register:寄存器地址
//Data:数据
//返回值:0,正常
//                其他,错误代码
u8 MPU6050_Write_Byte(u8 Register,u8 Data)
{
        IIC_Start();
        IIC_Send_Byte((MPU_Address<<1)|0); //注意写一位写字节时,发送的是从机IIC的地址
        if(IIC_Wait_Ack()) //等待从机应答,IIC_Wait_Ack该函数的返回值若为1,则表示没有接收到从机的应答信号,IIC通讯结束
        {
                IIC_Stop();
                return 1;
        }
        IIC_Send_Byte(Register);
        IIC_Wait_Ack();
        IIC_Send_Byte(Data);
        if(IIC_Wait_Ack()) //等待从机应答,IIC_Wait_Ack该函数的返回值若为1,则表示没有接收到从机的应答信号,IIC通讯结束
        {
                IIC_Stop();
                return 1;
        }
        IIC_Stop();
        return 0;
}
//IIC读一个字节
//Register:寄存器地址
//返回值:读到的数据
u8 MPU6050_Read_Byte(u8 Register)
{
        u8 res;
        IIC_Start();
        IIC_Send_Byte((MPU_Address<<1)|0);
        IIC_Wait_Ack();
        IIC_Send_Byte(Register);
        IIC_Wait_Ack();
        IIC_Start();
        IIC_Send_Byte((MPU_Address<<1)|1);
        IIC_Wait_Ack();
        res=IIC_Read_Byte(0);
        IIC_Stop();
        return res;
}

使用特权

评论回复
42
kqh11a|  楼主 | 2023-6-29 18:53 | 只看该作者
MyMPU6050.c
#include "stm32f4xx.h"               
#include "MyMPU6050.h"
#include "delay.h"
#include "usart.h"


//初始化MPU6050
//返回值:0,成功
//    其他,错误代码
u8 MPU6050_Init(void)
{
        //该步骤严格按读取MPU6050姿态的步骤进行
        u8 res;
        IIC_Init();
    //#define MPU_PWR_MGMT1_REG                0X6B        //电源管理寄存器1
        MPU6050_Write_Byte(MPU_PWR_MGMT1_REG,0X80);        //复位MPU6050  通过对电源管理寄存器1的位7写1来实现
    //位7 DEVICE_RESET:该位设置1,重启内部寄存器到默认值。复位完成后该位自动清0。
    delay_ms(100);
        MPU6050_Write_Byte(MPU_PWR_MGMT1_REG,0X00);        //唤醒MPU6050  通过使电源管理寄存器1清0,进入正常工作模式
    //设置角速度传感器(陀螺仪)和加速度传感器的满量程范围
    //设置两个传感器的满量程范围(FSR),分别通过陀螺仪配置寄存器(0X1B)和加速度传感器配置寄存器(0X1C)设置。
    //我们一般设置陀螺仪的满量程范围为2000dps,加速度传感器的满量程范围为2g。
        MPU6050_Set_Gyro_Fsr(3);                                        //陀螺仪传感器,±2000dps
        MPU6050_Set_Accel_Fsr(0);                                        //加速度传感器,±2g
        MPU6050_Set_Rate(50);                                                //设置采样率50Hz
    //设置其他参数,其中包括关闭中断、关闭AUX IIC接口、禁止FIFO、设置陀螺仪采样率和设置数字低通滤波器(DLPF)
        MPU6050_Write_Byte(MPU_INT_EN_REG,0X00);        //关闭所有中断  将中断使能寄存器的所有位写入0,关闭所有中断
        MPU6050_Write_Byte(MPU_USER_CTRL_REG,0X00);        //I2C主模式关闭 也就是MPU6050充当主机,通过IIC和磁力传感器进行通讯,实现九轴传感器
        MPU6050_Write_Byte(MPU_FIFO_EN_REG,0X00);        //关闭FIFO  将FIFO使能寄存器的所有位写入0,来关闭FIFO
        MPU6050_Write_Byte(MPU_INTBP_CFG_REG,0X80);        //INT引脚低电平有效
        res=MPU6050_Read_Byte(MPU_DEVICE_ID_REG);   //通过读取WHO_AM_I寄存器获取MPU6050的ID
        if(res==MPU_Address)//器件ID正确   //判断ID是否是0X68
        {
        //配置系统时钟源并使能角速度传感器和加速度传感器
                MPU6050_Write_Byte(MPU_PWR_MGMT1_REG,0X01);        //设置CLKSEL,PLL X轴为参考 通过设置电源管理寄存器1的最低位,设置系统时钟为001
                MPU6050_Write_Byte(MPU_PWR_MGMT2_REG,0X00);        //加速度与陀螺仪都工作  通过设置电源管理寄存器2的所有位为0来使能加速度计和陀螺仪,设置为1则加速度计和陀螺仪的X,Y,Z轴进入待机模式
                MPU6050_Set_Rate(50);                                                //设置采样率为50Hz
        }
    else
        return 1; //ID错误
        return 0;
}
//设置MPU6050的陀螺仪传感器满量程范围
//FS_SEL:0,±250dps;1,±500dps;2,±1000dps;3,±2000dps
//返回值:0,设置成功
//                其他,设置失败
u8 MPU6050_Set_Gyro_Fsr(u8 FS_SEL)
{
        return MPU6050_Write_Byte(MPU_GYRO_CFG_REG,FS_SEL<<3); //设置陀螺仪配置寄存器的位3和位4,这里选择量程3,±2000dps,所以配置为3即可
}
//设置MPU6050加速度传感器满量程范围
//AFS_SEL::0,±2g;1,±4g;2,±8g;3,±16g
//返回值:0,设置成功
//    其他,设置失败
u8 MPU6050_Set_Accel_Fsr(u8 AFS_SEL)
{
        return MPU6050_Write_Byte(MPU_ACCEL_CFG_REG,AFS_SEL<<3); //配置加速度传感器配置寄存器的位3和位4,所以需要左移三位,这里设置0,±2g;
}
//设置MPU6050的数字低通滤波器
//PinLv:数字低通滤波频率
//返回值:0,设置成功
//    其他,设置失败
u8 MPU6050_Set_LPF(u16 PinLv)
{
        u8 Data=0;
        if(PinLv>=188)  //这里解释一下,为什么分别设置数字低通滤波频率为188 98 42 20 10 并且得到的低通滤波频率为1 2 3 4 5 6
                                        //首先设置MPU6050的数字低通滤波器其实质是设置配置寄存器的低3位,根据官方MPU6050寄存器手册
                Data=1;     //当设置的数字低通滤波器频率大于188Hz时,配置寄存器的低三位写入001,也就是1
        else if(PinLv>=98)
                Data=2;                //当设置的数字低通滤波器频率大于98Hz时,配置寄存器的低三位写入010,也就是2
        else if(PinLv>=42)
                Data=3;                //当设置的数字低通滤波器频率大于42Hz时,配置寄存器的低三位写入011,也就是3
        else if(PinLv>=20)
                Data=4;                //当设置的数字低通滤波器频率大于20Hz时,配置寄存器的低三位写入100,也就是4
        else if(PinLv>=10)
                Data=5;                //当设置的数字低通滤波器频率大于10Hz时,配置寄存器的低三位写入101,也就是5
        else
                Data=6;                //其他情况下均写入111,表示6
        return MPU6050_Write_Byte(MPU_CFG_REG,Data);  //通过写配置寄存器的第三位即可设置数字低通滤波器
    //#define MPU_CFG_REG                                0X1A        //配置寄存器
}
//设置MPU6050采样率
//Rate:4~1000Hz
//返回值:0,设置成功
//    其他,设置失败
u8 MPU6050_Set_Rate(u16 Rate) //这里一定要假设MPU6050的输出频率为1Khz,输出频率可以是1Khz或者8Khz,其值和数字低通滤波器的设置有关,当数字低通滤波器的低三位写入0或者7时,为8Khz,其余均是1Khz
{
        u8 Data;  //定义Data是采样率分频寄存器写入的8位数值
        if(Rate>1000) //设置范围
                Rate=1000;
        if(Rate<4)    //设置范围
                Rate=4;
        Data=1000/Rate-1;  //采样频率 = 陀螺仪输出频率 / (1+SMPLRT_DIV)  其中SMPLRT_DIV就是Data,寄存器中写入的值
        //采样频率 = 陀螺仪输出频率 / (1+Data) 其中输出频率是1Khz
        Data=MPU6050_Write_Byte(MPU_SAMPLE_RATE_REG,Data); //设置数字低通滤波器
        return MPU6050_Set_LPF(Rate/2); //自动设置数字低通滤波器为采样频率的一半
}
//得到温度值
//返回值:温度值(扩大了100倍)
short MPU6050_Get_Temperature(void)
{
        u8 Buffer[2]; //温度的值是由两个八位寄存器读取的,所以定义一个存储两字节大小的数组
        short raw;  //短整型16位
        float temperature;
        MPU6050_Read_Len(MPU_Address,MPU_TEMP_OUTH_REG,2,Buffer);
        raw=((u16)Buffer[0]<<8)|Buffer[1]; //16位温度值需要两个8位进行或运算
        temperature=36.53+((double)raw)/340; //Temperature = 36.53 + regval/340 ,计算温度的公式 其中regval是从0X41和0X42寄存器读出的值
        return temperature*100;
}
//得到陀螺仪原始值
//GX,GY,GZ:陀螺仪X,Y,Z轴的原始读数
//返回值:0,成功
//    其他,错误代码
u8 MPU6050_Get_Gyroscope(short *GX,short *GY,short *GZ)
{
        u8 Buffer[6];
        u8 res;
        res=MPU6050_Read_Len(MPU_Address,MPU_GYRO_XOUTH_REG,6,Buffer);//读陀螺仪的原始值是通过读6个陀螺仪数据输出寄存器,这些寄存器都是8位的,每两个寄存器拼接成一个16位的原始数据
        if(res==0)//返回值为0,表示读成功
        {
                *GX=((u16)Buffer[0]<<8)|Buffer[1];//因为先读的是寄存器的高8位
                *GY=((u16)Buffer[2]<<8)|Buffer[3];
                *GZ=((u16)Buffer[4]<<8)|Buffer[5];
        }
        return res;
}
//得到加速度计原始值
//AX,AY,AZ:加速度计X,Y,Z轴的原始读数
//返回值:0,成功
//    其他,错误代码
u8 MPU6050_Get_Accelerometer(short *AX,short *AY,short *AZ)
{
        u8 Buffer[6];
        u8 res;
        res=MPU6050_Read_Len(MPU_Address,MPU_ACCEL_XOUTH_REG,6,Buffer);//读加速度计的原始值是通过读6个加速度数据输出寄存器,这些寄存器都是8位的,每两个寄存器拼接成一个16位的原始数据
        if(res==0)//返回值为0,表示读成功
        {
                *AX=((u16)Buffer[0]<<8)|Buffer[1];//因为先读的是寄存器高8位
                *AY=((u16)Buffer[2]<<8)|Buffer[3];
                *AZ=((u16)Buffer[4]<<8)|Buffer[5];
        }
        return res;
}
//IIC连续写
//Address:器件地址
//Register:寄存器地址
//Length:要写入的长度
//Buffer:数据区
//返回值:0,正常
//                其他,错误代码
u8 MPU6050_Write_Len(u8 Address,u8 Register,u8 Length,u8 *Buffer)
{
        u8 i;
        IIC_Start(); //发送起始信号
        IIC_Send_Byte((Address<<1)|0); //主机向从机发送器件地址,也就是主机想要和从机的哪块地址进行通讯,地址最低位是读写位
        //IIC发送的从机地址是7位,最低位是R/W:主从写方向位,(Address<<1)|0表示左移一位再把最低位置0,也就表示主机写数据到从机
        if(IIC_Wait_Ack()) //等待从机应答,IIC_Wait_Ack该函数的返回值若为1,则表示没有接收到从机的应答信号,IIC通讯结束
        {
                IIC_Stop();
                return 1;
        }
        IIC_Send_Byte(Register); //跳过if判断语句就意味着从机接收到了主机的信号,主机发送寄存器地址
        IIC_Wait_Ack(); //等待从机应答
        for(i=0;i<Length;i++)
        {
                IIC_Send_Byte(Buffer[i]);//通过循环一位一位的发送数据,发送Length字节长的数据
                if(IIC_Wait_Ack())//IIC时序规定每发送一位,从机都要应答一次
                {
                        IIC_Stop();
                        return 1;
                }
        }
        IIC_Stop(); //发送完毕,IIC通讯结束
        return 0;
}
//IIC连续读
//Address:器件地址
//Register:要读取的寄存器地址
//Length:要读取的长度
//Buffer:读取到的数据存储区
//返回值:0,正常
//                其他,错误代码
u8 MPU6050_Read_Len(u8 Address,u8 Register,u8 Length,u8 *Buffer)
{
        IIC_Start(); //发送起始信号
        IIC_Send_Byte((Address<<1)|0); //主机向从机发送器件地址,也就是主机想要和从机的哪块地址进行通讯
        //IIC发送的从机地址是7位,最低位是R/W:主从写方向位,(Address<<1)|0表示左移一位再把最低位置0,也就表示主机写数据到从机
        if(IIC_Wait_Ack()) //等待从机应答,IIC_Wait_Ack该函数的返回值若为1,则表示没有接收到从机的应答信号,IIC通讯结束
        {
                IIC_Stop();
                return 1;
        }
        IIC_Send_Byte(Register); //跳过if判断语句就意味着从机接收到了主机的信号,主机发送寄存器地址
        IIC_Wait_Ack(); //等待从机应答
        IIC_Start(); //发送起始信号
        IIC_Send_Byte((Address<<1)|1); //主机向从机发送器件地址,也就是主机想要和从机的哪块地址进行通讯
        //IIC发送的从机地址是7位,最低位是R/W:主从写方向位,(Address<<1)|1表示左移一位再把最低位置1,也就表示主机从从机中读数据
        IIC_Wait_Ack(); //等待从机应答
        while(Length)
        {
                if(Length==1)//如果只写入了一个节长的数据,那么发送NAck
                {
                        *Buffer=IIC_Read_Byte(0); //不产生应答
                }
                else
                        *Buffer=IIC_Read_Byte(1);//产生应答
                Length--;
                Buffer++;
        }
        IIC_Stop();
        return 0;
}
//IIC写一个字节
//Register:寄存器地址
//Data:数据
//返回值:0,正常
//                其他,错误代码
u8 MPU6050_Write_Byte(u8 Register,u8 Data)
{
        IIC_Start();
        IIC_Send_Byte((MPU_Address<<1)|0); //注意写一位写字节时,发送的是从机IIC的地址
        if(IIC_Wait_Ack()) //等待从机应答,IIC_Wait_Ack该函数的返回值若为1,则表示没有接收到从机的应答信号,IIC通讯结束
        {
                IIC_Stop();
                return 1;
        }
        IIC_Send_Byte(Register);
        IIC_Wait_Ack();
        IIC_Send_Byte(Data);
        if(IIC_Wait_Ack()) //等待从机应答,IIC_Wait_Ack该函数的返回值若为1,则表示没有接收到从机的应答信号,IIC通讯结束
        {
                IIC_Stop();
                return 1;
        }
        IIC_Stop();
        return 0;
}
//IIC读一个字节
//Register:寄存器地址
//返回值:读到的数据
u8 MPU6050_Read_Byte(u8 Register)
{
        u8 res;
        IIC_Start();
        IIC_Send_Byte((MPU_Address<<1)|0);
        IIC_Wait_Ack();
        IIC_Send_Byte(Register);
        IIC_Wait_Ack();
        IIC_Start();
        IIC_Send_Byte((MPU_Address<<1)|1);
        IIC_Wait_Ack();
        res=IIC_Read_Byte(0);
        IIC_Stop();
        return res;
}

使用特权

评论回复
43
kqh11a|  楼主 | 2023-6-29 18:55 | 只看该作者
MyMPU6050.h

#ifndef _MYMPU6050__H_
#define _MYMPU6050__H_
#include "sys.h"
#include "MyI2C.h"

/
//MyMPU6050.h头文件的寄存器地址宏定义均来源于MPU6050寄存器手册。如果想要了解每一种寄存器对应位的具体功能,请查阅MPU6050寄存器手册。
#define MPU_SELF_TESTX_REG                0X0D        //自检寄存器X
#define MPU_SELF_TESTY_REG                0X0E        //自检寄存器Y
#define MPU_SELF_TESTZ_REG                0X0F        //自检寄存器Z
#define MPU_SELF_TESTA_REG                0X10        //自检寄存器A
#define MPU_SAMPLE_RATE_REG                0X19        //采样频率分频器
#define MPU_CFG_REG                                0X1A        //配置寄存器
#define MPU_GYRO_CFG_REG                0X1B        //陀螺仪配置寄存器
#define MPU_ACCEL_CFG_REG                0X1C        //加速度计配置寄存器
#define MPU_MOTION_DET_REG                0X1F        //运动检测阀值设置寄存器
#define MPU_FIFO_EN_REG                        0X23        //FIFO使能寄存器
#define MPU_I2CMST_CTRL_REG                0X24        //IIC主机控制寄存器
#define MPU_I2CSLV0_ADDR_REG        0X25        //IIC从机0器件地址寄存器
#define MPU_I2CSLV0_REG                        0X26        //IIC从机0数据地址寄存器
#define MPU_I2CSLV0_CTRL_REG        0X27        //IIC从机0控制寄存器
#define MPU_I2CSLV1_ADDR_REG        0X28        //IIC从机1器件地址寄存器
#define MPU_I2CSLV1_REG                        0X29        //IIC从机1数据地址寄存器
#define MPU_I2CSLV1_CTRL_REG        0X2A        //IIC从机1控制寄存器
#define MPU_I2CSLV2_ADDR_REG        0X2B        //IIC从机2器件地址寄存器
#define MPU_I2CSLV2_REG                        0X2C        //IIC从机2数据地址寄存器
#define MPU_I2CSLV2_CTRL_REG        0X2D        //IIC从机2控制寄存器
#define MPU_I2CSLV3_ADDR_REG        0X2E        //IIC从机3器件地址寄存器
#define MPU_I2CSLV3_REG                        0X2F        //IIC从机3数据地址寄存器
#define MPU_I2CSLV3_CTRL_REG        0X30        //IIC从机3控制寄存器
#define MPU_I2CSLV4_ADDR_REG        0X31        //IIC从机4器件地址寄存器
#define MPU_I2CSLV4_REG                        0X32        //IIC从机4数据地址寄存器
#define MPU_I2CSLV4_DO_REG                0X33        //IIC从机4写数据寄存器
#define MPU_I2CSLV4_CTRL_REG        0X34        //IIC从机4控制寄存器
#define MPU_I2CSLV4_DI_REG                0X35        //IIC从机4读数据寄存器

#define MPU_I2CMST_STA_REG                0X36        //IIC主机状态寄存器
#define MPU_INTBP_CFG_REG                0X37        //中断/旁路设置寄存器
#define MPU_INT_EN_REG                        0X38        //中断使能寄存器
#define MPU_INT_STA_REG                        0X3A        //中断状态寄存器

#define MPU_ACCEL_XOUTH_REG                0X3B        //加速度值,X轴高8位寄存器
#define MPU_ACCEL_XOUTL_REG                0X3C        //加速度值,X轴低8位寄存器
#define MPU_ACCEL_YOUTH_REG                0X3D        //加速度值,Y轴高8位寄存器
#define MPU_ACCEL_YOUTL_REG                0X3E        //加速度值,Y轴低8位寄存器
#define MPU_ACCEL_ZOUTH_REG                0X3F        //加速度值,Z轴高8位寄存器
#define MPU_ACCEL_ZOUTL_REG                0X40        //加速度值,Z轴低8位寄存器

#define MPU_TEMP_OUTH_REG                0X41        //温度值高八位寄存器
#define MPU_TEMP_OUTL_REG                0X42        //温度值低8位寄存器

#define MPU_GYRO_XOUTH_REG                0X43        //陀螺仪值,X轴高8位寄存器
#define MPU_GYRO_XOUTL_REG                0X44        //陀螺仪值,X轴低8位寄存器
#define MPU_GYRO_YOUTH_REG                0X45        //陀螺仪值,Y轴高8位寄存器
#define MPU_GYRO_YOUTL_REG                0X46        //陀螺仪值,Y轴低8位寄存器
#define MPU_GYRO_ZOUTH_REG                0X47        //陀螺仪值,Z轴高8位寄存器
#define MPU_GYRO_ZOUTL_REG                0X48        //陀螺仪值,Z轴低8位寄存器

#define MPU_I2CSLV0_DO_REG                0X63        //IIC从机0数据寄存器
#define MPU_I2CSLV1_DO_REG                0X64        //IIC从机1数据寄存器
#define MPU_I2CSLV2_DO_REG                0X65        //IIC从机2数据寄存器
#define MPU_I2CSLV3_DO_REG                0X66        //IIC从机3数据寄存器

#define MPU_I2CMST_DELAY_REG        0X67        //IIC主机延时管理寄存器
#define MPU_SIGPATH_RST_REG                0X68        //信号通道复位寄存器
#define MPU_MDETECT_CTRL_REG        0X69        //运动检测控制寄存器
#define MPU_USER_CTRL_REG                0X6A        //用户控制寄存器
#define MPU_PWR_MGMT1_REG                0X6B        //电源管理寄存器1
#define MPU_PWR_MGMT2_REG                0X6C        //电源管理寄存器2
#define MPU_FIFO_CNTH_REG                0X72        //FIFO计数寄存器高八位
#define MPU_FIFO_CNTL_REG                0X73        //FIFO计数寄存器低八位
#define MPU_FIFO_RW_REG                        0X74        //FIFO读写寄存器
#define MPU_DEVICE_ID_REG                0X75        //器件ID寄存器

//如果MPU6050芯片的引脚A0接地,IIC地址为0X68
//如果MPU6050芯片的引脚A0接电源3.3V,则IIC的地址为0X69
#define MPU_Address 0X68



u8 MPU6050_Init(void);
u8 MPU6050_Set_Gyro_Fsr(u8 FS_SEL);
u8 MPU6050_Set_Accel_Fsr(u8 AFS_SEL);
u8 MPU6050_Set_LPF(u16 PinLv);
u8 MPU6050_Set_Rate(u16 Rate);
short MPU6050_Get_Temperature(void);
u8 MPU6050_Get_Gyroscope(short *GX,short *GY,short *GZ);
u8 MPU6050_Get_Accelerometer(short *AX,short *AY,short *AZ);
u8 MPU6050_Write_Len(u8 Address,u8 Register,u8 Length,u8 *Buffer);
u8 MPU6050_Read_Len(u8 Address,u8 Register,u8 Length,u8 *Buffer);
u8 MPU6050_Write_Byte(u8 Register,u8 Data);
u8 MPU6050_Read_Byte(u8 Register);


#endif

使用特权

评论回复
44
Bblythe| | 2023-12-1 07:14 | 只看该作者

减小检测部分与电压误差或电流放大器敏感的输入端之间的连接而引入的噪声

使用特权

评论回复
45
周半梅| | 2023-12-1 09:10 | 只看该作者

引线越长,它能接收和传送的干扰信号频率就越低

使用特权

评论回复
46
Pulitzer| | 2023-12-1 10:13 | 只看该作者

输入电压端上测得的值比它实际

使用特权

评论回复
47
童雨竹| | 2023-12-1 12:09 | 只看该作者

引线的长和宽影响它的电阻和电感量

使用特权

评论回复
48
Wordsworth| | 2023-12-1 13:12 | 只看该作者

它们的放置要尽可能靠近

使用特权

评论回复
49
Clyde011| | 2023-12-1 14:15 | 只看该作者

大地的地会通过散热器(用绝缘体与漏极隔开)从这些节点获取能量

使用特权

评论回复
50
万图| | 2023-12-1 16:11 | 只看该作者

输入电源电流环路

使用特权

评论回复
51
Uriah| | 2023-12-1 17:14 | 只看该作者

交流节点会引起特有的问题

使用特权

评论回复
52
帛灿灿| | 2023-12-1 19:10 | 只看该作者

输入和输出电流环路连接的位置只能是相应的输入 输出电容的接线端

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则