找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 3270|回复: 0
打印 上一主题 下一主题
收起左侧

A为三轴MEMS加速度计,G为三轴MEMS陀螺仪.挪动MPU6050模块,则数据变化。

[复制链接]
跳转到指定楼层
楼主

一、连接单片机板

MPU6050 电路图,参看:MPU6050开发 -- 初识

从电路图上看了引出四根线:电源、GND、SCL、SDA. 连接单片机板。

单片机部分电路图:


思考:SCL、SDA应该接在单片机的哪个I/O口呢?

STC89C52 没有集成 I2C 控制器,只能通过软件模拟方法实现 I2C 功能,因此,普通I/O口都可以实现,不需要固定。你可以任意使用 STC89C52 单片机两个引脚,作为数据和时钟,然后自己编写模块 I2C 代码。

那么我们就定义51单片机端口:
//****************************************
sbit    SCL=P1^5;//IIC时钟引脚定义
sbit    SDA=P1^4;//IIC数据引脚定义

//****************************************

二、测试程序


  1. //****************************************
  2. // Update to MPU6050 by shinetop
  3. // MCU: STC89C52
  4. // 2012.3.1
  5. // 功能: 显示加速度计和陀螺仪的10位原始数据
  6. //****************************************
  7. // 使用单片机STC89C52
  8. // 晶振:11.0592M
  9. // 显示:串口
  10. // 编译环境 Keil uVision2
  11. //****************************************
  12. #include <REG52.H>
  13. #include <math.h>    //Keil library  
  14. #include <stdio.h>   //Keil library
  15. #include <INTRINS.H>
  16. typedef unsigned char  uchar;
  17. typedef unsigned short ushort;
  18. typedef unsigned int   uint;
  19. //****************************************
  20. // 定义51单片机端口
  21. //****************************************
  22. sbit    SCL=P1^5; //IIC时钟引脚定义
  23. sbit    SDA=P1^4; //IIC数据引脚定义
  24. //****************************************
  25. // 定义MPU6050内部地址
  26. //****************************************
  27. #define SMPLRT_DIV 0x19 //陀螺仪采样率,典型值:0x07(125Hz)
  28. #define CONFIG 0x1A //低通滤波频率,典型值:0x06(5Hz)
  29. #define GYRO_CONFIG 0x1B //陀螺仪自检及测量范围,典型值:0x18(不自检,2000deg/s)
  30. #define ACCEL_CONFIG 0x1C //加速计自检、测量范围及高通滤波频率,典型值:0x01(不自检,2G,5Hz)
  31. #define ACCEL_XOUT_H 0x3B
  32. #define ACCEL_XOUT_L 0x3C
  33. #define ACCEL_YOUT_H 0x3D
  34. #define ACCEL_YOUT_L 0x3E
  35. #define ACCEL_ZOUT_H 0x3F
  36. #define ACCEL_ZOUT_L 0x40
  37. #define TEMP_OUT_H 0x41
  38. #define TEMP_OUT_L 0x42
  39. #define GYRO_XOUT_H 0x43
  40. #define GYRO_XOUT_L 0x44
  41. #define GYRO_YOUT_H 0x45
  42. #define GYRO_YOUT_L 0x46
  43. #define GYRO_ZOUT_H 0x47
  44. #define GYRO_ZOUT_L 0x48
  45. #define PWR_MGMT_1 0x6B //电源管理,典型值:0x00(正常启用)
  46. #define WHO_AM_I 0x75 //IIC地址寄存器(默认数值0x68,只读)
  47. #define SlaveAddress 0xD0 //IIC写入时的地址字节数据,+1为读取
  48. //**************************************************************************************************
  49. //定义类型及变量
  50. //**************************************************************************************************
  51. uchar dis[6]; //显示数字(-511至512)的字符数组
  52. int dis_data; //变量
  53. //**************************************************************************************************
  54. //函数声明
  55. //**************************************************************************************************
  56. void  Delay5us();
  57. void  delay(unsigned int k); //延时
  58. void  lcd_printf(uchar *s,int temp_data);
  59. //********************************MPU6050操作函数***************************************************
  60. void  InitMPU6050(); //初始化MPU6050
  61. void  I2C_Start();
  62. void  I2C_Stop();
  63. void  I2C_SendACK(bit ack);
  64. bit   I2C_RecvACK();
  65. void  I2C_SendByte(uchar dat);
  66. uchar I2C_RecvByte();
  67. void  I2C_ReadPage();
  68. void  I2C_WritePage();
  69. void  display_ACCEL_x();
  70. void  display_ACCEL_y();
  71. void  display_ACCEL_z();
  72. uchar Single_ReadI2C(uchar REG_Address); //读取I2C数据
  73. void  Single_WriteI2C(uchar REG_Address,uchar REG_data);    //向I2C写入数据
  74. //********************************************************************************
  75. //整数转字符串
  76. //********************************************************************************
  77. void lcd_printf(uchar *s,int temp_data)
  78. {
  79. if(temp_data<0)
  80. {
  81. temp_data=-temp_data;
  82. *s='-';
  83. }
  84. else *s=' ';
  85. *++s =temp_data/10000+0x30;
  86. temp_data=temp_data%10000;     //取余运算
  87. *++s =temp_data/1000+0x30;
  88. temp_data=temp_data%1000;     //取余运算
  89. *++s =temp_data/100+0x30;
  90. temp_data=temp_data%100;     //取余运算
  91. *++s =temp_data/10+0x30;
  92. temp_data=temp_data%10;      //取余运算
  93. *++s =temp_data+0x30;
  94. }
  95. //******************************************************************************************************
  96. //串口初始化
  97. //*******************************************************************************************************
  98. void init_uart()
  99. {
  100. TMOD=0x21;
  101. TH1=0xfd; //实现波特率9600(系统时钟11.0592MHZ)
  102. TL1=0xfd;
  103. SCON=0x50;
  104. PS=1;      //串口中断设为高优先级别
  105. TR0=1;   //启动定时器
  106. TR1=1;
  107. ET0=1;     //打开定时器0中断
  108. ES=1;
  109. EA=1;
  110. }
  111. //*************************************************************************************************
  112. //串口发送函数
  113. //*************************************************************************************************
  114. void  SeriPushSend(uchar send_data)
  115. {
  116. SBUF=send_data;  
  117. while(!TI);TI=0;
  118. }
  119. //*************************************************************************************************
  120. //************************************延时*********************************************************
  121. //*************************************************************************************************
  122. void delay(unsigned int k)
  123. {
  124. unsigned int i,j;
  125. for(i=0;i<k;i++)
  126. {
  127. for(j=0;j<121;j++);
  128. }
  129. }
  130. //************************************************************************************************
  131. //延时5微秒(STC90C52RC@12M)
  132. //不同的工作环境,需要调整此函数
  133. //注意当改用1T的MCU时,请调整此延时函数
  134. //************************************************************************************************
  135. void Delay5us()
  136. {
  137. _nop_();_nop_();_nop_();_nop_();
  138. _nop_();_nop_();_nop_();_nop_();
  139. _nop_();_nop_();_nop_();_nop_();
  140. _nop_();_nop_();_nop_();_nop_();
  141. _nop_();_nop_();_nop_();_nop_();
  142. _nop_();_nop_();_nop_();_nop_();
  143. }
  144. //*************************************************************************************************
  145. //I2C起始信号
  146. //*************************************************************************************************
  147. void I2C_Start()
  148. {
  149. SDA = 1;                    //拉高数据线
  150. SCL = 1;                    //拉高时钟线
  151. Delay5us();                 //延时
  152. SDA = 0;                    //产生下降沿
  153. Delay5us();                 //延时
  154. SCL = 0;                    //拉低时钟线
  155. }
  156. //*************************************************************************************************
  157. //I2C停止信号
  158. //*************************************************************************************************
  159. void I2C_Stop()
  160. {
  161. SDA = 0;                    //拉低数据线
  162. SCL = 1;                    //拉高时钟线
  163. Delay5us();                 //延时
  164. SDA = 1;                    //产生上升沿
  165. Delay5us();                 //延时
  166. }
  167. //**************************************************************************************************
  168. //I2C发送应答信号
  169. //入口参数:ack (0:ACK 1:NAK)
  170. //**************************************************************************************************
  171. void I2C_SendACK(bit ack)
  172. {
  173. SDA = ack;                  //写应答信号
  174. SCL = 1;                    //拉高时钟线
  175. Delay5us();                 //延时
  176. SCL = 0;                    //拉低时钟线
  177. Delay5us();                 //延时
  178. }
  179. //****************************************************************************************************
  180. //I2C接收应答信号
  181. //****************************************************************************************************
  182. bit I2C_RecvACK()
  183. {
  184. SCL = 1;                    //拉高时钟线
  185. Delay5us();                 //延时
  186. CY = SDA;                   //读应答信号
  187. SCL = 0;                    //拉低时钟线
  188. Delay5us();                 //延时
  189. return CY;
  190. }
  191. //*****************************************************************************************************
  192. //向I2C总线发送一个字节数据
  193. //*****************************************************************************************************
  194. void I2C_SendByte(uchar dat)
  195. {
  196. uchar i;
  197. for (i=0; i<8; i++)         //8位计数器
  198. {
  199. dat <<= 1;              //移出数据的最高位
  200. SDA = CY;               //送数据口
  201. SCL = 1;                //拉高时钟线
  202. Delay5us();             //延时
  203. SCL = 0;                //拉低时钟线
  204. Delay5us();             //延时
  205. }
  206. I2C_RecvACK();
  207. }
  208. //*****************************************************************************************************
  209. //从I2C总线接收一个字节数据
  210. //******************************************************************************************************
  211. uchar I2C_RecvByte()
  212. {
  213. uchar i;
  214. uchar dat = 0;
  215. SDA = 1;                    //使能内部上拉,准备读取数据,
  216. for (i=0; i<8; i++)         //8位计数器
  217. {
  218. dat <<= 1;
  219. SCL = 1;                //拉高时钟线
  220. Delay5us();             //延时
  221. dat |= SDA;             //读数据               
  222. SCL = 0;                //拉低时钟线
  223. Delay5us();             //延时
  224. }
  225. return dat;
  226. }
  227. //*****************************************************************************************************
  228. //向I2C设备写入一个字节数据
  229. //*****************************************************************************************************
  230. void Single_WriteI2C(uchar REG_Address,uchar REG_data)
  231. {
  232. I2C_Start();                  //起始信号
  233. I2C_SendByte(SlaveAddress);   //发送设备地址+写信号
  234. I2C_SendByte(REG_Address);    //内部寄存器地址,
  235. I2C_SendByte(REG_data);       //内部寄存器数据,
  236. I2C_Stop();                   //发送停止信号
  237. }
  238. //*******************************************************************************************************
  239. //从I2C设备读取一个字节数据
  240. //*******************************************************************************************************
  241. uchar Single_ReadI2C(uchar REG_Address)
  242. {
  243. uchar REG_data;
  244. I2C_Start();                   //起始信号
  245. I2C_SendByte(SlaveAddress);    //发送设备地址+写信号
  246. I2C_SendByte(REG_Address);     //发送存储单元地址,从0开始
  247. I2C_Start();                   //起始信号
  248. I2C_SendByte(SlaveAddress+1);  //发送设备地址+读信号
  249. REG_data=I2C_RecvByte();       //读出寄存器数据
  250. I2C_SendACK(1);                //接收应答信号
  251. I2C_Stop();                    //停止信号
  252. return REG_data;
  253. }
  254. //******************************************************************************************************
  255. //初始化MPU6050
  256. //******************************************************************************************************
  257. void InitMPU6050()
  258. {
  259. Single_WriteI2C(PWR_MGMT_1, 0x00); //解除休眠状态
  260. Single_WriteI2C(SMPLRT_DIV, 0x07);
  261. Single_WriteI2C(CONFIG, 0x06);
  262. Single_WriteI2C(GYRO_CONFIG, 0x18);
  263. Single_WriteI2C(ACCEL_CONFIG, 0x01);
  264. }
  265. //******************************************************************************************************
  266. //合成数据
  267. //******************************************************************************************************
  268. int GetData(uchar REG_Address)
  269. {
  270. uchar H,L;
  271. H=Single_ReadI2C(REG_Address);
  272. L=Single_ReadI2C(REG_Address+1);
  273. return ((H<<8)+L);   //合成数据
  274. }
  275. //******************************************************************************************************
  276. //超级终端(串口调试助手)上显示10位数据
  277. //******************************************************************************************************
  278. void Display10BitData(int value)
  279. {  uchar i;
  280. // value/=64; //转换为10位数据
  281. lcd_printf(dis, value); //转换数据显示
  282. for(i=0;i<6;i++)
  283. {
  284. SeriPushSend(dis[ i]);
  285. }
  286. // DisplayListChar(x,y,dis,4); //启始列,行,显示数组,显示长度
  287. }
  288. //*******************************************************************************************************
  289. //主程序
  290. //*******************************************************************************************************
  291. void main()
  292. {
  293. delay(500); //上电延时
  294. init_uart();
  295. InitMPU6050(); //初始化MPU6050
  296. delay(150);
  297. while(1)
  298. {
  299. SeriPushSend('A');  
  300. SeriPushSend(0x20);SeriPushSend('X'); SeriPushSend(':');
  301. Display10BitData(GetData(ACCEL_XOUT_H)); //显示X轴加速度
  302. SeriPushSend(0x20);SeriPushSend('Y'); SeriPushSend(':');
  303. Display10BitData(GetData(ACCEL_YOUT_H)); //显示Y轴加速度
  304. SeriPushSend(0x20);SeriPushSend('Z'); SeriPushSend(':');
  305. Display10BitData(GetData(ACCEL_ZOUT_H)); //显示Z轴加速度
  306. SeriPushSend(0x20);
  307. SeriPushSend('G');  
  308. SeriPushSend(0x20);SeriPushSend('X'); SeriPushSend(':');
  309. Display10BitData(GetData(GYRO_XOUT_H)); //显示X轴角速度
  310. SeriPushSend(0x20);SeriPushSend('Y'); SeriPushSend(':');
  311. Display10BitData(GetData(GYRO_YOUT_H)); //显示Y轴角速度
  312. SeriPushSend(0x20);SeriPushSend('Z'); SeriPushSend(':');
  313. Display10BitData(GetData(GYRO_ZOUT_H)); //显示Z轴角速度     
  314. SeriPushSend(0x0d);
  315. SeriPushSend(0x0a);//换行,回车
  316. delay(2000);
  317. }
  318. }
复制代码


三、使用keil烧写程序

四、测试

打开串口调试工具进行测试。

如果引脚接错会打印 -00001,正确打印信息如下图。

A 为三轴MEMS加速度计,G为三轴MEMS陀螺仪。挪动MPU6050模块,则数据变化。


评分

参与人数 1黑币 +50 收起 理由
admin + 50 共享资料的黑币奖励!

查看全部评分

分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏2 分享淘帖 顶 踩
回复

使用道具 举报

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

本版积分规则

小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

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