当前位置:   article > 正文

STM32入门笔记12_3_软件I2C读写MPU6050_stm32 oled i2c 读写

stm32 oled i2c 读写

软件I2C读写MPU6050

程序架构

在这里插入图片描述

主要程序

main.c

#include "stm32f10x.h" 
#include "delay.h"
#include "OLED.h"
#include "MPU6050.h"
uint8_t ID;
int main(void)
{
	OLED_Init();
	MPU6050_Init();
	OLED_ShowString(1, 1, "ID:");
	ID = MPU6050_GetID();
	OLED_ShowHexNum(1, 4, ID, 2);
	MPU6050_DataTypeDef MPU6050_DataStructure;
	while(1)
	{
		// 读取数据
		MPU6050_GetData(&MPU6050_DataStructure);
		// 显示数据
		OLED_ShowSignedNum(2, 1, MPU6050_DataStructure.AccX, 5);
		OLED_ShowSignedNum(3, 1, MPU6050_DataStructure.AccY, 5);
		OLED_ShowSignedNum(4, 1, MPU6050_DataStructure.AccZ, 5);
		OLED_ShowSignedNum(2, 8, MPU6050_DataStructure.GyroX, 5);
		OLED_ShowSignedNum(3, 8, MPU6050_DataStructure.GyroY, 5);
		OLED_ShowSignedNum(4, 8, MPU6050_DataStructure.GyroZ, 5);
	}
}

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27

MyI2C.c

#include "stm32f10x.h"
#include "Delay.h"
#define I2CPORT GPIOB         // I2C所用端口
#define I2CSCL_PIN GPIO_Pin_10       // I2C SLC所用引脚
#define I2CSDA_PIN GPIO_Pin_11		 // I2C	SDA所用引脚

/*
 *	初始化MyI2C
 */
void MyI2C_Init(void)
{
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
	// 配置GPIOB 10 11 为开漏输出
	GPIO_InitTypeDef GPIO_InitStructure;
	GPIO_InitStructure.GPIO_Pin=I2CSCL_PIN|I2CSDA_PIN;
	GPIO_InitStructure.GPIO_Mode=GPIO_Mode_Out_OD;
	GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;
	GPIO_Init(GPIOB, &GPIO_InitStructure);
	
	GPIO_SetBits(I2CPORT, I2CSCL_PIN|I2CSDA_PIN);
}

/*
 *	写时钟线
 */
void MyI2C_W_SCL(uint8_t BitValue)
{
	GPIO_WriteBit(I2CPORT, I2CSCL_PIN, (BitAction) BitValue);
	Delay_us(10);
}

/*
 *  写数据线
 */
void MyI2C_W_SDA(uint8_t BitValue)
{
	GPIO_WriteBit(I2CPORT, I2CSDA_PIN, (BitAction) BitValue);\
	Delay_us(10);
}

/* 
 * 	读数据线
 */
uint8_t MyI2C_R_SDA(void)
{
	uint8_t BitValue;
	BitValue = GPIO_ReadInputDataBit(I2CPORT, I2CSDA_PIN);
	Delay_us(10);
	return BitValue;
}

/*
 *  起始条件 SCL高电平期间 SDA从高电平切换到低电平
 */
void MyI2C_Start(void)
{
	MyI2C_W_SDA(1);
	MyI2C_W_SCL(1);  // SLC高电平
	MyI2C_W_SDA(0);  // SDA切换到低电平
	MyI2C_W_SCL(0);  // 为下一个信号做准备
	
}

/*
 *  终止条件 SCL高电平期间 SDA从低电平切换到高电平
 */
void MyI2C_Stop(void)
{
	MyI2C_W_SDA(0);
	MyI2C_W_SCL(1);  // 因传输在停止条件后终止,故不需将SLC拉低
	MyI2C_W_SDA(1);
}

/*
 * 发送一个字节 SCL低电平间 主机将数据位依次放到SDA线上,然后释放SCL
 * 从机在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);  // 主机释放SCL 从机读数据
		MyI2C_W_SCL(0);	 // 主机下拉SCL 准备放数据
	}
}

/*
 *  接收一个字节  SCL低电平间 从机将数据位依次放到SDA线上, 然后释放SCL
 *  主机在SCL高电平期间读取数据位
 */
uint8_t MyI2C_ReceiveByte(void)
{
	uint8_t Byte = 0x00;
	uint8_t i;
	MyI2C_W_SDA(1);  // 主机释放SDA
	for(i=0; i<8; ++i)
	{
		MyI2C_W_SCL(1);  // SCL高电平
		if(MyI2C_R_SDA() == 1)
			Byte |= (0x80 >> i);
		MyI2C_W_SCL(0);
	}
	return Byte;
}

/*
 *  发送应答  0表示应答 1表示非应答
 */
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); // 主机释放SDA
	MyI2C_W_SCL(1);
	AckBit = MyI2C_R_SDA();
	MyI2C_W_SCL(0);
	return AckBit;
}

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 116
  • 117
  • 118
  • 119
  • 120
  • 121
  • 122
  • 123
  • 124
  • 125
  • 126
  • 127
  • 128
  • 129
  • 130
  • 131

MyI2C.h

