OpenEdv-开源电子网

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

SHT30温湿度数据读取问题,急急急

[复制链接]

23

主题

94

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
1113
金钱
1113
注册时间
2016-8-26
在线时间
256 小时
发表于 2018-8-6 11:40:58 | 显示全部楼层 |阅读模式
10金钱
各位,最近我在调试sht30这个传感器,在读取温湿度数据时,遇到一个问题:读取数据时,总是只能读取第一个字节,后边的全是0XFF,如下图: 111.png
1、IIC驱动应该没问题,因为驱动程序可以操作AT24C02和OLED(IIC接口)。

2、但是问题如图中那样,只有温度的高8位数据算正常,后边的全是0XFF。
3、也测试过读取传感器ID,也是同样的现象。

4、请问这种现象,问题可能出在哪?

最佳答案

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

问题解决了。首先感谢坛友“pcbzy”的帮助。问题是Read_I2c()函数时序有点小问题。
正点原子逻辑分析仪DL16劲爆上市
回复

使用道具 举报

23

主题

94

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
1113
金钱
1113
注册时间
2016-8-26
在线时间
256 小时
 楼主| 发表于 2018-8-6 11:40:59 | 显示全部楼层
问题解决了。首先感谢坛友“pcbzy”的帮助。问题是Read_I2c()函数时序有点小问题。
回复

使用道具 举报

1

主题

25

帖子

0

精华

初级会员

Rank: 2

积分
101
金钱
101
注册时间
2018-5-19
在线时间
10 小时
发表于 2018-8-6 13:52:35 | 显示全部楼层
周期模式测量结果的读出前,一定要保证周期性数据采集模式测量命令先执行完毕,即先要保证有测量结果你才能去读它。
同时你确定一下,读取的第一个字节是不是固定为0x65?如果用手摸传感器,第一个读得的字节会不会改变?

可以加微信  baofeng_zouyu  聊更方便些
回复

使用道具 举报

0

主题

2

帖子

0

精华

新手入门

积分
8
金钱
8
注册时间
2019-6-29
在线时间
9 小时
发表于 2019-9-27 18:45:31 | 显示全部楼层
我也遇到同样问题,能贴出READ_I2C()函数看看嘛?
回复

使用道具 举报

23

主题

94

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
1113
金钱
1113
注册时间
2016-8-26
在线时间
256 小时
 楼主| 发表于 2019-9-29 10:45:13 | 显示全部楼层
nj786c 发表于 2019-9-27 18:45
我也遇到同样问题,能贴出READ_I2C()函数看看嘛?

这个是430单片机的代码
//IIC读取一个字节
u8 IIC_Read_Byte(u8 ack)
{   
    u8 i,receive=0;
    SDA_IN;//SDA设置为输入
    SCL_0;
    for(i=0;i<8;i++ )
    {
        SCL_1;
        delay_us(20);
        receive<<=1;
        if((SDA_INPUT & SDA) == SDA)
            receive |= 0x01;
        else
            receive &= 0xfe;
        SCL_0;
        delay_us(20);
    }
    if (!ack)
        IIC_NAck();//发送nACK
    else
        IIC_Ack(); //发送ACK   
    return receive;
}
回复

使用道具 举报

0

主题

4

帖子

0

精华

新手上路

积分
33
金钱
33
注册时间
2020-3-6
在线时间
10 小时
发表于 2020-3-13 09:43:23 | 显示全部楼层
void Read_sht30(void)    //读取
{          
  //unsigned char a=0;
  

  Cmd_Write_sht30(0x20,0x32); //数据采集频率1 m/s
  delay_ms(5000);
  IIC_Start();           //起始信号
  IIC_Send_Byte(0x88+1);         //发送设备地址+读信号
  while(IIC_Wait_Ack());
  BUFt[0]=IIC_Read_Byte(1);  //发送ACK
  BUFt[1]=IIC_Read_Byte(1);  //发送ACK
  //a=
  IIC_Read_Byte(1); //
  BUFh[0]=IIC_Read_Byte(1);  //发送ACK
  BUFh[1]=IIC_Read_Byte(1);  //发送ACK
  
  IIC_Stop();                          //发送停止信号
  delay_ms(20);
  
}


