当前位置:   article > 正文

STM32-IIC_stm32 iic slave

stm32 iic slave

图片均来自江科大STM32教学PPT

IIC

IIC简介

  • I2C(Inter IC Bus)是由Philips公司开发的一种通用数据总线
  • 两根通信线:SCL(Serial Clock)、SDA(Serial Data)
  • 同步,半双工
  • 带数据应答
  • 支持总线挂载多设备(一主多从、多主多从)

硬件电路

  • 所有I2C设备的SCL连在一起,SDA连在一起
  • 设备的SCL和SDA均要配置成开漏输出模式
  • SCL和SDA各添加一个上拉电阻,阻值一般为4.7KΩ左右

在这里插入图片描述

IIC时序基本单元

  • 起始条件:SCL高电平期间,SDA从高电平切换到低电平,然后主机要把SCL拽下来(占用SCL总线),也是方便基本时序单元拼接(低电平开始,低电平结束)。
  • 终止条件:SCL先放手回弹至高电平,高电平期间,SDA从低电平切换到高电平,产生一个上升沿,作为终止条件。
  • 起始和终止都是由主机产生,总线空闲状态时,从机始终放手。

在这里插入图片描述


实线代表主机控制,虚线代表从机控制

  • 发送一个字节:SCL低电平期间,主机将数据位依次放到SDA线上(高位先行),然后释放SCL,从机将在SCL高电平期间读取数据位,所以SCL高电平期间SDA不允许有数据变化,依次循环上述过程8次,即可发送一个字节。

在这里插入图片描述

  • 接收一个字节:SCL低电平期间,从机将数据位依次放到SDA线上(高位先行),然后释放SCL,主机将在SCL高电平期间读取数据位,所以SCL高电平期间SDA不允许有数据变化,依次循环上述过程8次,即可接收一个字节(主机在接收之前,需要释放SDA)

在这里插入图片描述

  • 发送应答主机在接收完一个字节之后,在下一个时钟发送一位数据,数据0表示应答,数据1表示非应答
  • 接收应答主机在发送完一个字节之后,在下一个时钟接收一位数据,判断从机是否应答,数据0表示应答,数据1表示非应答(主机在接收之前,需要释放SDA)

在这里插入图片描述

IIC时序

指定地址写

对于指定设备(Slave Address),在指定地址(Reg Address)下,写入指定数据(Data)

  • 指定设备(Slave Address):从机地址
  • 指定地址(Reg Address):某个设备内,寄存器地址
  • 指定数据(Data):要在寄存器中写入的数据

在这里插入图片描述

  • 第一个字节:从机地址(7位)+读写位(1位)
  • 接跟着就是接收从机的应答位
  • 最后主机不需要发送数据,就产生停止条件。在停止条件前,先拉低SDA,为后续 SDA的上升沿做准备。然后释放SCL,再释放SDA。这样就产生了SCL高电平期间,SDA产生上升沿。

当前地址读

对于指定设备(Slave Address),在当前地址指针指示的地址下,读取从机数据(Data)
在这里插入图片描述

主机发出了“读”的命令,随后数据传输方向就要反过来。从机发,主机读。要把SDA的控制权交给从机,主机调用接收一个字节的时序,进行接收操作。从机在SCL低电平写入SDA,主机在SCL高电平期间读取SDA。

【在读的时序中,IIC协议规定是,主机进行寻址时,一旦读(1)写(0)标志位给1,下一个字节就必须立马转为读的时序,所以主机还来不及指定,要读哪个寄存器,就得开始接收,所以这里就没有指定地址的环节,就需要用到当前地址指针】

指定地址读

对于指定设备(Slave Address),在指定地址(Reg Address)下,读取从机数据(Data)

