【I2C】软件I2C读写MPU6050

本文介绍了如何在STM32F10x微控制器上基于软件I2C驱动开发MPU6050运动传感器模块,包括编写驱动程序的基本代码、初始化函数、读写寄存器函数,以及如何解除芯片睡眠模式和读取数据寄存器。通过这些步骤,实现了对MPU6050的初始化和数据读取,可用于加速度计和陀螺仪数据的实时显示。
摘要由CSDN通过智能技术生成

基于【软件I2C驱动】增加【MPU6050】模块驱动代码

1、完成MPU6050驱动文件导入操作和编写驱动程序基本代码(参考之前文章)

//将【MPU6050】驱动文件放在【Hardware】文件夹中

2、在MPU6050.c中初始化函数MPU6050_Init读/写寄存器函数

#include "stm32f10x.h"                  // Device header

#include "MyI2C.h"

#define    MPU6050_ADDRESS        0xD0        //宏定义从机地址

//指定地址写寄存器

/*

参数1:8位寄存器地址

参数2:8位数据

*/

void MPU6050_WriteReg(uint8_t RegAddress,uint8_t Data)

{

    //调用Start产生起始条件开始传输

    MyI2C_Start();

    

   //第一个字节时序(必须是发送)——字节内容:从机地址(7位)+读写位(1位)

    MyI2C_SendByte(MPU6050_ADDRESS);    //1101 000 0    (0代表即将进行写入操作)

    //【接收应答】

    MyI2C_ReceiveAck();

    

    //第二个字节时序——指定具体读写的寄存器地址

    MyI2C_SendByte(RegAddress);

    //这个字节存放在MPU6050的当前地址指针里

    //【接收应答】

    MyI2C_ReceiveAck();

    

    //第三个字节时序——指定主机写入指定寄存器地址的内容

    MyI2C_SendByte(Data);

    //【接收应答】

    MyI2C_ReceiveAck();

    

    //调用Stop产生终止条件结束传输

    MyI2C_Stop();

}

//指定地址读寄存器

/*

参数:指定主机读取的地址

*/

uint8_t MPU6050_ReadReg(uint8_t RegAddress)

{

    //定义变量存储主机读取的数据

    uint8_t Data;

    

    //调用Start产生起始条件开始传输

    MyI2C_Start();

    

   //第一个字节时序(必须是发送)——字节内容:从机地址(7位)+读写位(1位)

    MyI2C_SendByte(MPU6050_ADDRESS);    //1101 000 0    (0代表即将进行写入操作)

    //【接收应答】

    MyI2C_ReceiveAck();

    

    //第二个字节时序——指定具体读写的寄存器地址

    MyI2C_SendByte(RegAddress);

    //这个字节存放在MPU6050的当前地址指针里

    //【接收应答】

    MyI2C_ReceiveAck();

    

    //转入【读取】时序

    //调用Start产生【重复起始】(重新指定读写位)

    MyI2C_Start();

    

    //第三个字节时序——字节内容:从机地址(7位)+读写位(1位)

    MyI2C_SendByte(MPU6050_ADDRESS | 0xD1);    //1101 000 1    (1代表即将进行读取操作)

    //【接收应答】

    MyI2C_ReceiveAck();

    

    //第四个字节时序——从机得到主机赋予的SDA控制权

    //从机发送一个字节,主机接收一个字节

    Data = MyI2C_ReceiveByte();

    //【发送应答】

    MyI2C_SendAck(1);

    

    //调用Stop产生终止条件结束传输

    MyI2C_Stop();

    

    return Data;

}

void MPU6050_Init(void)

{

    //本模块基于【MyI2C】底层函数

    MyI2C_Init();

}

3、在MPU6050.h中声明初始化函数初始化函数MPU6050_Init及读/写寄存器函数

void MPU6050_Init(void);

void MPU6050_WriteReg(uint8_t RegAddress,uint8_t Data);

uint8_t MPU6050_ReadReg(uint8_t RegAddress);

4、在主程序main.c中#include "MPU6050.h"

#include "MPU6050.h"

5、在主循环中编写程序主体

#include "MPU6050.h"

int main(void)