温度和湿度都没有出来
回复

使用道具 举报

0

主题

4

帖子

0

精华

新手上路

积分
33
金钱
33
注册时间
2020-3-6
在线时间
10 小时
发表于 2020-3-13 09:45:25 | 显示全部楼层
//IO方向设置
#define SDA_IN()        {P1DIR &= ~BIT6;}        //设置成输入状态
#define SDA_OUT()       {P1DIR |= BIT6;}       //设置成输出状态  

#define SDA_L()         P1OUT   &= ~BIT6
#define SDA_H()         P1OUT   |= BIT6
#define SDA_READ        ((P1IN << 6) & 0x01)

#define SCL_L()         P1OUT &= ~BIT7
#define SCL_H()         P1OUT |= BIT7

#define SDA_DIR_OUT     P1DIR |= BIT6
#define SDA_DIR_IN      P1DIR &= ~BIT6       


IC为msp432p401R ,用p1.6,1.7位I2c引脚,用模拟端口调试,不知道io口设置方向对不对?请大家指教
回复

使用道具 举报

23

主题

94

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
1113
金钱
1113
注册时间
2016-8-26
在线时间
256 小时
 楼主| 发表于 2020-3-16 11:09:11 | 显示全部楼层
wolf1235 发表于 2020-3-13 09:45
//IO方向设置
#define SDA_IN()        {P1DIR &= ~BIT6;}        //设置成输入状态
#define SDA_OUT()  ...

这是在我msp430f5438上通过的代码,看有木有帮助

//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
#ifndef __SHT3X_H__
#define __SHT3X_H__

#include <msp430x54x.h>

// CRC
#define POLYNOMIAL  0x131 // P(x) = x^8 + x^5 + x^4 + 1 = 100110001

#define  SHT30W   0x88
#define  SHT30R   0x89

#define   SDA_OUT       (P4DIR |= BIT1)   //p4.1=out/in
#define   SDA_IN          (P4DIR &=~BIT1)
#define   SDA_1           (P4OUT |= BIT1)
#define   SDA_0           (P4OUT &=~BIT1)
#define   SDA_INPUT     P4IN
#define   SDA                BIT1

#define   SCL_1           (P4OUT |= BIT2)   //p4.2=out
#define   SCL_0           (P4OUT &=~BIT2)
#define   SCL_IN          (P4DIR &=~BIT2)
#define   SCL_OUT       (P4DIR |= BIT2)

void IIC_Init(void);
void IIC_Start(void);
void IIC_Stop(void);
void IIC_Ack(void);
void IIC_NAck(void);
u8 IIC_Wait_Ack(void );
void IIC_Send_Byte(u8 data);
u8 Read_I2c(void);

u8 SHT3X_GetTempAndHumi(void);    //读取温湿度
u8 SHT3X_WriteCmd(u8 msb,u8 lsb);   //发送命令
u8 SHT3X_CheckCrc(u8 data[], u8 BytesNum, u8 rx_crc);



