文章目录
MPU6050 ,能同时检测三轴加速度、 三轴陀螺仪(三轴角速度)的运动数据以及温度数据。利用其内部的 DMP 模块(Digital Motion Processor 数字运动处理器) ,可对传感器数据进行滤波、融合处理,直接通过 IIC 接口向主控器输出姿态解算后的数据,降低主控器的运算量。其姿态解算频率最高可达 200Hz
| 参数 | 说明 |
|---|---|
| 供电 | 3.3V-5V |
| 通讯接口 | IIC 协议,支持的 IIC 时钟最高频率为 400KHz |
| 测量维度 | 加速度: 3 维 陀螺仪: 3 维 |
| ADC 分辨率 | 加速度: 16 位 陀螺仪: 16 位 |
| 加速度测量范围 | ±2g、 ±4g、 ±8g、 ±16g 其中 g 为重力加速度常数, g=9.8m/s ² |
| 加速度最高分辨率 | 16384 LSB/g |
| 加速度测量精度 | 0.1g |
| 加速度输出频率 | 最高 1000Hz |
| 陀螺仪测量范围 | ±250 º/s 、 ±500 º/s 、 ±1000 º/s、 ±2000 º/s、 |
| 陀螺仪最高分辨率 | 131 LSB/( º/s) |
| 陀螺仪测量精度 | 0.1 º/s |
| 陀螺仪输出频率 | 最高 8000Hz |
| DMP 姿态解算频率 | 最高 200Hz |
| 温度传感器测量范围 | -40~ +85℃ |
| 温度传感器分辨率 | 340 LSB/℃ |
| 温度传感器精度 | ±1℃ |
| 工作温度 | -40~ +85℃ |
| 功耗 | 500uA~3.9mA (工作电压 3.3V) |
| 引脚名称 | 说明 |
|---|---|
| VCC | 3.3/5V 电源输入 |
| GND | 地线 |
| SCL | I2C 从时钟信号线 SCL (模块上已接上拉电阻) |
| SDA | I2C 从数据信号线 SDA (模块上已接上拉电阻) |
| XDA | I2C 主串行数据信号线,用于外接传感器(模块上已接上拉电阻) |
| XCL | I2C 主串行时钟信号线,用于外接传感器(模块上已接上拉电阻) |
| AD0 | 从机地址设置引脚接地或悬空时, 地址为: 0x68;接 VCC 时,地址为:0x69 |
| INT | 中断输出引脚 |
备注:SDA/SCL、 XDA/XCL 通讯引脚分别为两组 I2C 信号线;当模块与外部主机通讯时, 使用 SDA/SCL,如与 STM32 芯片通讯; 而 XDA/XCL 则用于 MPU6050 芯片与其它I2C 传感器通讯时使用,但一般不这样使用。
模块引脚与单片机连接
| 引脚名称 | 开发板连接 |
|---|---|
| VCC | 接3.3或5V |
| GND | GND |
| SCL | PB6 |
| SDL | PB7 |
| AD0 | 悬空或者接地 |
| INT | PA11 |
编程要点
(1) 初始化 STM32 的 I2C(软件模拟);
(2) 使用 I2C 向 MPU6050 写入控制参数;
(3) 定时读取加速度、角速度及温度数据;
#define GPIO_PORT_I2C GPIOB /* GPIO端口*/
#define RCC_I2C_PORT RCC_APB2Periph_GPIOB /* GPIO时钟*/
#define I2C_SCL_PIN GPIO_Pin_6 /* 连接SCL的GPIO */
#define I2C_SDA_PIN GPIO_Pin_7 /* 连接SDL的GPIO */
#define I2C_SCL_1() GPIO_SetBits(GPIO_PORT_I2C, I2C_SCL_PIN) /* SCL = 1 */
#define I2C_SCL_0() GPIO_ResetBits(GPIO_PORT_I2C, I2C_SCL_PIN) /* SCL = 0 */
#define I2C_SDA_1() GPIO_SetBits(GPIO_PORT_I2C, I2C_SDA_PIN) /* SDA = 1 */
#define I2C_SDA_0() GPIO_ResetBits(GPIO_PORT_I2C, I2C_SDA_PIN) /* SDA = 0 */
#define I2C_SDA_READ() GPIO_ReadInputDataBit(GPIO_PORT_I2C, I2C_SDA_PIN) /*读SDA数据 */
static void i2c_Delay(void)
{
uint8_t i;
for (i = 0; i < 10; i++);
}
//当SCL高电平时,SDA出现一个下跳沿表示I2C总线启动信号
void i2c_Start(void)
{
/* _____
*SDA \_____________
* __________
*SCL \________
*/
I2C_SDA_1();
I2C_SCL_1();
i2c_Delay();
I2C_SDA_0();
i2c_Delay();
I2C_SCL_0();
i2c_Delay();
}
//当SCL高电平时,SDA出现一个上跳沿表示I2C总线停止信号
void i2c_Stop(void)
{
/* _______
*SDA __________/
* ____________
*SCL _____/
*/
I2C_SDA_0();
I2C_SCL_1();
i2c_Delay();
I2C_SDA_1();
}
/*CPU向I2C总线设备发送8bit数据
*/
void i2c_SendByte(uint8_t _ucByte)
{
uint8_t i;
/* 先发送高7位,*/
for (i = 0; i < 8; i++)
{
if (_ucByte & 0x80)
{
I2C_SDA_1();//发送的1
}
else
{
I2C_SDA_0();//发送的0
}
i2c_Delay();
I2C_SCL_1();
i2c_Delay();
I2C_SCL_0();
if (i == 7)
{
I2C_SDA_1(); //释放总线
}
_ucByte <<= 1; /*左移一个 bit */
i2c_Delay();
}
}
/*
CPU从I2C设备读取8bit数据
*/
uint8_t i2c_ReadByte(u8 ack)
{
uint8_t i;
uint8_t value;
/* 读取到第一个bit为数据的bit7 */
value = 0;
for (i = 0; i < 8; i++)
{
value <<= 1;
I2C_SCL_1();
i2c_Delay();
if (I2C_SDA_READ())
{
value++;
}
I2C_SCL_0();
i2c_Delay();
}
if(ack==0)
i2c_NAck();
else
i2c_Ack();
return value;
}
/*
CPU产生一个时钟,并读取器件的ACK应答信号
*/
uint8_t i2c_WaitAck(void)
{
uint8_t re;
I2C_SDA_1(); /* CPU释放SDA总线 */
i2c_Delay();
I2C_SCL_1(); /* CPU驱动SCL = 1, 此器件会返回ACK应答 */
i2c_Delay();
if (I2C_SDA_READ()) /* CPU读取SDA口状态 */
{
re = 1;
}
else
{
re = 0;
}
I2C_SCL_0();
i2c_Delay();
return re;
}
/*
CPU产生一个ACK信号
*/
void i2c_Ack(void)
{
/* ____
*SCL ______/ \______
* ____ _____
*SDA \_______/
*/
I2C_SDA_0(); /* CPU驱动SDA = 0 */
i2c_Delay();
I2C_SCL_1(); /* CPU产生1个时钟 */
i2c_Delay();
I2C_SCL_0();
i2c_Delay();
I2C_SDA_1(); /* CPU释放SDA总线 */
}
/*
CPU产生1个NACK信号
*/
void i2c_NAck(void)
{
/* ____
*SCL ______/ \______
* __________________
*SDA
*/
I2C_SDA_1(); /* CPU驱动SDA = 1 */
i2c_Delay();
I2C_SCL_1(); /* CPU产生一个时钟 */
i2c_Delay();
I2C_SCL_0();
i2c_Delay();
}
/*
配置I2C总线的GPIO
*/
void i2c_GPIO_Config(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd(RCC_I2C_PORT, ENABLE); //时钟
GPIO_InitStructure.GPIO_Pin = I2C_SCL_PIN | I2C_SDA_PIN;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_OD; //开漏输出
GPIO_Init(GPIO_PORT_I2C, &GPIO_InitStructure);
//停止信号,复位I2C总线上的所有设备
i2c_Stop();
}
/*
CPU发送设备地址,然后读取设备应答是否有设备
*/
uint8_t i2c_CheckDevice(uint8_t _Address)
{
uint8_t ucAck;
i2c_GPIO_Config(); /* 配置GPIO */
i2c_Start(); /*I2C开始信号*/
/* 发送设备地址和读写控制bit(0=写,1=读)bit7位先传 */
i2c_SendByte(_Address|I2C_WR);
ucAck = i2c_WaitAck(); /*检测设备应答 */
i2c_Stop(); /* I2C结束信号 */
return ucAck;
}
mp6050使用软件I2C读写数据
写
void MPU6050_WriteReg(u8 reg_add,u8 reg_dat)
{
i2c_Start();
i2c_SendByte(MPU6050_SLAVE_ADDRESS);
i2c_WaitAck();
i2c_SendByte(reg_add);
i2c_WaitAck();
i2c_SendByte(reg_dat);
i2c_WaitAck();
i2c_Stop();
}
读
void MPU6050_ReadData(u8 reg_add,unsigned char*Read,u8 num)
{
unsigned char i;
i2c_Start();
i2c_SendByte(MPU6050_SLAVE_ADDRESS);
i2c_WaitAck();
i2c_SendByte(reg_add);
i2c_WaitAck();
i2c_Start();
i2c_SendByte(MPU6050_SLAVE_ADDRESS+1);
i2c_WaitAck();
for(i=0;i<(num-1);i++){
*Read=i2c_ReadByte(1);
Read++;
}
*Read=i2c_ReadByte(0);
i2c_Stop();
}
1、电源管理寄存器

