今天的读ID号是建立在上篇文章中有了底层的I2C通讯的6个基本时序来编写的。首先需要完成的就是MPU6050的初始化函数
然后就是编写 指定地址写函数:
一:开始
二:发送 从机地址+读写位(1:读 0:写)
三:接收应答位
四:发送 指定寄存器地址(用于指定读写哪个寄存器)
五:接收应答位
六:发送(要写入指定寄存器下的数据)
七:接收应答位
八:终止
这个过程不是自己瞎编的,而是要根据MPU6050的时序图来确定的:
接下来要写的函数是指定地址读的函数:
一:开始
二:发送 从机地址+读写位
三:接收应答位
四:发送 指定寄存器地址(用于指定读哪个寄存器)
五:接收应答位
六:开始
七:发送 从机地址+读写位1(1:读 0:写)
八:接收应答位
九:接收一个字节(此时,总线控制权交给从机)
十:发送应答位(0:就是给从机应答(从机继续发数据) 1:就是不给从机应答(从机停止发数据))
十一:终止
好了,到此读写MPU6050的基本操作就都完成了,剩下的事就是往不同的寄存器内写入不同的数据,实现不同的功能了,这个明天在学习吧,今天的代码贴出来看看吧:
#include "stm32f10x.h" // Device header
#include "MPU6050.h"
#include "MyI2C.h"#define MPU6050_ADDRESS 0xD0 /*指定地址写函数:一:开始二:发送 从机地址+读写位(1:读 0:写)三:接收应答位四:发送 指定寄存器地址(用于指定读写哪个寄存器)五:接收应答位六:发送(要写入指定寄存器下的数据)七:接收应答位八:终止
*/
void MPU6050_WriteReg(uint8_t Address, uint8_t Data)
{MyI2C_Star();MyI2C_SendByte(MPU6050_ADDRESS);MyI2C_ReceiveAck();MyI2C_SendByte(Address);MyI2C_ReceiveAck();MyI2C_SendByte(Data); //如果想实现指定地址写多个数据,可以在此处加循环,循环数据个数次MyI2C_ReceiveAck(); //每次循环都要加接收应答位MyI2C_Stop();
}/*指定地址读的函数:一:开始二:发送 从机地址+读写位三:接收应答位四:发送 指定寄存器地址(用于指定读哪个寄存器)五:接收应答位六:开始七:发送 从机地址+读写位1(1:读 0:写)八:接收应答位九:接收一个字节(此时,总线控制权交给从机)十:发送应答位(0:就是给从机应答(从机继续发数据) 1:就是不给从机应答(从机停止发数据))十一:终止*/
uint8_t MPU6050_ReadReg(uint8_t Address)
{uint8_t Data;MyI2C_Star();MyI2C_SendByte(MPU6050_ADDRESS);MyI2C_ReceiveAck();MyI2C_SendByte(Address);MyI2C_ReceiveAck();MyI2C_Star();MyI2C_SendByte(MPU6050_ADDRESS | 0x01);MyI2C_ReceiveAck();Data = MyI2C_ReceiveByte();MyI2C_SendAck(1);MyI2C_Stop();return Data;
}void MPU6050_Init(void)
{MyI2C_Init();
}
写了一个MPU6050.h文件,方便测试一下今天的功能:
#ifndef __MPU6050_H
#define __MPU6050_Hvoid MPU6050_Init(void);uint8_t MPU6050_ReadReg(uint8_t Address);void MPU6050_WriteReg(uint8_t Address, uint8_t Data);#endif
然后就是主函数调用一下,验证结果了:
#include "stm32f10x.h" // Device header
#include "OLED.h"
#include "MPU6050.h"
#include "MPU6050_Reg.h"int main(void)
{OLED_Init(); //oled 屏幕初始化MPU6050_Init();uint8_t ID = MPU6050_ReadReg(MPU6050_WHO_AM_I);OLED_ShowHexNum(1,1, ID, 2);while(1){}
}
编译下载后的结果如图: