OpenEdv-开源电子网

 找回密码
 立即注册
正点原子全套STM32/Linux/FPGA开发资料,上千讲STM32视频教程免费下载...
查看: 16125|回复: 19

求51单片机 关于MPU6050输出角度程序问题!

[复制链接]

13

主题

206

帖子

1

精华

高级会员

Rank: 4

积分
613
金钱
613
注册时间
2014-10-26
在线时间
32 小时
发表于 2014-12-7 15:16:03 | 显示全部楼层 |阅读模式
5金钱

先上个淘宝送的MPU6050  I2C输出1602显示 加速度和角速度的代码~
[mw_shl_code=c,true]//**************************************** // 功能: 显示加速度计和陀螺仪的10位原始数据 // 显示:LCD1602 //**************************************** #include <REG52.H> #include <math.h> //Keil library #include <stdio.h> //Keil library #include <INTRINS.H> typedef unsigned char uchar; typedef unsigned short ushort; typedef unsigned int uint; //**************************************** // 定义51单片机端口 //**************************************** #define DataPort P2 //LCD1602数据端口 sbit SCL=P1^0; //IIC时钟引脚定义 sbit SDA=P1^1; //IIC数据引脚定义 sbit LCM_RS=P0^7; //LCD1602命令端口 sbit LCM_RW=P0^6; //LCD1602命令端口 sbit LCM_EN=P0^5; //LCD1602命令端口 //**************************************** // 定义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为读取 //**************************************** //定义类型及变量 //**************************************** uchar dis[4]; //显示数字(-511至512)的字符数组 int dis_data; //变量 //int Temperature,Temp_h,Temp_l; //温度及高低位数据 //**************************************** //函数声明 //**************************************** void delay(unsigned int k); //延时 //LCD相关函数 void InitLcd(); //初始化lcd1602 void lcd_printf(uchar *s,int temp_data); void WriteDataLCM(uchar dataW); //LCD数据 void WriteCommandLCM(uchar CMD,uchar Attribc); //LCD指令 void DisplayOneChar(uchar X,uchar Y,uchar DData); //显示一个字符 void DisplayListChar(uchar X,uchar Y,uchar *DData,L); //显示字符串 //MPU6050操作函数 void InitMPU6050(); //初始化MPU6050 void Delay5us(); void I2C_Start(); void I2C_Stop(); void I2C_SendACK(bit ack); bit I2C_RecvACK(); void I2C_SendByte(uchar dat); uchar I2C_RecvByte(); void I2C_ReadPage(); void I2C_WritePage(); void display_ACCEL_x(); void display_ACCEL_y(); void display_ACCEL_z(); uchar Single_ReadI2C(uchar REG_Address); //读取I2C数据 void Single_WriteI2C(uchar REG_Address,uchar REG_data); //向I2C写入数据 //**************************************** //整数转字符串 //**************************************** void lcd_printf(uchar *s,int temp_data) { if(temp_data<0) { temp_data=-temp_data; *s='-'; } else *s=' '; *++s =temp_data/100+0x30; temp_data=temp_data%100; //取余运算 *++s =temp_data/10+0x30; temp_data=temp_data%10; //取余运算 *++s =temp_data+0x30; } //**************************************** //延时 //**************************************** void delay(unsigned int k) { unsigned int i,j; for(i=0;i<k;i++) { for(j=0;j<121;j++); } } //**************************************** //LCD1602初始化 //**************************************** void InitLcd() { WriteCommandLCM(0x38,1); WriteCommandLCM(0x08,1); WriteCommandLCM(0x01,1); WriteCommandLCM(0x06,1); WriteCommandLCM(0x0c,1); DisplayOneChar(0,0,'A'); DisplayOneChar(0,1,'G'); } //**************************************** //LCD1602写允许 //**************************************** void WaitForEnable(void) { DataPort=0xff; LCM_RS=0;LCM_RW=1;_nop_(); LCM_EN=1;_nop_();_nop_(); while(DataPort&0x80); LCM_EN=0; } //**************************************** //LCD1602写入命令 //**************************************** void WriteCommandLCM(uchar CMD,uchar Attribc) { if(Attribc)WaitForEnable(); LCM_RS=0;LCM_RW=0;_nop_(); DataPort=CMD;_nop_(); LCM_EN=1;_nop_();_nop_();LCM_EN=0; } //**************************************** //LCD1602写入数据 //**************************************** void WriteDataLCM(uchar dataW) { WaitForEnable(); LCM_RS=1;LCM_RW=0;_nop_(); DataPort=dataW;_nop_(); LCM_EN=1;_nop_();_nop_();LCM_EN=0; } //**************************************** //LCD1602写入一个字符 //**************************************** void DisplayOneChar(uchar X,uchar Y,uchar DData) { Y&=1; X&=15; if(Y)X|=0x40; X|=0x80; WriteCommandLCM(X,0); WriteDataLCM(DData); } //**************************************** //LCD1602显示字符串 //**************************************** void DisplayListChar(uchar X,uchar Y,uchar *DData,L) { uchar ListLength=0; Y&=0x1; X&=0xF; while(L--) { DisplayOneChar(X,Y,DData[ListLength]); ListLength++; X++; } } //************************************** //延时5微秒(STC90C52RC@12M) //不同的工作环境,需要调整此函数 //当改用1T的MCU时,请调整此延时函数 //************************************** void Delay5us() { _nop_();_nop_();_nop_();_nop_(); _nop_();_nop_();_nop_();_nop_(); _nop_();_nop_();_nop_();_nop_(); _nop_();_nop_();_nop_();_nop_(); _nop_();_nop_();_nop_();_nop_(); _nop_();_nop_();_nop_();_nop_(); } //************************************** //I2C起始信号 //************************************** void I2C_Start() { SDA = 1; //拉高数据线 SCL = 1; //拉高时钟线 Delay5us(); //延时 SDA = 0; //产生下降沿 Delay5us(); //延时 SCL = 0; //拉低时钟线 } //************************************** //I2C停止信号 //************************************** void I2C_Stop() { SDA = 0; //拉低数据线 SCL = 1; //拉高时钟线 Delay5us(); //延时 SDA = 1; //产生上升沿 Delay5us(); //延时 } //************************************** //I2C发送应答信号 //入口参数:ack (0:ACK 1:NAK) //************************************** void I2C_SendACK(bit ack) { SDA = ack; //写应答信号 SCL = 1; //拉高时钟线 Delay5us(); //延时 SCL = 0; //拉低时钟线 Delay5us(); //延时 } //************************************** //I2C接收应答信号 //************************************** bit I2C_RecvACK() { SCL = 1; //拉高时钟线 Delay5us(); //延时 CY = SDA; //读应答信号 SCL = 0; //拉低时钟线 Delay5us(); //延时 return CY; } //************************************** //向I2C总线发送一个字节数据 //************************************** void I2C_SendByte(uchar dat) { uchar i; for (i=0; i<8; i++) //8位计数器 { dat <<= 1; //移出数据的最高位 SDA = CY; //送数据口 SCL = 1; //拉高时钟线 Delay5us(); //延时 SCL = 0; //拉低时钟线 Delay5us(); //延时 } I2C_RecvACK(); } //************************************** //从I2C总线接收一个字节数据 //************************************** uchar I2C_RecvByte() { uchar i; uchar dat = 0; SDA = 1; //使能内部上拉,准备读取数据, for (i=0; i<8; i++) //8位计数器 { dat <<= 1; SCL = 1; //拉高时钟线 Delay5us(); //延时 dat |= SDA; //读数据 SCL = 0; //拉低时钟线 Delay5us(); //延时 } return dat; } //************************************** //向I2C设备写入一个字节数据 //************************************** void Single_WriteI2C(uchar REG_Address,uchar REG_data) { I2C_Start(); //起始信号 I2C_SendByte(SlaveAddress); //发送设备地址+写信号 I2C_SendByte(REG_Address); //内部寄存器地址, I2C_SendByte(REG_data); //内部寄存器数据, I2C_Stop(); //发送停止信号 } //************************************** //从I2C设备读取一个字节数据 //************************************** uchar Single_ReadI2C(uchar REG_Address) { uchar 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); Single_WriteI2C(CONFIG, 0x06); Single_WriteI2C(GYRO_CONFIG, 0x18); Single_WriteI2C(ACCEL_CONFIG, 0x01); } //************************************** //合成数据 //************************************** int GetData(uchar REG_Address) { char H,L; H=Single_ReadI2C(REG_Address); L=Single_ReadI2C(REG_Address+1); return (H<<8)+L; //合成数据 } //************************************** //在1602上显示10位数据 //************************************** void Display10BitData(int value,uchar x,uchar y) { value/=64; //转换为10位数据 lcd_printf(dis, value); //转换数据显示 DisplayListChar(x,y,dis,4); //启始列,行,显示数组,显示长度 } //********************************************************* //主程序 //********************************************************* void main() { delay(500); //上电延时 InitLcd(); //液晶初始化 InitMPU6050(); //初始化MPU6050 delay(150); 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); //显示Z轴角速度 delay(500); } } [/mw_shl_code]
上面测序确实能测出  加速度和角速度,  但是加速度有问题,  我静止不动时,  XYZ都有数值,而且不同位置静止时  数值还不一样!