在这里插入图片描述

  • 第二个字节就是用来指定地址,地址指针就指向了这个地址,
  • 紧接着不给发写入数据,而是直接再来个起始条件,重新寻址(从机地址),指定读写标志位(因为时要读,就写1),
  • 接着,主机接收一个字节,这个字节就是地址指针指向的地址下的数据。
  • 指针地址会在读写操作后自增。
  • 如果只读一个字节就停止,就要给从机发个非应答,然后从机就会释放总线,把SDA的控制权交还给主机。
  • 从机发送数据的权利开始于读写标志位为1,结束于主机应答为1。

软件模拟IIC代码示例

IIC.c

#include "stm32f10x.h"                  // Device header
#include "Delay.h"

//	用于将SCL信号线设置为指定值。GPIOB的Pin10被用来控制SCL信号线
void MyI2C_W_SCL(uint8_t BitValue)
{
    GPIO_WriteBit(GPIOB,GPIO_Pin_10,(BitAction)BitValue);
    Delay_us(10);
}

//	用于将SDA信号线设置为指定值。GPIOB的Pin11被用来控制SDA信号线。
void MyI2C_W_SDA(uint8_t BitValue)
{
    GPIO_WriteBit(GPIOB,GPIO_Pin_11,(BitAction)BitValue);
    Delay_us(10);
}

//	用于读取SDA信号线的值。GPIOB的Pin11被用来读取SDA信号线的值
uint8_t MyI2C_R_SDA(void)
{
    uint8_t BitValue;
    BitValue=GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_11);
    Delay_us(10);
    return BitValue;
}

//	用于初始化IIC总线
void MyI2C_Init(void)
{
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);
    GPIO_InitTypeDef GPIO_InitStructure;
    GPIO_InitStructure.GPIO_Mode=GPIO_Mode_Out_OD;
    GPIO_InitStructure.GPIO_Pin=GPIO_Pin_10|GPIO_Pin_11;
    GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;
    GPIO_Init(GPIOB,&GPIO_InitStructure);
    // SCL和SDA都处于高电平,空闲状态
    GPIO_SetBits(GPIOB,GPIO_Pin_10|GPIO_Pin_11);
}

//	用于发送起始信号
void MyI2C_Start(void)
{
    MyI2C_W_SDA(1);
    MyI2C_W_SCL(1);

    MyI2C_W_SDA(0);
    MyI2C_W_SCL(0);

}

//	用于发送停止信号
void MyI2C_Stop(void)
{
    MyI2C_W_SDA(0);
    MyI2C_W_SCL(1);
    MyI2C_W_SDA(1);
}

//	用于发送一个字节。从高位到低位依次发送每个位
void MyI2C_SendByte(uint8_t Byte)
{
    uint8_t i;
    for(i=0; i<8; i++)
    {
        MyI2C_W_SDA(Byte & (0x80 >> i));
        MyI2C_W_SCL(1);
        MyI2C_W_SCL(0);
    }
}

uint8_t MyI2C_ReceiveByte(void)
{
    uint8_t i, Byte = 0x00;  // 声明变量i和Byte,Byte用于存储接收到的字节数据,初始值为0x00
    MyI2C_W_SDA(1);  // 设置SDA线为高电平,准备接收数据
    for(i = 0; i < 8; i++)  // 循环8次,接收8位数据
    {
        MyI2C_W_SCL(1);  // 设置SCL线为高电平,准备读取数据位
        if(MyI2C_R_SDA() == 1)  // 检查SDA线的电平,如果为高电平,则表示接收到的数据位为1
        {
            Byte |= (0x80 >> i);  // 使用位或操作将接收到的数据位存储到Byte中,右移操作(0x80 >> i)确定位的位置
        }
        MyI2C_W_SCL(0);  // 设置SCL线为低电平,准备接收下一个数据位
    }

    return Byte;  // 返回接收到的字节数据
}

