软件IIC读取MPU6050

软件IIC读取MPU6050

    • 最终现象
    • 一、GY-521 MPU6050三维角度传感器简介
    • 二、程序分析
      • 1、mpu6050.c
      • 2、MPU6050_reg.h

最终现象

在这里插入图片描述

一、GY-521 MPU6050三维角度传感器简介

在这里插入图片描述
一共八个引脚,一般只用到四个,其余的我也没有试过。
VCC、GND分别接5V电源和地;SCL、SDA分别是IIC通讯中的时钟引脚和数据引脚。
MPU6050 是 全球首款整合性 6 轴运动处理组件,免除了组合陀螺仪与加速器时之轴间差的问题。内部整合了 3 轴陀螺仪和 3 轴加速度传感器,可以使用 InvenSense 公司提供的运动处理资料库,非常方便的实现姿态解算,降低了运动处理运算对操作系统的负荷,同时大大降低了开发难度。
MPU6050之所以称之为6轴,是因为它能感应 X、Y、Z三个方向的加速度和X、Y、Z方向的角速度:
在这里插入图片描述
PS.mpu6050是这个GY-521模块上的芯片,注意不要被这个名字搞蒙了。

二、程序分析

1、mpu6050.c

#include "stm32f10x.h"                  // Device header
#include "MyI2C.h"
#include "MPU6050_Reg.h"#define MPU6050_ADDRESS		0xD0  //写void MPU6050_WriteReg(uint8_t RegAddress, uint8_t Data)
{MyI2C_Start();//发送起始信号MyI2C_SendByte(MPU6050_ADDRESS);//发送mpu6050设备号及读写位(写)MyI2C_ReceiveAck();//等待从机响应MyI2C_SendByte(RegAddress);//发送要写入数据的寄存器的地址MyI2C_ReceiveAck();//等待从机响应MyI2C_SendByte(Data);//发送数据MyI2C_ReceiveAck();//等待从机响应MyI2C_Stop();//发送停止信号
}uint8_t MPU6050_ReadReg(uint8_t RegAddress)
{uint8_t Data;MyI2C_Start();//发送起始信号MyI2C_SendByte(MPU6050_ADDRESS);//发送mpu6050设备号及读写位(写)MyI2C_ReceiveAck();//等待从机响应MyI2C_SendByte(RegAddress);//发送要写入数据的寄存器的地址,此时mpu6050内部寄存器指针就会指向这个地址,下面再进行发送起始信号,见下方//并且发送mpu6050设备号及读写位(读)MyI2C_ReceiveAck();//等待从机响应MyI2C_Start();//二次起始,为读数据做准备MyI2C_SendByte(MPU6050_ADDRESS | 0x01);//发送mpu6050设备号及读写位(读)MyI2C_ReceiveAck();//等待从机响应Data = MyI2C_ReceiveByte();//读取八位数据MyI2C_SendAck(1);//向从机发送不想再读数据的响应MyI2C_Stop();//发送停止信号return Data;
}void MPU6050_Init(void)
{MyI2C_Init();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)//这就是根据MPU6050手册进行读取寄存器值的操作
{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;
}

由于MPU6050模块使用IIC与主机通讯,这里解释一下代码中#define MPU6050_ADDRESS 0xD0 为什么会这样设置。如果IIC的通讯时序忘记了可以去复习一下:https://www.bilibili.com/video/BV1th411z7sn/?p=31&spm_id_from=pageDriver&vd_source=2a10d30b8351190ea06d85c5d0bfcb2a
起始位过后可以选择八位地址位,但实际上只有七位是地址位,最低位是读写控制位,如果是写的话就给0,读的话就给1。从手册中可以找到MPU6050的从机地址是0X68,只有低七位有效,这里需要进行写入操作,所以最终给的八位地址位就是0XD0,如果进行读的话就是0XD1。
mpu6050.c中都是调用最底层的IIC协议来组成特定的通讯时序,使用这种方法可以很容易的控制各类使用IIC协议的外设,只需要更改自己的驱动代码,而不需要去更改底层的IIC通讯协议。
可以看到MPU6050的初始化就是调用了IIC的初始化之后,向几个寄存器写入不同的值就好了,这一般不用改动。最后的从MPU6050读取数据也是查看手册或者直接用这个就好了,都是固定的,不同寄存器读出来的就是不同的量,将低八位和高八位拼接起来就是完整的16位数据。