#ifndef __MYI2C_H 
#define __MYI2C_H
void MyI2C_Init(void);
void MyI2C_W_SCL(uint8_t BitValue);
void MyI2C_W_SDA(uint8_t BitValue);
uint8_t MyI2C_R_SDA(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

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14

MPU6050.c

#include "stm32f10x.h"
#include "MyI2C.h"
#include "MPU6050_REG.h"

#define MPU_ADDRESS 0xD0

/*
 *  往指定地址写入指定数据
 */
void MPU6050_WriteReg(uint8_t RegAddress, uint8_t Data)
{
	// 起始条件
	MyI2C_Start();
	// 呼叫设备(MPU6050)
	MyI2C_SendByte(MPU_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();
	// 呼叫设备(MPU6050)
	MyI2C_SendByte(MPU_ADDRESS);
	// 接收应答
	MyI2C_ReceiveACK();
	// 寻找地址
	MyI2C_SendByte(RegAddress);
	// 接收应答
	MyI2C_ReceiveACK();
	// 再次起始
	MyI2C_Start();
	MyI2C_SendByte(MPU_ADDRESS | 0x01);
	// 接收应答
	MyI2C_ReceiveACK();
	// 读取数据
	Data = MyI2C_ReceiveByte();
	// 发送应答
	MyI2C_SendAck(1); 
	// 终止条件
	MyI2C_Stop();
	return Data;
}

/*
 *  配置MPU6050
 */
void MPU6050_Init(void)
{
	// I2C初始化
	MyI2C_Init();
	MPU6050_WriteReg(PWR_MGMT_1, 0x01);
	MPU6050_WriteReg(PWR_MGMT_2, 0x00);
	MPU6050_WriteReg(SMPLRT_DIV, 0x09);
	MPU6050_WriteReg(CONFIG, 0x06);
	MPU6050_WriteReg(GYRO_CONFIG, 0x18);
	MPU6050_WriteReg(ACCEL_CONFIG, 0x18);
}
/*
 * 获取ID号
 */
uint8_t MPU6050_GetID(void)
{
	return MPU6050_ReadReg(WHO_AM_I);
}
/*
 *  获取MPU6050数据
 */
void MPU6050_GetData(MPU6050_DataTypeDef * MPU_DataStructure)
{
	uint16_t Data_H, Data_L;  // 高位数据和低位数据
	Data_H = MPU6050_ReadReg(ACCEL_XOUT_H);
	Data_L = MPU6050_ReadReg(ACCEL_XOUT_L);
	MPU_DataStructure->AccX=(Data_H<<8) | Data_L;
	
	Data_H = MPU6050_ReadReg(ACCEL_YOUT_H);
	Data_L = MPU6050_ReadReg(ACCEL_YOUT_L);
	MPU_DataStructure->AccY=(Data_H<<8) | Data_L;
	
	Data_H = MPU6050_ReadReg(ACCEL_ZOUT_H);
	Data_L = MPU6050_ReadReg(ACCEL_ZOUT_L);
	MPU_DataStructure->AccZ=(Data_H<<8) | Data_L;
	
	Data_H = MPU6050_ReadReg(GYRO_XOUT_H);
	Data_L = MPU6050_ReadReg(GYRO_XOUT_L);
	MPU_DataStructure->GyroX=(Data_H<<8) | Data_L;
	
	Data_H = MPU6050_ReadReg(GYRO_YOUT_H);
	Data_L = MPU6050_ReadReg(GYRO_YOUT_L);
	MPU_DataStructure->GyroY=(Data_H<<8) | Data_L;
	
	Data_H = MPU6050_ReadReg(GYRO_ZOUT_H);
	Data_L = MPU6050_ReadReg(GYRO_ZOUT_L);
	MPU_DataStructure->GyroZ=(Data_H<<8) | Data_L;
}

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111

MPU6050.h

#ifndef __MPU6050_H
#define __MPU6050_H
#include "MPU6050_REG.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(MPU6050_DataTypeDef * MPU_DataStructure);
#endif

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

MPU6050_REG.h

#ifndef __MPU6050_REG_H
#define __MPU6050_REG_H
// 寄存器地址
#define SMPLRT_DIV 				0x19
#define CONFIG					0x1A
#define GYRO_CONFIG 			0x1B
#define ACCEL_CONFIG 			0x1C
#define ACCEL_XOUT_H 			0x3B
#define ACCEL_XOUT_L 			0x3C
#define ACCEL_YOUT_H 			0x3D
#define ACCEL_YOUT_L 			0x3E
#define ACCEL_ZOUT_H 			0x3F
#define ACCEL_ZOUT_L 			0x40
#define TEMP_OUT_H 				0x41
#define	TEMP_OUT_L				0x42
#define	GYRO_XOUT_H				0x43
#define	GYRO_XOUT_L				0x44
#define	GYRO_YOUT_H				0x45
#define	GYRO_YOUT_L				0x46
#define	GYRO_ZOUT_H				0x47
#define	GYRO_ZOUT_L				0x48

#define	PWR_MGMT_1				0x6B
#define	PWR_MGMT_2				0x6C
#define	WHO_AM_I				0x75

/*
 *  MPU6050数据结构体
 */
typedef struct
{
	int16_t AccX;
	int16_t AccY;
	int16_t AccZ;
	int16_t GyroX;
	int16_t GyroY;
	int16_t GyroZ;
} MPU6050_DataTypeDef;

#endif

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41

参考资料

【STM32入门教程-2023持续更新中】

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/小蓝xlanll/article/detail/462395
推荐阅读
相关标签
  

闽ICP备14008679号