STM32基础教程——软件I2C
目录
前言
I2C
MPU6050
技术实现
原理图
连线图
代码实现
技术要点
I2C初始化
SCL输出和SDA输入输出控制
起始信号
停止信号
发送一个字节
读取一个字节
发送应答位
接收应答位
MPU6050初始化
指定地址写
指定地址读
读取数据寄存器
问题记录
前言
I2C
I2C(Inter-Integrated Circuit)是一种由飞利浦公司在1980年代开发的串行通信协议,主要用于在同一电路板上的短距离集成电路之间的通信。它以两线式接口著称,这两条线分别是SDA(数据线)和SCL(时钟线),允许通过这些线路在支持I2C协议的各种设备之间进行双向通信。I2C协议支持多主多从架构,使得多个设备可以通过共享的数据线和时钟线实现有效的通信。其特点是简单、成本低,并且能够支持多种速度标准,如标准模式(100 kbit/s)、快速模式(400 kbit/s)以及高速模式(3.4 Mbit/s),适用于各种应用场景,包括但不限于传感器数据交换、EEPROM编程等。
I2C主要特点 (部分)
- 并行总线/I2C总线协议转换器
- 多主机功能,该模块既可做主设备也可做从设备
- I2C主设备功能
——产生时钟
——产生起始和终止信号
- I2C从设备功能
——可编程的I2C地址检测
——可响应两个从地址的双地址功能
——停止检测位
- 支持不同的通讯速度
——标准速度(高达100kHz)
——快速(高达400kHz)
模式选择
接口可以下列4种模式中的一种运行:
- 从发送器模式
- 从接收器模式
- 主发送器模式
- 主接收器模式
该模块默认地工作于从模式接口在生成起始条件后自动地从从模式切换到主模式: 当仲裁丢失或产生停止信号时,则从主模式切换到从模式。允许多主机功能。
通信流
主模式时,I2C接口启动数据传输并产生时钟信号。串行数据传输总是以起始条件开始并以停止条件结束。起始条件和停止条件都是在主模式下由软件控制产生。
从模式时,I2C接口能识别它自己的地址(7位或10位)和广播呼叫地址。软件能够控制开启或禁止广播呼叫地址的识别。
数据和地址按8位/字节传输,高位在前。跟在起始条件之后的1或2个字节是地址(7位模式为1个字节,10位模式为2个字节)。地址只在主模式发送。
在一个字节传输的8个时钟后的第9个时钟期间,接收器必须回送一个应答位(ACK)给发送器。
软件可以开启或禁止应答(ACK),并可以设置I2C接口的地址(7位、10位地址或广播呼叫地址)
I2C主模式
在主模式时,I2C接口启动数据传输并产生时钟信号。串行数据传输总是以起始条件开始并以停止条件结束。当通过START位在总线上产生了起始条件,设备就进入了主模式。
起始条件
当BUSY=0时,设置START=1,I2C接口将产生一个开始条件并切换至主模式。
一旦发出开始条件:SB位被硬件置位,然后主设备等待读SR1寄存器,紧跟着将从地址写入DR寄存器(EV5)。
从地址的发送
从地址通过内部移位寄存器被送到SDA线上。
在7位地址模式时,只需送出一个地址字节。
——一旦改地址字节被送出,ADDR位被硬件置位,随后主设备等待一次读SR1寄存器,跟着读SR2寄存器。根据送出从地址的最低位,主设备决定进入发送器模式还是接收器模式。
在 7位地址模式时,
——要进入发送器模式,主设备发送从地址时置最低位为‘0’。
——要进入接收器模式,主设备发送从地址时置最低为‘1’。
主发送器
在发送了地址和清除了ADDR位后,主设备通过内部移位寄存器将字节从DR寄存器发送到SDA线上。
主设备等待,直到TxE被清除。(EV8)
当收到应答脉冲时:
TxE位被硬件置位,如果TxE被置位并且在上一次数据发送结束之前没有写入新的数据字节到DR寄存器,则BTF位被硬件置位,在清除BTF之前I2C接口将保持SCL为低电平;读出I2C_SR1之后再写入I2C_DR寄存器将清除BTF位。
关闭通信
在DR寄存器中写入最后一个字节后,通过设置STOP位产生一个停止条件(EV8_2)然后I2C接口将自动回到从模式。
主接收器
在发送地址和清除ADDR之后,I2C接口进入主接收器模式。在此模式下,I2C接口从SDA线接收数据字节,并通过内部移位寄存器送至DR寄存器。在每个字节后,I2C接口依次执行以下操作:
- 如果ACK位被置位,发出一个应答脉冲。
- 硬件设置RxNE=1(EV7)
如果RxNE位被置位,并且在接收新数据结束之前,DR寄存器中的数据没有被读走,硬件将设置BTF=1,在清除BTF之前I2C接口将保持SCL为低电平读出I2C_SR1之后再读出I2C_DR寄存器将清除BTF位。
关闭通信
主设备在从从设备接收到最后一个字节后发送一个NACK。接收到NACK后,从设备释放对SCL和SDA线的控制:主设备就可以发送一个停止/重起始条件。
- 为了在收到最后一个字节后发送一个NACK,在读倒数第二个数据字节之后(在倒数第二个RxNE事件之后)必须清除ACK位。
- 为了产生一个停止/重起始条件软件必须在读倒数第二个数据字节之后(在倒数第二个RxNE事件之后)设置STOP/START位。
- 只接收一个字节时,刚好在EV6之后(EV6_1时,清除ADDR之后)要关闭应答和停止条件的产生位。
在产生了停止条件后,I2C接口自动回到从模式。
MPU6050
MPU6050是一款集成的运动处理传感器,它结合了一个3轴陀螺仪和一个3轴加速度计,能够提供精确的角速度和加速度数据,常用于姿态检测、运动跟踪及导航等应用。该器件支持I2C和SPI通信接口,便于与微控制器(如Arduino、STM32等)连接,并且内置数字运动处理器(DMP),可以分担主控芯片的数据处理负担,提高系统效率。MPU6050广泛应用于无人机、机器人、可穿戴设备等领域,因其高性价比和易用性而受到开发者青睐。
技术实现
原理图
连线图
代码实现
main.c
/**********************************************************
1.实验名称:I2C读取MPU6050
2.实验环境:STM32F103C8T6最小系统板
3.实验内容:使用I2C协议与MPU6050通信,读取寄存器获取加速度计和陀螺仪数据,显示加速度和角速度
4.作者;abai
5.实验时间:2025-4-28
**********************************************************/
#include "stm32f10x.h" // Device header
#include "Delay.h" //延时函数
#include "OLED.h"
#include "MPU6050.h"int main(void)
{int16_t Acce_x,Acce_y,Acce_z,Gyro_x,Gyro_y,Gyro_z;/*OLED初始化*/OLED_Init();MPU6050_Init();while(1){MPU6050_GetValue(&Acce_x,&Acce_y,&Acce_z,&Gyro_x,&Gyro_y,&Gyro_z);OLED_ShowString(1,1,"Acce:");OLED_ShowString(1,9,"Gyro:");OLED_ShowSignedNum(2,1,Acce_x,5);OLED_ShowSignedNum(3,1,Acce_y,5);OLED_ShowSignedNum(4,1,Acce_z,5);OLED_ShowSignedNum(2,9,Gyro_x,5);OLED_ShowSignedNum(3,9,Gyro_y,5);OLED_ShowSignedNum(4,9,Gyro_z,5);}
}
MPU6050_Reg.h
#ifndef MPU6050_REG_H
#define MPU6050_REG_H//寄存器宏
#define MPU6050_SMPLRT_DIV 0X19
#define MPU6050_CONFIG 0X1A
#define MPU6050_GYRO_CONFIG 0X1B
#define MPU6050_ACCEL_CONFIG 0X1C
#define MPU6050_ACCEL_XOUT_H 0X3B
#define MPU6050_ACCEL_XOUT_L 0X3C
#define MPU6050_ACCEL_YOUT_H 0X3D
#define MPU6050_ACCEL_YOUT_L 0X3E
#define MPU6050_ACCEL_ZOUT_H 0X3F
#define MPU6050_ACCEL_ZOUT_L 0X40
#define MPU6050_TEMP_OUT_H 0X41
#define MPU6050_TEMP_OUT_L 0X42
#define MPU6050_GYRO_XOUT_H 0X43
#define MPU6050_GYRO_XOUT_L 0X44
#define MPU6050_GYRO_YOUT_H 0X45
#define MPU6050_GYRO_YOUT_L 0X46
#define MPU6050_GYRO_ZOUT_H 0X47
#define MPU6050_GYRO_ZOUT_L 0X48
#define MPU6050_PWR_MGMT_1 0X6B
#define MPU6050_PWR_MGMT_2 0X6C
#define MPU6050_WHO_AM_I 0X75#endif
MPU6050.h
#ifndef MPU6050_H
#define MPU6050_H#include "stm32f10x.h" // Device headervoid MPU6050_Init(void);
void MPU6050_WriteReg(uint8_t RegAddress, uint8_t Data);
uint8_t MPU6050_RedReg(uint8_t RegAddress);
void MPU6050_GetValue(int16_t* Acce_x, int16_t* Acce_y, int16_t* Acce_z,int16_t* Gyro_x, int16_t* Gyro_y, int16_t* Gyro_z);
void MPU6050_RedTemp(int16_t* Temp);#endif
MPU6050.c
#include "MPU6050.h"
#include "MPU6050_Reg.h"#define MPU6050_ADDRESS 0xD0void MPU6050_Init(void)
{MyI2C_Init();//解除睡眠MPU6050_WriteReg(MPU6050_PWR_MGMT_1,0X01); //电源管理寄存器1//6个轴均不待机MPU6050_WriteReg(MPU6050_PWR_MGMT_2,0X00); //电源管理寄存器2MPU6050_WriteReg(MPU6050_SMPLRT_DIV,0X09); //采样率分频寄存器MPU6050_WriteReg(MPU6050_CONFIG,0x06); //不使用帧同步,低通滤波采用最平滑滤波即110BMPU6050_WriteReg(MPU6050_GYRO_CONFIG,0X18); //陀螺仪配置寄存器sMPU6050_WriteReg(MPU6050_ACCEL_CONFIG,0X18); //加速度计寄存器}//指定地址写
void MPU6050_WriteReg(uint8_t RegAddress, uint8_t Data)
{MyI2C_Start();MyI2C_SendByte(MPU6050_ADDRESS);MyI2C_ReceiveACK();MyI2C_SendByte(RegAddress);MyI2C_ReceiveACK();MyI2C_SendByte(Data);MyI2C_ReceiveACK();MyI2C_Stop();
}
//指定地址读
uint8_t MPU6050_RedReg(uint8_t RegAddress)
{uint8_t ByteValue;MyI2C_Start();MyI2C_SendByte(MPU6050_ADDRESS);MyI2C_ReceiveACK();MyI2C_SendByte(RegAddress);MyI2C_ReceiveACK();MyI2C_Start();MyI2C_SendByte(MPU6050_ADDRESS | 0x01);MyI2C_ReceiveACK();ByteValue = MyI2C_ReceiveByte();MyI2C_SendACK(1);MyI2C_Stop();return ByteValue;
}//读取数据寄存器
void MPU6050_GetValue(int16_t* Acce_x, int16_t* Acce_y, int16_t* Acce_z,int16_t* Gyro_x, int16_t* Gyro_y, int16_t* Gyro_z)
{uint8_t Data_H,Data_L;//加速度计X轴Data_H = MPU6050_RedReg(MPU6050_ACCEL_XOUT_H);Data_L = MPU6050_RedReg(MPU6050_ACCEL_XOUT_L);*Acce_x = (Data_H << 8) | Data_L;//加速度计Y轴Data_H = MPU6050_RedReg(MPU6050_ACCEL_YOUT_H);Data_L = MPU6050_RedReg(MPU6050_ACCEL_YOUT_L);*Acce_y = (Data_H << 8) | Data_L;//加速度计Z轴Data_H = MPU6050_RedReg(MPU6050_ACCEL_ZOUT_H);Data_L = MPU6050_RedReg(MPU6050_ACCEL_ZOUT_L);*Acce_z = (Data_H << 8) | Data_L;//陀螺仪x轴Data_H = MPU6050_RedReg(MPU6050_GYRO_XOUT_H);Data_L = MPU6050_RedReg(MPU6050_GYRO_XOUT_L);*Gyro_x = (Data_H << 8) | Data_L;//陀螺仪y轴Data_H = MPU6050_RedReg(MPU6050_GYRO_YOUT_H);Data_L = MPU6050_RedReg(MPU6050_GYRO_YOUT_L);*Gyro_y = (Data_H << 8) | Data_L;//陀螺仪Z轴Data_H = MPU6050_RedReg(MPU6050_GYRO_ZOUT_H);Data_L = MPU6050_RedReg(MPU6050_GYRO_ZOUT_L);*Gyro_z = (Data_H << 8) | Data_L;
}void MPU6050_RedTemp(int16_t* Temp)
{int16_t Data_H,Data_L;Data_H = MPU6050_RedReg(MPU6050_TEMP_OUT_H);Data_L = MPU6050_RedReg(MPU6050_TEMP_OUT_L);*Temp = (Data_H << 8) | Data_L;
}
MyI2C.h
#ifndef MYI2C_H
#define MYI2C_H#include "stm32f10x.h" // Device header
#include "Delay.h"void MyI2C_Init(void);
void MyI2C_SCL_W(uint8_t BitValue);
void MyI2C_SDA_W(uint8_t BitValue);
uint8_t MyI2C_SDA_R(void);
void MyI2C_Start(void);
void MyI2C_Stop(void);
void MyI2C_SendByte(uint8_t Byte);
void MyI2C_SendACK(uint8_t ACKBit);
uint8_t MyI2C_ReceiveByte(void);
uint8_t MyI2C_ReceiveACK(void);#endif
MyI2C.c
#include "MyI2C.h"void MyI2C_Init(void)
{RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);GPIO_InitTypeDef GPIO_InitStruct;GPIO_InitStruct.GPIO_Pin = GPIO_Pin_10 | GPIO_Pin_11;GPIO_InitStruct.GPIO_Mode = GPIO_Mode_Out_OD; GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;GPIO_Init(GPIOB,&GPIO_InitStruct);
}void MyI2C_SCL_W(uint8_t BitValue)
{GPIO_WriteBit(GPIOB,GPIO_Pin_10,(BitAction)BitValue);Delay_us(10);
}void MyI2C_SDA_W(uint8_t BitValue)
{GPIO_WriteBit(GPIOB,GPIO_Pin_11,(BitAction)BitValue);Delay_us(10);
}uint8_t MyI2C_SDA_R(void)
{uint8_t BitValue;BitValue = GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_11);Delay_us(10);return BitValue;
}void MyI2C_Start(void)
{MyI2C_SDA_W(1);MyI2C_SCL_W(1);MyI2C_SDA_W(0);MyI2C_SCL_W(0);
}void MyI2C_Stop(void)
{MyI2C_SDA_W(0);MyI2C_SCL_W(1);MyI2C_SDA_W(1);
}void MyI2C_SendByte(uint8_t Byte)
{uint8_t i;MyI2C_SCL_W(0);for(i=0;i<8;i++){MyI2C_SDA_W((Byte<<i)&0x80);MyI2C_SCL_W(1);MyI2C_SCL_W(0);}//释放SDAMyI2C_SDA_W(1);
}uint8_t MyI2C_ReceiveByte(void)
{uint8_t ByteValue = 0x00;uint8_t i;MyI2C_SDA_W(1);MyI2C_SCL_W(0);for(i=0;i<8;i++){MyI2C_SCL_W(1);if(MyI2C_SDA_R() == 1)ByteValue |= (0x80>>i);MyI2C_SCL_W(0);} return ByteValue;
}void MyI2C_SendACK(uint8_t ACKBit)
{MyI2C_SDA_W(ACKBit);MyI2C_SCL_W(1);MyI2C_SCL_W(0);
}uint8_t MyI2C_ReceiveACK(void)
{uint8_t ACKBit;//主机释放SDAMyI2C_SDA_W(1);MyI2C_SCL_W(1);ACKBit = MyI2C_SDA_R();MyI2C_SCL_W(0);return ACKBit;
}
OLED部分代码参照文章《STM32基础教程——OLED显示》http://【STM32基础教程 ——OLED显示 - CSDN App】https://blog.csdn.net/2301_80319641/article/details/145837521?sharetype=blog&shareId=145837521&sharerefer=APP&sharesource=2301_80319641&sharefrom=link
技术要点
I2C初始化
void MyI2C_Init(void)
{RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);GPIO_InitTypeDef GPIO_InitStruct;GPIO_InitStruct.GPIO_Pin = GPIO_Pin_10 | GPIO_Pin_11;GPIO_InitStruct.GPIO_Mode = GPIO_Mode_Out_OD; GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;GPIO_Init(GPIOB,&GPIO_InitStruct);
}
I2C初始化,目的将PB10和PB11分别作为SCL,SDA。初始化GPIO将它们均配置为开漏输出,因为从设备MPU6050的SDA和SCL引脚均配置了外部弱上拉。输出模式下依旧能够读取输入,当主机接收从机发送的数据时,SDA连接的引脚的数据依旧会在每个APB2时钟被采样到输入数据寄存器。在开漏模式下,对输入数据寄存器的访问可以得到I/O状态。但是推挽输出模式下不可以。这与它们的电气特性有关。
SCL输出和SDA输入输出控制
void MyI2C_SCL_W(uint8_t BitValue)
{GPIO_WriteBit(GPIOB,GPIO_Pin_10,(BitAction)BitValue);Delay_us(10);
}void MyI2C_SDA_W(uint8_t BitValue)
{GPIO_WriteBit(GPIOB,GPIO_Pin_11,(BitAction)BitValue);Delay_us(10);
}uint8_t MyI2C_SDA_R(void)
{uint8_t BitValue;BitValue = GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_11);Delay_us(10);return BitValue;
}
对模拟SDA和SCL的读写进行封装
起始信号
void MyI2C_Start(void)
{MyI2C_SDA_W(1);MyI2C_SCL_W(1);MyI2C_SDA_W(0);MyI2C_SCL_W(0);
}
I2C起始信号,在SCL高电平期间,SDA产生一个下降沿。
起始信号模拟过程:
- 将SDA拉高
- 将SCL拉高
- 将SDA拉低产生下降沿
- 将SCL拉低产生下降沿
停止信号
void MyI2C_Stop(void)
{MyI2C_SDA_W(0);MyI2C_SCL_W(1);MyI2C_SDA_W(1);
}
I2C停止信号:在SCL高电平期间,SDA产生一个上升沿。
终止信号模拟过程:
- 将SDA拉低
- 将SCL拉高
- 将SDA拉高
发送一个字节
void MyI2C_SendByte(uint8_t Byte)
{uint8_t i;MyI2C_SCL_W(0);for(i=0;i<8;i++){MyI2C_SDA_W((Byte<<i)&0x80);MyI2C_SCL_W(1);MyI2C_SCL_W(0);}//释放SDAMyI2C_SDA_W(1);
}
现将SCL拉低,允许SDA数据发生变化,然后使用for循环循环8次发送一个完整的数据字节,每次对数据字节先移位,然后将最高位发送(通过位设置/清除寄存器)。 将SCL拉高再拉低完成一位的发送。数据发送完毕后要将SDA拉高释放SDA。
读取一个字节
uint8_t MyI2C_ReceiveByte(void)
{uint8_t ByteValue = 0x00;uint8_t i;MyI2C_SDA_W(1);MyI2C_SCL_W(0);for(i=0;i<8;i++){MyI2C_SCL_W(1);if(MyI2C_SDA_R() == 1)ByteValue |= (0x80>>i);MyI2C_SCL_W(0);} return ByteValue;
}
读取字节数据之前,先释放SDA,然后将SCL拉低允许数据变化。使用for循环完成一个字节的读取,进入循环先将SCL拉高,保证数据稳定,经对应位的数据赋给临时变量,然后将SCL拉低,允许数据变化。读取完成后将数据字节返回。
发送应答位
void MyI2C_SendACK(uint8_t ACKBit)
{MyI2C_SDA_W(ACKBit);MyI2C_SCL_W(1);MyI2C_SCL_W(0);
}
先发送应答信号,然后将时钟信号拉高再拉低完成一个时钟周期,同时防止影响后续操作。
接收应答位
uint8_t MyI2C_ReceiveACK(void)
{uint8_t ACKBit;//主机释放SDAMyI2C_SDA_W(1);MyI2C_SCL_W(1);ACKBit = MyI2C_SDA_R();MyI2C_SCL_W(0);return ACKBit;
}
主机先释放SDA, 将SCL拉高,保证SDA数据稳定。读取ACK信号,最后将SCL拉低,防止影响后续操作。
MPU6050初始化
void MPU6050_Init(void)
{MyI2C_Init();//解除睡眠MPU6050_WriteReg(MPU6050_PWR_MGMT_1,0X01); //电源管理寄存器1//6个轴均不待机MPU6050_WriteReg(MPU6050_PWR_MGMT_2,0X00); //电源管理寄存器2MPU6050_WriteReg(MPU6050_SMPLRT_DIV,0X09); //采样率分频寄存器MPU6050_WriteReg(MPU6050_CONFIG,0x06); //不使用帧同步,低通滤波采用最平滑滤波即110BMPU6050_WriteReg(MPU6050_GYRO_CONFIG,0X18); //陀螺仪配置寄存器MPU6050_WriteReg(MPU6050_ACCEL_CONFIG,0X18); //加速度计寄存器
}
MPU6050初始化,先初始化I2C,然后指定电源管理寄存器1写入命令0x01,解除MPU6050睡眠,再指定电源管理寄存器2,写入命令0x00,设置6个轴均不待机。然后指定采样分频率寄存器,写入命令0x09,采用10分频。制定MPOU6050 配置寄存器,写入命令0x06,不采用帧同步,采用最平滑的滤波对应位写入110B。对陀螺仪和加速度计寄存器均配置为不自检模式,量程选择最大范围。
指定地址写
//指定地址写
void MPU6050_WriteReg(uint8_t RegAddress, uint8_t Data)
{MyI2C_Start();MyI2C_SendByte(MPU6050_ADDRESS);MyI2C_ReceiveACK();MyI2C_SendByte(RegAddress);MyI2C_ReceiveACK();MyI2C_SendByte(Data);MyI2C_ReceiveACK();MyI2C_Stop();
}
先发送I2C起始信号,然后发从从机7位地址 加一位读写控制位,这里读写控制位清零,写入从机地址。然后接收应答位。发送要写入的寄存器的地址,接收应答位,再将数据写入,接收应答位,然后发送停止信号。
指定地址读
//指定地址读
uint8_t MPU6050_RedReg(uint8_t RegAddress)
{uint8_t ByteValue;MyI2C_Start();MyI2C_SendByte(MPU6050_ADDRESS);MyI2C_ReceiveACK();MyI2C_SendByte(RegAddress);MyI2C_ReceiveACK();MyI2C_Start();MyI2C_SendByte(MPU6050_ADDRESS | 0x01);MyI2C_ReceiveACK();ByteValue = MyI2C_ReceiveByte();MyI2C_SendACK(1);MyI2C_Stop();return ByteValue;
}
- 发送I2C起始信号
- 发送从机地址加一位读写控制位,读写控制位清零,写入数据。
- 接收应答
- 发送指定寄存器的地址
- 接收应答
- 发送I2C起始信号
- 发送从机地址及一位读写控制位,读写控制位置1,读取数据
- 接收应答标志位
- 接收数据
- 发送非应答信号
- 发送停止信号
读取数据寄存器
//读取数据寄存器
void MPU6050_GetValue(int16_t* Acce_x, int16_t* Acce_y, int16_t* Acce_z,int16_t* Gyro_x, int16_t* Gyro_y, int16_t* Gyro_z)
{uint8_t Data_H,Data_L;//加速度计X轴Data_H = MPU6050_RedReg(MPU6050_ACCEL_XOUT_H);Data_L = MPU6050_RedReg(MPU6050_ACCEL_XOUT_L);*Acce_x = (Data_H << 8) | Data_L;//加速度计Y轴Data_H = MPU6050_RedReg(MPU6050_ACCEL_YOUT_H);Data_L = MPU6050_RedReg(MPU6050_ACCEL_YOUT_L);*Acce_y = (Data_H << 8) | Data_L;//加速度计Z轴Data_H = MPU6050_RedReg(MPU6050_ACCEL_ZOUT_H);Data_L = MPU6050_RedReg(MPU6050_ACCEL_ZOUT_L);*Acce_z = (Data_H << 8) | Data_L;//陀螺仪x轴Data_H = MPU6050_RedReg(MPU6050_GYRO_XOUT_H);Data_L = MPU6050_RedReg(MPU6050_GYRO_XOUT_L);*Gyro_x = (Data_H << 8) | Data_L;//陀螺仪y轴Data_H = MPU6050_RedReg(MPU6050_GYRO_YOUT_H);Data_L = MPU6050_RedReg(MPU6050_GYRO_YOUT_L);*Gyro_y = (Data_H << 8) | Data_L;//陀螺仪Z轴Data_H = MPU6050_RedReg(MPU6050_GYRO_ZOUT_H);Data_L = MPU6050_RedReg(MPU6050_GYRO_ZOUT_L);*Gyro_z = (Data_H << 8) | Data_L;
}
读取加速度计和陀螺仪的数据寄存器,分别读取加速度计和陀螺仪的X,Y,Z轴高8位数据寄存器和低8位数据寄存器。传递指针参数存储相应的数据。
问题记录
暂无