2、MPU6050_reg.h

这里就是人家从手册中找到的寄存器地址封装成头文件方便修改。

#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

3、IIC.c
软件IIC顾名思义就是控制IO口的高低电平来模拟产生时钟信号,控制数据通信。这里使用PB10模拟时钟输出,PB11控制数据交互,以此封装:起始位,停止位,发送一个字节,读取一个字节,发送主机响应,接收从机响应。这里代码看不懂的话可以看:
https://www.bilibili.com/video/BV1th411z7sn/?p=33&spm_id_from=pageDriver&vd_source=2a10d30b8351190ea06d85c5d0bfcb2a

#include "stm32f10x.h"                  // Device header
#include "Delay.h"//PB10、PB11
void MyI2C_W_SCL(uint8_t BitValue)//这三个函数将读写io口封装起来,增强可读性
{GPIO_WriteBit(GPIOB, GPIO_Pin_10, (BitAction)BitValue);Delay_us(10);
}void MyI2C_W_SDA(uint8_t BitValue)
{GPIO_WriteBit(GPIOB, GPIO_Pin_11, (BitAction)BitValue);Delay_us(10);
}uint8_t MyI2C_R_SDA(void)
{uint8_t BitValue;BitValue = GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_11);Delay_us(10);return BitValue;
}void MyI2C_Init(void)//软件iic的两个gpio初始化,注意是开漏输出
{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);
}void MyI2C_Start(void)//发送起始信号
{MyI2C_W_SDA(1);//确保SCL,SDA都释放,然后先拉低SDA,再拉低SCLMyI2C_W_SCL(1);MyI2C_W_SDA(0);MyI2C_W_SCL(0);
}void MyI2C_Stop(void)//发送停止信号
{MyI2C_W_SDA(0);//此时SCL一定为低,所以拉低SDA,然后先释放SCL,再释放SDAMyI2C_W_SCL(1);MyI2C_W_SDA(1);
}void MyI2C_SendByte(uint8_t Byte)//通过SDA发送一个字节
{uint8_t i;//进入此函数时SCL为低电平,此时主机向SDA发送数据,然后拉高SCL,从机就会读取数据,循环发送8位for (i = 0; i < 8; i ++){MyI2C_W_SDA(Byte & (0x80 >> i));MyI2C_W_SCL(1);MyI2C_W_SCL(0);}
}uint8_t MyI2C_ReceiveByte(void)//通过SDA读取一个字节,由从机发送
{uint8_t i, Byte = 0x00;MyI2C_W_SDA(1);//主机释放SDA,让从机掌握SDA控制权for (i = 0; i < 8; i ++){MyI2C_W_SCL(1);if (MyI2C_R_SDA() == 1){Byte |= (0x80 >> i);}//在SCL为高电平期间,主机可以从SDA中读取从机发送的数据,循环接收8位MyI2C_W_SCL(0);}return Byte;
}void MyI2C_SendAck(uint8_t AckBit)//发送主机响应信号
{MyI2C_W_SDA(AckBit);//进入此函数时,SCL为低电平,此时向SDA写入数据,然后拉高SCL,从机就会读取数据MyI2C_W_SCL(1);MyI2C_W_SCL(0);
}uint8_t MyI2C_ReceiveAck(void)//接收从机响应
{uint8_t AckBit;MyI2C_W_SDA(1);//主机释放SDA,让从机掌握SDA控制权MyI2C_W_SCL(1);AckBit = MyI2C_R_SDA();//在SCL为高电平期间,主机可以从SDA中读取从机发送的数据MyI2C_W_SCL(0);return AckBit;
}

