MS5611做D1、D2转换时,读出三个字节的AD值都是0。有用过这款芯片的朋友,麻烦指导一下,谢谢!

2019-07-20 10:33发布

我遇到的问题:
1. 因为读出的AD值都是0,转换过来的温度和的压力都是固定值 24.38℃,1017 mbar。
2. 读PROM时,我看网上 for (i=0;i<=6;i++),第一次循环,i = 0时,读校验值的高、低字节时收不到ack,其他的应有的ack都有收到,唯独这两次没有收到。不知道这个有没有影响,因为我看到网上有些读PROM是i=1开始的 for (i=1;i<=6;i++) ,也有从for (i=0;i<=6;i++)这样的,而且后面的校验方法都一样。不知道那个是对的?我读出的校验值是这样的。
Cal_C[0] = 65535
Cal_C[1] = 49510
Cal_C[2] = 50850
Cal_C[3] = 30456
Cal_C[4] = 27979
Cal_C[5] = 32325
Cal_C[6] = 27582


[mw_shl_code=applescript,true]#include"MS5611.h"
#include "BspUsart.h"

/*
C1 压力灵敏度 SENS|T1
C2  压力补偿  OFF|T1
C3        温度压力灵敏度系数 TCS
C4        温度系数的压力补偿 TCO
C5        参考温度 T|REF
C6         温度系数的温度 TEMPSENS
*/
uint16_t  Cal_C[7];                //用于存放PROM中的6组数据1-6

double OFF_;
float Aux;
/*
dT 实际和参考温度之间的差异
TEMP 实际温度       
*/
uint32_t dT,TEMP;
/*
OFF 实际温度补偿
SENS 实际温度灵敏度
*/
uint64_t OFf,SENS;
uint32_t D1_Pres,D2_Temp;        // 数字压力值,数字温度值

uint32_t Pressure,Pressure_old,qqp;                                //大气压
uint32_t TEMP2,T2,OFF2,SENS2;        //温度校验值


static void MS561101BA_EN(void)
{

         //配置LED灯
        GPIO_InitTypeDef GPIO_InitStructure;
        RCC_AHB1PeriphClockCmd(        RCC_AHB1Periph_GPIOB, ENABLE );         

          GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1;                        //LED
          GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;                  //推挽输出
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
          GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
                GPIO_Init(GPIOB, &GPIO_InitStructure);
       
                GPIO_SetBits(GPIOB,GPIO_Pin_1);
       
}



/*******************************************************************************
  * @函数名称        MS561101BA_RESET
  * @函数说明   使能MS5611模块
  * @输入参数   无
  * @输出参数   无
  * @返回参数   无
*******************************************************************************/
void MS561101BA_RESET(void)
{
                I2C_Start();
                I2C_Send_Byte(0xEE);//CSB接地,主机地址:0XEE,否则 0X77
          I2C_Wait_Ack();
    I2C_Send_Byte(0x1E);//发送复位命令
          I2C_Wait_Ack();
    I2C_Stop();
       
}
/*******************************************************************************
  * @函数名称        MS5611_init
  * @函数说明   初始化5611
  * @输入参数          无
  * @输出参数   无
  * @返回参数   无
*******************************************************************************/
u8 MS5611_init(void)
{         
  u8  inth,intl;
  int i;
         
         
        MS561101BA_EN();
        delay_ms(100);
         
        I2C_Init();
        delay_ms(100);
         
        MS561101BA_RESET();
        delay_ms(100);
         
  for (i=0;i<=6;i++)
        {

                I2C_Start();
    I2C_Send_Byte(0xEE);
                I2C_Wait_Ack();
                I2C_Send_Byte(0xA0 + (i*2));
                I2C_Wait_Ack();
    I2C_Stop();
                delay_us(5);
                I2C_Start();
                I2C_Send_Byte(0xEE+0x01);  //进入接收模式
                delay_us(1);
                I2C_Wait_Ack();
                inth = I2C_Read_Byte(1);                  //带ACK的读数据
                delay_us(1);
                intl = I2C_Read_Byte(0);                         //最后一个字节NACK
                I2C_Stop();
    Cal_C = (((uint16_t)inth << 8) | intl);
                printf("Cal_C[%d] = %d ",i,Cal_C);
        }
         return !Cal_C[0];
}


