目录

一、mpu6050简介

二、IIC协议底层如下

        1,myiic.c代码:

        2,myiic.h文件:

        3,mpu6050.c

        4,mpu6050.h

        5,mpu6050地址映射定义

        

6.主函数获取三轴加速度和三轴角速度

三、结果演示


一、mpu6050简介

1)16位ADC采集传感器的模拟信号,量化范围:-32768~32767。
2)加速度计满量程范围选择:±2、±4、±8、±16(g) g表示重力加速度1g=9.8m/s²
3)陀螺仪满量程选择:±250、±500、±1000、±2000(°/sec) 每秒钟旋转了多少度(如果测量的物体运动非常剧烈,可以把满量程选择大一些,如果运动比较平缓,可以选择更小的量程,这样分辨率会更大。)可配置的数字低通滤波器在这个芯片可以配置寄存器来选择对输出的数据进行低通滤波)可配置的时钟源和可配置的采样分频(为AD转换和芯片内部其他电路提供时钟,控制分频系数,可以控制AD转化的快慢。)
4)I2C从机地址:当AD0=0时,地址为0xD0,当AD0=1时,地址为0xD1,AD0是板子引出来的引脚,可以调节I2C从机地址的最低位。
5)(16位表示时,有两种方式,①是把1101000转成16进制0x68,但是因为还有一位读写位,一般使用(0x68<<1)|读写位。读1写0。②把0x68左移一位后的数据当作从机地址,也就是0xD0,再或上读写位。

二、IIC协议底层如下

        1,myiic.c代码:

#include "myiic.h"
#include "main.h"
#include "Delay.h"

static void iic_delay(void)
{
    Delay_us(10);
}
 
/* 起始信号 */
void iic_start(void)
{
    /* SCL为高电平期间, SDA从高电平往低电平跳变*/
    IIC_SDA ( 1 );
    IIC_SCL ( 1 );
    iic_delay( );
    IIC_SDA ( 0 );
    iic_delay( );
    IIC_SCL ( 0 );
    iic_delay( );  /* 钳住总线, 准备发送/接收数据 */
}
 
/* 停止信号 */
void iic_stop(void)
{
    /* SCL为高电平期间, SDA从低电平往高电平跳变*/
    IIC_SDA ( 0 );
    iic_delay( );
    IIC_SCL ( 1 );
    iic_delay( );
    IIC_SDA ( 1 );  /* 发送总线停止信号*/
    iic_delay( );
}
 
/* 等待应答信号 */
uint8_t iic_wait_ack (void) /* return 1:fail 0:succeed*/
{
    uint8_t AckBit;
    IIC_SDA (1);    /* 主机释放SDA线 */
    iic_delay( );
    IIC_SCL (1);    /* 从机返回ACK*/
    iic_delay( );
    AckBit = IIC_READ_SDA; /* SCL高电平读取SDA状态*/ 

    IIC_SCL(0);         /* SCL低电平表示结束ACK检查 */ 
    iic_delay( );
    return AckBit;
}
 

//发送应答位
void iic_SendAck(uint8_t AckBit)
{
    IIC_SDA(AckBit);
    iic_delay();
    IIC_SCL(1);
    IIC_SCL(0);
}

 
/* 发送一个字节数据 */
void iic_send_byte(uint8_t data)
{
    for (uint8_t t = 0; t < 8; t++)
    {
        /* 高位先发 */
        IIC_SDA(data & (0x80 >> t));
        iic_delay( );
        IIC_SCL ( 1 );
        iic_delay( );
        IIC_SCL ( 0 );
    }
}
 
/* 读取1字节数据 */
uint8_t iic_read_byte (void)
{ 
    uint8_t receive = 0 ;
    for (uint8_t t = 0; t < 8; t++)
    {
        /* 高位先输出,先收到的数据位要左移 */ 
        IIC_SCL ( 1 );
        iic_delay( );
        if ( IIC_READ_SDA == 1 ) { receive |= (0x80 >> t);}
        IIC_SCL ( 0 );
        iic_delay( );
    }
    return receive;
}


        2,myiic.h文件:

#ifndef __MYIIC_H
#define __MYIIC_H
#include "stm32f1xx_hal.h"
/******************************************************************************************/
/* 引脚 定义 */
 
#define IIC_SCL_GPIO_PORT               GPIOB
#define IIC_SCL_GPIO_PIN                GPIO_PIN_10
#define IIC_SCL_GPIO_CLK_ENABLE()       do{ __HAL_RCC_GPIOB_CLK_ENABLE(); }while(0)   /* PB口时钟使能 */
 
#define IIC_SDA_GPIO_PORT               GPIOB
#define IIC_SDA_GPIO_PIN                GPIO_PIN_11
#define IIC_SDA_GPIO_CLK_ENABLE()       do{ __HAL_RCC_GPIOB_CLK_ENABLE(); }while(0)   /* PB口时钟使能 */
 
/******************************************************************************************/
 
/* IO操作 */
#define IIC_SCL(x)        do{ x ? \
                              HAL_GPIO_WritePin(IIC_SCL_GPIO_PORT, IIC_SCL_GPIO_PIN, GPIO_PIN_SET) : \
                              HAL_GPIO_WritePin(IIC_SCL_GPIO_PORT, IIC_SCL_GPIO_PIN, GPIO_PIN_RESET); \
                          }while(0)       /* SCL */
 
