(软件实现IIC)IIC详解,STM32F103外设IIC驱动代码配置,以和MPU6050通信为例_stm32f103iic例程-程序员宅基地

技术标签: 嵌入式硬件  

IIC总线介绍

1.两根通信线:SCL和SDA
2.同步、半双工、带有数据应答

IIC电路规范

1.所有的IIC设备的SCL和SDA共用同一条总线
2.两根总线的配置都要为开漏输出


3.SCL和SDA上面各添加了上拉电阻;上拉电阻的阻值一般为4.7KΩ
意义:为避免高电平期间引脚处于浮空,通过加上电阻拉到高电平,使总线处于弱上拉,这样一来所以设备只能对总线进行下拉(置低电平)或者放手(置高电平)操作
弱上拉的好处:
1.杜绝了电源短路现象,保证电路安全
2.避免引脚模式的频繁切换,开漏加弱上拉模式,同时兼具了输入和输出的功能
3.具有《线与》的现象:只要有一个设备输出低电平,总线就处于低电平,只有全部设备输出为高电平,总线才为高电平;可以利用这个特性,执行多主机模式下的时钟同步和总线仲裁。所以SCL虽然在一主多从模式下可以使用推挽输出,但是任然采用开漏弱上拉输出的模式。


4.开漏输出和上拉电阻共同作用,实现了“线与”的功能(解决多机通信互相干扰的问题)
对照下图理解
在这里插入图片描述
引脚配置为开漏输出(如下图)
在这里插入图片描述

IIC时序结构

1.起始条件:

SCL为高电平时;SDA由高电平变为低电平

2.终止条件:

SCL为高电平时;SDA由低电平变为高电平
类似串口时序的起始位和停止位;这也是一帧完整数据帧的特征
如下图
在这里插入图片描述

3.发送一个字节(8位):

SCL为低电平期间,主机将一位数据写输入SDA上,将SCL电平拉至高电平,在SCL为高电平期间,从机进行接收并读取数据(此时不能改变SDA电平状态);循环八次即可发送一个字节(8位)
如下图
IIC数据高位先行;串口时序是低位先行
在这里插入图片描述

4.接收一个字节(8位):

SCL低电平期间,从机将数据写入SDA上,然后拉高SCL至高电平,SCL在高电平期间,主机读取SDA上的数据(此时不能改变SDA电平状态);循环八次即可接收一个字节(8位);【主机读取SDA上的数据之前,要先释放SDA,即将SDA拉至高电平
如下图
释放SDA:意思就是切换为输入模式,必须先放手,如果不放手别的设备无论发送什么都将是低电平(原因是线与特性)
在这里插入图片描述

5.发送应答:

在接收完一个字节后,主机在下一个时钟SCL为低电平时,在SDA上发送一位数据(0:应答 、 1:非应答)

6.接收应答:

在发送完一个字节后,从机在下一个时钟SCL为低电平时,在SDA上发送一位数据,主机接收一位数据(0:应答 、 1:非应答)【与上面一样:主机接收SDA上的数据之前,要先释放SDA,即将SDA拉至高电平
如下图
在这里插入图片描述

IIC数据帧

协议标准里分为7位地址和11位地址;下文以7位地址数据帧为例子
具有IIC通信的设备在出厂时就已经分频好了对应地址,例如:
MPU6050:1101 000
AT24C02: 1010 000
当然地址也能通过引脚灵活替换

1.发送一帧数据:

起始条件+要发送到的地址(最低为0为发送数据、1为读取数据)+应答位+发送的8位数据+应答位+…+停止条件
在这里插入图片描述

在指定设备1101000写(0),在指定地址下0001 1001,写入数据1010 1010

时序图如下:
下方第一个应答位是从机产生的,也是由从机释放交出SDA控制权,因为从机要在低电平尽快变换数据;所以上升沿和SCL下降沿几乎同时发生
在这里插入图片描述

2.接收一帧数据:

起始条件+要读取的地址(最低为0为发送数据、1为读取数据)+应答位+读取的8位数据+应答位+…+读取的8位数据+应答位(1,不应答,因为想停止读取)+停止条件
在这里插入图片描述

在指定设备1101 000读(1),在当前地址指针指示的地址下(每读一次指针加1),读入数据0000 1111,主机不读了应答位就置1,然后发送停止条件

时序图如下:
在这里插入图片描述