/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/******************************模拟IIC总线*************************************
//端口初始化
void IIC_Init(void)
{
    SCL_OUT;            //SCL管脚为输出
    SDA_OUT;            //SDA管脚为输出
    SCL_1;
    SDA_1;
}

//开始条件
void IIC_Start(void)        //scl为高电平期间,sda产生一个下降沿
{   
    SDA_OUT;              //sda线输出
    SDA_1;                    
    SCL_1;
    delay_us(20);
    SDA_0;          //START:when CLK is high,DATA change form high to low
    delay_us(20);
    SCL_0;          //钳住I2C总线,准备发送或接收数据
    delay_us(20);
}

//停止条件
void IIC_Stop(void)         //scl高电平期间,sda产生一上升沿
{  
    SDA_OUT;//sda线输出
    SCL_0;
    SDA_0;//STOP:when CLK is high DATA change form low to high
    delay_us(20);
    SCL_1;
    delay_us(20);
    SDA_1;//发送I2C总线结束信号
    delay_us(20);               
}

//单片机给传感器应答
void IIC_Ack(void)        
{
    SDA_OUT;
    SCL_OUT;

    SDA_0;
    //delay_us(20);
    SCL_0;  
    delay_us(20);
    SCL_1;
    delay_us(20);
    SCL_0;
    delay_us(20);
}

//单片机不给传感器应答
void IIC_NAck(void)      
{
    SDA_OUT;
    SDA_1;
    delay_us(20);
    SCL_1;
    delay_us(20);
    SCL_0;
    delay_us(20);
}


//等待应答信号到来
//返回值:1,接收应答失败
//        0,接收应答成功
u8 IIC_Wait_Ack(void)
{  
    u8 ucErrTime=0;
    SDA_IN;      //SDA设置为输入  
    SCL_1;delay_us(20);
                         
    while((SDA_INPUT&SDA) == SDA)
    {
        ucErrTime++;
        if(ucErrTime>250)
        {
            IIC_Stop();
            return 1;
        }
    }
    SCL_0;//时钟输出0
    delay_us(20);
    //SDA_0;delay_us(20);
    return 0;  
}
/*******************************************************************************
函数名称:IIC_Send_Byte
函数功能:向I2C总线写入一个字节数据
入口参数:待写入的数据data
出口参数:无
备    注:一个字节为8位,单片机分8次写入I2C总线
*******************************************************************************/
void IIC_Send_Byte(u8 data)
{  
    u8 t,temp;   
    SDA_OUT;             
    SCL_0;//拉低时钟开始数据传输
    for(t=0;t<8;t++)
    {              
        temp = data&0x80;
        if(temp == 0x80)
            SDA_1;              //判断发送位,送数据到数据线上
        else
            SDA_0;          
        delay_us(20);   //
        SCL_1;
        delay_us(20);
        SCL_0;       
        delay_us(20);
        data<<=1;
    }
    delay_us(20);
}

//读取1字节数据
u8 Read_I2c(void)
{
    SDA_IN;                             //置数据线为输入方向
    u8 i,q0;
    u8 byte=0;
    for(i=0;i<8;i++)
    {
        SCL_1;                          //置时钟为高电平,使数据线数据有效
        delay_us(20);
        byte=byte<<1;
        q0=(SDA_INPUT & SDA);
        if(q0==SDA)
            byte=(byte|0x01);           //将数据存入byte
        delay_us(20);
        SCL_0;
        delay_us(20);
    }
    SDA_0;
    delay_us(20);                 
    SCL_1;                              // clk #9 for IIC_Ack
    delay_us(20);                       // SCL high time (t_HIGH)
    SCL_0;
    delay_us(20);
    SDA_1;                              // release SDA-line
    delay_us(20);

    return(byte);
}

//IIC读取一个字节
u8 IIC_Read_Byte(u8 ack)
{   
    u8 i,receive=0;
    SDA_IN;//SDA设置为输入
    SCL_0;
    for(i=0;i<8;i++ )
    {
        SCL_1;
        delay_us(20);
        receive<<=1;
        if((SDA_INPUT & SDA) == SDA)
            receive |= 0x01;
        else
            receive &= 0xfe;
        SCL_0;
        delay_us(20);
    }
    if (!ack)
        IIC_NAck();//发送nACK
    else
        IIC_Ack(); //发送ACK   
    return receive;
}


