注册 登录
查看: 1571|回复: 23

K60硬件I2C读取气压高度计MS5611高度计,麻烦看一下,谢谢!

[复制链接]
发表于 2014-9-5 21:21:23 | 显示全部楼层 |阅读模式
本帖最后由 快乐的味道1992 于 2014-9-5 21:25 编辑

最近在用GY-86模块,读取MS5611气压高度传感器时,读不出数据,不知道为什么?我把山外I2C文件中读字节宏修改成这样了:#define i2c_write_byte(I2Cn,data)   (I2C_D_REG(I2CN[I2Cn]) = (data))//;i2c_Wait(I2Cn)  所以每次读/写,需要加:i2c_Wait(I2Cn)。这是因为MS5611内部无寄存器,而山外的I2C库代需要知道寄存器地址才能读/写,所以需要根据山外I2C库定义的i2c宏函数驱动MS5611!下面是我写的代码不能读数,但当我把void MS561101BA_PROM_READ(I2Cn_e i2cn,uint16* C1,uint16* C2,uint16* C3,uint16* C4,uint16* C5,uint16* C6)和uint32 MS561101BA_DO_CONVERSION(I2Cn_e i2cn,uint8 command)函数里的i2c_Wait(I2Cn)注释掉时,每次按下复位键数据只能更新一次,能够读数据,而且模块放在不同位置,气压高度值在变化!该怎样修改下面的代码(代码中没有虚假读),谢谢!关于GY-86模块资料在附件中,另外附件中还有个STM32读取MS5611程序,是在某个论坛里找的,由于文件太大只能上传个别C文件。
  1. //MS561101BA复位
  2. void MS561101BA_RESET(I2Cn_e i2cn)
  3. {     
  4.   i2c_Start(i2cn);                                               //发送启动信号
  5.   i2c_write_byte(i2cn, MS561101BA_ADDRESS);      //发送从机地址和写位
  6.   i2c_Wait(i2cn);                                                //等待接收完成
  7.   DELAY_US(100);
  8.   
  9.   i2c_write_byte(i2cn, MS561101BA_RST);                          //发送RESET指令
  10.   i2c_Wait(i2cn);                                                //等待接收完成
  11.   DELAY_US(100);
  12.   
  13.   i2c_Stop(i2cn);
  14. }

  15. //从PROM读取出厂校准数据
  16. void MS561101BA_PROM_READ(I2Cn_e i2cn,uint16* C1,uint16* C2,uint16* C3,uint16* C4,uint16* C5,uint16* C6)
  17. {
  18.   uint16 d1,d2;
  19.   uint8 i;
  20.   uint16 Cal_C[6];  //用于存放PROM中的6组数据
  21.   for(i=0;i<6;i++)
  22.    {
  23.      i2c_Start(i2cn);                                               //发送启动信号
  24.      i2c_write_byte(i2cn, MS561101BA_ADDRESS);      //发送从机地址和写位
  25.      i2c_Wait(i2cn);                                                //等待接收完成
  26.      
  27.      i2c_write_byte(i2cn, MS561101BA_PROM_RD+i*2);
  28.      i2c_Wait(i2cn);                                                //等待接收完成
  29.      
  30.      i2c_Start(i2cn);                                               //发送启动信号
  31.      i2c_write_byte(i2cn, MS561101BA_ADDRESS+0x01);      //发送从机地址和读位
  32.      i2c_Wait(i2cn);                                                //等待接收完成
  33.      
  34.      d1=I2C_D_REG(I2CN[i2cn]);                                      //读高字节  
  35.      d2=I2C_D_REG(I2CN[i2cn]);                                     //读低字节
  36.      i2c_Stop(i2cn);
  37.      //DELAY_MS(10);
  38.      Cal_C=(d1<<8)|d2;
  39.    }
  40.   *C1 = Cal_C[0];
  41.   *C2 = Cal_C[1];
  42.   *C3 = Cal_C[2];
  43.   *C4 = Cal_C[3];
  44.   *C5 = Cal_C[4];
  45.   *C6 = Cal_C[5];
  46.   //打印PROM读取出厂校准数据,检测数据传输是否正常
  47.   //printf("C1 =%d\n",Cal_C[0]);
  48.   //printf("C2 =%d\n",Cal_C[1]);
  49.   //printf("C3 =%d\n",Cal_C[2]);
  50.   //printf("C4 =%d\n",Cal_C[3]);
  51.   //printf("C5 =%d\n",Cal_C[4]);
  52.   //printf("C6 =%d\n",Cal_C[5]);
  53. }

  54. uint32 MS561101BA_DO_CONVERSION(I2Cn_e i2cn,uint8 command)
  55. {
  56.   uint32 conversion=0;
  57.   uint32 conv1,conv2,conv3;
  58.   
  59.   i2c_Start(i2cn);          //发送启动信号
  60.   i2c_write_byte(i2cn, MS561101BA_ADDRESS);
  61.   i2c_Wait(i2cn);                                                //等待接收完成
  62.   
  63.   i2c_write_byte(i2cn,command);
  64.   i2c_Wait(i2cn);                                                //等待接收完成
  65.   i2c_Stop(i2cn);
  66.   
  67.   //DELAY_MS(20);  
  68.   
  69.   i2c_Start(i2cn);          //发送启动信号
  70.   i2c_write_byte(i2cn, MS561101BA_ADDRESS);
  71.   i2c_Wait(i2cn);                                                //等待接收完成
  72.   
  73.   i2c_write_byte(i2cn,0x00);
  74.   i2c_Wait(i2cn);                                                //等待接收完成
  75.   i2c_Stop(i2cn);


  76.   i2c_Start(i2cn);          //发送启动信号
  77.   i2c_write_byte(i2cn, MS561101BA_ADDRESS+0x01);      //发送从机地址和读位
  78.   i2c_Wait(i2cn);                                                //等待接收完成
  79.   
  80.   conv1=I2C_D_REG(I2CN[i2cn]);
  81.   conv2=I2C_D_REG(I2CN[i2cn]);
  82.   conv3=I2C_D_REG(I2CN[i2cn]);
  83.   i2c_Stop(i2cn);
  84.   
  85.   conversion= (conv1<<16) + (conv2<<8) + conv3;
  86.   return conversion;
  87. }
  88. //我把以上的代码放在山外K60MK60_i2c.c文件中
  89. /**********************************以下是MS5611使用的函数*******************************************/
  90. #include "ms5611.h"
  91. #include "common.h"
  92. #include "MK60_i2c.h"
  93. #include "MK60_uart.h"

  94. uint8 exchange_Pres_num[8];//压力数据
  95. uint8 exchange_Temp_num[8];//温度数据

  96. uint16 PROM_data[6];  //用于存放PROM中的6组数据
  97. uint32 D1_Pres,D2_Temp; // 存放数字压力和温度

  98. float dT,Temperature,Temperature2;//实际和参考温度之间的差异,实际温度,中间值
  99. double OFF,SENS;  //实际温度抵消,实际温度灵敏度

  100. //读取数字温度
  101. float MS561101BA_GetTemperature(uint8 OSR_Temp)
  102. {
  103.   D2_Temp= MS561101BA_DO_CONVERSION(MS561101BA_I2C_Moudle, OSR_Temp);  
  104.   DELAY_MS(10);
  105.   
  106.   dT=D2_Temp - (((uint32)PROM_data[5])<<8);
  107.   Temperature=2000+dT*((uint32)PROM_data[6])/8388608.0;
  108.   return Temperature;
  109. }

  110. //读取数字气压
  111. float MS561101BA_GetPressure(uint8 OSR_Pres)
  112. {
  113.   float Pressure;        //温度补偿大气压
  114.   float Aux,OFF2,SENS2;  //温度校验值  
  115.   D1_Pres= MS561101BA_DO_CONVERSION(MS561101BA_I2C_Moudle, OSR_Pres);
  116.   
  117.   DELAY_MS(10);
  118.   
  119.   OFF=(uint32)(PROM_data[2]<<16)+((uint32)PROM_data[4]*dT)/128.0;
  120.   SENS=(uint32)(PROM_data[1]<<15)+((uint32)PROM_data[3]*dT)/256.0;
  121.   //温度补偿
  122.   if(Temperature < 2000)// second order temperature compensation when under 20 degrees C
  123.   {
  124.     Temperature2 = (dT*dT) / 0x80000000;
  125.     Aux = (Temperature-2000)*(Temperature-2000);
  126.     OFF2 = 2.5*Aux;
  127.     SENS2 = 1.25*Aux;
  128.     if(Temperature < -1500)
  129.     {
  130.       Aux = (Temperature+1500)*(Temperature+1500);
  131.       OFF2 = OFF2 + 7*Aux;
  132.       SENS2 = SENS + 5.5*Aux;
  133.     }
  134.   }
  135.   else  //(Temperature > 2000)
  136.   {
  137.     Temperature2 = 0;
  138.     OFF2 = 0;
  139.     SENS2 = 0;
  140.   }
  141.   Temperature = Temperature - Temperature2;
  142.   OFF = OFF - OFF2;
  143.   SENS = SENS - SENS2;  
  144.   Pressure=(D1_Pres*SENS/2097152.0-OFF)/32768.0;
  145.   return Pressure;
  146. }

  147. void MS561101BA_Init(void)
  148. {
  149.   MS561101BA_RESET(MS561101BA_I2C_Moudle);
  150.   //DELAY_MS(100);
  151.   MS561101BA_PROM_READ(MS561101BA_I2C_Moudle,&PROM_data[0],&PROM_data[1],&PROM_data[2],&PROM_data[3],&PROM_data[4],&PROM_data[5]);
  152.   //DELAY_MS(100);
  153. }