{

    //MPU6050_Init为上层模块,已调用底层的MyI2C_Init

    MPU6050_Init();

    

    OLED_Init();

    

    //读取芯片ID号函数的【WHO_AM_I】寄存器(地址0x75)

    uint8_t ID = MPU6050_ReadReg(0x75);

    

    OLED_ShowHexNum(1,1,ID,2);

    while(1)

    {

    }

}

实现功能:上电后初始化I2C和OLED模块,通过软件I2C读取从机指定地址【0x75】(芯片ID号函数的【WHO_AM_I】寄存器),通过OLED显示芯片ID号为【68】


上一个程序验证了【读寄存器】功能正常,现在进行验证【写寄存器】功能

1、解除芯片睡眠模式(否则写入无效)

//在电源管理寄存器1【0x6B】写入【0x00】,解除睡眠模式

    MPU6050_WriteReg(0x6B,0x00);

2、在主循环中编写程序主体

int main(void)

{

    //MPU6050_Init为上层模块,已调用底层的MyI2C_Init

    MPU6050_Init();

    

    OLED_Init();

    

    //在电源管理寄存器1【0x6B】写入【0x00】,解除睡眠模式

    MPU6050_WriteReg(0x6B,0x00);

    

    //向【0x19】寄存器写入【0xAA】

    MPU6050_WriteReg(0x19,0xAA);

    

    //读取【0x19】寄存器(地址0x19)

    uint8_t ID = MPU6050_ReadReg(0x19);

    

    OLED_ShowHexNum(1,1,ID,2);

    while(1)

    {

    }

}

实现功能:上电后初始化I2C和OLED模块,解除睡眠模式以开启写入功能,通过软件I2C在从机指定地址【0x19】写入【0xAA】并通过OLED显示该寄存器值为【0xAA】


完善MPU6050模块初始化程序

1、完成MPU6050寄存器宏定义文件导入操作和编写宏定义寄存器代码(参考之前文章)

//将【MPU6050_Reg.h】宏定义文件放在【Hardware】文件夹中

2、完善MPU6050.c中初始化函数MPU6050_Init和获取数据寄存器函数MPU6050_GetData

void MPU6050_Init(void)

{

    //本模块基于【MyI2C】底层函数

    MyI2C_Init();

    

    //配置电源管理寄存器1

    MPU6050_WriteReg(MPU6050_PWR_MGMT_1,0x01);

    

    //配置电源管理寄存器2

    MPU6050_WriteReg(MPU6050_PWR_MGMT_2,0x00);

    

    //采样率分频

    MPU6050_WriteReg(MPU6050_SMPLRT_DIV,0x09);

    

    //配置寄存器

    MPU6050_WriteReg(MPU6050_CONFIG,0x06);

    

    //陀螺仪配置寄存器

    MPU6050_WriteReg(MPU6050_GYRO_CONFIG,0x18);

    

    //加速度计配置寄存器

    MPU6050_WriteReg(MPU6050_ACCEL_CONFIG,0x18);

    

    //配置之后陀螺仪内部开始连续不断地进行数据转换

    //输出的数据存放在对应的数据寄存器中

}

//获取数据寄存器

/*返回6个int16_t的数据,分别表示XYZ的【加速度值】和【陀螺仪值】

参数均为int16_t的指针类型,之后在主函数里定义变量【数据高/低8位】

通过指针把主函数变量的地址传递到子函数

子函数中通过传递过来的地址操作主函数的变量

子函数结束后,主函数变量的值就是子函数想要返回的值

程序逻辑:分别读取6个轴数据寄存器的高/低位,拼接成16位数据并通过指针变量返回

*/

void MPU6050_GetData(int16_t *AccX,int16_t *AccY,int16_t *AccZ,

                     int16_t *GyroX,int16_t *GyroY,int16_t *GyroZ)

