12、STM32F103C8T6 软件IIC读取MPU6050

本文介绍了如何通过软件IIC接口进行引脚配置,实现六种时序单元的操作,包括SCL和SDA的控制、起始和停止信号、数据发送与接收,以及如何在嵌入式系统中与MPU6050传感器进行通信,包括初始化、写入读取操作和传感器数据的获取。
摘要由CSDN通过智能技术生成

一、软件IIC的引脚配置及六块时序单元

通过函数来间接设置SCL和SDA总线,方便加延时

//写 scl总线
void myiic_w_scl(uint8_t bitvalue)
{
	//Delay_us();
	GPIO_WriteBit(GPIOB, GPIO_Pin_10, (BitAction)bitvalue);
	Delay_us(10); //方便修改延时
}

//写 sda总线
void myiic_w_sda(uint8_t bitvalue)
{
	GPIO_WriteBit(GPIOB, GPIO_Pin_11, (BitAction)bitvalue);
	Delay_us(10); //方便修改延时
}

//读 sda总线
uint8_t myiic_r_sda(void)
{
	uint8_t bitvalue;
	bitvalue = GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_11);
	Delay_us(10); //方便修改延时
	return bitvalue;
}

1、引脚配置

void myiic_init(void)
{
	//开时钟
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
	
	//配置GPIO SCL,SDA初始化为开漏输出, 
	// 开漏模式既可以输出,又可以输入。 输入时,先输出1,再直接读取输入寄存器
	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_10MHz;
	GPIO_Init(GPIOB, &GPIO_InitStructure);
	
	//SCL和SDA置为高电平, 释放总线, 此时IIC总线处于空闲状态
	GPIO_SetBits(GPIOB, GPIO_Pin_10 | GPIO_Pin_11);
}

2、起始信号

//起始信号需要注意:先拉高sda,再拉高scl, 防止和停止信号冲突
void myiic_start(void)
{
	myiic_w_sda(1);
	myiic_w_scl(1);
	myiic_w_sda(0);
	myiic_w_scl(0);	//结束再将时钟线拉低,方便下次使用
}

3、停止信号

//停止信号:先拉低数据线,原理同上
void myiic_stop(void)
{
	myiic_w_sda(0);
	myiic_w_scl(1);
	myiic_w_sda(1);
}

4、发送一个字节

void myiic_sendbyte(uint8_t byte)
{
	uint8_t i;
	for(i = 0; i < 8; i++)
	{
        //设置最高位数据
		myiic_w_sda(byte & (0x80 >> i)); 
        //释放SCL	(释放SCL之后,从机就会立刻将SDA的数据读走)
		myiic_w_scl(1);	
        //拉低SCL	驱动时钟走一个脉冲(可以继续放下一位数据)
		myiic_w_scl(0); 
	}
}

5、接收一个字节

//接收一个字节:SCL低电平,从机需要将数据放到SDA上,为了防止主机干扰从机写入数据,主机需要先释放SDA(切换为输入模式)
uint8_t myiic_ReceiveByte(void)
{
	uint8_t i, byte = 0x00;

	//主机释放SDA 从机使用,将数据放在SDA上
	myiic_w_sda(1);	
	
	for(i = 0; i < 8; i++)
	{
        //主机释放SCL 读取数据
		myiic_w_scl(1);	
        //如果是 1 置1,如果是 0 ,不用管,因为 byte初始化为 0x00;
		if(myiic_r_sda() == 1)	
		{
			byte |= 0x80 >> i;
		}
        //读取一位数据后,拉低SCL,从机放下一位数据
		myiic_w_scl(0); 
	}
	return byte;
}

6、发送应答

void myiic_SendAck(uint8_t ackBit)
{
	//函数进来时SCL低电平,主机将数据放在SDA上
	myiic_w_sda(ackBit);
	//SCL高电平,从机读取应答
	myiic_w_scl(1);
	//SCL低电平,进入下一个时序单元
	myiic_w_scl(0);
}

7、接收应答

uint8_t myiic_ReceiveAck(void)
{
	uint8_t ackBit;
	//函数进入时SCL低电平,主机释放SDA,防止从机干扰,同时从机将应答位放在SDA上
	myiic_w_sda(1);
	//SCL高电平,主机读取应答位
	myiic_w_scl(1);	
	ackBit = myiic_r_sda();
	//SCL低电平,进入下一个时序单元
	myiic_w_scl(0);
	
	return ackBit;
}