MS5611头文件:
  1. #ifndef __MS5611_H__
  2. #define __MS5611_H__

  3. #include "common.h"

  4. #define  MS561101BA_D1 0x40
  5. #define  MS561101BA_D2 0x50
  6. #define  MS561101BA_RST 0x1E

  7. //#define  MS561101BA_D1_OSR_256 0x40
  8. //#define  MS561101BA_D1_OSR_512 0x42
  9. //#define  MS561101BA_D1_OSR_1024 0x44
  10. //#define  MS561101BA_D1_OSR_2048 0x46
  11. #define  MS561101BA_D1_OSR_4096 0x48

  12. //#define  MS561101BA_D2_OSR_256 0x50
  13. //#define  MS561101BA_D2_OSR_512 0x52
  14. //#define  MS561101BA_D2_OSR_1024 0x54
  15. //#define  MS561101BA_D2_OSR_2048 0x56
  16. #define  MS561101BA_D2_OSR_4096 0x58

  17. #define  MS561101BA_ADC_RD 0x00
  18. #define  MS561101BA_PROM_RD 0xA0
  19. #define  MS561101BA_PROM_CRC 0xAE

  20. #define  MS561101BA_I2C_Moudle      I2C0
  21. #define  MS561101BA_SlaveAddress    0xee  //定义器件在IIC总线中的从地址
  22. #define  MS561101BA_ADDRESS         MS561101BA_SlaveAddress

  23. float MS561101BA_GetTemperature(uint8 OSR_Temp);
  24. float MS561101BA_GetPressure(uint8 OSR_Pres);
  25. void MS561101BA_Init(void);
  26. //void Exchange_Number(void);

  27. #endif








