读MPU6050数据输出全是0,郁闷,求大神指点
本帖最后由 宁采儿 于 2013-11-7 11:35 编辑#include"sys.h"
#include"usart.h"
#include"delay.h"
#include"led.h"
#include"sys.h"
#include"delay.h"
#include "i2c.h"
typedef enum
{
FALSE=0,
TRUE=!FALSE
}bool;
//****************************************
// 定义MPU6050内部地址
//****************************************
#define SMPLRT_DIV 0x19 //陀螺仪采样率,典型值:0x07(125Hz)
#define CONFIG 0x1A //低通滤波频率,典型值:0x06(5Hz)
#define GYRO_CONFIG 0x1B //陀螺仪自检及测量范围,典型值:0x18(不自检,2000deg/s)
#define ACCEL_CONFIG 0x1C //加速计自检、测量范围及高通滤波频率,典型值:0x01(不自检,2G,5Hz)
#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 //电源管理,典型值:0x00(正常启用)
#define WHO_AM_I 0x75 //IIC地址寄存器(默认数值0x68,只读)
#define SlaveAddress 0xD0 //IIC写入时的地址字节数据,+1为读取
void I2c_Start()
{
SDA_H;
SCL_H;
delay_us(5);
SDA_L;
delay_us(5);
SCL_L;
}
void I2c_Stop()
{
SCL_L;
SDA_L;
delay_us(5);
SCL_H;
SDA_H;
delay_us(5);
}
void I2C_GPIO_Config(void)
{
GPIO_InitTypeDefGPIO_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
GPIO_InitStructure.GPIO_Pin =GPIO_Pin_6|GPIO_Pin_7;//SCL+SDA
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_10MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_OD;
GPIO_Init(GPIOB, &GPIO_InitStructure);
}
/************IIC start or stop ***************/
//开始信号:在SCL为高电平的时候,SDA由高电平向低电平跳变,开始传送数据;
//结束信号:在SCL为高电平的是后,SDA由低电平向高电平跳变,结束传送数据;
// 应答信号:接收数据的IC在接收到8bit后,向发送数据的IC发出特定的低电平脉冲,表示已收到数据。CPU向受控单元发出一个信号后,
//等待受控单元发出一个应答信号,CPU接收到应答信号后,根据实际情况作出是否继续传输数据的判断
//**************************************
//I2C发送应答信号
//入口参数:ack (0:ACK 1:NAK)
//**************************************
void I2C_SendACK(u8 ack)
{
if(!ack)
SDA_L; //写应答信号
else
SDA_H;
SCL_H; //拉高时钟线
delay_us(5); //延时
SCL_L; //拉低时钟线
delay_us(5); //延时
}
//**************************************
//I2C接收应答信号
//**************************************
bool I2C_RecvACK()
{
u8 CY;
SCL_H; //拉高时钟线
delay_us(5); //延时
if(SDA_read)
CY=1;
else
CY=0;
SCL_L; //拉低时钟线
delay_us(5); //延时
if(CY)
return TRUE;
else
return FALSE;
}
//**************************************
//向I2C总线发送一个字节数据
//**************************************
void I2C_SendByte(u8 dat)
{
u8 i;
for (i=0; i<8; i++) //8位计数器
{
if(dat&0x80)
SDA_H;
else
SDA_L;
SCL_H; //拉高时钟线
delay_us(5); //延时
SCL_L; //拉低时钟线
delay_us(5); //延时
dat <<= 1; //移出数据的最高位
}
I2C_RecvACK();
}
//**************************************
//从I2C总线接收一个字节数据
//**************************************
u8 I2C_RecvByte()
{
u8 i;
u8 dat = 0;
SDA_H; //使能内部上拉,准备读取数据,
for (i=0; i<8; i++) //8位计数器
{
SCL_H; //拉高时钟线
delay_us(5); //延时
if(SDA_read)
dat |=0x01; //读数据
SCL_L; //拉低时钟线
delay_us(5); //延时
dat <<= 1;
}
return dat;
}
//**************************************
//向I2C设备写入一个字节数据
//**************************************
void Single_WriteI2C(u8 REG_Address,u8 REG_data)
{
I2c_Start(); //起始信号
I2C_SendByte(SlaveAddress); //发送设备地址+写信号
I2C_SendByte(REG_Address); //内部寄存器地址,
I2C_SendByte(REG_data); //内部寄存器数据,
I2c_Stop(); //发送停止信号
}
//**************************************
//从I2C设备读取一个字节数据
//**************************************
u8 Single_ReadI2C(u8 REG_Address)
{
u8 REG_data;
I2c_Start(); //起始信号
I2C_SendByte(SlaveAddress); //发送设备地址+写信号
I2C_SendByte(REG_Address); //发送存储单元地址,从0开始
I2c_Start(); //起始信号
I2C_SendByte(SlaveAddress+1);//发送设备地址+读信号
REG_data=I2C_RecvByte(); //读出寄存器数据
I2C_SendACK(1); //接收应答信号
I2c_Stop(); //停止信号
return REG_data;
}
//**************************************
//初始化MPU6050
//**************************************
void InitMPU6050()
{
Single_WriteI2C(PWR_MGMT_1, 0x00); //解除休眠状态电源管理寄存器
Single_WriteI2C(SMPLRT_DIV, 0x07); //陀螺仪采样率,典型值:0x07(125Hz)
Single_WriteI2C(CONFIG, 0x06); //低通滤波频率,典型值:0x06(5Hz)
Single_WriteI2C(GYRO_CONFIG, 0x18); //陀螺仪自检及测量范围,典型值:0x18(不自检,2000deg/s)
Single_WriteI2C(ACCEL_CONFIG, 0x01); //加速计自检、测量范围及高通滤波频率,典型值:0x01(不自检,2G,5Hz)
}
//**************************************
//合成数据
//**************************************
//int32_t GetData(u8 REG_Address)
int32_t GetData(u8 REG_Address)
{
u8 H,L;
H=Single_ReadI2C(REG_Address); //#define ACCEL_XOUT_H 0x3B
L=Single_ReadI2C(REG_Address+1); //#define ACCEL_XOUT_L 0x3C
return (H<<8)+L; //合成数据
}
int main(void)
{
SystemInit();
delay_init(72);
uart_init(9600);
I2C_GPIO_Config();
InitMPU6050();
delay_ms(100);
while(1)
{
printf("XSpeed is %d\n\n",GetData(ACCEL_XOUT_H)); //显示X轴加速度
printf("YSpeed is %d\n\n",GetData(ACCEL_YOUT_H)); //显示Y轴加速度
printf("ZSpeed is %d\n\n",GetData(ACCEL_ZOUT_H)); //显示Z轴加速度
printf("XCSpeed is %d\n\n",GetData(GYRO_XOUT_H)); //显示X轴加速度
printf("YCSpeed is %d\n\n",GetData(GYRO_YOUT_H)); //显示Y轴加速度
printf("ZCSpeed is %d\n\n",GetData(GYRO_ZOUT_H)); //显示Z轴加速度
LED0=!LED0;
LED1=!LED1;
delay_ms(100);
delay_ms(100);
}
}
我试过读0X68,结果也读错数据。我用的是MPU6050的模块。 void InitMPU6050()函数里面先复位一下器件试试,也是操作PWR_MGMT_1寄存器 本帖最后由 avrwoo 于 2013-11-7 12:37 编辑
调试中发现是加速度一直有数值显示,运动停下来的话是数据保持不动,陀螺仪不动的话数据就是零,运动后才有数据,总感觉加速度和陀螺的输出都应该是静止时是零,运动才应有数据显示,不知道哪位用过的朋友给讲解下?LZ的可能是I2C的这地方程序有问题,可能是时序不准, samo110 发表于 2013-11-7 12:15 static/image/common/back.gif
void InitMPU6050()函数里面先复位一下器件试试,也是操作PWR_MGMT_1寄存器
用51调试就能正常读取数据,这个代码是移植的51的,居然不通。。。晚上看看你的方法行不 avrwoo 发表于 2013-11-7 12:35 static/image/common/back.gif
调试中发现是加速度一直有数值显示,运动停下来的话是数据保持不动,陀螺仪不动的话数据就是零,运动后才有 ...
陀螺仪测的是角速度,要运动才有数据,但是由于存在零漂,静止时一般也有较小的数据
加速度计测得就是加速度,这个数据是包括重力加速度的,所以静止时有数据,但是变化不大,一般就找姿态的话加速度计就是用这个本地重力加速度来测角度的 宁采儿 发表于 2013-11-7 13:48 static/image/common/back.gif
用51调试就能正常读取数据,这个代码是移植的51的,居然不通。。。晚上看看你的方法行不 ...
这个是论坛里一个网友的AVR的程序,我试了可以读出数据,你看看。 samo110 发表于 2013-11-7 15:21 static/image/common/back.gif
陀螺仪测的是角速度,要运动才有数据,但是由于存在零漂,静止时一般也有较小的数据
加速度计测得就是加 ...
哦。明白了。谢谢。 慢慢来,有条件话对照着IIC总线时序调试调试,应答信号要有。不然不是全0就是全1.我前段时间也是遇到这种问题。后来发现是IIC通信中没有给应答信号造成的 samo110 发表于 2013-11-7 12:15 static/image/common/back.gif
void InitMPU6050()函数里面先复位一下器件试试,也是操作PWR_MGMT_1寄存器
这位大神,我现在对你真是佩服的五体投地啊,调了4天左右,一直搞不好。无奈试了一下你的方案,草,一下子就有数据读出来了。感激。。。 宁采儿 发表于 2013-11-8 02:00 static/image/common/back.gif
这位大神,我现在对你真是佩服的五体投地啊,调了4天左右,一直搞不好。无奈试了一下你的方案,草,一下 ...
之前我也是遇到你这种情况,一直读出-1……
页:
[1]