二、读写MPU6050

MPU6050命令的宏定义

//0xD0: 1101 0000(1101 000 是MPU6050的从机地址, 最后一位读写位,0 代表写入操作)
#define MPU6050_ADDRESS 0xD0 //写地址 读地址,需要或上 0x01

#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

1、MPU6050初始化

void MPU6050_Init(void)
{
	myiic_init();
	
	//对MPU6050硬件电路进行初始化配置
	//芯片的写寄存器功能,需要解除芯片的睡眠模式,否则写入是无效的
	//睡眠模式 是电源管理寄存器1 的SLEEP控制的,写入0x00,解除睡眠模式,该寄存器地址为 0x6B;
    //解除睡眠,选择陀螺仪时钟
	MPU6050_Write_Reg(MPU6050_PWR_MGMT_1, 0x01); 
    //6 轴均不待机
	MPU6050_Write_Reg(MPU6050_PWR_MGMT_2, 0x00);
    //采样分频为 10	
	MPU6050_Write_Reg(MPU6050_SMPLRT_DIV, 0x09);
    //滤波参数给最大	
	MPU6050_Write_Reg(MPU6050_CONFIG, 0x06);
    //陀螺仪和下面加速度计都选择最大量程		
	MPU6050_Write_Reg(MPU6050_GYRO_CONFIG, 0x18);	
	MPU6050_Write_Reg(MPU6050_ACCEL_CONFIG, 0x18);
}

2、MPU6050指定地址写一个字节

void MPU6050_Write_Reg(uint8_t regAddress, uint8_t data)
{
	myiic_start();
	myiic_sendbyte(MPU6050_ADDRESS);
	myiic_ReceiveAck();

	myiic_sendbyte(regAddress);
	myiic_ReceiveAck();

	myiic_sendbyte(data);
	myiic_ReceiveAck();

	myiic_stop();
}

3、MPU6050指定地址读一个字节

uint8_t MPU6050_Read_Reg(uint8_t regAddress)
{
	uint8_t data;
	myiic_start();
	myiic_sendbyte(MPU6050_ADDRESS);
	myiic_ReceiveAck();

	myiic_sendbyte(regAddress);
	myiic_ReceiveAck();

	myiic_start();
	myiic_sendbyte(MPU6050_ADDRESS | 0x01);
	myiic_ReceiveAck();
	data = myiic_ReceiveByte();
	myiic_SendAck(1);
	myiic_stop();

	return data;
}

4、获取ID号

uint8_t MPU6050_GetID(void)
{
	return MPU6050_Read_Reg(MPU6050_WHO_AM_I);
}

5、获取加速度、陀螺仪

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_Read_Reg(MPU6050_ACCEL_XOUT_H);
	dataL = MPU6050_Read_Reg(MPU6050_ACCEL_XOUT_L);
	*accX = (dataH << 8) | dataL;
	
	dataH = MPU6050_Read_Reg(MPU6050_ACCEL_YOUT_H);
	dataL = MPU6050_Read_Reg(MPU6050_ACCEL_YOUT_L);
	*accY = (dataH << 8) | dataL;
	
	dataH = MPU6050_Read_Reg(MPU6050_ACCEL_ZOUT_H);
	dataL = MPU6050_Read_Reg(MPU6050_ACCEL_ZOUT_L);
	*accZ = (dataH << 8) | dataL;
	
	dataH = MPU6050_Read_Reg(MPU6050_GYRO_XOUT_H);
	dataL = MPU6050_Read_Reg(MPU6050_GYRO_XOUT_L);
	*gyroX = (dataH << 8) | dataL;
	
	dataH = MPU6050_Read_Reg(MPU6050_GYRO_YOUT_H);
	dataL = MPU6050_Read_Reg(MPU6050_GYRO_YOUT_L);
	*gyroY = (dataH << 8) | dataL;

	dataH = MPU6050_Read_Reg(MPU6050_GYRO_ZOUT_H);
	dataL = MPU6050_Read_Reg(MPU6050_GYRO_ZOUT_L);
	*gyroZ = (dataH << 8) | dataL;
}

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值