STM32F103C8T6 MPU6050 原始数据通过串口读取(CubeMx生成 HAL库) 您所在的位置:网站首页 pc串口数据显示程序 STM32F103C8T6 MPU6050 原始数据通过串口读取(CubeMx生成 HAL库)

STM32F103C8T6 MPU6050 原始数据通过串口读取(CubeMx生成 HAL库)

2024-06-02 12:15| 来源: 网络整理| 查看: 265

STM32F103C8T6 MPU6050 原始数据通过串口读取(CubeMx生成 HAL库)

文章目录 STM32F103C8T6 MPU6050 原始数据通过串口读取(CubeMx生成 HAL库) 前言一、MPU6050简介二、CubeMx设置三、MPU6050驱动结果展示

前言

MPU6050作为一个六轴惯性测量单元,经常在各种设备中被使用,经过一段时间的调试,对其进行小总结,有错误还请各位大佬指出。

一、MPU6050简介

1.基础介绍 在这里插入图片描述

​ MPU6050采用I2C口与单片机进行通信,作为一款六轴运动处理组件,其整合了3轴陀螺仪和三轴加速度传感器,并且含有第二I2C接口用于连接外部磁力传感器。利用自带的数字运动处理(DMP: Digital Motion Processor)硬件加速引擎,通过主 IIC 接口,向应用端输出完整的 9 轴融合演算数据。有了 DMP,我们可以使用 InvenSense 公司提供的运动处理资料库,非常方便的实现姿态解算,降低了运动处理运算对操作系统的负荷,同时大大降低了开发难度。

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

MPU6050的内部框图入图所示:

在这里插入图片描述 ​​

SCL和SDA是连接在MCU的I2C接口,MCU可以通过这个I2C接口来控制MPU6050,另外的I2C接口用于连接外部设备,若连接磁传感器,就可以组成九![轴传感器。AD0 是从 IIC 接口(接 MCU)的地址控制引脚,该引脚控制IIC 地址的最低位。如果接 GND,则 MPU6050 的 IIC 地址是:0X68,如果接 VDD,则是0X69,注意:这里的地址是不包含数据传输的最低位的(最低位用来表示读写)!!

​ 2.利用STM3F1读取MPU6050的原始数据步骤。 1)初始化I2C接口

void MPU_IIC_Init(void)

2)复位MPU6050:让传感器内部的所有寄存器回复默认值(对电源管理寄存器(0x6B)的bit7写1实现)。复位后,电源管理寄存器1恢复默认值(0x40)然后设置该寄存器为0x00,唤醒MPU6050。 在这里插入图片描述

#define MPU_PWR_MGMT1_REG 0X6B //电源管理寄存器1 MPU_Write_Byte(MPU_PWR_MGMT1_REG,0X80); //复位MPU6050 MPU_Write_Byte(MPU_PWR_MGMT1_REG,0X00); //唤醒MPU6050

3)设置角速度传感器(陀螺仪)和加速度传感器的满量程范围 设置两个传感器的满量程范围(FSR),分别通过陀螺仪配置寄存器(0X1B)和加速度传感器配置寄存器(0X1C)设置。一般设置陀螺仪的满量程范围为±2000dps,加速度传感器的满量程范围为±2g

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