3.先发送要读取的地址,再接收该地址数据:

起始条件+要发送到的地址(最低为0为发送数据、1为读取数据)+应答位+发送的8位数据+应答位+…+
起始条件+要读取的地址(最低为0为发送数据、1为读取数据)+应答位+读取的8位数据+应答位+…+读取的8位数据+应答位(1,不应答,因为想停止读取)+停止条件
在这里插入图片描述

在指定设备1101000写(0),发送指定读取寄存器地址0001 1001,再次发送起始条件,在指定设备1101000读(1),读入数据1010 1010(每读取一次地址指针加1:因此可以连续读取一片寄存器),不想读取主机发送非应答(1)

在这里插入图片描述

4.字节写:

起始条件+要发送到的设备地址(最低为0为发送数据、1为读取数据)+应答位+要发送到要写入的地址+应答位+发送的8位数据+应答位+…+停止条件

5.随机读:

起始条件+要发送到的设备地址(最低为0为发送数据、1为读取数据)+应答位+要发送到要写入的地址+应答位+发送的8位数据+应答位+…+
起始条件+要读取的地址(最低为0为发送数据、1为读取数据)+应答位+读取的8位数据+应答位+…+读取的8位数据+应答位(1,不应答,因为想停止读取)+停止条件
在这里插入图片描述

I2C外设简介

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

STM32F103C8T6 硬件I2C资源:I2C1、I2C2

I2C框图

在这里插入图片描述

I2C基本结构

在这里插入图片描述

主机发送

在这里插入图片描述

主机接收

在这里插入图片描述

软件/硬件波形对比

在这里插入图片描述
在这里插入图片描述

软件IIC程序代码配置

软件IIC通信层

.c

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

void MyI2C_W_SCL(uint8_t BitValue)
{
    
    GPIO_WriteBit(GPIOB, GPIO_Pin_10, (BitAction)BitValue);//BitAction:枚举
    Delay_us(10);
}

void MyI2C_W_SDA(uint8_t BitValue)
{
    
    GPIO_WriteBit(GPIOB, GPIO_Pin_11, (BitAction)BitValue);
    Delay_us(10);
}

/***********************************************************
*@fuction	:MyI2C_R_SDA
*@brief		:读SDA线的电平
*@param		:--
*@return	:void
*@author	:--
*@date		:2023-07-24
***********************************************************/

uint8_t MyI2C_R_SDA(void)
{
    
    uint8_t BitValue;
    BitValue = GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_11);
    Delay_us(10);
    return BitValue;
}

/***********************************************************
*@fuction	:MyI2C_Init
*@brief		:初始化
*@param		:--
*@return	:void
*@author	:--
*@date		:2023-07-24
***********************************************************/

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);

    GPIO_SetBits(GPIOB, GPIO_Pin_10 | GPIO_Pin_11);		//高电平:IIC总线处于空闲状态
}

/***********************************************************
*@fuction	:MyI2C_Start
*@brief		:起始条件
*@param		:--
*@return	:void
*@author	:--先把SCL和SDA都释放:输出1;先拉低SDA;再拉低SCL:兼容起始条件和重复起始条件
*@date		:2023-07-24
***********************************************************/

void MyI2C_Start(void)
{
    
    MyI2C_W_SDA(1);
    MyI2C_W_SCL(1);
    MyI2C_W_SDA(0);		//先拉低SDA
    MyI2C_W_SCL(0);		//再拉低SCL
}

/***********************************************************
*@fuction	:MyI2C_Stop
*@brief		:终止条件
*@param		:--
*@return	:void
*@author	:--:先拉低SDA;再释放SCL;在释放SDA
*@date		:2023-07-24
***********************************************************/

void MyI2C_Stop(void)
{
    
    MyI2C_W_SDA(0);
    MyI2C_W_SCL(1);
    MyI2C_W_SDA(1);
}

/***********************************************************
*@fuction	:MyI2C_SendByte
*@brief		:发送一个字节
*@param		:--
*@return	:void
*@author	:--
*@date		:2023-07-24
***********************************************************/

void MyI2C_SendByte(uint8_t Byte)
{
    
    uint8_t i;
    for (i = 0; i < 8; i ++)	//循环8次
    {
    
        MyI2C_W_SDA(Byte & (0x80 >> i));//取决于Byte的最高位xxxx xxxx & 1000 0000 = x000 0000 = 0x80(1) | 0x00(0)
        MyI2C_W_SCL(1);		
        MyI2C_W_SCL(0);
    }
}