#define IIC_SDA(x)        do{ x ? \
                              HAL_GPIO_WritePin(IIC_SDA_GPIO_PORT, IIC_SDA_GPIO_PIN, GPIO_PIN_SET) : \
                              HAL_GPIO_WritePin(IIC_SDA_GPIO_PORT, IIC_SDA_GPIO_PIN, GPIO_PIN_RESET); \
                          }while(0)       /* SDA */
 
#define IIC_READ_SDA     HAL_GPIO_ReadPin(IIC_SDA_GPIO_PORT, IIC_SDA_GPIO_PIN) /* 读取SDA */
 
void iic_start(void);
void iic_stop(void);
uint8_t iic_wait_ack(void);
void iic_send_byte(uint8_t data);
uint8_t iic_read_byte (void);
void iic_SendAck(uint8_t AckBit);													
#endif

        3,mpu6050.c

#include "main.h"
#include "myiic.h"
#include "mpu6050_reg.h"
#include "Delay.h"
#include "mpu6050.h"
#define MPU6050_ADDRESS		    0xD0

void MPU6050_WriteReg(uint8_t RegAddress, uint8_t Data)
{
	iic_start();
	iic_send_byte(MPU6050_ADDRESS);
	iic_wait_ack();
	iic_send_byte(RegAddress);
	iic_wait_ack();
	iic_send_byte(Data);
	iic_wait_ack();
	iic_stop();
}

uint8_t MPU6050_ReadReg(uint8_t RegAddress)
{
	uint8_t Data;
	
	iic_start();
	iic_send_byte(MPU6050_ADDRESS);
	iic_wait_ack();
	iic_send_byte(RegAddress);
	iic_wait_ack();
	iic_stop();
	
	iic_start();
	iic_send_byte(MPU6050_ADDRESS | 0x01);
	iic_wait_ack();
	Data = iic_read_byte();
	iic_SendAck(1);
	iic_stop();
	return Data;
}
void MPU6050_Init(void)
{
	MPU6050_WriteReg(MPU6050_PWR_MGMT_1, 0x01);
	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);
}
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;
	
	DataH = MPU6050_ReadReg(MPU6050_ACCEL_XOUT_H);
	DataL = MPU6050_ReadReg(MPU6050_ACCEL_XOUT_L);
	*AccX = (DataH << 8) | DataL;
	
	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;
}

void MY_MPU6050_GetData(mpu6050_data *date)
					