{

    uint8_t DataH,DataL;

    

    //读取高/低8位的值放在DataH/L中

    DataH = MPU6050_ReadReg(MPU6050_ACCEL_XOUT_H);

    DataL = MPU6050_ReadReg(MPU6050_ACCEL_XOUT_L);

    *AccX = (DataH << 8) | DataL;

    //高8位左移8位或上低8位=【加速度计X轴的16位数据】

    //用指针引用传递进来的地址,把读到的数据通过指针返回回去

    

    //读取高/低8位的值放在DataH/L中

    DataH = MPU6050_ReadReg(MPU6050_ACCEL_YOUT_H);

    DataL = MPU6050_ReadReg(MPU6050_ACCEL_YOUT_L);

    *AccY = (DataH << 8) | DataL;

    //高8位左移8位或上低8位=【加速度计Y轴的16位数据】

    //用指针引用传递进来的地址,把读到的数据通过指针返回回去

    

    //读取高/低8位的值放在DataH/L中

    DataH = MPU6050_ReadReg(MPU6050_ACCEL_ZOUT_H);

    DataL = MPU6050_ReadReg(MPU6050_ACCEL_ZOUT_L);

    *AccZ = (DataH << 8) | DataL;

    //高8位左移8位或上低8位=【加速度计Z轴的16位数据】

    //用指针引用传递进来的地址,把读到的数据通过指针返回回去

    

    //读取高/低8位的值放在DataH/L中

    DataH = MPU6050_ReadReg(MPU6050_GYRO_XOUT_H);

    DataL = MPU6050_ReadReg(MPU6050_GYRO_XOUT_L);

    *GyroX = (DataH << 8) | DataL;

    //高8位左移8位或上低8位=【陀螺仪X轴的16位数据】

    //用指针引用传递进来的地址,把读到的数据通过指针返回回去

    

    //读取高/低8位的值放在DataH/L中

    DataH = MPU6050_ReadReg(MPU6050_GYRO_XOUT_H);

    DataL = MPU6050_ReadReg(MPU6050_GYRO_XOUT_L);

    *GyroY = (DataH << 8) | DataL;

    //高8位左移8位或上低8位=【陀螺仪Y轴的16位数据】

    //用指针引用传递进来的地址,把读到的数据通过指针返回回去

    

    //读取高/低8位的值放在DataH/L中

    DataH = MPU6050_ReadReg(MPU6050_GYRO_XOUT_H);

    DataL = MPU6050_ReadReg(MPU6050_GYRO_XOUT_L);

    *GyroZ = (DataH << 8) | DataL;

    //高8位左移8位或上低8位=【陀螺仪Z轴的16位数据】

    //用指针引用传递进来的地址,把读到的数据通过指针返回回去

}

3、在MPU6050.h中声明初始化函数MPU6050_Init和获取数据寄存器函数MPU6050_GetData

void MPU6050_Init(void);

uint8_t MPU6050_GetID(void);

void MPU6050_WriteReg(uint8_t RegAddress,uint8_t Data);

uint8_t MPU6050_ReadReg(uint8_t RegAddress);

void MPU6050_GetData(int16_t *AccX,int16_t *AccY,int16_t *AccZ,

                                        int16_t *GyroX,int16_t *GyroY,int16_t *GyroZ);

4、在主程序main.c中#include "MPU6050.h"

#include "MPU6050.h"

5、在主循环中编写程序主体

//定义变量用于接受XZY轴的加速度值和陀螺仪值

int16_t AX,AY,AZ,GX,GY,GZ;

uint8_t ID;

int main(void)

{

    //MPU6050_Init为上层模块,已调用底层的MyI2C_Init

    MPU6050_Init();

    

    OLED_Init();

    OLED_ShowString(1,1,"ID:");

    ID = MPU6050_GetID();

    OLED_ShowHexNum(1,4,ID,2);

    

    while(1)

    {

        //不断读取数据

        MPU6050_GetData(&AX,&AY,&AZ,&GX,&GY,&GZ);

        OLED_ShowSignedNum(2,1,AX,5);

        OLED_ShowSignedNum(3,1,AY,5);

        OLED_ShowSignedNum(4,1,AZ,5);

        OLED_ShowSignedNum(2,8,GX,5);

        OLED_ShowSignedNum(3,8,GY,5);

        OLED_ShowSignedNum(4,8,GZ,5);

    }

}

实现功能:上电后初始化I2C和OLED模块,显示芯片ID号,在循环中通过软件I2C不断读取加速度计和陀螺仪数据寄存器,并通过OLED显示对应XYZ轴数值


  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值