既然这样,我就姑且不理他,  我套用原子哥  给出关于ADX345 加速度求角度 公式 
参考网站:http://www.openedv.com/posts/list/36065.htm
然后求得的数值也不正常~~ 个人认为加速度有问题   (就是图片的第一行的三个数,分别为XYZ的 3个加速度)第二行是我套用公式算出来的


最佳答案

查看完整内容[请看2#楼]

回复【15楼】oc: --------------------------------- 至今没解决,然后我用STM32移植别人的程序了
学习!
正点原子逻辑分析仪DL16劲爆上市
回复

使用道具 举报

13

主题

206

帖子

1

精华

高级会员

Rank: 4

积分
613
金钱
613
注册时间
2014-10-26
在线时间
32 小时
 楼主| 发表于 2014-12-7 15:16:04 | 显示全部楼层
回复【15楼】oc:
---------------------------------
至今没解决,然后我用STM32移植别人的程序了
学习!
回复

使用道具 举报

530

主题

11万

帖子

34

精华

管理员

Rank: 12Rank: 12Rank: 12

积分
165309
金钱
165309
注册时间
2010-12-1
在线时间
2108 小时
发表于 2014-12-7 23:22:23 | 显示全部楼层
帮顶。。。。。
我是开源电子网www.openedv.com站长,有关站务问题请与我联系。
正点原子STM32开发板购买店铺http://openedv.taobao.com
正点原子官方微信公众平台,点击这里关注“正点原子”
回复

使用道具 举报

13

主题

206

帖子

1

精华

高级会员

Rank: 4

积分
613
金钱
613
注册时间
2014-10-26
在线时间
32 小时
 楼主| 发表于 2014-12-8 13:42:55 | 显示全部楼层
回复【2楼】正点原子:
---------------------------------我在想,单纯的套用ADXL345的 用 3个加速度 算  角度,是不是不行?  我搞了几天没也搞出来,  得到的角度, 都是在漂,
学习!
回复

使用道具 举报

530

主题

11万

帖子

34

精华

管理员

Rank: 12Rank: 12Rank: 12

积分
165309
金钱
165309
注册时间
2010-12-1
在线时间
2108 小时
发表于 2014-12-8 13:56:34 | 显示全部楼层
回复【3楼】q27488:
---------------------------------
可以,但是ADXL345侧角度准确度不行。
我是开源电子网www.openedv.com站长,有关站务问题请与我联系。
正点原子STM32开发板购买店铺http://openedv.taobao.com
正点原子官方微信公众平台,点击这里关注“正点原子”
回复

使用道具 举报

0

主题

1

帖子

0

精华

新手入门

积分
21
金钱
21
注册时间
2015-4-6
在线时间
0 小时
发表于 2015-4-6 11:06:21 | 显示全部楼层
我想问一下,我用你的程序我怎么不能在lcd上显示任何数值?
回复

使用道具 举报

0

主题

1

帖子

0

精华

新手入门

积分
21
金钱
21
注册时间
2015-4-7
在线时间
0 小时
发表于 2015-4-7 21:48:47 | 显示全部楼层
楼主,我是按照你的这个程序写的,可是,在上电的瞬间LCD显示数据,然后就是稳态值004,怎么也不再变化,这是怎么回事呀?求解,谢谢!!!
回复

使用道具 举报

13

主题

206

帖子

1

精华

高级会员

Rank: 4

积分
613
金钱
613
注册时间
2014-10-26
在线时间
32 小时
 楼主| 发表于 2015-4-8 20:53:33 | 显示全部楼层
回复【5楼】我是小孩子:
---------------------------------
你检查你的LCD的三个控制端口 和8个数据是不是 不一样~
学习!
回复

使用道具 举报

0

主题

1

帖子

0

精华

新手入门

积分
21
金钱
21
注册时间
2015-4-18
在线时间
0 小时
发表于 2015-4-18 10:53:01 | 显示全部楼层
确实不错 ,感觉很有启发
杨军
回复

使用道具 举报

1

主题

9

帖子

0

精华

初级会员

Rank: 2

积分
112
金钱
112
注册时间
2015-7-27
在线时间
21 小时
发表于 2015-7-27 12:43:59 | 显示全部楼层
楼主,我是按照你的这个程序写的,怎么显示004不变呢??
回复

使用道具 举报

4

主题

24

帖子

0

精华

初级会员

Rank: 2

积分
135
金钱
135
注册时间
2014-9-17
在线时间
20 小时
发表于 2015-8-5 12:20:07 | 显示全部楼层
回复【4楼】正点原子:
---------------------------------
想问您一下 , 6050输出角度准确度怎么样
回复

使用道具 举报

530

主题

11万

帖子

34

精华

管理员

Rank: 12Rank: 12Rank: 12

积分
165309
金钱
165309
注册时间
2010-12-1
在线时间
2108 小时
发表于 2015-8-6 23:01:56 | 显示全部楼层
回复【10楼】加菲老爷:
---------------------------------
精确到0.1度没问题。
我是开源电子网www.openedv.com站长,有关站务问题请与我联系。
正点原子STM32开发板购买店铺http://openedv.taobao.com
正点原子官方微信公众平台,点击这里关注“正点原子”
回复

使用道具 举报

0

主题

5

帖子

0

精华

新手上路

积分
26
金钱
26
注册时间
2015-7-28
在线时间
0 小时
发表于 2015-8-11 15:08:33 | 显示全部楼层
顶。。。。。。。
菜鸟
回复

使用道具 举报

0

主题

1

帖子

0

精华

新手入门

积分
21
金钱
21
注册时间
2015-8-11
在线时间
0 小时
发表于 2015-8-11 18:33:09 | 显示全部楼层
回复【9楼】aa849319372:
---------------------------------
#define        WHO_AM_I            0x75       //IIC地址寄存器(默认数值0x68,只读)
改成  
#define        WHO_AM_I            0x68        //IIC地址寄存器(默认数值0x68,只读)
回复

使用道具 举报

1

主题

5

帖子

0

精华

新手上路

积分
29
金钱
29
注册时间
2015-8-10
在线时间
0 小时
发表于 2015-8-12 11:33:12 | 显示全部楼层
楼主,问一下连接里的角度x,y,z传的参数是哪三个?
回复

使用道具 举报

7

主题

55

帖子

0

精华

初级会员

Rank: 2

积分
114
金钱
114
注册时间
2015-4-28
在线时间
2 小时
发表于 2015-8-21 21:41:10 | 显示全部楼层
楼主可以把最后解决问题的过程写出来吗
回复

使用道具 举报

7

主题

55

帖子

0

精华

初级会员

Rank: 2

积分
114
金钱
114
注册时间
2015-4-28
在线时间
2 小时
发表于 2015-8-24 00:47:39 | 显示全部楼层
回复【16楼】q27488:
---------------------------------
谢谢你的回复,请问这个角度怎么算出来,我把下面的代码得到的结果传到 星星条下面也就是原子哥给别人的那个代码,得不到角度,最大数值就是11
                Display10BitData(GetData(ACCEL_XOUT_H)); //显示X轴加速度
Display10BitData(GetData(ACCEL_YOUT_H)); //显示Y轴加速度
Display10BitData(GetData(ACCEL_ZOUT_H)); //显示Z轴加速度

**************************
原子哥的代码
**************************
//得到角度
//x,y,z:x,y,z方向的重力加速度分量(不需要单位,直接数值即可)
//dir:要获得的角度.0,与Z轴的角度;1,与X轴的角度;2,与Y轴的角度.
//返回值:角度值.单位0.1°.
short ADXL345_Get_Angle(float x,float y,float z,u8 dir)
{
float temp;
  float res=0;
switch(dir)
{
case 0://与自然Z轴的角度
  temp=sqrt((x*x+y*y))/z;
  res=atan(temp);
  break;
case 1://与自然X轴的角度
  temp=x/sqrt((y*y+z*z));
  res=atan(temp);
  break;
  case 2://与自然Y轴的角度
  temp=y/sqrt((x*x+z*z));
  res=atan(temp);
  break;
  }
return res*1800/3.14;
}
回复

使用道具 举报

5

主题

19

帖子

0

精华

初级会员

Rank: 2

积分
145
金钱
145
注册时间
2015-10-30
在线时间
41 小时
发表于 2015-10-31 21:11:59 | 显示全部楼层
回复【6楼】lalal321:
---------------------------------
对啊,稳态我我的也是3和4,怎么处理呢
回复

使用道具 举报

5

主题

19

帖子

0

精华

初级会员

Rank: 2

积分
145
金钱
145
注册时间
2015-10-30
在线时间
41 小时
发表于 2015-10-31 21:14:29 | 显示全部楼层
回复【11楼】正点原子:
------------------------------原子哥,,你回复一个行不。。。。。我的原始数据为什么只有003---004,别的没有了,而且不准确,怎么办 啊
回复

使用道具 举报

530

主题

11万

帖子

34

精华

管理员

Rank: 12Rank: 12Rank: 12

积分
165309
金钱
165309
注册时间
2010-12-1
在线时间
2108 小时
发表于 2015-11-1 23:39:08 | 显示全部楼层
回复【19楼】faguoduifangui:
---------------------------------
可以参考我们代码.
我是开源电子网www.openedv.com站长,有关站务问题请与我联系。
正点原子STM32开发板购买店铺http://openedv.taobao.com
正点原子官方微信公众平台,点击这里关注“正点原子”
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则



关闭

原子哥极力推荐上一条 /2 下一条

正点原子公众号

QQ|手机版|OpenEdv-开源电子网 ( 粤ICP备12000418号-1 )

GMT+8, 2024-11-23 12:05

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

快速回复 返回顶部 返回列表