/***********************************************************
*@fuction	:MyI2C_ReceiveByte
*@brief		:接收一个字节
*@param		:--
*@return	:uint8_t Byte
*@author	:--
*@date		:2023-07-24
***********************************************************/

uint8_t MyI2C_ReceiveByte(void)
{
    
    uint8_t i, Byte = 0x00;
    MyI2C_W_SDA(1);	//主机释放SDA//从机把数据放到SDA
    for (i = 0; i < 8; i ++)	//循环8次
    {
    
        MyI2C_W_SCL(1);		//高电平读取
        if (MyI2C_R_SDA() == 1)//判断SDA数据是否为高电平
        {
    
            Byte |= (0x80 >> i);//如果为高电平,将高电平写入Byte,不是高电平则不需要修改(Byte初始值默认低电平)
        }
        MyI2C_W_SCL(0);		//拉低SCL,从机继续写入
    }
    return Byte;
}

/***********************************************************
*@fuction	:MyI2C_SendAck
*@brief		:发送一个应答字节
*@param		:--
*@return	:void
*@author	:--
*@date		:2023-07-24
***********************************************************/

void MyI2C_SendAck(uint8_t AckBit)
{
    
    MyI2C_W_SDA(AckBit);//主机把应答位放到SDA上
    MyI2C_W_SCL(1);//拉高SCL,从机读取
    MyI2C_W_SCL(0);//拉低SCL,进入下一个时序单元
}

/***********************************************************
*@fuction	:MyI2C_ReceiveAck
*@brief		:接收应答
*@param		:--
*@return	:uint8_t AckBit
*@author	:--
*@date		:2023-07-24
***********************************************************/

uint8_t MyI2C_ReceiveAck(void)
{
    
    uint8_t AckBit;
    MyI2C_W_SDA(1);		//主机释放SDA
    MyI2C_W_SCL(1);		//拉高SCL,读取SDA数据
    AckBit = MyI2C_R_SDA();//读取数据放到AckBit上
    MyI2C_W_SCL(0);		//拉低SCL,进入下一个时序单元
    return AckBit;
}

.h

#ifndef __MYI2C_H
#define __MYI2C_H
#include "stdint.h"
void MyI2C_Init(void);
void MyI2C_Start(void);
void MyI2C_Stop(void);
void MyI2C_SendByte(uint8_t Byte);
uint8_t MyI2C_ReceiveByte(void);
void MyI2C_SendAck(uint8_t AckBit);
uint8_t MyI2C_ReceiveAck(void);

#endif

MPU6050_Soft.c

#include "stm32f10x.h"               
#include "MyI2C.h"
#include "MPU6050_Soft_Reg.h"
#include "MPU6050_Soft.h"

#define MPU6050_ADDRESS		0xD0	//写地址

/***********************************************************
*@fuction	:MPU6050_WriteReg
*@brief		:指定地址写一个字节
*@param		:--
*@return	:void
*@author	:--
*@date		:2023-07-24
***********************************************************/

void MPU6050_WriteReg(uint8_t RegAddress, uint8_t Data)
{
    
	MyI2C_Start();
	MyI2C_SendByte(MPU6050_ADDRESS);	//发送从机地址
	MyI2C_ReceiveAck();					//接收应答;返回应答位;可判断
	MyI2C_SendByte(RegAddress);			//发送指定寄存器里的内容;MPU6050当前地址指针里
	MyI2C_ReceiveAck();					//接收应答
	/****************************
	后两句套起来循环,可以写多个字节
	****************************/
	MyI2C_SendByte(Data);				//发送字节:写入指定寄存器地址下的数据
	MyI2C_ReceiveAck();					//接收应答
	
	MyI2C_Stop();						//终止时序
}

/***********************************************************
*@fuction	:MPU6050_ReadReg
*@brief		:指定地址读一个字节
*@param		:--
*@return	:uint8_t Data
*@author	:--
*@date		:2023-07-24
***********************************************************/

