江协科技10-3软件I2C读写MPU6050

因为我们的读写操作都是依靠SCL和SDA的电平变化来达成的,所以直接封装好,然后再进行操作

不多bb,直接看代码吧

main.c

cpp 复制代码
#include "stm32f10x.h"                  // Device header
#include "Delay.h"
#include "OLED.h"
#include "MPU6050.h"

uint8_t ID;
int16_t AX, AY, AZ, GX, GY, GZ;

int main(void)
{
	OLED_Init();
	MPU6050_Init();
	
	OLED_ShowString(1, 1, "ID:");
	ID = MPU6050_GetID();
	OLED_ShowHexNum(1, 4, ID, 2);
	
	while (1)
	{
		MPU6050_GetData(&AX, &AY, &AZ, &GX, &GY, &GZ);
		OLED_ShowSignedNum(2, 1, AX, 5);
		OLED_ShowSignedNum(3, 1, AY, 5);
		OLED_ShowSignedNum(4, 1, AZ, 5);
		OLED_ShowSignedNum(2, 8, GX, 5);
		OLED_ShowSignedNum(3, 8, GY, 5);
		OLED_ShowSignedNum(4, 8, GZ, 5);
	}
}

myl2C.c

cpp 复制代码
#include "stm32f10x.h"                  // Device header
#include "Delay.h"

void MyI2C_W_SCL(uint8_t BitValue)
{
	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)
{
	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);
}
//还记得吗怎么开始的,即SCL和SDA都是高电平,然后SDA先变为低电平然后SCL再变为低电平
void MyI2C_Start(void)
{
	MyI2C_W_SDA(1);
	MyI2C_W_SCL(1);
	MyI2C_W_SDA(0);
	MyI2C_W_SCL(0);
}


//还记得怎么停止的吗,此时SCL已经变为低电平了(由于是数据的跳变),由于SDA为数据位,不管其为高低电平
//先将其置为低电平,然后SCL变为高电平,然后SDA开始跳变为高电平
void MyI2C_Stop(void)
{
	MyI2C_W_SDA(0);
	MyI2C_W_SCL(1);
	MyI2C_W_SDA(1);
}
//对于SDA来说由于有电平的跳变,所以在开始和结束的时候,都要将其给规整到合适的位置

//发送数据,主机先将数据放到SDA上去,然后在由低电平跳跃到高电平,然后从机会接收数据,然后SCL关闭
void MyI2C_SendByte(uint8_t Byte)
{
	uint8_t i;
	for (i = 0; i < 8; i ++)
	{
		MyI2C_W_SDA(!!(Byte & (0x80 >> i)));
		MyI2C_W_SCL(1);
		MyI2C_W_SCL(0);
	}
}
//由于是从高位开始发送数据,所以先从0x80开始去调用位置
//这个是怎么理解的(Byte & (0x80 >> i),就是取一个二进制位,然后在主机控制SCL高低电平,从机在高电平处取位
//比如你有个二进制位数10101010   这里有个10000000即(0x80)
//将两者按位置与即10101010
//             即 10000000
//很明显就只能得到了你这个二进制数据的高位即1