主函数中初始化MPU6050之后即可调用MPU6050_GetData(&AX, &AY, &AZ, &GX, &GY, &GZ);将读取的数据存储到定义的全局变量中。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/666846.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

如何用ETL工具实现API调用

一、API调用的好处 API调用有很多好处&#xff0c;下面列举了几个主要的优势&#xff1a; 模块化和可重用性&#xff1a;API调用使得软件开发过程更加模块化和可用。通过将功能封装在API中&#xff0c;可以将其用作独立的模块&#xff0c;并在不同的应用程序或系统中进行重复使…

父类之王“Object”类和内部类

&#x1f468;‍&#x1f4bb;作者简介&#xff1a;&#x1f468;&#x1f3fb;‍&#x1f393;告别&#xff0c;今天 &#x1f4d4;高质量专栏 &#xff1a;☕java趣味之旅 欢迎&#x1f64f;点赞&#x1f5e3;️评论&#x1f4e5;收藏&#x1f493;关注 &#x1f496;衷心的希…

NLP深入学习:《A Survey of Large Language Models》详细学习(一)

文章目录 1. 前言2. 摘要部分3. 引言部分4. Overview 部分4.1 LLMs 背景4.2 GPT 系列模型的技术演变 5. 参考 1. 前言 最近正在读这边 LLM 论文的综述&#xff0c;鉴于读得费劲&#xff0c;如果将整个论文读完再来写会比较费劲。当前采取的策略是部分内容走读记录&#xff0c;…

3 编辑器(Vim)

1.完成 vimtutor。备注&#xff1a;它在一个 80x24&#xff08;80 列&#xff0c;24 行&#xff09; 终端窗口看起来效果最好。 2.下载我们提供的 vimrc&#xff0c;然后把它保存到 ~/.vimrc。 通读这个注释详细的文件 &#xff08;用 Vim!&#xff09;&#xff0c; 然后观察 …

ref和reactive, toRefs的使用

看尤雨溪说&#xff1a;为什么Vue3 中应该使用 Ref 而不是 Reactive&#xff1f; toRefs import { ref, toRefs } from vue;// 定义一个响应式对象 const state ref({count: 0,name: Vue });// 使用toRefs转换为响应式引用对象 const reactiveState toRefs(state);// 现在你…

深入理解TCP网络协议(3)

目录 1.前言 2.流量控制 2.阻塞控制 3.延时应答 4.捎带应答 5.面向字节流 6.缓冲区 7.粘包问题 8.TCP异常情况 9.小结 1.前言 在前面的博客中,我们重点介绍了TCP协议的一些属性,有连接属性的三次握手和四次挥手,还有保证数据安全的重传机制和确认应答,还有为了提高效率…

vue3 之 组合式API—watch函数

watch函数 作用&#xff1a;侦听一个或者多个数据的变化&#xff0c;数据变化时执行回调函数 两个额外参数&#xff1a; 1.immediate&#xff08;立即执行&#xff09;2.deep&#xff08;深度侦听&#xff09; 场景&#xff1a;比如选择不同的内容请求后端不同数据时 如下图 …

重写Sylar基于协程的服务器(4、协程调度模块的设计)

重写Sylar基于协程的服务器&#xff08;4、协程调度模块的设计&#xff09; 重写Sylar基于协程的服务器系列&#xff1a; 重写Sylar基于协程的服务器&#xff08;0、搭建开发环境以及项目框架 || 下载编译简化版Sylar&#xff09; 重写Sylar基于协程的服务器&#xff08;1、日…

华为机考入门python3--(8)牛客8-合并表记录

分类&#xff1a;字典排序 知识点&#xff1a; 将输入转成int的列表 my_list list(map(int, input().strip().split( ))) 将列表转为元组 tuple(my_list) 访问元素为元组的列表 for first, second, third in my_list: 对字典进行排序 sorted(my_dict.items())…

负载均衡下的webshell上传+nginx解析漏洞

负载均衡下的webshell上传 一&#xff0c;负载均衡下webshell上传的四大难点 难点一&#xff1a;需要在每一台节点的相同位置上传相同内容的webshell 我们需要在每一台节点的相同位置都上传相同内容的 WebShell一旦有一台机器上没有&#xff0c;那么在请求轮到这台机器上的时…

