1.思路讲解
首先创建IIC模块,完成基本的起始终止,发送接收功能。然后创建MPU6050模块完成指定地址读写功能。
2.代码展示
IIC模块代码:
a.SDA,SCL读写
void MyIIC_W_SCL(uint8_t Value)
{
GPIO_WriteBit(GPIOB,GPIO_Pin_10,Value);
Delay_us(10);
}
void MyIIC_W_SDA(uint8_t Value)
{
GPIO_WriteBit(GPIOB,GPIO_Pin_11,Value);
Delay_us(10);
}
uint8_t MyIIC_R_SDA(void)
{
uint8_t Value=0;
Value = GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_11);
Delay_us(10);
return Value;
}
b.IIC的初始化,就是对IIC需要使用的IO口初始化,注意使用开漏输出,并将SCL,SDA拉高为高电平。
void MyIIC_Init(void)
{
GPIO_InitTypeDef GPIOBInitStrcture;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);
GPIOBInitStrcture.GPIO_Mode=GPIO_Mode_Out_OD;//开漏输出模式
GPIOBInitStrcture.GPIO_Pin=GPIO_Pin_10 | GPIO_Pin_11;
GPIOBInitStrcture.GPIO_Speed=GPIO_Speed_50MHz;
GPIO_Init(GPIOB,&GPIOBInitStrcture);
GPIO_SetBits(GPIOB,GPIO_Pin_10 | GPIO_Pin_11);//将SCL SDA置高电平 使IIC处于空闲状态
}
c.起始状态代码,SCL高电平期间,SDA由高到低,这里将SCL也下拉,是为了后面主机在SCL低电平期间输入数据到SDA,此步放到下一个写入数据代码也可以。
void MyIIC_Start(void)
{
//起始状态:SCL,SDA 都在高电平 在SCL高电平时将SDA下拉进行起始状态,随后将SCL下拉
MyIIC_W_SDA(1);
MyIIC_W_SCL(1);
MyIIC_W_SDA(0);
MyIIC_W_SCL(0);
}
d. 终止状态,SCL高电平期间,SDA从低电平上升到高电平。
void MyIIC_Stop(void)
{
//终止状态:在SCL高电平状态下,将SDA从低电平上拉到高电平,进入终止状态
MyIIC_W_SDA(0);
MyIIC_W_SCL(1);
MyIIC_W_SDA(1);
}
e.发送字节
void MyIIC_SendByte(uint8_t Value)
{
uint8_t i;
//发送字节:在SCL低电平时,主机在SDA输入一个数据,在SCL高电平时从机在SDA上读取数据
for(i=0;i<8;i++)
{
MyIIC_W_SDA(Value & (0x80 >> i));
MyIIC_W_SCL(1);
MyIIC_W_SCL(0);
}
}
f.接收字节,这里接收的思路是用0X80(1000 000)的i位移位去与SDA上从机传输的数据对比,如果哪一位是1则哪一位为1。
uint8_t MyIIC_ReadByte(void)
{
uint8_t Value=0x00;
uint8_t i=0;
//读入字节:主机释放SDA,将SDA置1,从机控制SDA,在SCL为低电平时,从机在SDA上放入数据
//在SCL为高电平时主机从SDA上读取数据
MyIIC_W_SDA(1);
for(i=0;i<8;i++)
{
MyIIC_W_SCL(1);
if(MyIIC_R_SDA() == 1){Value |= (0x80>>i);}
MyIIC_W_SCL(0);
}
return Value;
}
g.发送应答
void MyIIC_SendAck(uint8_t Ack)
{
MyIIC_W_SDA(Ack);
MyIIC_W_SCL(1);
MyIIC_W_SCL(0);
}
h.接收应答
uint8_t MyIIC_ReceiveAck(void)//收到0表示从机应答,1表示不应答
{
uint8_t Ack;
MyIIC_W_SDA(1);
MyIIC_W_SCL(1);
Ack=MyIIC_R_SDA();
MyIIC_W_SCL(0);
return Ack;
}
3.MPU6050代码展示
a.指定地址写,起始条件,写入从机地址,接收应答,写入寄存器地址,接收应答,写入数据,接收应答,终止条件。
void MPU6050_WriteReg(uint8_t RegAddress,uint8_t Value)//寄存器地址,数据
{
MyIIC_Start();
MyIIC_SendByte(0xd0);//MPU6050的地址
MyIIC_ReceiveAck();
MyIIC_SendByte(RegAddress);//写入寄存器地址
MyIIC_ReceiveAck();
MyIIC_SendByte(Value);
MyIIC_ReceiveAck();
MyIIC_Stop();
}
b.指定地址读,起始条件,写入从机地址,接收应答,写入寄存器地址,接收应答。起始条件,写入从机地址,但是第八位为1,表示进行读操作。接收应答,读取从机输出的数据,发送应答,终止条件。返回读取数据。
uint8_t MPU6050_ReadReg(uint8_t RegAddress)
{
uint8_t Value;
//假写操作
MyIIC_Start();
MyIIC_SendByte(0xd0);//MPU6050的地址
MyIIC_ReceiveAck();
MyIIC_SendByte(RegAddress);//写入寄存器地址
MyIIC_ReceiveAck();
MyIIC_Start();
MyIIC_SendByte(0xd1);//从机读地址
MyIIC_ReceiveAck();
Value = MyIIC_ReadByte();
MyIIC_SendAck(1);
MyIIC_Stop();
return Value;
}