uint8_t MPU6050_ReadReg(uint8_t RegAddress)
{
    
	uint8_t Data;		//存储读的字节
	/****************************
	指定地址
	****************************/
	MyI2C_Start();
	MyI2C_SendByte(MPU6050_ADDRESS);
	MyI2C_ReceiveAck();
	MyI2C_SendByte(RegAddress);
	MyI2C_ReceiveAck();
	/****************************
	重新指定读写位
	****************************/
	MyI2C_Start();								//重复起始位
	MyI2C_SendByte(MPU6050_ADDRESS | 0x01);		//或上0x01 将写地址 改为 读地址
	MyI2C_ReceiveAck();
	/****************************
	后两句套起来循环,可以读多个字节
	****************************/
	Data = MyI2C_ReceiveByte();					//接收字节
	MyI2C_SendAck(1);							//不给从机应答
	
	MyI2C_Stop();								//终止时序
	
	return Data;
}

/***********************************************************
*@fuction	:MPU6050_Init
*@brief		:初始化
*@param		:--
*@return	:void
*@author	:--
*@date		:2023-07-24
***********************************************************/

void MPU6050_Init(void)		//建立在MyI2C之上
{
    
	MyI2C_Init();			//继承一下底层
	/*********************************
			MPU6050寄存器的配置
	*********************************/
	MPU6050_WriteReg(MPU6050_PWR_MGMT_1, 0x01);//配置电源管理寄存器1
	MPU6050_WriteReg(MPU6050_PWR_MGMT_2, 0x00);//配置电源管理寄存器1
	MPU6050_WriteReg(MPU6050_SMPLRT_DIV, 0x09);//采样率分频:10分频
	MPU6050_WriteReg(MPU6050_CONFIG, 0x06);		//数字低通滤波器
	MPU6050_WriteReg(MPU6050_GYRO_CONFIG, 0x18);//陀螺仪
	MPU6050_WriteReg(MPU6050_ACCEL_CONFIG, 0x18);//加速度计
}

/***********************************************************
*@fuction	:MPU6050_GetID
*@brief		:读取设备ID号
*@param		:--
*@return	:void
*@author	:--
*@date		:2023-07-24
***********************************************************/

uint8_t MPU6050_GetID(void)
{
    
	return MPU6050_ReadReg(MPU6050_WHO_AM_I);
}

/**
  ************************************************************************** 
  ** -------------------------------------------------------------------- **
  ** @name          : MPU6050_GetData
  ** @brief         : 获取数据寄存器
  ** @param         : None
  ** @retval        : int16_t *AccX, int16_t *AccY, int16_t *AccZ,
					  int16_t *GyroX, int16_t *GyroY, int16_t *GyroZ
  ** @author        : XRaccoon
  ** -------------------------------------------------------------------- **
  ** @attention     : None
  ** -------------------------------------------------------------------- **
  ************************************************************************** 
**/
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位;低8位
	/*******************************
	            加速度值
	*******************************/
	DataH = MPU6050_ReadReg(MPU6050_ACCEL_XOUT_H);		//读取高八位的值
	DataL = MPU6050_ReadReg(MPU6050_ACCEL_XOUT_L);		//读取第八位的值
	*AccX = (DataH << 8) | DataL;		//高八位左移8位,再或上第八位:加速度计X轴的16位数据;(通过指针变量返回)
	
	DataH = MPU6050_ReadReg(MPU6050_ACCEL_YOUT_H);
	DataL = MPU6050_ReadReg(MPU6050_ACCEL_YOUT_L);
	*AccY = (DataH << 8) | DataL;
	
	DataH = MPU6050_ReadReg(MPU6050_ACCEL_ZOUT_H);
	DataL = MPU6050_ReadReg(MPU6050_ACCEL_ZOUT_L);
	*AccZ = (DataH << 8) | DataL;
	/*******************************
	            陀螺仪值
	*******************************/	
	DataH = MPU6050_ReadReg(MPU6050_GYRO_XOUT_H);
	DataL = MPU6050_ReadReg(MPU6050_GYRO_XOUT_L);
	*GyroX = (DataH << 8) | DataL;
	
	DataH = MPU6050_ReadReg(MPU6050_GYRO_YOUT_H);
	DataL = MPU6050_ReadReg(MPU6050_GYRO_YOUT_L);
	*GyroY = (DataH << 8) | DataL;
	
	DataH = MPU6050_ReadReg(MPU6050_GYRO_ZOUT_H);
	DataL = MPU6050_ReadReg(MPU6050_GYRO_ZOUT_L);
	*GyroZ = (DataH << 8) | DataL;
}

MPU6050_Soft.h