处理SERVLET中的错误

处理SERVLET中的错误 问题陈述 一位用户在使用在线计算机应用程序时输入一个非数字字符做数字加法。servlet试图将用户输入的值转换成整数型时,引发了NumberFormException类型的异常。要创建一个Web应用程序来使用自定义错误页面处理该异常。该自定义错误页面需要向用户提供关…

【Linux】Ext2 文件系统

文件系统 前言一、磁盘硬件1. 磁盘的物理存储结构2. 磁盘存储的逻辑抽象结构 二、理解 Ext2 文件系统1. 初步理解文件系统2. 深入理解文件系统&#xff08;1&#xff09;inode Table&#xff08;2&#xff09;Data blocks&#xff08;3&#xff09;inode Bitmap&#xff08;4&a…

【Vue】2-9、Vue-CLI 脚手架

一、单页面程序 什么是单页面程序&#xff1f; 单页面程序&#xff08;Single Page Application&#xff09;简称 SPA&#xff0c;顾名思义&#xff0c;指的是一个 Web 网站中只有唯一一个 HTML 页面&#xff0c;所有的功能与交互都在这唯一的一个页面内完成。 二、Vue-CLI …

万能写作辅助器设计

为了构建一个万能写作辅助器,我们需要设计几个关键组件,每个组件都有其特定的功能和交互方式。以下是这些组件的详细设计和描述: 对话生成器(Dialogue Generator) 功能:生成对话内容。输入:可接受拖拽过来的组件,如角色名称、情感标签、场景描述等。管理:能够管理各种…

【学习笔记】详解换根法(换根DP)

一.换根DP的概念 1.换根DP是什么&#xff1f; 换根DP&#xff0c;又叫二次扫描&#xff0c;是树形DP的一种。 2.换根DP能解决什么问题&#xff1f; 换根DP能解决不指定根结点&#xff0c;并且根节点的变化会对一些值产生影响的问题。例如子结点深度和、点权和等。如果要 暴力…

java社区养老年人服务系统springboot+vue

为了帮助用户更好的了解和理解程序的开发流程与相关内容&#xff0c;本文将通过六个章节进行内容阐述。 第一章&#xff1a;描述了程序的开发背景&#xff0c;程序运用于现实生活的目的与意义&#xff0c;以及程序文档的结构安排信息&#xff1b; 第二章&#xff1a;描述了程序…

python Cloudflare 批量关闭IPv6兼容性脚本

Cloudflare免费版控制台不给关IPv6&#xff0c;需要使用API关闭&#xff0c;先从我的个人资料里面申请API令牌&#xff0c;再执行脚本 import requests import jsonheaders {X-Auth-Email:cloudflare登入账户, #输入登入账户的邮箱X-Auth-Key: Global API Key, #输入上图申请…

数据结构(C语言)代码实现(六)——单链表的实现

目录 参考、格式 头文件LinkList.h 一、将函数的小括号写成中括号 二、读取权限冲突 三、L->Last指针没有移动 四、函数指针的使用 头文件完整代码 测试函数&#xff08;主函数&#xff09;test.cpp 测试结果 参考、格式 数据结构课本2.3节&#xff08;严蔚敏版&a…

嵌入式学习第三篇——51单片机

目录 1&#xff0c;嵌入式系统 1&#xff0c;嵌入式系统的定义 2&#xff0c;单片机的定义 2&#xff0c;51单片机 1&#xff0c;开发环境 2&#xff0c;开发板使用的基本思路 1&#xff0c;查看原理图&#xff0c;查看芯片手册 2&#xff0c;获得调用硬件的管…

博途PLC限幅器(SCL代码)

PLC限幅器详细介绍,可以参考下面文章: https://rxxw-control.blog.csdn.net/article/details/128701050https://rxxw-control.blog.csdn.net/article/details/128701050三菱PLC限幅器 https://rxxw-control.blog.csdn.net/article/details/135212965