本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?注册

x
回复

使用道具 举报

发表于 2014-9-5 21:36:47 | 显示全部楼层
读不出数据,得示波器测测波形,然后对比手册的波形,看看差异在哪里
回复 支持 反对

使用道具 举报

 楼主| 发表于 2014-9-5 21:38:30 | 显示全部楼层
山外メ雲ジ 发表于 2014-9-5 21:36
读不出数据,得示波器测测波形,然后对比手册的波形,看看差异在哪里

我把等待应答加到函数里就会出现一直等待应答信号这种情况
回复 支持 反对

使用道具 举报

发表于 2014-9-5 21:39:34 | 显示全部楼层
快乐的味道1992 发表于 2014-9-5 21:38
我把等待应答加到函数里就会出现一直等待应答信号这种情况

有没有用示波器看过时序图?
另外,I2C 一次读写后,需要隔一段时间才能进行第二次读写操作
回复 支持 反对

使用道具 举报

 楼主| 发表于 2014-9-5 21:39:50 | 显示全部楼层
山外メ雲ジ 发表于 2014-9-5 21:36
读不出数据,得示波器测测波形,然后对比手册的波形,看看差异在哪里

附件中有个模拟I2C读取MS5611是其他论坛里用STM32搞出来的,软件模拟I2C
回复 支持 反对