/**************************实现函数********************************************
*函数原型:unsigned long MS561101BA_getConversion(void)
*功  能:    读取 MS561101B 的转换结果
*******************************************************************************/
unsigned long MS561101BA_getConversion(uint8_t command)
{

                        unsigned long conversion = 0;
                        volatile u8 temp[3];
       
            I2C_Start();
                        I2C_Send_Byte(0xEE);                 //写地址
                        I2C_Wait_Ack();
                        I2C_Send_Byte(command); //写转换命令
                        I2C_Wait_Ack();
                        I2C_Stop();

                        delay_ms(100);
                        I2C_Start();
                        I2C_Send_Byte(0xEE);                 //写地址
                        I2C_Wait_Ack();
                        I2C_Send_Byte(0);                                // start read sequence
                        I2C_Wait_Ack();
                        I2C_Stop();
                 
                        delay_ms(100);
                        I2C_Start();
                        I2C_Send_Byte(0xEE+0x01);  //进入接收模式
                        I2C_Wait_Ack();
                        temp[0] = I2C_Read_Byte(1);  //带ACK的读数据  bit 23-16
                        temp[1] = I2C_Read_Byte(1);  //带ACK的读数据  bit 8-15
                        temp[2] = I2C_Read_Byte(0);  //带NACK的读数据 bit 0-7
                        I2C_Stop();
                       
                        conversion = (unsigned long)temp[0] * 65536 + (unsigned long)temp[1] * 256 + (unsigned long)temp[2];
                        return conversion;

}

/**************************实现函数********************************************
*函数原型:void MS561101BA_GetTemperature(void)
*功  能:    读取 温度转换结果
*******************************************************************************/

void MS561101BA_GetTemperature(void)
{
       
        D2_Temp = MS561101BA_getConversion(0x58);
        delay_ms(20);
        dT=D2_Temp - (((uint32_t)Cal_C[5])<<8);
        TEMP=2000+dT*((uint32_t)Cal_C[6])/8388608;
}

///***********************************************
//  * @brief  读取气压
//  * @param  NoneDDDDDD30
//  * @retval None
//************************************************/
void MS561101BA_getPressure(void)
{
        D1_Pres= MS561101BA_getConversion(0x48);
        delay_ms(20);
       
        OFF_=(uint32_t)Cal_C[2]*65536+((uint32_t)Cal_C[4]*dT)/128;
        SENS=(uint32_t)Cal_C[1]*32768+((uint32_t)Cal_C[3]*dT)/256;

        if(TEMP<2000)
        {
                Aux = (2000-TEMP)*(2000-TEMP);
                T2 = (dT*dT) / 0x80000000;
                OFF2 = 2.5f*Aux;
                SENS2 = 1.25f*Aux;
               
                TEMP = TEMP - T2;
                OFF_ = OFF_ - OFF2;
                SENS = SENS - SENS2;       
        }
       
  Pressure= (D1_Pres*SENS/2097152-OFF_)/32768;
       
}

#include "I2C.h"
#include "timer.h"

void I2C_Init(void)
{
  GPIO_InitTypeDef  GPIO_InitStructure;

  RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB, ENABLE);//使能GPIOA时钟

  //GPIOA11,A12初始化设置
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11 | GPIO_Pin_10;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;//普通输出模式
  GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;//推挽输出
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;//100MHz
  GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;//上拉
  GPIO_Init(GPIOB, &GPIO_InitStructure);//初始化
        I2C_SDA_H;
        I2C_SCL_H;
}

//void I2C_SDA_Out(void)
//{
//        GPIO_InitTypeDef GPIO_InitStructure;
//       
//  GPIO_InitStructure.GPIO_Pin = I2C_SDA;
//        GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
//        GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;  
//       
//        GPIO_Init(GPIOB,&GPIO_InitStructure);
//}
//void I2C_SDA_IN(void)
//{
//        GPIO_InitTypeDef GPIO_InitStructure;
//       
//  GPIO_InitStructure.GPIO_Pin = I2C_SDA;
//       
//        GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;  
//       
//        GPIO_Init(GPIOB,&GPIO_InitStructure);
//}