#include "stm32f10x.h"               
#include "MyI2C.h"
#include "MPU6050_Soft_Reg.h"
#include "MPU6050_Soft.h"

#define MPU6050_ADDRESS		0xD0	//写地址

/***********************************************************
*@fuction	:MPU6050_WriteReg
*@brief		:指定地址写一个字节
*@param		:--
*@return	:void
*@author	:--
*@date		:2023-07-24
***********************************************************/

void MPU6050_WriteReg(uint8_t RegAddress, uint8_t Data)
{
    
	MyI2C_Start();
	MyI2C_SendByte(MPU6050_ADDRESS);	//发送从机地址
	MyI2C_ReceiveAck();					//接收应答;返回应答位;可判断
	MyI2C_SendByte(RegAddress);			//发送指定寄存器里的内容;MPU6050当前地址指针里
	MyI2C_ReceiveAck();					//接收应答
	/****************************
	后两句套起来循环,可以写多个字节
	****************************/
	MyI2C_SendByte(Data);				//发送字节:写入指定寄存器地址下的数据
	MyI2C_ReceiveAck();					//接收应答
	
	MyI2C_Stop();						//终止时序
}

/***********************************************************
*@fuction	:MPU6050_ReadReg
*@brief		:指定地址读一个字节
*@param		:--
*@return	:uint8_t Data
*@author	:--
*@date		:2023-07-24
***********************************************************/

uint8_t MPU6050_ReadReg(uint8_t RegAddress)
{
    
	uint8_t Data;		//存储读的字节
	/****************************
	指定地址
	****************************/
	MyI2C_Start();
	MyI2C_SendByte(MPU6050_ADDRESS);
	MyI2C_ReceiveAck();
	MyI2C_SendByte(RegAddress);
	MyI2C_ReceiveAck();
	/****************************
	重新指定读写位
	****************************/
	MyI2C_Start();								//重复起始位
	MyI2C_SendByte(MPU6050_ADDRESS | 0x01);		//或上0x01 将写地址 改为 读地址
	MyI2C_ReceiveAck();
	/****************************
	后两句套起来循环,可以读多个字节
	****************************/
	Data = MyI2C_ReceiveByte();					//接收字节
	MyI2C_SendAck(1);							//不给从机应答
	
	MyI2C_Stop();								//终止时序
	
	return Data;
}

/***********************************************************
*@fuction	:MPU6050_Init
*@brief		:初始化
*@param		:--
*@return	:void
*@author	:--
*@date		:2023-07-24
***********************************************************/

void MPU6050_Init(void)		//建立在MyI2C之上
{
    
	MyI2C_Init();			//继承一下底层
	/*********************************
			MPU6050寄存器的配置
	*********************************/
	MPU6050_WriteReg(MPU6050_PWR_MGMT_1, 0x01);//配置电源管理寄存器1
	MPU6050_WriteReg(MPU6050_PWR_MGMT_2, 0x00);//配置电源管理寄存器1
	MPU6050_WriteReg(MPU6050_SMPLRT_DIV, 0x09);//采样率分频:10分频
	MPU6050_WriteReg(MPU6050_CONFIG, 0x06);		//数字低通滤波器
	MPU6050_WriteReg(MPU6050_GYRO_CONFIG, 0x18);//陀螺仪
	MPU6050_WriteReg(MPU6050_ACCEL_CONFIG, 0x18);//加速度计
}

/***********************************************************
*@fuction	:MPU6050_GetID
*@brief		:读取设备ID号
*@param		:--
*@return	:void
*@author	:--
*@date		:2023-07-24
***********************************************************/

uint8_t MPU6050_GetID(void)
{
    
	return MPU6050_ReadReg(MPU6050_WHO_AM_I);
}