{
	uint8_t DataH, DataL;
	
	DataH = MPU6050_ReadReg(MPU6050_ACCEL_XOUT_H);
	DataL = MPU6050_ReadReg(MPU6050_ACCEL_XOUT_L);
	date->AccX = (DataH << 8) | DataL;
	
	DataH = MPU6050_ReadReg(MPU6050_ACCEL_YOUT_H);
	DataL = MPU6050_ReadReg(MPU6050_ACCEL_YOUT_L);
	date->AccY = (DataH << 8) | DataL;
	
	DataH = MPU6050_ReadReg(MPU6050_ACCEL_ZOUT_H);
	DataL = MPU6050_ReadReg(MPU6050_ACCEL_ZOUT_L);
	date->AccZ = (DataH << 8) | DataL;
	
	DataH = MPU6050_ReadReg(MPU6050_GYRO_XOUT_H);
	DataL = MPU6050_ReadReg(MPU6050_GYRO_XOUT_L);
	date->GyroX = (DataH << 8) | DataL;
	
	DataH = MPU6050_ReadReg(MPU6050_GYRO_YOUT_H);
	DataL = MPU6050_ReadReg(MPU6050_GYRO_YOUT_L);
	date->GyroY = (DataH << 8) | DataL;
	
	DataH = MPU6050_ReadReg(MPU6050_GYRO_ZOUT_H);
	DataL = MPU6050_ReadReg(MPU6050_GYRO_ZOUT_L);
	date->GyroZ  = (DataH << 8) | DataL;
}

        4,mpu6050.h

#ifndef __Mpu6050_H__
#define __Mpu6050_H__
void MPU6050_GetData(int16_t *AccX, int16_t *AccY, int16_t *AccZ, 
						int16_t *GyroX, int16_t *GyroY, int16_t *GyroZ);
void MPU6050_Init(void);
uint8_t MPU6050_GetID(void);

typedef  struct mpu6050{
	int16_t AccX;
	int16_t AccY;
	int16_t AccZ;
	int16_t GyroX; 
	int16_t GyroY;
	int16_t GyroZ;
}mpu6050_data;
void MY_MPU6050_GetData(mpu6050_data *date);

#endif

        5,mpu6050地址映射定义

#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

        

6.主函数获取三轴加速度和三轴角速度

mpu6050_data mydate_mpu6050;//获取数据结构体

int main(void)
{
  /* USER CODE BEGIN 1 */
	uint8_t ID;
  /* USER CODE END 1 */

  /* MCU Configuration--------------------------------------------------------*/

  /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
  HAL_Init();

  /* USER CODE BEGIN Init */

  /* USER CODE END Init */

  /* Configure the system clock */
  SystemClock_Config();

  /* USER CODE BEGIN SysInit */

  /* USER CODE END SysInit */

  /* Initialize all configured peripherals */
  MX_GPIO_Init();
  /* USER CODE BEGIN 2 */
	Delay_Init();
	OLED_Init();
	MPU6050_Init();
	ID = MPU6050_GetID();
	OLED_ShowHexNum(1,1,ID,3,OLED_8X16);
	OLED_Update();

  while (1)
  {
		MY_MPU6050_GetData(&mydate_mpu6050);
		OLED_ShowSignedNum(1,17,mydate_mpu6050.AccX,5,OLED_8X16);
		OLED_ShowSignedNum(1,33,mydate_mpu6050.AccY,5,OLED_8X16);
		OLED_ShowSignedNum(1,49,mydate_mpu6050.AccZ,5,OLED_8X16);	
		OLED_ShowSignedNum(60,17,mydate_mpu6050.GyroX,5,OLED_8X16);
		OLED_ShowSignedNum(60,33,mydate_mpu6050.GyroY,5,OLED_8X16);
		OLED_ShowSignedNum(60,49,mydate_mpu6050.GyroZ,5,OLED_8X16);
		OLED_Update();
	}
 

三、结果演示

Logo

魔乐社区(Modelers.cn) 是一个中立、公益的人工智能社区,提供人工智能工具、模型、数据的托管、展示与应用协同服务,为人工智能开发及爱好者搭建开放的学习交流平台。社区通过理事会方式运作,由全产业链共同建设、共同运营、共同享有,推动国产AI生态繁荣发展。

更多推荐