#define MPU_GYRO_CFG_REG 0X1B //陀螺仪配置寄存器 #define MPU_ACCEL_CFG_REG 0X1C //加速度计配置寄存器 //fsr:0,±250dps;1,±500dps;2,±1000dps;3,±2000dps uint8_t MPU_Set_Gyro_Fsr(uint8_t fsr) { return MPU_Write_Byte(MPU_GYRO_CFG_REG,fsr u8 data=0; if(lpf>=188)data=1; else if(lpf>=98)data=2; else if(lpf>=42)data=3; else if(lpf>=20)data=4; else if(lpf>=10)data=5; else data=6; return MPU_Write_Byte(MPU_CFG_REG,data);//设置数字低通滤波器 } //设置MPU6050的采样率(假定Fs=1KHz) //rate:4~1000(Hz) uint8_t MPU_Set_Rate(uint16_t rate) { uint8_t data; if(rate>1000)rate=1000; if(rate MPU_Write_Byte(MPU_PWR_MGMT1_REG,0X01); //设置CLKSEL,PLL X轴为参考 MPU_Write_Byte(MPU_PWR_MGMT2_REG,0X00); //加速度与陀螺仪都工作 MPU_Set_Rate(50); //设置采样率为50Hz } else return 1; return 0; } //设置MPU6050陀螺仪传感器满量程范围 //fsr:0,±250dps;1,±500dps;2,±1000dps;3,±2000dps //返回值:0,设置成功 // 其他,设置失败 uint8_t MPU_Set_Gyro_Fsr(uint8_t fsr) { return MPU_Write_Byte(MPU_GYRO_CFG_REG,fsr uint8_t data=0; if(lpf>=188)data=1; else if(lpf>=98)data=2; else if(lpf>=42)data=3; else if(lpf>=20)data=4; else if(lpf>=10)data=5; else data=6; return MPU_Write_Byte(MPU_CFG_REG,data);//设置数字低通滤波器 } //设置MPU6050的采样率(假定Fs=1KHz) //rate:4~1000(Hz) //返回值:0,设置成功 // 其他,设置失败 uint8_t MPU_Set_Rate(uint16_t rate) { uint8_t data; if(rate>1000)rate=1000; if(rate uint8_t buf[6],res; res=MPU_Read_Len(MPU_ADDR,MPU_GYRO_XOUTH_REG,6,buf); if(res==0) { *gx=((uint16_t)buf[0] *ax=((uint16_t)buf[0] MPU_IIC_Stop(); return 1; } MPU_IIC_Send_Byte(reg); //写寄存器地址 MPU_IIC_Wait_Ack(); //等待应答 for(i=0; i MPU_IIC_Stop(); return 1; } } MPU_IIC_Stop(); return 0; } //IIC连续读 //addr:器件地址 //reg:要读取的寄存器地址 //len:要读取的长度 //buf:读取到的数据存储区 //返回值:0,正常 // 其他,错误代码 uint8_t MPU_Read_Len(uint8_t addr,uint8_t reg,uint8_t len,uint8_t *buf) { MPU_IIC_Start(); MPU_IIC_Send_Byte((addr if(len==1)*buf=MPU_IIC_Read_Byte(0);//读数据,发送nACK else *buf=MPU_IIC_Read_Byte(1); //读数据,发送ACK len--; buf++; } MPU_IIC_Stop(); //产生一个停止条件 return 0; } //IIC写一个字节 //reg:寄存器地址 //data:数据 //返回值:0,正常 // 其他,错误代码 uint8_t MPU_Write_Byte(uint8_t reg,uint8_t data) { MPU_IIC_Start(); MPU_IIC_Send_Byte((MPU_ADDR MPU_IIC_Stop(); return 1; } MPU_IIC_Stop(); return 0; } //IIC读一个字节 //reg:寄存器地址 //返回值:读到的数据 uint8_t MPU_Read_Byte(uint8_t reg) { uint8_t res; MPU_IIC_Start(); MPU_IIC_Send_Byte((MPU_ADDRBRR = IIC_SDA_PIN /* SDA = 0 */ #define IIC_SDA_READ() ((GPIO_PORT_IIC->IDR & IIC_SDA_PIN) != 0) /* 读SDA口线状态 */ #endif void IIC_GPIO_Init(void); /* ********************************************************************************************************* * 函 数 名: IIC_Delay * 功能说明: IIC总线位延迟,最快400KHz * 形 参:无 * 返 回 值: 无 ********************************************************************************************************* */ static void IIC_Delay(void) { uint8_t i; /*  下面的时间是通过安富莱AX-Pro逻辑分析仪测试得到的。 CPU主频72MHz时,在内部Flash运行, MDK工程不优化 循环次数为10时,SCL频率 = 205KHz 循环次数为7时,SCL频率 = 347KHz, SCL高电平时间1.5us,SCL低电平时间2.87us 循环次数为5时,SCL频率 = 421KHz, SCL高电平时间1.25us,SCL低电平时间2.375us IAR工程编译效率高,不能设置为7 */ for (i = 0; i /* 当SCL高电平时,SDA出现一个上跳沿表示IIC总线停止信号 */ IIC_SDA_0(); IIC_SCL_1(); IIC_Delay(); IIC_SDA_1(); } /* ********************************************************************************************************* * 函 数 名: IIC_SendByte * 功能说明: CPU向IIC总线设备发送8bit数据 * 形 参:_ucByte : 等待发送的字节 * 返 回 值: 无 ********************************************************************************************************* */ void IIC_Send_Byte(uint8_t _ucByte) { uint8_t i; /* 先发送字节的高位bit7 */ for (i = 0; i IIC_SDA_1(); } else { IIC_SDA_0(); } IIC_Delay(); IIC_SCL_1(); IIC_Delay(); IIC_SCL_0(); if (i == 7) { IIC_SDA_1(); // 释放总线 } _ucByte value uint8_t re; IIC_SDA_1(); /* CPU释放SDA总线 */ IIC_Delay(); IIC_SCL_1(); /* CPU驱动SCL = 1, 此时器件会返回ACK应答 */ IIC_Delay(); if (IIC_SDA_READ()) /* CPU读取SDA口线状态 */ { re = 1; } else { re = 0; } IIC_SCL_0(); IIC_Delay(); return re; } /* ********************************************************************************************************* * 函 数 名: IIC_Ack * 功能说明: CPU产生一个ACK信号 * 形 参:无 * 返 回 值: 无 ********************************************************************************************************* */ void IIC_Ack(void) { IIC_SDA_0(); /* CPU驱动SDA = 0 */ IIC_Delay(); IIC_SCL_1(); /* CPU产生1个时钟 */ IIC_Delay(); IIC_SCL_0(); IIC_Delay(); IIC_SDA_1(); /* CPU释放SDA总线 */ } /* ********************************************************************************************************* * 函 数 名: IIC_NAck * 功能说明: CPU产生1个NACK信号 * 形 参:无 * 返 回 值: 无 ********************************************************************************************************* */ void IIC_NAck(void) { IIC_SDA_1(); /* CPU驱动SDA = 1 */ IIC_Delay(); IIC_SCL_1(); /* CPU产生1个时钟 */ IIC_Delay(); IIC_SCL_0(); IIC_Delay(); } /* ********************************************************************************************************* * 函 数 名: IIC_GPIO_Config * 功能说明: 配置IIC总线的GPIO,采用模拟IO的方式实现 * 形 参:无 * 返 回 值: 无 ********************************************************************************************************* */ void IIC_GPIO_Init(void) { GPIO_InitTypeDef GPIO_InitStructure; RCC_IIC_ENABLE; /* 打开GPIO时钟 */ GPIO_InitStructure.Pin = IIC_SCL_PIN | IIC_SDA_PIN; GPIO_InitStructure.Speed = GPIO_SPEED_FREQ_HIGH; GPIO_InitStructure.Mode = GPIO_MODE_OUTPUT_OD; /* 开漏输出 */ HAL_GPIO_Init(GPIO_PORT_IIC, &GPIO_InitStructure); /* 给一个停止信号, 复位IIC总线上的所有设备到待机模式 */ IIC_Stop(); } /* ********************************************************************************************************* * 函 数 名: IIC_CheckDevice * 功能说明: 检测IIC总线设备,CPU向发送设备地址,然后读取设备应答来判断该设备是否存在 * 形 参:_Address:设备的IIC总线地址 * 返 回 值: 返回值 0 表示正确, 返回1表示未探测到 ********************************************************************************************************* */ uint8_t IIC_CheckDevice(uint8_t _Address) { uint8_t ucAck; IIC_GPIO_Init(); /* 配置GPIO */ IIC_Start(); /* 发送启动信号 */ /* 发送设备地址+读写控制bit(0 = w, 1 = r) bit7 先传 */ IIC_Send_Byte(_Address|IIC_WR); ucAck = IIC_Wait_Ack(); /* 检测设备的ACK应答 */ IIC_Stop(); /* 发送停止信号 */ return ucAck; }