//	发送应答
void MyI2C_SendAck(uint8_t AckBit)
{
    MyI2C_W_SDA(AckBit);  // 设置SDA线的电平,用于发送ACK位(AckBit)
    MyI2C_W_SCL(1);      // 设置SCL线为高电平,发送ACK信号
    MyI2C_W_SCL(0);      // 设置SCL线为低电平,完成ACK信号的发送
}

//	接收应答
uint8_t MyI2C_ReceiveAck(void)
{
    uint8_t AckBit;
    MyI2C_W_SDA(1);      // 将SDA线设置为输入模式,准备接收ACK位
    MyI2C_W_SCL(1);      // 设置SCL线为高电平,准备读取ACK位的电平
    AckBit = MyI2C_R_SDA();  // 读取SDA线的电平,获取ACK位的值
    MyI2C_W_SCL(0);      // 设置SCL线为低电平,完成ACK位的读取
    return AckBit;       // 返回接收到的ACK位
}


  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107

MPU6050.c

#include "stm32f10x.h"                  // Device header
#include "MyI2C.h"
#include "MPU6050_Reg.h"

#define MPU6050_ADDRESS		0xD0

void MPU6050_WriteReg(uint8_t RegAddress, uint8_t Data)
{
    // 启动I2C通信
    MyI2C_Start();

    // 发送设备地址,并等待应答
    MyI2C_SendByte(MPU6050_ADDRESS);
    MyI2C_ReceiveAck();

    // 发送寄存器地址,并等待应答
    MyI2C_SendByte(RegAddress);
    MyI2C_ReceiveAck();

    // 发送数据,并等待应答
    MyI2C_SendByte(Data);
    MyI2C_ReceiveAck();

    // 停止I2C通信
    MyI2C_Stop();
}

uint8_t MPU6050_ReadReg(uint8_t RegAddress)
{
    uint8_t Data;

    // 启动I2C通信
    MyI2C_Start();

    // 发送设备地址,并等待应答
    MyI2C_SendByte(MPU6050_ADDRESS);
    MyI2C_ReceiveAck();

    // 发送寄存器地址,并等待应答
    MyI2C_SendByte(RegAddress);
    MyI2C_ReceiveAck();

    // 再次启动I2C通信
    MyI2C_Start();

    // 发送设备地址,并等待应答,设置为读模式
    MyI2C_SendByte(MPU6050_ADDRESS | 0x01);
    MyI2C_ReceiveAck();

    // 读取数据
    Data = MyI2C_ReceiveByte();

    // 发送应答位
    MyI2C_SendAck(1);

    // 停止I2C通信
    MyI2C_Stop();

    return Data;
}

void MPU6050_Init(void)
{
    MyI2C_Init();
    //	配置电源管理寄存器
    MPU6050_WriteReg(MPU6050_PWR_MGMT_1,0X01);		//	选择陀螺仪时钟
    MPU6050_WriteReg(MPU6050_PWR_MGMT_2,0X00);

    //	这部分参考MPU6050寄存器映射手册
    MPU6050_WriteReg(MPU6050_SMPLRT_DIV	,0X09);		//	配置采样率分频
    MPU6050_WriteReg(MPU6050_CONFIG	,0X06);			//	配置寄存器
    MPU6050_WriteReg(MPU6050_GYRO_CONFIG,0X18);		//	陀螺仪配置寄存器
    MPU6050_WriteReg(MPU6050_ACCEL_CONFIG,0X18);	//	加速度计寄存器配置
}

