【求助】关于mpu6050模块,数据全是FF
本帖最后由 边个叫我 于 2013-5-7 21:20 编辑小弟不才,买了个mpu6050模块,打算用avr单片机(mega16)先读数出来。但是怎样都是FF的读数。。。
我不知道是什么情况。
检查过iic时序图,还没发现错误。。。。
恳请各位英雄帮帮忙。。。{:3_60:}/*avr_usart_mpu6050*/
#include"iom16v.h"
#include"macros.h"
#include"mpu6050.h"
void main(void)
{
uint b;
delayms(5000); //上电延时
I2C_Init();
// InitLcd(); //液晶初始化
uart_init(19200);
InitMPU6050(); //初始化MPU6050
delayms(5000); //上电延时
while(1)
{
/*
Display10BitData(GetData(ACCEL_XOUT_H),2,0); //显示X轴加速度
Display10BitData(GetData(ACCEL_YOUT_H),7,0); //显示Y轴加速度
Display10BitData(GetData(ACCEL_ZOUT_H),12,0); //显示Z轴加速度
Display10BitData(GetData(GYRO_XOUT_H),2,1); //显示X轴角速度
Display10BitData(GetData(GYRO_YOUT_H),7,1); //显示Y轴角速度
Display10BitData(GetData(GYRO_ZOUT_H),12,1); //显示
*/
uart_sendB('a');
b = GetData(ACCEL_XOUT_H);
// uart_sendB(b);
/*
uart_sendB(GetData(ACCEL_XOUT_H));
uart_sendB(GetData(ACCEL_YOUT_H));
uart_sendB(GetData(ACCEL_ZOUT_H));
uart_sendB(GetData(GYRO_XOUT_H));
uart_sendB(GetData(GYRO_YOUT_H));
uart_sendB(GetData(GYRO_ZOUT_H));*/
//flag=0;
uart_sendB(b>>8);
uart_sendB(b&0xff);
delayms(5000);
}
}
/*mpu6050.h*/
/*****************************************************
普通IO模拟I2C通信,MPU-6050数据处理
*****************************************************/
#ifndef__MPU6050_H__
#define__MPU6050_H__
typedef unsigned charuchar;
typedef unsigned int uint;
//-------------------------------------------------------
//端口定义
//-------------------------------------------------------
//#define SCL PC0 //输出1
#define Hign_SCL PORTC |= (1 << PC0)
#define Low_SCL PORTC &= ~(1 << PC0)
//#define SDA PC1 //输出1/输入0
#define Hign_SDA PORTC |= (1 << PC1)
#define Low_SDA PORTC &= ~(1 << PC1)
#define Read_SDA PINC & (1 << PC1)
#define EN_SDA_1 DDRC |= (1 << PC1)//输出1
#define EN_SDA_0 DDRC &= ~(1 << PC1) //输入0
//-------------------------------------------------------
// 定义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为读取
#definemclk 12000000
#pragma interrupt_handler uart_rx:12
//-------------------------------------------------------
// 函数声明
//-------------------------------------------------------
voidInitMPU6050(void); //初始化MPU6050
voiddelayus(uint n);
voiddelayms(uint lms);
voidI2C_Init(void);
voidI2C_Start(void);
voidI2C_Stop(void);
voidI2C_Ack(void);
voidI2C_NoAck(void);
uchar I2C_WaitAck(void);
voidI2C_SendByte(uchar dat);
uchar I2C_RecvByte(uchar ack);
uchar Single_ReadI2C(uchar REG_Address);
voidSingle_WriteI2C(uchar REG_Address,uchar REG_data);
int GetData(uchar REG_Address); //16位数据合成
//-------------------------------------------------------
// 延时函数
//-------------------------------------------------------
void delayus(unsigned int n)
{
unsigned int i=0;
for(i=0;i<n;i++)
asm("nop");
}
//-------------------------------------------------------
// 延时函数
//8M 延时计算公式 = 2.88+(n-1)*0.75 us
//
//ms级别的延时函数
void delayms(unsigned int lms)
{
while(lms--)
{
delayus(1000); //延时1ms
}
}
//-------------------------------------------------------
//USART
//-------------------------------------------------------
uchar rdata,flag=0;
void uart_init(uint baud)
{
UCSRB=0x00;
UCSRA=0x00; //控制寄存器清零
UCSRC=(1<<URSEL)|(0<<UPM0)|(3<<UCSZ0);
//选择UCSRC,异步模式,禁止
// 校验,1位停止位,8位数据位
baud=mclk/16/baud-1 ; //波特率最大为65K
UBRRL=baud;
UBRRH=baud>>8; //设置波特率
UCSRB=(1<<TXEN)|(1<<RXEN)|(1<<RXCIE);
//接收、发送使能,接收中断使能
SREG=BIT(7); //全局中断开放
DDRD|=0X02; //配置TX为输出(很重要)
}
void uart_sendB(uchar data)
{
while(!(UCSRA&(BIT(UDRE)))) ;
UDR=data;
while(!(UCSRA&(BIT(TXC))));
UCSRA|=BIT(TXC);
}
void uart_rx(void)
{
UCSRB&=~BIT(RXCIE);
rdata=UDR;
flag=1;
UCSRB|=BIT(RXCIE);
}
//-------------------------------------------------------
//I2C初始化
//--
void I2C_Init(void)
{
PORTC &= ~(1 << PC0); //SCL的PORT状态锁定为0,以后不再改变
DDRC &= ~(1 << PC0); //SCL设置为输入口
PORTC &= ~(1 << PC1); //SDA的PORT状态锁定为0,以后不再改变
DDRC &= ~(1 << PC1); //SDA设置为输入口
delayus(10);
}
//-------------------------------------------------------
//I2C起始信号
//在SCL为高电平的时候,SDA由高电平向低电平跳变,开始传送数据
//-------------------------------------------------------
void I2C_Start(void)
{
EN_SDA_1; //使能输出
Hign_SDA; //拉高数据线
Hign_SCL; //拉高时钟线
delayus(5);
Low_SDA; //产生下降沿
delayus(5);
Low_SCL;
}
//-------------------------------------------------------
//I2C停止信号
//在SCL为高电平的时候,SDA由低电平向高电平跳变,结束传送数据
//-------------------------------------------------------
void I2C_Stop(void)
{
EN_SDA_1; //使能输出
Low_SDA;
Hign_SCL;
delayus(5);
// Hign_SCL;
Hign_SDA;
delayus(5);
}
//-------------------------------------------------------
//I2C产生应答信号
//-------------------------------------------------------
void I2C_Ack(void)
{
Low_SCL;
EN_SDA_1; //使能SDA输出
Low_SDA;
delayus(5);
Hign_SCL;
delayus(5);
Low_SCL;
delayus(5);
}
//-------------------------------------------------------
//I2C不产生应答信号
//-------------------------------------------------------
void I2C_NoAck(void)
{
Low_SCL;
EN_SDA_1; //使能SDA输出
Hign_SDA;
delayus(5);
Hign_SCL;
delayus(5);
Low_SCL;
delayus(5);
}
/*******************************************************************************
* Function Name: I2C_WaitAck
* Input : None
* Output : 1,接收应答失败
0,接收应答成功
* Return : Wheather Reserive Slave Acknowledge Single
****************************************************************************** */
uchar I2C_WaitAck(void) //返回为:=1有ACK,=0无ACK
{
uchar errTime = 0;
EN_SDA_0;
Hign_SDA;
delayus(10);
Hign_SCL;
delayus(10);
while(Read_SDA)
{
errTime++;
if(errTime>250)
{
I2C_Stop();
return 1;
}
}
Low_SCL;//时钟输出0
return 0;
}
//-------------------------------------------------------
//向I2C总线发送一个字节数据
//返回从机有无应答,1,有应答,0,无应答
//-------------------------------------------------------
void I2C_SendByte(uchar dat)
{
uchar i;
EN_SDA_1; //使能SDA输出
Low_SCL;
for (i=0; i<8; i++) //8位计数器
{
if(dat & 0x80)
{Hign_SDA;}
else
{Low_SDA;}
dat <<= 1; //移出数据的最高位
Hign_SCL; //SCL高电平,保持数据
delayus(10);
Low_SCL; //SCL低电平,数据被送入I2C
delayus(10);
}
}
//-------------------------------------------------------
//从I2C总线接收一个字节数据
//ack=1时,发送ACK,ack=0,发送nACK
//-------------------------------------------------------
uchar I2C_RecvByte(uchar ack)
{
uchar i;
uchar dat = 0;
EN_SDA_0; //使能SDA输入
for (i=0; i<8; i++) //8位计数器
{
Low_SCL;
delayus(10);
Hign_SCL;
dat <<= 1;
if(Read_SDA) dat++;
delayus(10);
}
if(!ack)
{
I2C_NoAck();
}
else
{
I2C_Ack();
}
return dat;
}
//-------------------------------------------------------
//向I2C设备写入一个字节数据
//-------------------------------------------------------
void Single_WriteI2C(uchar REG_Address,uchar REG_data)
{
I2C_Start(); //起始信号
I2C_SendByte(SlaveAddress); //发送设备地址+写信号
I2C_WaitAck();
I2C_SendByte(REG_Address); //内部寄存器地址
I2C_WaitAck();
I2C_SendByte(REG_data); //内部寄存器数据
I2C_WaitAck();
I2C_Stop(); //发送停止信号
}
//-------------------------------------------------------
//从I2C设备读取一个字节数据
//-------------------------------------------------------
uchar Single_ReadI2C(uchar REG_Address)
{
uchar REG_data;
I2C_Start(); //起始信号
I2C_SendByte(SlaveAddress); //发送设备地址+写信号
I2C_WaitAck();
I2C_SendByte(REG_Address); //发送存储单元地址,从0开始
I2C_WaitAck();
I2C_Start(); //起始信号
I2C_SendByte(SlaveAddress+1);//发送设备地址+读信号
I2C_WaitAck();
REG_data=I2C_RecvByte(0); //读出寄存器数据
I2C_Stop(); //停止信号
return REG_data;
}
//-------------------------------------------------------
//初始化MPU6050
//-------------------------------------------------------
void InitMPU6050(void)
{
Single_WriteI2C(PWR_MGMT_1, 0x00); //解除休眠状态
Single_WriteI2C(SMPLRT_DIV, 0x07);
Single_WriteI2C(CONFIG, 0x06);
Single_WriteI2C(GYRO_CONFIG, 0x18);
Single_WriteI2C(ACCEL_CONFIG, 0x01);
}
//-------------------------------------------------------
//合成数据
//-------------------------------------------------------
int GetData(uchar REG_Address)
{
uint H;
uchar L;
H=Single_ReadI2C(REG_Address);
L=Single_ReadI2C(REG_Address+1);
return (H<<8)+L; //合成数据
}
#endif
大神呢?
自顶。。。 请问楼主的问题得到解决了吗,我也正困惑呢,要是楼主完成了希望分享一下 我也遇到了跟你同样的问题,读出的寄存器值全部都是255,迷茫无助了,求神兵天降。。。楼主解决了能告知一下吗? 兄弟给你个治疗吧,这种问题只有靠时间来解决,熟悉的工程师 估计10分钟搞定,本身找问题也是种学习 兄弟,我的问题今天解决了,问题出在IIC上了。我的是忘记了应答信号,拔下模块也是返回FF,你用示波器试试看跟我的问题一样吗。 兄弟给我指点指点吧 我的问题是mpu6050 id 是FF,是什么问题,求救啊 这种问题最好对照示波器去检查一遍,使用stm32模拟的I2C程序,发现不知道是谁挖了个坑,如下
AD+R填错了,所以读出全为FF。大家留点心! 是不是论坛里的程序?我也是用的这个,读不出来,只要把 I2C_Stop();改成 Low_SCL;就OK了;你试试
uchar I2C_WaitAck(void) //返回为:=1有ACK,=0无ACK
{
uchar errTime = 0;
EN_SDA_0;
Hign_SDA;
delayus(10);
Hign_SCL;
delayus(10);
while(Read_SDA)
{
errTime++;
if(errTime>250)
{
I2C_Stop();
return 1;
}
}
Low_SCL;//时钟输出0
return 0;
}
我也遇到这个问题了,全部是FF,楼主解决了吗?
页:
[1]