IIC.h

#ifndef _IIC_H #define _IIC_H #include #define IIC_WR 0 /* 写控制bit */ #define IIC_RD 1 /* 读控制bit */ void IIC_Start(void); void IIC_Stop(void); void IIC_Send_Byte(uint8_t _ucByte); uint8_t IIC_Read_Byte(uint8_t ack); uint8_t IIC_Wait_Ack(void); void IIC_Ack(void); void IIC_NAck(void); uint8_t IIC_CheckDevice(uint8_t _Address); void IIC_GPIO_Init(void); #endif

完成所有驱动文件的添加之后记得将User文件夹添加到c/c++路径中编译,编译成功后就可以开始编写主函数。

首先添加头文件 在这里插入图片描述 为了串口打印方便,加入printf函数 在这里插入图片描述

int main(void) { /* USER CODE BEGIN 1 */ short aacx,aacy,aacz; //加速度传感器原始数据 short gyrox,gyroy,gyroz; //陀螺仪原始数据 short temp; //温度 /* 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(); MX_DMA_Init(); MX_I2C1_Init(); MX_USART1_UART_Init(); /* USER CODE BEGIN 2 */ MPU_Init(); /* USER CODE END 2 */ /* Infinite loop */ /* USER CODE BEGIN WHILE */ while (1) { /* USER CODE END WHILE */ /* USER CODE BEGIN 3 */ HAL_Delay(500); MPU_Get_Accelerometer(&aacx,&aacy,&aacz); MPU_Get_Gyroscope(&gyrox,&gyroy,&gyroz); temp=MPU_Get_Temperature(); printf("AAC_X:%5d AAC_Y:%5d AAC_Z:%5d\r\nGYRO_X:%5d GYRO_Y:%5d GYRO_Z:%5d\r\n", aacx,aacy,aacz,gyrox,gyroy,gyroz); } /* USER CODE END 3 */ } 结果展示

STM32F103C8T6 MPU6050 原始数据读取(CubeMx生成 HAL库)

在这里插入图片描述

原始数据的读取对于MPU6050的使用而言只是第一步,要想取得俯仰角(pitch),横滚角(roll),航偏角(yaw)的数据,还需要使用官方给出的DMP库或者卡尔曼滤波。



【本文地址】

公司简介

联系我们

今日新闻

    推荐新闻

    专题文章
      CopyRight 2018-2019 实验室设备网 版权所有