//	获取MPU6050的ID号
uint8_t MPU6050_GetID(void)
{
    return MPU6050_ReadReg(MPU6050_WHO_AM_I);
}

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;

    // 读取加速度计X轴数据
    DataH = MPU6050_ReadReg(MPU6050_ACCEL_XOUT_H);
    DataL = MPU6050_ReadReg(MPU6050_ACCEL_XOUT_L);
    *AccX = (DataH << 8) | DataL;  // 组合高位和低位数据得到16位的加速度计X轴数据

    // 读取加速度计Y轴数据
    DataH = MPU6050_ReadReg(MPU6050_ACCEL_YOUT_H);
    DataL = MPU6050_ReadReg(MPU6050_ACCEL_YOUT_L);
    *AccY = (DataH << 8) | DataL;  // 组合高位和低位数据得到16位的加速度计Y轴数据

    // 读取加速度计Z轴数据
    DataH = MPU6050_ReadReg(MPU6050_ACCEL_ZOUT_H);
    DataL = MPU6050_ReadReg(MPU6050_ACCEL_ZOUT_L);
    *AccZ = (DataH << 8) | DataL;  // 组合高位和低位数据得到16位的加速度计Z轴数据

    // 读取陀螺仪X轴数据
    DataH = MPU6050_ReadReg(MPU6050_GYRO_XOUT_H);
    DataL = MPU6050_ReadReg(MPU6050_GYRO_XOUT_L);
    *GyroX = (DataH << 8) | DataL; // 组合高位和低位数据得到16位的陀螺仪X轴数据

    // 读取陀螺仪Y轴数据
    DataH = MPU6050_ReadReg(MPU6050_GYRO_YOUT_H);
    DataL = MPU6050_ReadReg(MPU6050_GYRO_YOUT_L);
    *GyroY = (DataH << 8) | DataL; // 组合高位和低位数据得到16位的陀螺仪Y轴数据

    // 读取陀螺仪Z轴数据
    DataH = MPU6050_ReadReg(MPU6050_GYRO_ZOUT_H);
    DataL = MPU6050_ReadReg(MPU6050_GYRO_ZOUT_L);
    *GyroZ = (DataH << 8) | DataL; // 组合高位和低位数据得到16位的陀螺仪Z轴数据
}

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 116
  • 117

IIC外设

简介

  • STM32内部集成了硬件I2C收发电路,可以由硬件自动执行时钟生成、起始终止条件生成、应答位收发、数据收发等功能,减轻CPU的负担
  • 支持多主机模型
  • 支持7位/10位地址模式
  • 支持不同的通讯速度,标准速度(高达100 kHz),快速(高达400 kHz)
  • 支持DMA
  • 兼容SMBus协议

STM32F103C8T6 硬件I2C资源:I2C1、I2C2

IIC框图

  • 发送数据时,把一个字节的数据写到数据寄存器DR中,当移位寄存器没有数据移位时,数据就会进一步转到移位寄存器里,会置状态寄存器TXE为1,就可以把下一个数据放到DR里,前一个数据移位完成,下一个数据就就可以无缝衔接。
  • 接收数据:数据一位一位移到移位寄存器,接收完了一个字节的数据,数据整体转到数据寄存器里,同时置标志位RXNE=1,表示数据寄存器非空,就可以读取数据寄存器里的数据。

在这里插入图片描述

IIC基本结构

在这里插入图片描述

主机发送

在这里插入图片描述

主机接收

在这里插入图片描述

软件/硬件波形对比

在这里插入图片描述

硬件IIC代码示例

#include "stm32f10x.h"                  // Device header
#include "MPU6050_Reg.h"

#define MPU6050_ADDRESS		0xD0

//	防止超时
void MPU6050_WaitEvent(I2C_TypeDef* I2Cx, uint32_t I2C_EVENT)
{
    uint32_t Timeout;
    Timeout=10000;
    while (I2C_CheckEvent(I2Cx, I2C_EVENT) != SUCCESS)
    {
        Timeout--;
        if(Timeout==0)
        {
            break;
        }
    }
}