//sht30获取温湿度
u8 SHT3X_GetTempAndHumi(void)
{
    int temp=0,humi=0;
    u8 BUFt[6]={0};
    u8 bytes[2];//收到的数据
    u8 checksum;//收到的crc
    u8 error = 0;

    IIC_Init();
    IIC_Start();               
    IIC_Send_Byte(SHT30W);           //地址+写
    //while(IIC_Wait_Ack());        //从机应答
    if(IIC_Wait_Ack())                        //从机应答
    {
        //进入这里表示sht30不存在或者通信故障,此时温湿度数据默认为0xFFFF
        return error = 1;
    }
    else
    {
        IIC_Send_Byte(0x22);        //发送0x2220,启动周期测量
        //while(IIC_Wait_Ack());
        //IIC_Wait_Ack();
        if(IIC_Wait_Ack())
        {
            return error =1;
        }
        IIC_Send_Byte(0x20);        
        //while(IIC_Wait_Ack());
        //IIC_Wait_Ack();
        if(IIC_Wait_Ack())
        {
            return error =1;
        }
        //IIC_Stop();               //周期读取sht30数据,按照时序图,不需要发送停止信号         
        delay_ms(2);                //此处延时必须要有,等待数据读取完成                  

        IIC_Start();               
        IIC_Send_Byte(SHT30W);      //地址+写
        //while(IIC_Wait_Ack());
        //IIC_Wait_Ack();       
        if(IIC_Wait_Ack())
        {
            return error =1;
        }
        IIC_Send_Byte(0xe0);        //0xE000,读取周期测量模式结果
        //while(IIC_Wait_Ack());
        //IIC_Wait_Ack();
        if(IIC_Wait_Ack())
        {
            return error =1;
        }
        IIC_Send_Byte(0x00);        
        //while(IIC_Wait_Ack());
        //IIC_Wait_Ack();
        if(IIC_Wait_Ack())
        {
            return error =1;
        }
        //IIC_Stop();               //周期读取sht30数据,按照时序图,不需要发送停止信号

        IIC_Start();               
        IIC_Send_Byte(SHT30R);      //地址+读
        //while(IIC_Wait_Ack());
        //IIC_Wait_Ack();
        if(IIC_Wait_Ack())
        {
            return error =1;
        }
        BUFt[0] = IIC_Read_Byte(1);        //温度高
        BUFt[1] = IIC_Read_Byte(1);        //温度低
        BUFt[2] = IIC_Read_Byte(1);        //crc
        BUFt[3] = IIC_Read_Byte(1);        //湿度高
        BUFt[4] = IIC_Read_Byte(1);        //湿度低
        BUFt[5] = IIC_Read_Byte(0);        //crc
        IIC_Stop();

        bytes[0] = BUFt[0];
        bytes[1] = BUFt[1];
        checksum = BUFt[2];
        temp = (BUFt[0]<<8) | BUFt[1];
        humi = (BUFt[3]<<8) | BUFt[4];
        if(!SHT3X_CheckCrc(bytes,2,checksum))   //校验通多,计算温度
        {
            temp = (int)(175*(float)temp / 65535 - 45);
            if(temp < -40)     temp = -40;
            if(temp > 125)     temp = 125;

        }
        bytes[0] = BUFt[3];
        bytes[1] = BUFt[4];
        checksum = BUFt[5];
        if(!SHT3X_CheckCrc(bytes,2,checksum))               //校验通多,计算湿度
        {
            humi = (u16)(100*(float)humi / 65535);
        }
    }
    return error;
}



回复

使用道具 举报

0

主题

4

帖子

0

精华

新手上路

积分
33
金钱
33
注册时间
2020-3-6
在线时间
10 小时
发表于 2020-3-16 13:24:27 | 显示全部楼层
你硬件上面外接上拉电阻了吗
回复

使用道具 举报

0

主题

4

帖子

0

精华

新手上路

积分
33
金钱
33
注册时间
2020-3-6
在线时间
10 小时
发表于 2020-3-16 13:24:54 | 显示全部楼层
谢谢您
回复

使用道具 举报

23

主题

94

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
1113
金钱
1113
注册时间
2016-8-26
在线时间
256 小时
 楼主| 发表于 2020-3-16 13:53:57 | 显示全部楼层
wolf1235 发表于 2020-3-16 13:24
你硬件上面外接上拉电阻了吗

SCL 和 SDA都接了4.7K电阻
回复

使用道具 举报

0

主题

1

帖子

0

精华

新手入门

积分
7
金钱
7
注册时间
2024-1-10
在线时间
2 小时
发表于 2024-1-10 23:50:20 | 显示全部楼层
pcbzy 发表于 2018-8-6 13:52
周期模式测量结果的读出前,一定要保证周期性数据采集模式测量命令先执行完毕,即先要保证有测量结果你才能 ...

您好,我也遇到了相同问题。能不能请教您一下,小白不是很懂
回复

使用道具 举报

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

本版积分规则



关闭

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

正点原子公众号

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

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

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

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