描述:这个寄存器允许用户配置电源模式和时钟源。它也提供1位重置整个设备,和1位使能温度传感器
SLEEP 设置1时,设备进入低功耗休眠模式;TEMP_DIS用于设置是否使能温度传感器,0 则使能
CLKSEL[2:0]时钟源如下,

内部8M RC晶振精度不高,一般选择X/Y/Z轴陀螺作为参考PLL的时钟源,设置CLKSEL=001
2、陀螺仪寄存器
该寄存器用于触发陀螺仪自检并配置陀螺仪的量程范围。

FS_SEL[1:0]的取值:0,±250° /S; 1,±500° /S; 2,±1000° /S; 3,±2000° /S;
一般设置为3,±2000dps,因为陀螺仪的ADC为16位分辨率,所以得到灵敏度为65536/4000 = 16.4LSB(°/S)
3、加速度传感器
该寄存器用于触发加速计自检并配置加速计满标度范围。该寄存器还配置数字高通滤波器(DHPF)。

AFS_SEL[1:0]选择范围:0, ±2g; 1,±4g; 2,±8g; 3,±16g;
一般设置为0,±2g ,灵敏度为65536/4=16384 LSB/g
4、 采样率
该寄存器指定用于生成MPU-60X0采样率的陀螺仪输出速率的除法器。

