IIC通讯读取MPU6050 |
您所在的位置:网站首页 › mpu6050读取数据 › IIC通讯读取MPU6050 |
江科大自化协学习记录,本实验利用IIC读取MPU6050数值,并且在OLED屏上显示 代码在最后面,笔者水平一般,各位凑合着看。 ![]() 首先是OLED显示的代码,底层驱动来自江科大自化协。 链接就放在这里了,喜欢的自取啦: 江科大自化协资料下载: https://pan.baidu.com/s/1SqKyKr5Fsl_9gBJi8aVxTw 提取码:8kzh,链接里压缩包的解压密码:32 1.IIC通讯 1.1物理层I2C(同步半双工)通讯协议(Inter-Integrated Circuit)是由 Phiilps(飞利浦) 公司开发的,由于它引脚少,硬件实现简单,可扩展性强,不需要 USART、 CAN 等通讯协议的外部收发设备,现在被广泛地使用在系统内多个集成电路(IC)间的通讯。 ![]() MPU6050固定ID为0x68 ![]() 为避免被控IC的SDA线和CPU同时输出时电源线短路的问题,统一采用弱上拉电阻配开漏输出的模式。输出低电平时开关MOS导通,处于强下拉的状态,当输出高电平时管脚属于浮空输出的状态,取代了高电平的强上拉输出。为避免这一情况,在VDD接4.1k电阻,处于弱上拉模式。 一个 I2C 总线只使用两条总线线路,一条双向串行数据线(SDA) ,一条串行时钟线(SCL)。数据线即用来表示数据,时钟线用于数据收发同步。 1.2协议层![]() 上图是IIC通讯的基本时序单元。从机捕获到SCL高电平,SDA下降沿时,处于复位状态,等待主机召唤。终止条件时SCL和SDA均处于高电平状态。(释放SDA就是拉高SDA) ![]() 高八位发送。 ![]() I2C 的数据和地址传输都带响应。响应包括“应答(ACK)”和“非应答(NACK)”两种信号。作为数据接收端时,当设备(无论主从机)接收到 I2C 传输的一个字节数据或地址后,若希望对方继续发送数据,则需要向对方发送“应答(ACK)”信号,发送方会继续发送下一个数据;若接收端希望结束数据传输,则向对方发送“非应答(NACK)”信号,发送方接收到该信号后会产生一个停止信号,结束信号传输。 ![]() 读写顺序,一般是1位地址和10位地址。 ![]() 从机地址+读写位,确定哪台设备写入还是读出。send byte:操作地址寄存器。后续是从机应答。 ![]() ![]() 要切换读写方向,只能重置起始位。 1.3MPU6050 1.3.1基本数据![]() 加速度计测量加速度,陀螺仪测量角度。 所有寄存器商店都默认00,除101默认0x40,111默认0x68(ID号0x68),电源管理寄存器1,默认睡眠模式。 1.3.2寄存器IIC通讯格式: ![]() 开始+地址+写+应答+重置+应答+数据段+应答。写同理 ![]() 第一列和第二列均为寄存器地址,第一列十六进制,第二列十进制。rw代表可读可写,r代表只读。 1.3.2.1SMPLRT_DIV:采样分频寄存器![]() ![]() 时钟为内部晶振,外部晶振,外部引脚的方波。本文档以陀螺仪晶振为例。不使用8KHz外部晶振,使用1kHz的晶振。 1.3.2.2CONFIG:配置寄存器![]() 外部同步设置和低通滤波器设置,主要考虑低通滤a波器设置部分。 ![]() ![]() 高三位为陀螺仪的XYZ轴的使能位。中间是满量程选择位。 ![]() 自测响应=自测使能数据-自测失能数据 下面是自测响应表,上电时,先使能自测数据,再失能自测读取数据,二者相减得到自测响应。 ![]() 前两位基本相同,后两位为配置高通滤波器。 ![]() ![]() 数据寄存器,包括加速度计寄存器,温度计寄存器,陀螺仪寄存器。 ![]() 其余数据均是一样的操作方法,以一个十六位无符号整型的补码变量存在。 1.4根据IIC时序读写MPU6050数值 1.4.1软件IIC底层驱动代码:代码如下: ![]() 在初始化完成后,基本上就可以写IIC通讯的底层驱动了: 起始: ![]() 按照通讯时序的要求,在开始时先把SCL和SDA都拉高。但是在结束的时候,以SCL时钟线为参考,SDA数据并不总是低电平,为重复起始条件发送时操作成功,需手动把SDA线先拉低到低电平,再操作SCL线。 终止: ![]() 终止时以时钟线为参考,SDA不总是低电平,需先将SDA拉低,再将其拉高完成终止操作。总结一下就是,在SCL时钟线高电平的期间,SDA数据线不能有任何电平的翻转,若SCL时钟线高电平的期间SDA从低电平拉到高电平则重复开始,从高电平拉到低电平则会认为此时发送数据已结束。 发送八字节数据: ![]() 按高八位的顺序持续写入数据,直到八个字节的时钟走完。移位运算加括号保证优先级。除终止时序SCL以高电平结束,其他我们都会让他以低电平结束。 接收一个字节的数据: ![]() 此时IIC_W_SDA写1是为了释放SDA。因为IIC通信,引脚配置的是开漏输出,且写了1主机依然可以对它进行更改。 发送接收ACK: ![]() 测试代码和测试实验现象如下: ![]() 读取MPU6050的ID,看是否能读取到,验证代码有没有写错。因为在IIC_Recive_ACK()这个函数中,我们先释放了(IIC_W_SDA(1)),如果收到应答,返回值应该是000,将返回值在OLED屏幕上显示出来如下: ![]() 我们的程序没有问题,可以进行下一步的操作。 1.4.2读写MPU6050寄存器将MPU6050的寄存器都用宏定义封装如下,各变量定义查看1.3.2: ![]() 写寄存器的具体过程是:起始—>主机发送MPU6050地址_—>收到应答位—>发送寄存器地址—>收到应答位—>发送数据—>收到应答位—>结束 读寄存器过程大致相同,区别只是在于刚开始时要写一下MPU设备地址,叫一下MPU,让他知道我们要和它进行通讯了。 代码如下: ![]() ![]() 对着手册地址和定义,先使能MPU6050: ![]() 再读取它们的值,在OLED屏上显示: ![]() 在main函数的主循环中,调用OLED显示函数显示值: ![]() 但是我报错寄了一直找不到原因,等我找到了再发出来。 |
今日新闻 |
推荐新闻 |
CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3 |