void MPU6050_WriteReg(uint8_t RegAddress, uint8_t Data)
{
    // 在I2C总线上生成起始条件
    I2C_GenerateSTART(I2C2, ENABLE);

    // 等待起始条件发送完成并且主模式被选中
    MPU6050_WaitEvent(I2C2, I2C_EVENT_MASTER_MODE_SELECT);

    // 发送带有写方向的MPU6050设备的7位地址
    I2C_Send7bitAddress(I2C2, MPU6050_ADDRESS, I2C_Direction_Transmitter);
    // 等待地址发送完成并且发送器模式被选中
    MPU6050_WaitEvent(I2C2, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED);

    // 发送要写入的寄存器地址
    I2C_SendData(I2C2, RegAddress);
    // 等待数据字节传输完成
    MPU6050_WaitEvent(I2C2, I2C_EVENT_MASTER_BYTE_TRANSMITTING);

    // 发送要写入寄存器的数据
    I2C_SendData(I2C2, Data);
    // 等待数据字节传输完成
    MPU6050_WaitEvent(I2C2, I2C_EVENT_MASTER_BYTE_TRANSMITTING);

    // 在I2C总线上生成停止条件
    I2C_GenerateSTOP(I2C2, ENABLE);
}

uint8_t MPU6050_ReadReg(uint8_t RegAddress)
{
    uint8_t Data;
    // 在I2C总线上生成起始条件
    I2C_GenerateSTART(I2C2, ENABLE);
    // 等待起始条件发送完成并且主模式被选中
    MPU6050_WaitEvent(I2C2, I2C_EVENT_MASTER_MODE_SELECT);

    // 发送带有写方向的MPU6050设备的7位地址
    I2C_Send7bitAddress(I2C2, MPU6050_ADDRESS, I2C_Direction_Transmitter);
    // 等待地址发送完成并且发送器模式被选中
    MPU6050_WaitEvent(I2C2, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED);

    // 发送要读取的寄存器地址
    I2C_SendData(I2C2, RegAddress);
    // 等待数据字节传输完成
    MPU6050_WaitEvent(I2C2, I2C_EVENT_MASTER_BYTE_TRANSMITTED);

    // 重新生成起始条件
    I2C_GenerateSTART(I2C2, ENABLE);
    // 等待起始条件发送完成并且主模式被选中
    MPU6050_WaitEvent(I2C2, I2C_EVENT_MASTER_MODE_SELECT);

    // 发送带有读方向的MPU6050设备的7位地址
    I2C_Send7bitAddress(I2C2, MPU6050_ADDRESS, I2C_Direction_Receiver);
    // 等待地址发送完成并且接收器模式被选中
    MPU6050_WaitEvent(I2C2, I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED);

    // 禁用应答
    I2C_AcknowledgeConfig(I2C2, DISABLE);
    // 生成停止条件
    I2C_GenerateSTOP(I2C2, ENABLE);
    // 等待数据字节接收完成
    MPU6050_WaitEvent(I2C2, I2C_EVENT_MASTER_BYTE_RECEIVED);

    // 读取接收到的数据
    Data = I2C_ReceiveData(I2C2);
    // 启用应答
    I2C_AcknowledgeConfig(I2C2, ENABLE);
    return Data;
}

void MPU6050_Init(void)
{

    RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C2,ENABLE);
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);

    GPIO_InitTypeDef GPIO_InitStructure;
    GPIO_InitStructure.GPIO_Mode=GPIO_Mode_AF_OD;
    GPIO_InitStructure.GPIO_Pin=GPIO_Pin_10|GPIO_Pin_11;
    GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;
    GPIO_Init(GPIOB,&GPIO_InitStructure);

    I2C_InitTypeDef I2C_InitStruct;
    I2C_InitStruct.I2C_Mode=I2C_Mode_I2C;
    I2C_InitStruct.I2C_ClockSpeed=50000;
    I2C_InitStruct.I2C_DutyCycle=I2C_DutyCycle_2;
    I2C_InitStruct.I2C_Ack=I2C_Ack_Enable;
    I2C_InitStruct.I2C_AcknowledgedAddress=I2C_AcknowledgedAddress_7bit;
    I2C_InitStruct.I2C_OwnAddress1=0X00;
    I2C_Init(I2C2,&I2C_InitStruct);

    I2C_Cmd(I2C2,ENABLE);

    //	配置电源管理寄存器
    MPU6050_WriteReg(MPU6050_PWR_MGMT_1,0X01);		//	选择陀螺仪时钟
    MPU6050_WriteReg(MPU6050_PWR_MGMT_2,0X00);

    //	这部分参考MPU6050寄存器映射手册
    MPU6050_WriteReg(MPU6050_SMPLRT_DIV	,0X09);		//	配置采样率分频
    MPU6050_WriteReg(MPU6050_CONFIG	,0X06);			//	配置寄存器
    MPU6050_WriteReg(MPU6050_GYRO_CONFIG,0X18);		//	陀螺仪配置寄存器
    MPU6050_WriteReg(MPU6050_ACCEL_CONFIG,0X18);	//	加速度计寄存器配置
}