使用道具 举报

发表于 2014-9-5 21:40:30 | 显示全部楼层
I2C,这东西,需要调的,单独提高代码,没测过时序图,不好说是什么原因。
例如 外部是否有加上拉电阻?
回复 支持 反对

使用道具 举报

 楼主| 发表于 2014-9-5 21:40:45 | 显示全部楼层
山外メ雲ジ 发表于 2014-9-5 21:39
有没有用示波器看过时序图?
另外,I2C 一次读写后,需要隔一段时间才能进行第二次读写操作

没有看时序,实验室示波器让老师借走了,MS5611需要连续读取数据!
回复 支持 反对

使用道具 举报

 楼主| 发表于 2014-9-5 21:41:55 | 显示全部楼层
格拉姆 发表于 2014-9-5 21:40
I2C,这东西,需要调的,单独提高代码,没测过时序图,不好说是什么原因。
例如 外部是否有加上拉电阻?

我是参考别人用软件模拟I2C的代码,移植过来的,变成了K60硬件I2C,就出现问题了
回复 支持 反对

使用道具 举报

 楼主| 发表于 2014-9-5 21:42:49 | 显示全部楼层
格拉姆 发表于 2014-9-5 21:40
I2C,这东西,需要调的,单独提高代码,没测过时序图,不好说是什么原因。
例如 外部是否有加上拉电阻?

这还是个一个成品的模块,附件中有原理图,已经加上了上啦电阻
回复 支持 反对

使用道具 举报

发表于 2014-9-5 21:43:53 | 显示全部楼层
快乐的味道1992 发表于 2014-9-5 21:42
这还是个一个成品的模块,附件中有原理图,已经加上了上啦电阻

这里仅仅是举例说明,很多细节问题,不是看代码就可以解决的。所以想办法找个示波器或者逻辑分析仪。

回复 支持 反对

使用道具 举报

 楼主| 发表于 2014-9-5 21:45:05 | 显示全部楼层
山外メ雲ジ 发表于 2014-9-5 21:39
有没有用示波器看过时序图?
另外,I2C 一次读写后,需要隔一段时间才能进行第二次读写操作

你以前搞过这个芯片吗?我是用这个模块做多旋翼飞行器的,麻烦看下MS5611的芯片文档,里面有中文,谢谢了!
回复 支持 反对

使用道具 举报

 楼主| 发表于 2014-9-5 21:46:50 | 显示全部楼层
快乐的味道1992 发表于 2014-9-5 21:45
你以前搞过这个芯片吗?我是用这个模块做多旋翼飞行器的,麻烦看下MS5611的芯片文档,里面有中文,谢谢了 ...

飞控板用的是K60
回复 支持 反对

使用道具 举报

 楼主| 发表于 2014-9-5 21:48:55 | 显示全部楼层
山外メ雲ジ 发表于 2014-9-5 21:39
有没有用示波器看过时序图?
另外,I2C 一次读写后,需要隔一段时间才能进行第二次读写操作

那连续读取时要加延时,还用虚假读吗?
回复 支持 反对

使用道具 举报

发表于 2014-9-5 21:51:56 | 显示全部楼层
快乐的味道1992 发表于 2014-9-5 21:45
你以前搞过这个芯片吗?我是用这个模块做多旋翼飞行器的,麻烦看下MS5611的芯片文档,里面有中文,谢谢了 ...

我没搞过这东西,如果你软件I2C可以,那可以直接用软件I2C。

硬件I2C,当初我们也是调了很久的。
回复 支持 反对

使用道具 举报

 楼主| 发表于 2014-9-5 21:56:39 | 显示全部楼层
山外メ雲ジ 发表于 2014-9-5 21:51
我没搞过这东西,如果你软件I2C可以,那可以直接用软件I2C。

硬件I2C,当初我们也是调了很久的。