/**
  ************************************************************************** 
  ** -------------------------------------------------------------------- **
  ** @name          : MPU6050_GetData
  ** @brief         : 获取数据寄存器
  ** @param         : None
  ** @retval        : int16_t *AccX, int16_t *AccY, int16_t *AccZ,
					  int16_t *GyroX, int16_t *GyroY, int16_t *GyroZ
  ** @author        : XRaccoon
  ** -------------------------------------------------------------------- **
  ** @attention     : None
  ** -------------------------------------------------------------------- **
  ************************************************************************** 
**/
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位;低8位
	/*******************************
	            加速度值
	*******************************/
	DataH = MPU6050_ReadReg(MPU6050_ACCEL_XOUT_H);		//读取高八位的值
	DataL = MPU6050_ReadReg(MPU6050_ACCEL_XOUT_L);		//读取第八位的值
	*AccX = (DataH << 8) | DataL;		//高八位左移8位,再或上第八位:加速度计X轴的16位数据;(通过指针变量返回)
	
	DataH = MPU6050_ReadReg(MPU6050_ACCEL_YOUT_H);
	DataL = MPU6050_ReadReg(MPU6050_ACCEL_YOUT_L);
	*AccY = (DataH << 8) | DataL;
	
	DataH = MPU6050_ReadReg(MPU6050_ACCEL_ZOUT_H);
	DataL = MPU6050_ReadReg(MPU6050_ACCEL_ZOUT_L);
	*AccZ = (DataH << 8) | DataL;
	/*******************************
	            陀螺仪值
	*******************************/	
	DataH = MPU6050_ReadReg(MPU6050_GYRO_XOUT_H);
	DataL = MPU6050_ReadReg(MPU6050_GYRO_XOUT_L);
	*GyroX = (DataH << 8) | DataL;
	
	DataH = MPU6050_ReadReg(MPU6050_GYRO_YOUT_H);
	DataL = MPU6050_ReadReg(MPU6050_GYRO_YOUT_L);
	*GyroY = (DataH << 8) | DataL;
	
	DataH = MPU6050_ReadReg(MPU6050_GYRO_ZOUT_H);
	DataL = MPU6050_ReadReg(MPU6050_GYRO_ZOUT_L);
	*GyroZ = (DataH << 8) | DataL;
}

MPU6050_Soft_Reg.h
MPU6050相关寄存器的宏定义

/**
  ******************************************************************************
  **--------------------------------------------------------------------------**
  ** @FileName      : MPU6050_Reg.h
  ** @Description   : None
  **--------------------------------------------------------------------------**
  ** @Author Date   : XRaccoon  2023-07-24
  ** @Version       : v1.0
  **--------------------------------------------------------------------------**
  ** @Function List : None
  **--------------------------------------------------------------------------**
  ** @Attention     : None
  **--------------------------------------------------------------------------**
  ******************************************************************************
  *
 **/

/* Define to prevent recursive inclusion -------------------------------------*/

#ifndef __M_P_U6050__REG_H_
#define __M_P_U6050__REG_H_


#endif
/******************************** END OF FILE *********************************/

#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	//电源管理寄存器1
#define	MPU6050_PWR_MGMT_2		0x6C	//电源管理寄存器2
#define	MPU6050_WHO_AM_I		0x75	

#endif

注意

硬件IIC见下章

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/qq_67808371/article/details/134191809

智能推荐

yolov5 + pyqt(登录界面)进行检测_在yolov5添加一个登录注册界面-程序员宅基地

文章浏览阅读313次。使用pyqt和yolov5进行界面开发,可实现单张图像,视频,摄像头进行检测,以及暂停,继续和停止等功能,可实时在lineEdit显示缺陷的信息,以及存放表格中和文件夹里_在yolov5添加一个登录注册界面

python基础_1、编写一个名为char.sh的脚本,功能如下(40分): a)由用户输入一个字符 b)判断-程序员宅基地

文章浏览阅读1.2w次,点赞2次,收藏6次。PyCharm 的初始设置(知道)目标恢复 PyCharm 的初始设置第一次启动 PyCharm新建一个 Python 项目设置 PyCharm 的字体显示PyCharm 的升级以及其他PyCharm 的官方网站地址是:https://www.jetbrains.com/pycharm/01. 恢复 PyCharm 的初始设置PyCharm 的 配置信息 是保存在 用户家目录下 的 .PyCharmxxxx.x 目录下的,xxxx.x 表示当前使用的 PyCharm 的版本号如果要恢_1、编写一个名为char.sh的脚本,功能如下(40分): a)由用户输入一个字符 b)判断

C# Task 暂停与取消-程序员宅基地

文章浏览阅读4.8k次。前言:①取消task任务之CancellationTokenSource的用法;②task的线程管控方法Task..Wait(time),Task.WaitAll(),Task.Wait..._c# task.start cancel token

TZOJ 3481 Highway Construction(树的直径+最短路)-程序员宅基地