//	获取MPU6050的ID号
uint8_t MPU6050_GetID(void)
{
    return MPU6050_ReadReg(MPU6050_WHO_AM_I);
}

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;

    // 读取加速度计X轴数据
    DataH = MPU6050_ReadReg(MPU6050_ACCEL_XOUT_H);
    DataL = MPU6050_ReadReg(MPU6050_ACCEL_XOUT_L);
    *AccX = (DataH << 8) | DataL;  // 组合高位和低位数据得到16位的加速度计X轴数据

    // 读取加速度计Y轴数据
    DataH = MPU6050_ReadReg(MPU6050_ACCEL_YOUT_H);
    DataL = MPU6050_ReadReg(MPU6050_ACCEL_YOUT_L);
    *AccY = (DataH << 8) | DataL;  // 组合高位和低位数据得到16位的加速度计Y轴数据

    // 读取加速度计Z轴数据
    DataH = MPU6050_ReadReg(MPU6050_ACCEL_ZOUT_H);
    DataL = MPU6050_ReadReg(MPU6050_ACCEL_ZOUT_L);
    *AccZ = (DataH << 8) | DataL;  // 组合高位和低位数据得到16位的加速度计Z轴数据

    // 读取陀螺仪X轴数据
    DataH = MPU6050_ReadReg(MPU6050_GYRO_XOUT_H);
    DataL = MPU6050_ReadReg(MPU6050_GYRO_XOUT_L);
    *GyroX = (DataH << 8) | DataL; // 组合高位和低位数据得到16位的陀螺仪X轴数据

    // 读取陀螺仪Y轴数据
    DataH = MPU6050_ReadReg(MPU6050_GYRO_YOUT_H);
    DataL = MPU6050_ReadReg(MPU6050_GYRO_YOUT_L);
    *GyroY = (DataH << 8) | DataL; // 组合高位和低位数据得到16位的陀螺仪Y轴数据

    // 读取陀螺仪Z轴数据
    DataH = MPU6050_ReadReg(MPU6050_GYRO_ZOUT_H);
    DataL = MPU6050_ReadReg(MPU6050_GYRO_ZOUT_L);
    *GyroZ = (DataH << 8) | DataL; // 组合高位和低位数据得到16位的陀螺仪Z轴数据
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 116
  • 117
  • 118
  • 119
  • 120
  • 121
  • 122
  • 123
  • 124
  • 125
  • 126
  • 127
  • 128
  • 129
  • 130
  • 131
  • 132
  • 133
  • 134
  • 135
  • 136
  • 137
  • 138
  • 139
  • 140
  • 141
  • 142
  • 143
  • 144
  • 145
  • 146
  • 147
  • 148
  • 149
  • 150
  • 151
  • 152
  • 153
  • 154
  • 155
  • 156
  • 157
  • 158
  • 159
  • 160
  • 161
  • 162
  • 163
  • 164
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/凡人多烦事01/article/detail/676653
推荐阅读
相关标签
  

闽ICP备14008679号