最近在折腾MPU6050模块,买的是网上那个串口输出数据的模块。但我想通过IIC去读取原始的数据。
我的IIC是直接利用读取EEPROM的模拟IIC,在EEPROM上是可以进行通信的,但是我在读取MPU6050的寄存器的时候就不好使。我想通过读取WHO AM I 寄存器的值去判定我通信是否有问题,但是就是读取不了。这里面应该就是初始化SDA和SCL的引脚后就应该能够读取内部寄存器的值吧,不需要做别的设置了吧?知道的大神帮忙解答下,折腾很久了,我想知道到底是我的思路问题还是模块的问题,因为我没有模块的原理图。这种硬件都不公开的模块就是个大坑,以后不能买。
下面是我的代码:(战舰版上运行)
[mw_shl_code=c,true]MPU6050_DEVICE_ADDR 定义成0xd0 和0xd2都试过了[/mw_shl_code]
[mw_shl_code=c,true]#define MPU6050_DEVICE_ADDR 0x68
#define SDA_IN() {GPIOE->CRL&=0XFFFFF0FF;GPIOE->CRL|=0X0000000;}//PE.2为浮空输入,设成上拉就不行
#define SDA_OUT() {GPIOE->CRL&=0XFFFFF0FF;GPIOE->CRL|=0X00000300;} //PE.2推挽输出
#define IIC_SDA PEout(2)
#define IIC_SCL PEout(3)
#define READ_SDA PEin(2)
//IIC引脚初始化
void I2C_Pin_Init()
{
GPIO_InitTypeDef GPIO_InitStructure;
RCC->APB2ENR|=1<<6;////开GPIOE时钟
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2|GPIO_Pin_3;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_Init(GPIOE, &GPIO_InitStructure);
GPIO_SetBits(GPIOE, GPIO_Pin_2|GPIO_Pin_3);
// RCC->APB2ENR|=1<<3;//开GPIOB时钟
// GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11|GPIO_Pin_10;
// GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
// GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
// GPIO_Init(GPIOB, &GPIO_InitStructure);
// GPIO_SetBits(GPIOB, GPIO_Pin_10|GPIO_Pin_11);
IIC_SDA=1;
IIC_SCL=1;
}
//主机开始信号
void Master_Start(void)
{
SDA_OUT(); //sda线输出
IIC_SDA=1;
IIC_SCL=1;
delay_us(4);
IIC_SDA=0;//START:when CLK is high,DATA change form high to low
delay_us(4);
IIC_SCL=0;//钳住I2C总线,准备发送或接收数据
}
//主机给出停止信号
void Master_Stop()
{
SDA_OUT();//sda线输出
IIC_SCL=0;
IIC_SDA=0;//STOP:when CLK is high DATA change form low to high
delay_us(4);
IIC_SCL=1;
IIC_SDA=1;//发送I2C总线结束信号
delay_us(4);
}
//主机给从机应答信号
void Master_SendAck()
{
IIC_SCL=0;
SDA_OUT();
IIC_SDA=0;
delay_us(2);
IIC_SCL=1;
delay_us(2);
IIC_SCL=0;
}
//主机给从机非应答信号
void Master_SendNack()
{
IIC_SCL=0;
SDA_OUT();
IIC_SDA=1;
delay_us(2);
IIC_SCL=1;
delay_us(2);
IIC_SCL=0;
}
//主机检查从机发来的应答信号
u8 Master_CheckAck()
{
u8 ucErrTime=0;
SDA_IN(); //SDA设置为输入
IIC_SDA=1;delay_us(1);
//SDA_IN(); //SDA设置为输入
IIC_SCL=1;delay_us(1);
while(READ_SDA)
{
ucErrTime++;
if(ucErrTime>250)
{
Master_Stop();
// return 1;
}
}
IIC_SCL=0;//时钟输出0
return 0;
}
//主机往IIC总线传送一字节数据
void Master_W_byte(u8 dat)
{
u8 t;
SDA_OUT();
IIC_SCL=0;//拉低时钟开始数据传输
for(t=0;t<8;t++)
{
IIC_SDA=(dat&0x80)>>7;
dat<<=1;
delay_us(2); //对TEA5767这三个延时都是必须的
IIC_SCL=1;
delay_us(2);
IIC_SCL=0;
delay_us(2);
}
}
//主机从IIC总线接收一字节数据
u8 Master_R_byte(void)
{
unsigned char i,receive=0;
SDA_IN();//SDA设置为输入
for(i=0;i<8;i++ )
{
IIC_SCL=0;
delay_us(2);
IIC_SCL=1;
receive<<=1;
if(READ_SDA)receive++;
delay_us(1);
}
// if (!ack)
// IIC_NAck();//发送nACK
// else
// IIC_Ack(); //发送ACK
return receive;
}
/*******************************************************************************
** 功能描述:主机通过I2C总线从MPU6050中的具体地址读取一个字节的数据
** 输 入:Reg_Addr:MPU6050中的具体要读取数据的地址
** 返 回:读取的一个字节数据
*-----------------------------------------------------------------------------*/
u8 Master_R_Onebyte(u8 Reg_Addr)
{
u8 data;
Master_Start();
Master_W_byte(MPU6050_DEVICE_ADDR);
Master_CheckAck();
Master_W_byte(Reg_Addr);
Master_CheckAck();
Master_Start();
Master_W_byte(MPU6050_DEVICE_ADDR+1);
Master_CheckAck();
data=Master_R_byte();
Master_SendNack();
Master_Stop();
return data;
}
/*******************************************************************************
** 功能描述:检查MPU6050是否连上
** 说 明:读取WHO_AM_I寄存器,看值是否为0x68
** 返 回:0表示检查到了MPU6050,1表示没有检查到MPU6050
*-----------------------------------------------------------------------------*/
u8 MPU6050_Check()
{
u8 temp=2;
temp=Master_R_Onebyte(WHO_AM_I); //读取WHO_AM_I寄存器的值
if(temp==0x68)return 0;
else return 1;
}
//这段是main,c文件中
while(MPU6050_Check())//检测不到MPU6050
{
LCD_ShowString(60,150,200,16,16,"MPU6050 Check Failed!",0);
delay_ms(500);
LCD_ShowString(60,150,200,16,16,"Please Check! ",0);
delay_ms(500);
LED0=!LED0;//DS0闪烁
}
LCD_ShowString(60,150,200,16,16,"MPU6050 Ready!",0);
[/mw_shl_code]
|