stm32f103用HAl库驱动Mpu6050,获取加速度和角加速度

目录

一、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();
	}
 

三、结果演示

  • 3
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
在使用STM32 HAL库进行IIC驱动MPU6050时,可以按照以下步骤进行配置和初始化: 1. 首先,添加所需的头文件,包括"oled.h"、"mpu6050.h"、"control.h"、"inv_mpu.h"和"inv_mpu_dmp_motion_driver.h"。\[1\] 2. 在初始化函数中,调用MX_I2C1_Init()函数来初始化IIC总线。\[2\] 3. 调用mpu_init()函数来初始化MPU6050。如果返回值为0,则表示初始化成功。\[2\] 4. 使用mpu_set_sensors()函数设置所需的传感器,例如陀螺仪和加速度计。\[2\] 5. 使用mpu_configure_fifo()函数设置FIFO,以确定传感器数据的存储方式。\[2\] 6. 使用mpu_set_sample_rate()函数设置采样率。\[2\] 7. 调用dmp_load_motion_driver_firmware()函数加载DMP固件。\[2\] 8. 使用dmp_set_orientation()函数设置陀螺仪方向。\[2\] 9. 使用dmp_enable_feature()函数设置DMP功能,例如姿态、敲击和原始数据的发送。\[2\] 10. 使用dmp_set_fifo_rate()函数设置DMP输出速率。\[2\] 11. 调用run_self_test()函数进行自检。\[2\] 12. 使用mpu_set_dmp_state()函数使能DMP。\[2\] 13. 在相关初始化函数定义之后,添加循环代码,通过mpu_dmp_get_data()函数获取角度数据,并进行相应的处理和输出。\[3\] 14. 最后,根据需要添加延时函数,以控制数据的采样频率。\[3\] 以上是使用STM32 HAL库进行IIC驱动MPU6050的基本步骤。根据具体的应用需求,你可能需要进行一些额外的配置和修改。 #### 引用[.reference_title] - *1* *2* *3* [HAL库 STM32CubeMX----SPI驱动OLED 与 IIC驱动MPU6050](https://blog.csdn.net/weixin_62213694/article/details/125018662)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insertT0,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值