传感器寄存器输出、FIFO输出和DMP采样均基于采样率。
在这陀螺仪的输出频率是1Khz或者8Khz,与数字低通滤波器(DLPF)的设置有关。
公式 采样频率 = 陀螺仪输出频率 / (1+SMPLRT_DIV)
当 DLPF_CFG=0/7 的时候,频率为 8Khz,其他情况是 1Khz。而且 DLPF 滤波频率一般设置
为采样率的一半。
例如:采样率,假设为125HZ,那么 SMPLRT_DIV=1000/125 - 1 = 7
5、 配置寄存器
该寄存器配置陀螺仪和加速度计的外部帧同步(FSYNC)引脚采样和数字低通滤波器(DLPF)设置。

其中,DLPF_CFG 配置低通滤波如下

一般我们设置角速度传感器的带宽为其采样率的一半, 如前面所说的,如果设置采样率为 125Hz,那么带宽就应该设置为 62Hz,取近似值 44Hz, 就应该设置 DLPF_CFG=011
初始化程序
#define MPU6050_RA_SMPLRT_DIV 0x19
#define MPU6050_RA_CONFIG 0x1A
#define MPU6050_RA_GYRO_CONFIG 0x1B
#define MPU6050_RA_ACCEL_CONFIG 0x1C
#define MPU6050_RA_PWR_MGMT_1 0x6B
#define MPU6050_RA_PWR_MGMT_2 0x6C
#define MPU6050_WHO_AM_I 0x75
#define MPU6050_SMPLRT_DIV 0 //8000Hz fix me
#define MPU6050_DLPF_CFG 0 //fix me
#define MPU6050_GYRO_OUT 0x43 //MPU6050陀螺仪数据寄存器地址
#define MPU6050_ACC_OUT 0x3B //MPU6050加速度数据寄存器地址
void MPU6050_Init(void)
{
int i=0,j=0;
for(i=0;i<1000;i++)
{
for(j=0;j<1000;j++);
}
MPU6050_WriteReg(MPU6050_RA_PWR_MGMT_1, 0x01);
MPU6050_WriteReg(MPU6050_RA_SMPLRT_DIV , 0x07); //值得设置
MPU6050_WriteReg(MPU6050_RA_CONFIG , 0x03);//值得设置
MPU6050_WriteReg(MPU6050_RA_ACCEL_CONFIG , 0x00);
MPU6050_WriteReg(MPU6050_RA_GYRO_CONFIG, 0x18);
}
1、 陀螺仪数据输出寄存器
通过读取这6个寄存器,就可以读到陀螺仪 x/y/z 轴的值,比如 x 轴的数据,可以通过读取 0X43(高 8 位)和 0X44(低 8 位)寄存器得到,其他轴以此类推
void MPU6050ReadGyro(short *gyroData)
{
u8 buf[6];
MPU6050_ReadData(MPU6050_GYRO_OUT,buf,6);
gyroData[0] = (buf[0] << 8) | buf[1];
gyroData[1] = (buf[2] << 8) | buf[3];
gyroData[2] = (buf[4] << 8) | buf[5];
}
2、加速度传感器数据输出寄存器
通过读取这6个寄存器,就可以读到加速度传感器 x/y/z 轴的值,比如读 x 轴的数据,可以通过读取0X3B(高 8 位)和0X3C(低8位)寄存器得到,其他轴以此类推
void MPU6050ReadAcc(short *accData)
{
u8 buf[6];
MPU6050_ReadData(MPU6050_ACC_OUT, buf, 6);
accData[0] = (buf[0] << 8) | buf[1];
accData[1] = (buf[2] << 8) | buf[3];
accData[2] = (buf[4] << 8) | buf[5];
}
3、 温度换算
温度传感器的值,可以通过读取 0X41(高 8 位)和 0X42(低 8 位)寄存器得到,
温度换算公式为:Temperature = 36.53 + regval/340
其中, Temperature 为计算得到的温度值,单位为℃, regval 为从 0X41 和 0X42 读到的温度传感器值
void MPU6050_ReturnTemp(float *Temperature)
{
short temp3;
u8 buf[2];
MPU6050_ReadData(MPU6050_RA_TEMP_OUT_H,buf,2);
temp3= (buf[0] << 8) | buf[1];
*Temperature=((double) temp3/340.0)+36.53;
}
4、主程序
uint8_t MPU6050ReadID(void)
{
unsigned char Re = 0;
MPU6050_ReadData(MPU6050_RA_WHO_AM_I,&Re,1); //读器件地址
if (Re != 0x68) {
MPU_ERROR("检测不到 MPU6050 模块");
return 0;
} else {
MPU_INFO("MPU6050 ID = %d\r\n",Re);
return 1;
}
}
int main(void)
{
short Accel[3];
short Gyro[3];
float Temp;
SysTick_Init();
SysTick->CTRL|=SysTick_CTRL_ENABLE_Msk;
USART_Config();
i2c_GPIO_Config();
MPU6050_Init();
//检测MPU6050
if (MPU6050ReadID() == 1)
{
while(1)
{
if(Task_Delay[0]==TASK_ENABLE)
{
Task_Delay[0]=1000;
}
if(Task_Delay[1]==0)
{
MPU6050ReadAcc(Accel);
printf("\加速度 %8d%8d%8d ",Accel[0],Accel[1],Accel[2]);
MPU6050ReadGyro(Gyro);
printf("陀螺仪 %8d%8d%8d ",Gyro[0],Gyro[1],Gyro[2]);
MPU6050_ReturnTemp(&Temp);
printf("温度 %8.2f",Temp);
Task_Delay[1]=500;//更新数据的频率
}
}
}
}
加速度: 2634 -2146 16238 陀螺仪: -63 -29 -33 温度: 21.51
加速度: 2680 -2312 16044 陀螺仪: -53 -18 -36 温度: 21.53
加速度: 2744 -2320 16196 陀螺仪: -48 -16 -36 温度: 21.66
加速度: -1 -1 -1 陀螺仪: -1 -1 -1 温度: 36.53
加速度: -1 -1 -1 陀螺仪: -1 -1 -1 温度: 36.53
加速度: -9586 3804 12182 陀螺仪: -456 -594 -72 温度: 22.14
加速度: -2452 -1740 15716 陀螺仪: -232 -436 -169 温度: 22.17
加速度: -986 -1736 16178 陀螺仪: -64 -184 -56 温度: 22.20
加速度: -194 -1790 16366 陀螺仪: -46 -9 -11 温度: 22.24
参考
MPU-6000.6050中文资料.pdf
野火MPU6050模块用户手册.pdf
MPU6050原始数据分析.pdf
文章目录1.开发板选择*用到的资源2.串口通信(个人理解)3.代码分析(注释比较详细)1.主函数2.串口1配置3.串口2配置以及中断函数4.注意问题5.源码链接1.开发板选择我用的是STM32F103RCT6的板子,不过代码大概在F103系列的板子上都可以运行,我试过在野火103的霸道板上也可以,主要看一下串口对应的引脚一不一样就行了,不一样的就更改一下。*用到的资源keil5软件这里用到了两个串口资源,采集数据一个,串口通信一个,板子对应引脚如下:串口1,TX:PA9,RX:PA10串口2,TX:PA2,RX:PA32.串口通信(个人理解)我就从串口采集传感器数据这个过程说一下我自己的理解,
LL库和HAL库简介LL:Low-Layer,底层库HAL:HardwareAbstractionLayer,硬件抽象层库LL库和hal库对比,很精简,这实际上是一个精简的库。LL库的配置选择如下:在STM32CUBEMX中,点击菜单的“ProjectManager”–>“AdvancedSettings”,在下面的界面中选择“AdvancedSettings”,然后在每个模块后面选择使用的库总结:1、如果使用的MCU是小容量的,那么STM32CubeLL将是最佳选择;2、如果结合可移植性和优化,使用STM32CubeHAL并使用特定的优化实现替换一些调用,可保持最大的可移植性。另外HAL和L
一、习惯约定图片来自PSINS(高精度捷联惯导算法)PSINS工具箱入门与详解.pptx二、基本旋转矩阵绕x轴逆时钟旋转α\alphaα角度Rx(α)=[ 1000cosαsinα0−sinαcosα]R_x(\alpha)=\begin{bmatrix}\1&0&0\\0&\cos\alpha&\sin\alpha\\0&-\sin\alpha&\cos\alpha\end{bmatrix}Rx(α)= 1000cosα−sinα0sinαcosα绕y轴逆时钟旋转α\alphaα角度Ry(α)=[ cosα0−sinα010sinα0cosα]R_y(\alpha
目录一、ESP32简单介绍二、ESP32Wi-Fi模块介绍三、ESP32Wi-Fi编程模型四、ESP32Wi-Fi事件处理流程 五、ESP32Wi-Fi开发环境六、ESP32Wi-Fi具体代码七、ESP32Wi-Fi代码解读6.1主程序app_main7.2自定义代码wifi_init_sta()八、ESP32Wi-Fi连接验证8.1测试方法8.2服务器模拟工具sscom58.3测试代码8.4测试结果前言为了开发一款亚马逊物联网产品,开始入手ESP32模块。为了能够记录自己的学习过程,特记录如下操作过程。一、ESP32简单介绍ESP32是一套Wi-Fi(2.4GHz)和蓝牙(4.2)双模解决方
有道无术,术尚可求,有术无道,止于术。本系列SpringBoot版本3.0.4本系列SpringSecurity版本6.0.2本系列SpringAuthorizationServer版本1.0.2源码地址:https://gitee.com/pearl-organization/study-spring-security-demo文章目录前言1.OAuth2AuthorizationServerMetadataEndpointFilter2.OAuth2AuthorizationEndpointFilter3.OidcProviderConfigurationEndpointFilter4.N
在我的代码中,我需要使用各种算法(包括CRC32)对文件进行哈希处理。因为我还在Digest系列中使用其他加密哈希函数,所以我认为为它们维护一个一致的接口(interface)会很好。为了记录,我确实找到了digest-crc,一颗完全符合我要求的gem。问题是,Zlib是标准库的一部分,并且有一个我想重用的CRC32工作实现。此外,它是用C编写的,因此它应该提供与digest-crc相关的卓越性能,后者是纯ruby实现。实现Digest::CRC32一开始看起来非常简单:%w(digestzlib).each{|f|requiref}classDigest::CRC32一切正常:
我正在尝试在我的机器上安装win32-apigem,但在构建native扩展时我遇到了一些问题:$geminstallwin32-api--no-ri--rdocTemporarilyenhancingPATHtoincludeDevKit...Buildingnativeextensions.Thiscouldtakeawhile...C:\Programs\dev_kit\bin\make.exe:***Couldn'treservespaceforcygwin'sheap,Win32error0ERROR:Errorinstallingwin32-api:ERROR:Failed
我在Windows上运行ruby1.9.2并试图移植在Ruby1.8中工作的代码。该代码使用以前运行良好的Open4.popen4。对于1.9.2,我做了以下事情:通过geminstallPOpen4安装了POpen4需要POpen4通过require'popen4'尝试像这样使用POpen4:Open4.popen4("cmd"){|io_in,io_out,io_er|...}当我这样做时,我得到了错误:nosuchfiletoload--win32/open3如果我尝试安装win32-open3(geminstallwin32-open3),我会收到错误消息:win32-op
DellInspiron5488加内存32G 原装内置内存仅仅8G,目前看,真的太小了! 1.内存型号Dell5488内存型号:DDR42666。笔记本有两个内存插槽,原装占了一个,还能扩展一个。 2.买内存如果买Dell原装笔记本内存,8G就得500块左右。 我咨询了一下,三星的笔记本内存,可以兼容。16G,299块(2023年2月23日,京东价) Dell5488内存组合,最多只能插两根16G内存。 我于是买了两根三星16G内存。装上,很爽😄 跑国产系统统信UOS,再也看不到用交换区了,32G内存,爽!
本文代码使用HAL库。文章目录前言一、MCP4017的重要特性二、MCP4017计算RBW阻值三、MCP4017地址四、MCP4017读写函数五、CubeMX创建工程(利用ADC测量MCP4017电压)、对应代码:总结前言一、MCP4017的重要特性蓝桥杯板子上的是MCP4017T-104ELT,如图1。MCP4017是一个可编程电阻,通过写入的数值可以改变电阻的大小。重点在于6引脚(W),5引脚(B