void I2C_Start(void)
{
        I2C_SDA_Out();
       
        I2C_SDA_H;
        I2C_SCL_H;
        delay_us(5);
        I2C_SDA_L;
        delay_us(6);
        I2C_SCL_L;       
}
void I2C_Stop(void)
{
        I2C_SDA_Out();
        I2C_SCL_L;
        I2C_SDA_L;
        I2C_SCL_H;
        delay_us(6);
        I2C_SDA_H;
        delay_us(6);
}
void I2C_Ack(void)
{
   I2C_SCL_L;
   I2C_SDA_Out();
   I2C_SDA_L;
   delay_us(2);
   I2C_SCL_H;
   delay_us(5);
   I2C_SCL_L;
}

//主机不产生应答信号NACK
void I2C_NAck(void)
{
   I2C_SCL_L;
   I2C_SDA_Out();
   I2C_SDA_H;
   delay_us(2);
   I2C_SCL_H;
   delay_us(5);
   I2C_SCL_L;
}
//等待从机应答信号
//返回值:1 接收应答失败
//                  0 接收应答成功
u8 I2C_Wait_Ack(void)
{
        u8 tempTime=0;

        I2C_SDA_IN();

        I2C_SDA_H;
        delay_us(1);
        I2C_SCL_H;
        delay_us(1);

        while(GPIO_ReadInputDataBit(GPIO_I2C,I2C_SDA))
        {
                tempTime++;
                if(tempTime>250)
                {
                        I2C_Stop();
                        return 1;
                }         
        }

        I2C_SCL_L;
        return 0;
}
//I2C 发送一个字节
void I2C_Send_Byte(u8 txd)
{
        u8 i=0;

        I2C_SDA_Out();
        I2C_SCL_L;//拉低时钟开始数据传输

        for(i=0;i<8;i++)
        {
                if((txd&0x80)>0) //0x80  1000 0000
                        I2C_SDA_H;
                else
                        I2C_SDA_L;

                txd<<=1;
                I2C_SCL_H;
                delay_us(2); //发送数据
                I2C_SCL_L;
                delay_us(2);
        }
}

//I2C 读取一个字节

u8 I2C_Read_Byte(u8 ack)
{
   u8 i=0,receive=0;

   I2C_SDA_IN();
   for(i=0;i<8;i++)
   {
                   I2C_SCL_L;
                delay_us(2);
                I2C_SCL_H;
                receive<<=1;
                if(GPIO_ReadInputDataBit(GPIO_I2C,I2C_SDA))
                   receive++;
                delay_us(1);       
   }

           if(ack==0)
                   I2C_NAck();
        else
                I2C_Ack();

        return receive;
}

[/mw_shl_code]
友情提示: 此问题已得到解决,问题已经关闭,关闭后问题禁止继续编辑,回答。
该问题目前已经被作者或者管理员关闭, 无法添加新回复
4条回答
Dwei03
1楼-- · 2019-07-20 14:27
xxssl
2楼-- · 2019-07-20 14:50
1、IIC为啥不是设置成开漏输出呢?当然不断切换IO输入输出也可以
2、for (i=0;i<=6;i++)只能得到Cal_C[0]-Cal_C[5]。你应该循环8次,得到Cal_C[0]-Cal_C[7],从而得到Cal_C[1]-Cal_C[6]。
3、u8 I2C_Wait_Ack(void)这个函数中
        if(tempTime>250)
        {
            I2C_Stop();
            return 1;
        }
直接跳出,会不会少一个时钟?或者I2C_Stop()结束了,后面的数据都无效了?
xxssl
3楼-- · 2019-07-20 16:00
 精彩回答 2  元偷偷看……
Dwei03
4楼-- · 2019-07-20 16:56
xxssl 发表于 2017-12-13 11:58
我用的是SPI接口,参考一下

我把OSR改成256,读出的AD值终于不是0,改成1024的话有时是0。OSR是 采样精度的意思吗?为何有这种情况的出现。

一周热门 更多>