软件I2C我也搞过了,但是没成功,所以就换成硬件了,GY-86是个10轴传感器,三轴重力加速度,三轴陀螺仪集成在MPU6050里,三轴地磁场传感器HMC5883L,这两个都用K60硬件读取成功了,都是用你的例程里I2C读写字节函数搞出来的,但是唯独最后一轴高度没有读出来,因为该芯片内部没有微控制器,所以不能操作寄存器读写数据
回复 支持 反对

使用道具 举报

 楼主| 发表于 2014-9-5 21:57:34 | 显示全部楼层
快乐的味道1992 发表于 2014-9-5 21:56
软件I2C我也搞过了,但是没成功,所以就换成硬件了,GY-86是个10轴传感器,三轴重力加速度,三轴陀螺仪集 ...

高度就是用MS5611气压高度计芯片
回复 支持 反对

使用道具 举报

 楼主| 发表于 2014-9-5 22:00:27 | 显示全部楼层
山外メ雲ジ 发表于 2014-9-5 21:51
我没搞过这东西,如果你软件I2C可以,那可以直接用软件I2C。

硬件I2C,当初我们也是调了很久的。

连续读取时要加延时,在开始读数据时还用虚假读吗?每次读写都得等待应答吗?库里面说连续读是需要加这个:
//进入接收模式(应答,需要接收多个数据,接收最后一个字节前需要禁用应答i2c_DisableAck)
#define i2c_EnterRxMode(I2Cn)       I2C_C1_REG(I2CN[I2Cn]) &= ~(I2C_C1_TX_MASK | I2C_C1_TXAK_MASK)  //
接收最后一个字节禁用应答

回复 支持 反对

使用道具 举报

发表于 2014-9-5 22:01:16 | 显示全部楼层
快乐的味道1992 发表于 2014-9-5 21:56
软件I2C我也搞过了,但是没成功,所以就换成硬件了,GY-86是个10轴传感器,三轴重力加速度,三轴陀螺仪集 ...

这个我还真的不知道怎么搞,没有测时序的话,不知道哪里出问题。
回复 支持 反对

使用道具 举报

 楼主| 发表于 2014-9-5 22:08:00 | 显示全部楼层
山外メ雲ジ 发表于 2014-9-5 22:01
这个我还真的不知道怎么搞,没有测时序的话,不知道哪里出问题。

以前在山外我行123注册的账号在现在这个论坛可以用吗?
回复 支持 反对

使用道具 举报

 楼主| 发表于 2014-9-5 22:09:02 | 显示全部楼层
山外メ雲ジ 发表于 2014-9-5 22:01
这个我还真的不知道怎么搞,没有测时序的话,不知道哪里出问题。

芯片文档里有操作时序,但是那个操作时序看得不太明白
回复 支持 反对

使用道具 举报

 楼主| 发表于 2014-9-5 22:12:26 | 显示全部楼层
山外メ雲ジ 发表于 2014-9-5 22:01
这个我还真的不知道怎么搞,没有测时序的话,不知道哪里出问题。

关于加速度计的校正,你知道怎么校正吗?有的人最小二乘法校正,但不是知道你有没有相关的最小二乘法的资料关于校正加速度计的
回复 支持 反对

使用道具 举报

发表于 2014-9-5 22:20:16 | 显示全部楼层
快乐的味道1992 发表于 2014-9-5 22:08
以前在山外我行123注册的账号在现在这个论坛可以用吗?

凡2014年08月24日前在山外-vcan123论坛注册的帐号,都可以直接登录我们的论坛。
回复 支持 反对

使用道具 举报

发表于 2014-9-6 21:13:49 | 显示全部楼层
快乐的味道1992 发表于 2014-9-5 21:48
那连续读取时要加延时,还用虚假读吗?

I2C 读数据,连续读,也是需要虚假读的。你分析一下代码,其实跟I2C的时序操作是对应的
回复 支持 反对

使用道具 举报

发表于 2015-7-30 16:02:24 | 显示全部楼层
你好,问下有没有解决你的问题?能不能把你改后的源码给我一份?谢谢了
回复 支持 反对

使用道具 举报

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

本版积分规则

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