//对于接收的流程,说白了就是主机读取从机数据的流程
//就是从机将数据放在SDA线上,然后主机从低电平变为高电平
//然后此时从机将数据发送给主机,然后主机变为低电平,此时从机继续准备数据
//MyI2C_W_SDA(1);图中有一行这个代码是什么意思呢
//就是从机没有主动权将数据放在SDA上,只有当主机将SDA给释放了,才能有这个机会
uint8_t MyI2C_ReceiveByte(void)
{
	uint8_t i, Byte = 0x00;
	MyI2C_W_SDA(1);
	for (i = 0; i < 8; i ++)
	{
		MyI2C_W_SCL(1);
		if (MyI2C_R_SDA()){Byte |= (0x80 >> i);}
		//这段代码很简单,如果此时读取的数据是1,则对byte进行或操作
		//如果此时读取的数据是0,则此时输入0
		MyI2C_W_SCL(0);
	}
	return Byte;
}
//当主机读取到从机的数据后,就会给从机发送信号,自己读取到了
//AckBit=1,表示从机继续发,AckBit=0,表示从机别发了
//然后继续主机控制SCL高电平,然后从机获取信息,然后主机控制高电平
void MyI2C_SendAck(uint8_t AckBit)
{
	MyI2C_W_SDA(AckBit);
	MyI2C_W_SCL(1);
	MyI2C_W_SCL(0);
}
//当从机收到主机的数据后的反应,还是和之前所说的一样,从机是没有主动权的
//当从机想要在SDA上发送数据,只有一条路,就是主机先释放SDA
//所以可以看到主机先释放了SDA,然后主机高电平,从机告诉主机是否继续,然后主机控制SCL为低电平
uint8_t MyI2C_ReceiveAck(void)
{
	uint8_t AckBit;
	MyI2C_W_SDA(1);
	MyI2C_W_SCL(1);
	AckBit = MyI2C_R_SDA();
	MyI2C_W_SCL(0);
	return AckBit;
}

myi2c.h

cpp 复制代码
#ifndef __MYI2C_H
#define __MYI2C_H

void MyI2C_Init(void);
void MyI2C_Start(void);
void MyI2C_Stop(void);
void MyI2C_SendByte(uint8_t Byte);
uint8_t MyI2C_ReceiveByte(void);
void MyI2C_SendAck(uint8_t AckBit);
uint8_t MyI2C_ReceiveAck(void);

#endif

mpu6050.c

cpp 复制代码
#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);
	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);
	MyI2C_ReceiveAck();
	MyI2C_SendByte(RegAddress);
	MyI2C_ReceiveAck();
	
	MyI2C_Start();
	MyI2C_SendByte(MPU6050_ADDRESS | 0x01);
	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)
{
	uint8_t DataH, DataL;
	
	DataH = MPU6050_ReadReg(MPU6050_ACCEL_XOUT_H);
	DataL = MPU6050_ReadReg(MPU6050_ACCEL_XOUT_L);
	*AccX = (DataH << 8) | DataL;
	//通过mpu6050自动读取陀螺仪等等的位置信息
	//然后传输到我们定义的函数里面
	
	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.h

cpp 复制代码
#ifndef __MPU6050_H
#define __MPU6050_H

void MPU6050_WriteReg(uint8_t RegAddress, uint8_t Data);
uint8_t MPU6050_ReadReg(uint8_t RegAddress);

void MPU6050_Init(void);
uint8_t MPU6050_GetID(void);
void MPU6050_GetData(int16_t *AccX, int16_t *AccY, int16_t *AccZ, 
						int16_t *GyroX, int16_t *GyroY, int16_t *GyroZ);

#endif
相关推荐
中烟创新4 天前
灯塔AI智能体获评“2025-2026中国数智科技年度十大创新力产品”
大数据·人工智能·科技
weixin_Todd_Wong20105 天前
联咏科技Novatek的系统级芯片(SoC) NT98692PG - ND 主要规格
科技
云卓SKYDROID5 天前
无人机实时信号传输技术要点解析!
科技·无人机·高科技·云卓科技
GAOJ_K5 天前
同步带模组稳定运行的关键
人工智能·科技·自动化·制造
朗心心理5 天前
北京朗心致远科技有限公司:专业的心理设备厂家与心理咨询室建设方案提供商
大数据·人工智能·科技
南山电子nscn5 天前
长晶科技逻辑门产品选型解析与应用概览
科技·逻辑门
AORUO奥偌5 天前
以智慧科技,筑就全时段护理守护网
大数据·人工智能·科技·智能病房呼叫系统·智能医护对讲系统·智慧病房系统
MicroTech20255 天前
MLGO微算法科技利用开放量子系统,Lindbladian 模拟驱动的新一代量子微分方程算法亮相
科技·算法·量子计算
整列机厂家-唯思特5 天前
连接器胶芯与PIN针自动化整列组装的技术实践
科技·自动化·制造