|
本帖最后由 边个叫我 于 2013-5-7 21:20 编辑
小弟不才,买了个mpu6050模块,打算用avr单片机(mega16)先读数出来。但是怎样都是FF的读数。。。
我不知道是什么情况。
检查过iic时序图,还没发现错误。。。。
恳请各位英雄帮帮忙。。。- [color=Cyan]/*avr_usart_mpu6050*/[/color]
- #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)
- {
- /*
- [color=Lime]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); //显示[/color]
- */
- uart_sendB('a');
- b = GetData(ACCEL_XOUT_H);
- // uart_sendB(b);
- /*
- [color=Cyan] 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));[/color]*/
- //flag=0;
- uart_sendB(b>>8);
- uart_sendB(b&0xff);
- delayms(5000);
- }
- }
- [color=Cyan]/*mpu6050.h*/[/color]
- /*****************************************************
- 普通IO模拟I2C通信,MPU-6050数据处理
-
- *****************************************************/
- #ifndef __MPU6050_H__
- #define __MPU6050_H__
- typedef unsigned char uchar;
- 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为读取
- #define mclk 12000000
- #pragma interrupt_handler uart_rx:12
- //-------------------------------------------------------
- // 函数声明
- //-------------------------------------------------------
- void InitMPU6050(void); //初始化MPU6050
- void delayus(uint n);
- void delayms(uint lms);
- void I2C_Init(void);
- void I2C_Start(void);
- void I2C_Stop(void);
- void I2C_Ack(void);
- void I2C_NoAck(void);
- uchar I2C_WaitAck(void);
- void I2C_SendByte(uchar dat);
- uchar I2C_RecvByte(uchar ack);
- uchar Single_ReadI2C(uchar REG_Address);
- void Single_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
复制代码 |
本帖子中包含更多资源
您需要 登录 才可以下载或查看,没有帐号?注册
x
阿莫论坛20周年了!感谢大家的支持与爱护!!
你熬了10碗粥,别人一桶水倒进去,淘走90碗,剩下10碗给你,你看似没亏,其实你那10碗已经没有之前的裹腹了,人家的一桶水换90碗,继续卖。说白了,通货膨胀就是,你的钱是挣来的,他的钱是印来的,掺和在一起,你的钱就贬值了。
|