文章浏览阅读435次。描述As head of the Accessible Commuting Movement (ACM), you've been lobbying the mayor to build a new highway in your city. Today is your lucky day, because your request was approved. There is one c..._最短路 树的直径

微信公众号怎么使用微信返利机器人查优惠券拿佣金返利?-程序员宅基地

文章浏览阅读110次。微信作为中国最受欢迎的社交媒体平台之一,提供了一个独特的机会,即通过搭建个人微信公众号查券返利机器人,帮助用户省钱购物,同时实现自身佣金收入。本文将为您提供一个详细的教程,指导您如何在微赚淘客系统的支持下,搭建您自己的查券返利机器人。通过以上步骤,您的微信公众号将具备查券与返利的功能。您的粉丝将能够通过您的公众号找到商品的最佳优惠券,从而实现省钱购物。同时,您将获得佣金,因为您的粉丝通过您的链接购买商品。链接:https://juejin.cn/post/7288517000581578806。

【bzoj3039】玉蟾宫 悬线法(单调栈)_rainbow和freda来到了湘-程序员宅基地

文章浏览阅读1.9k次。Description有一天,小猫rainbow和freda来到了湘西张家界的天门山玉蟾宫,玉蟾宫宫主蓝兔盛情地款待了它们,并赐予它们一片土地。 这片土地被分成N*M个格子,每个格子里写着’R’或者’F’,R代表这块土地被赐予了rainbow,F代表这块土地被赐予了freda。 现在freda要在这里卖萌。。。它要找一块矩形土地,要求这片土地都标着’F’并且面积最大。 但是rainbow和fr_rainbow和freda来到了湘

随便推点

Linux ssh远程登录_远程登录 xauth 是什么-程序员宅基地

文章浏览阅读1.8k次。Linux ssh命令ssh远程登录ssh讲解示例ssh登录限制_远程登录 xauth 是什么

YoloV5 最强剪枝技术 模型压缩,3ms推理的YoloV5mAP60_怎么看yolov5剪枝效果-程序员宅基地

文章浏览阅读8.8k次,点赞10次,收藏83次。UltraFastYoloV5发布!基于剪枝技术的模型压缩,3ms推理的YoloV5mAP60+_怎么看yolov5剪枝效果

如何通过审计安全事件日志检测密码喷洒(Password Spraying)攻击-程序员宅基地

文章浏览阅读440次。许多渗透测试人员和攻击者通常都会使用一种被称为“密码喷洒(Password Spraying)”的技术来进行测试和攻击。对密码进行喷洒式的攻击,这个叫法很形象,因为它属于自动化密码猜测的一种。这种针对所有用户的自动密码猜测通常是为了避免帐户被锁定,因为针对同一个用户的连续密码猜测会导致帐户被锁定。所以只有对所有用户同时执行特定的密码登录尝试,才能增加破..._事件4771 错误代码0x18

前端开发之走进 Vue.js-程序员宅基地

文章浏览阅读79次。Vue.js作为目前最热门最具前景的前端框架之一,其提供了一种帮助我们快速构建并开发前端项目的新的思维模式。本文旨在帮助大家认识Vue.js,了解Vue.js的开发流程,并进一步理解如何通过Vue.js来构建一个中大型的前端项目,同时做好相应的部署与优化工作。文章将以PPT图片附加文字介绍的形式展开,不会涉及知识点的具体代码,点到为止。有兴趣的同学可以..._前端vue可以输入图或文字

【软考】系统集成项目管理工程师(十一)项目人力资源管理_软考 项目人力资源管理-程序员宅基地

文章浏览阅读7.1k次,点赞15次,收藏14次。软考中级——系统集成项目管理工程师备考干货第十一章:项目人力资源管理。_软考 项目人力资源管理

Windows自动开机及自动执行脚本(后者需要一定的编程基础)_定时开机脚本怎么写-程序员宅基地

文章浏览阅读2.1w次,点赞4次,收藏34次。定时开机的方法windows定时开机是利用任务计划来实现的,具体的步骤如下(Win7为例):右击【计算机】 —> 管理 —> 依次按下图顺序点击,创建基本任务任务基本信息触发器根据需要自选选择操作。这里是关键性的一步,要选择启动程序,然后根据自己的需要启动某个脚本(如果只是想开机的话,就随便选一个浏览器之类的可执行程序 *.exe),下一步,点击完成。双击任务,选..._定时开机脚本怎么写

推荐文章

热门文章

相关标签