STM32 软件I2C读写MPU6050
接线图
代码配置
软件I2C只需要用GPIO的读写函数就行,在软件I2C初始化需要把SCL和SDA都初始化为开漏输出模式,还需要把SCL和SDA置高电平
1.配置初始化函数
//MyI2C初始化函数
void MyI2C_Init(void)
{
//配置GPIO
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);//开启GPIO B族时钟
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_OD;//配置为开漏输出
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11 | GPIO_Pin_10;//配置引脚
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;//速率
GPIO_Init(GPIOB, &GPIO_InitStructure);
GPIO_SetBits(GPIOB, GPIO_Pin_11 | GPIO_Pin_10);//将GPIO置高电平
}
功能函数
//写SCL函数
void MyI2C_W_SCL(uint8_t BitValue)
{
GPIO_WriteBit(GPIOB, GPIO_Pin_10, (BitAction)BitValue);
Delay_us(10);
}
//写SDA函数
void MyI2C_W_SDA(uint8_t BitValue)
{
GPIO_WriteBit(GPIOB, GPIO_Pin_11, (BitAction)BitValue);
Delay_us(10);
}
//读SDA函数
uint8_t MyI2C_R_SDA(void)
{
uint8_t BitValue;
BitValue = GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_11);
return BitValue;
}
配置I2C时序基本单元
//起始条件
void MyI2C_Start(void)
{
MyI2C_W_SDA(1);
MyI2C_W_SCL(1);
MyI2C_W_SDA(0);
MyI2C_W_SCL(0);
}
//终止条件
void MyI2C_Stop(void)
{
MyI2C_W_SDA(0);
MyI2C_W_SCL(1);
MyI2C_W_SDA(1);
}
//发送一个字节
void MyI2C_SendByte(uint8_t Byte)
{
//MyI2C_W_SDA(Byte & 0x80);//取出Byte的最高位
uint8_t i;
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)
{
uint8_t i, Byte = 0x00;
MyI2C_W_SDA(1);
for(i = 0; i < 8; i++)
{
MyI2C_W_SCL(1);
if(MyI2C_R_SDA() == 1)
{
Byte |= (0x80 >> i);
}
MyI2C_W_SCL(0);
}
return Byte;
}
//发送应答
void MyI2C_SendACK(uint8_t ACKBit)
{
MyI2C_W_SDA(ACKBit);
MyI2C_W_SCL(1);
MyI2C_W_SCL(0);
}
//接收应答
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;
}
MPU6050配置
#include "MPU6050.h"
//指定地址写时序
void MPU6050_WriteReg(uint8_t RegAddRess, uint8_t Data)
{
MyI2C_Start();
MyI2C_SendByte(0xD0);
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(0xD0);
MyI2C_ReceiveACK();
MyI2C_SendByte(RegAddRess);
MyI2C_ReceiveACK();
MyI2C_Start();
MyI2C_SendByte(0xD0 | 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);
}
void MPU6050_GetData(int16_t* AccX, int16_t* AccY, int16_t* AccZ,
int16_t* GyroX, int16_t* GyroY, int16_t* GyroZ)
{
uint8_t Data_H, Data_L;
Data_H = MPU6050_ReadReg(MPU6050_ACCEL_XOUT_H);
Data_L = MPU6050_ReadReg(MPU6050_ACCEL_XOUT_L);
*AccX = (Data_H << 8) | Data_L;
Data_H = MPU6050_ReadReg(MPU6050_ACCEL_YOUT_H);
Data_L = MPU6050_ReadReg(MPU6050_ACCEL_YOUT_L);
*AccY = (Data_H << 8) | Data_L;
Data_H = MPU6050_ReadReg(MPU6050_ACCEL_ZOUT_H);
Data_L = MPU6050_ReadReg(MPU6050_ACCEL_ZOUT_L);
*AccZ = (Data_H << 8) | Data_L;
Data_H = MPU6050_ReadReg(MPU6050_GYRO_XOUT_H);
Data_L = MPU6050_ReadReg(MPU6050_GYRO_XOUT_L);
*GyroX = (Data_H << 8) | Data_L;
Data_H = MPU6050_ReadReg(MPU6050_GYRO_YOUT_H);
Data_L = MPU6050_ReadReg(MPU6050_GYRO_YOUT_L);
*GyroY = (Data_H << 8) | Data_L;
Data_H = MPU6050_ReadReg(MPU6050_GYRO_ZOUT_H);
Data_L = MPU6050_ReadReg(MPU6050_GYRO_ZOUT_L);
*GyroZ = (Data_H << 8) | Data_L;
}
uint8_t MPU6050_GetID(void)
{
return MPU6050_ReadReg(MPU6050_WHO_AM_I);
}
头文件
#ifndef __MPU6050_H
#define __MPU6050_H
#include "stm32f10x.h"
#include "MyI2C.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
void MPU6050_Init(void);
void MPU6050_WriteReg(uint8_t RegAddRess, uint8_t Data);
uint8_t MPU6050_ReadReg(uint8_t RegAddRess);
void MPU6050_GetData(int16_t* AccX, int16_t* AccY, int16_t* AccZ,
int16_t* GyroX, int16_t* GyroY, int16_t* GyroZ);
uint8_t MPU6050_GetID(void);
#endif
主函数
#include "MyI2C.h"
#include "MPU6050.h"
int main(void)
{
int16_t AX, AY, AZ, GX, GY, GZ;
uint8_t ID;
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);
}
}