stm32Fxx 驱动sht20 温湿度传感器

2019-07-20 03:21发布

本帖最后由 mftang2016 于 2017-12-1 22:44 编辑

//系统硬件接口
PH4 -------I2C2_SCL
PH5--------I2C2_SDA

微信图片_20171201224057.jpg
测试结果如下图:(注释:得到温湿度数据被放大100倍,换算成实际值需要乘以0.01)
360截图20171128222646958.jpg

和硬件相关接口代码:

#define I2C_GPIO_CLK_ENABLE()           __HAL_RCC_GPIOH_CLK_ENABLE()
#define I2C_GPIO_CLK_DISABLE()          __HAL_RCC_GPIOH_CLK_DISABLE()

#define GPIO_PORT_I2C         GPIOH
#define I2C_SCL_PIN                GPIO_PIN_4                        
#define I2C_SDA_PIN                GPIO_PIN_5

#define I2C_SCL_1()  HAL_GPIO_WritePin( GPIO_PORT_I2C, I2C_SCL_PIN, GPIO_PIN_SET)       /* SCL = 1 */
#define I2C_SCL_0()  HAL_GPIO_WritePin( GPIO_PORT_I2C, I2C_SCL_PIN, GPIO_PIN_RESET)        /* SCL = 0 */

#define I2C_SDA_1()  HAL_GPIO_WritePin( GPIO_PORT_I2C, I2C_SDA_PIN, GPIO_PIN_SET)         /* SDA = 1 */
#define I2C_SDA_0()  HAL_GPIO_WritePin( GPIO_PORT_I2C, I2C_SDA_PIN, GPIO_PIN_RESET)        /* SDA = 0 */

#define I2C_SDA_READ()  ((GPIO_PORT_I2C->IDR & I2C_SDA_PIN) != 0)        /* read SDA status */
#define I2C_SCL_READ()  ((GPIO_PORT_I2C->IDR & I2C_SCL_PIN) != 0)        /* read SCLs tatus */


void  board_i2cInit( void )
{
    GPIO_InitTypeDef  GPIO_InitStruct;

    /* Enable the GPIO_I2C clock */
    I2C_GPIO_CLK_ENABLE();

    /* Configure the GPIO_I2C pin */
    GPIO_InitStruct.Pin = I2C_SCL_PIN|I2C_SDA_PIN;
    GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_OD;
    GPIO_InitStruct.Pull = GPIO_PULLUP;
    GPIO_InitStruct.Speed = GPIO_SPEED_FAST;

    HAL_GPIO_Init(GPIO_PORT_I2C, &GPIO_InitStruct);
}

相关文档 Sensirion_Humidity_SHT20_Datasheet_V3_8395437268751607934.pdf (573.72 KB, 下载次数: 217) 2017-11-28 22:21 上传 点击文件名下载附件

完整驱动代码:
sht2x.zip (7.49 KB, 下载次数: 362) 2017-11-28 22:10 上传 点击文件名下载附件

关键代码:应用i2c 驱动sht20
sht20 driver
[mw_shl_code=c,true]/**
  ******************************************************************************
  * @file    BSP/Components/sht2x.c
  * @Author  mingfei tang
  * @brief   Main program body
  ******************************************************************************
  * @attention
  *
  * <h2><center>&#169; COPYRIGHT(c) 2017 STMicroelectronics</center></h2>
  *
  * Redistribution and use in source and binary forms, with or without modification,
  * are permitted provided that the following conditions are met:
  *   1. Redistributions of source code must retain the above copyright notice,
  *      this list of conditions and the following disclaimer.
  *   2. Redistributions in binary form must reproduce the above copyright notice,
  *      this list of conditions and the following disclaimer in the documentation
  *      and/or other materials provided with the distribution.
  *   3. Neither the name of STMicroelectronics nor the names of its contributors
  *      may be used to endorse or promote products derived from this software
  *      without specific prior written permission.
  *
  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  *
  ******************************************************************************
  */

/* Includes ------------------------------------------------------------------*/
#include "stm32f4xx_hal.h"
#include "adafruit_i2c.h"
#include "sht2x.h"

/* Private typedef -----------------------------------------------------------*/

/* Private define ------------------------------------------------------------*/
#define I2C_ADDRESS (0x40 << 1)
#define POLY  0x131;  //P(x)=x^8+x^5+x^4+1 = 100110001

/* Private macro -------------------------------------------------------------*/
/* Private variables ---------------------------------------------------------*/
/* Private function prototypes -----------------------------------------------*/
/* Private functions ---------------------------------------------------------*/
static void i2c_Delay(uint16_t value );
static uint8_t sht2xdrv_CheckCrc(uint8_t data[], uint8_t nbrOfBytes, uint8_t checksum);
static uint8_t SHT2X_CheckOk(void);
static int32_t sht2xdrv_CalcTemperatureC(uint16_t u16sT);
static int32_t sht2xdrv_CalcRH(uint16_t u16sRH);

static void i2c_Delay(uint16_t value )
{
    uint16_t i;
    for (i = 0; i < value; i++);
}

static uint8_t sht2xdrv_CheckCrc(uint8_t data[], uint8_t nbrOfBytes, uint8_t checksum)
{
    uint8_t res = 0;
    uint8_t crc = 0;
    uint8_t byteCtr;
   
    //calculates 8-Bit checksum with given polynomial
    for (byteCtr = 0; byteCtr < nbrOfBytes; ++byteCtr)
    {
      crc ^= (data[byteCtr]);
      for (uint8_t bit = 8; bit > 0; --bit)
      {
        if (crc & 0x80)
        {
          crc = (crc << 1) ^ POLY;
        }
        else
        {
          crc = (crc << 1);
        }
      }
    }

    if (crc != checksum)
    {
      res = 1;
    }

    return res;
}

static uint8_t SHT2X_CheckOk(void)
{
    if (i2c_CheckDevice( I2C_ADDRESS ) == 0)
    {
         /* sensor is online*/
            return 1;
    }
    else
    {
          /* fail: send stop */
            i2c_Stop();
            return 0;
    }
}

static uint8_t sht2xdrv_ReadUserRegister( uint8_t *pRegisterValue )
{
    uint8_t ret = SHT2x_STATUS_OK;
    uint8_t cmd = USER_REG_R;
    i2c_Start();
   
    i2c_SendByte( I2C_ADDRESS | I2C_WR );  // Device address
    if (i2c_WaitAck() != 0)
    {
        goto cmd_fail;
    }
   
    i2c_SendByte( cmd);
    if (i2c_WaitAck() != 0)
    {
        goto cmd_fail;
    }
   
    //Read
    i2c_Start();
    i2c_SendByte(I2C_ADDRESS | I2C_RD);
    if (i2c_WaitAck() != 0)
    {
        goto cmd_fail;
    }
   
    *pRegisterValue = i2c_ReadByte();
    i2c_NAck();
   
    i2c_Stop();
    return ret;
   
cmd_fail:   
    i2c_Stop();
    ret = SHT2x_STATUS_ERR_BAD_DATA;
   
    return ret;
}

static int32_t sht2xdrv_CalcTemperatureC(uint16_t u16sT)
{
  int32_t temperatureC;       // variable for result

  u16sT &= ~0x0003;           // clear bits [1..0] (status bits)

  /*
     * Formula T = -46.85 + 175.72 * ST / 2^16 from data sheet 6.2,
     * optimized for integer fixed point (3 digits) arithmetic
     */

  temperatureC = (((uint32_t)17572 * u16sT) >> 16) - 4685;

  return (int32_t)temperatureC;
}

static int32_t sht2xdrv_CalcRH(uint16_t u16sRH)
{
  uint32_t humidityRH;       // variable for result

  u16sRH &= ~0x0003;          // clear bits [1..0] (status bits)

  /*
     * Formula RH = -6 + 125 * SRH / 2^16 from data sheet 6.1,
     * optimized for integer fixed point (3 digits) arithmetic
     */

  humidityRH = (((uint32_t)12500 * u16sRH) >> 16) - 600;

  return (int32_t)humidityRH;
}

uint8_t  sht2xdrv_GetTemp( int32_t *pMeasurand )
{
    uint8_t ret = SHT2x_STATUS_OK;
    uint8_t checksum;                   //checksum
    uint16_t rawdata;
    uint8_t cmd = TRIG_T_MEASUREMENT_HM;
    uint8_t data[3] = {0, 0, 0};        //data array for checksum v
   
    i2c_Start();
    i2c_SendByte( I2C_ADDRESS | I2C_WR );  // Device address
    if (i2c_WaitAck() != 0)
    {
        goto cmd_fail;
    }
   
    i2c_Delay( 100 );
    i2c_SendByte( cmd);
    if (i2c_WaitAck() != 0)
    {
        goto cmd_fail;
    }
   
    //Read
    i2c_Start();
    i2c_SendByte(I2C_ADDRESS | I2C_RD);
    if (i2c_WaitAck() != 0)
    {
        goto cmd_fail;
    }
   
    HAL_Delay( 70 );
    data[0] = i2c_ReadByte();
    i2c_Ack();        
    data[1] = i2c_ReadByte();
    i2c_Ack();        
    data[2] = i2c_ReadByte();
    i2c_NAck();
  
    i2c_Stop();
   
    rawdata = ((uint16_t)data[0] << 8) | data[1];
    checksum = data[2];

    ret = sht2xdrv_CheckCrc(data, 2, checksum);   
    if (ret != SHT2x_STATUS_OK)
    {
        return ret;
    }
    *pMeasurand = sht2xdrv_CalcTemperatureC(rawdata);
   
cmd_fail:
    i2c_Stop();
   
    return ret;
}

uint8_t  sht2xdrv_GetRH( int32_t *pMeasurand )
{
    uint8_t ret = SHT2x_STATUS_OK;
    uint8_t checksum;   //checksum
    uint16_t rawdata;
    uint8_t cmd = TRIG_RH_MEASUREMENT_POLL;
    uint8_t data[3] = {0, 0, 0}; //data array for checksum v
   
    i2c_Start();
    i2c_SendByte( I2C_ADDRESS | I2C_WR );  // Device address
    if (i2c_WaitAck() != 0)
    {
        goto cmd_fail;
    }
   
    i2c_SendByte( cmd);
    if (i2c_WaitAck() != 0)
    {
        goto cmd_fail;
    }
   
    //Read
    i2c_Start();
    HAL_Delay( 100 );
    i2c_SendByte(I2C_ADDRESS | I2C_RD);
    if (i2c_WaitAck() != 0)
    {
        goto cmd_fail;
    }
   
    HAL_Delay( 100 );
    data[0] = i2c_ReadByte();
    i2c_Ack();        
    data[1] = i2c_ReadByte();
    i2c_Ack();        
    data[2] = i2c_ReadByte();
    i2c_NAck();
     
    i2c_Stop();
   
    rawdata = ((uint16_t)data[0] << 8) | data[1];
    checksum = data[2];

    ret = sht2xdrv_CheckCrc(data, 2, checksum);   
    if (ret != SHT2x_STATUS_OK)
    {
        return ret;
    }
    *pMeasurand = sht2xdrv_CalcRH(rawdata);
   
cmd_fail:
    i2c_Stop();
   
    return ret;
}

uint8_t  sht2xdrv_ResetSht2x( void )
{
    uint8_t ret = SHT2x_STATUS_OK;
    uint8_t cmd = SOFT_RESET;
   
    i2c_Start();
    i2c_SendByte( I2C_ADDRESS | I2C_WR );  // Device address
    if (i2c_WaitAck() != 0)
    {
        goto cmd_fail;
    }
   
    i2c_SendByte( cmd);
    if (i2c_WaitAck() != 0)
    {
        goto cmd_fail;
    }
   
cmd_fail:
    i2c_Stop();
    ret = SHT2x_STATUS_ERR_TIMEOUT;
   
    return ret;
}

uint8_t  sht2xdrv_GetBatteryStatus(void)
{
  uint8_t reg;
  uint8_t error = SHT2x_STATUS_OK;

  error = sht2xdrv_ReadUserRegister(&#174;);

  if (error != SHT2x_STATUS_OK)
  {
    return error;
  }

  return (reg & 0x40);
}

uint8_t sht2xdrv_GetHeaterStatus(void)
{
  uint8_t reg;
  uint8_t error = SHT2x_STATUS_OK;

  error = sht2xdrv_ReadUserRegister(&#174;);

  if (error != SHT2x_STATUS_OK)
  {
    return error;
  }

  return (reg & 0x04);
}

uint8_t sht2xdrv_GetResolution(sht2xResolution_t *pResolution)
{
    uint8_t error = SHT2x_STATUS_OK;
    uint8_t reg = 0;

    error = sht2xdrv_ReadUserRegister(&#174;);
    if (error != SHT2x_STATUS_OK)
    {
        return error;
    }

    *pResolution = (sht2xResolution_t)(reg & SHT2x_RES_MASK);
    return error;
}

uint8_t regVal;
static int32_t s_TempData;
static int32_t s_RhData;
sht2xResolution_t sht2xResolutionvalue;
void SHT2X_test( void )
{
    i2c_Init();
    SHT2X_CheckOk();
    sht2xdrv_GetBatteryStatus();
   
    sht2xdrv_GetResolution( &sht2xResolutionvalue );
   
    sht2xdrv_GetTemp( &s_TempData );
    sht2xdrv_GetRH( &s_RhData );
}

/* End of this file */[/mw_shl_code]

i2c 部分
[mw_shl_code=c,true]/**
  ******************************************************************************
  * @file    BSP/Armfly_Discovery/armfly_i2c.c
  * @author  mingfei tang
  * @brief   Main program body
  ******************************************************************************
  * @attention
  *
  * <h2><center>&#169; COPYRIGHT(c) 2017 STMicroelectronics</center></h2>
  *
  * Redistribution and use in source and binary forms, with or without modification,
  * are permitted provided that the following conditions are met:
  *   1. Redistributions of source code must retain the above copyright notice,
  *      this list of conditions and the following disclaimer.
  *   2. Redistributions in binary form must reproduce the above copyright notice,
  *      this list of conditions and the following disclaimer in the documentation
  *      and/or other materials provided with the distribution.
  *   3. Neither the name of STMicroelectronics nor the names of its contributors
  *      may be used to endorse or promote products derived from this software
  *      without specific prior written permission.
  *
  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  *
  ******************************************************************************
  */
/* Includes ------------------------------------------------------------------*/
#include "stm32f4xx_hal.h"
#include "armfly_board.h"
#include "adafruit_i2c.h"

/* Private typedef -----------------------------------------------------------*/
/* Private define ------------------------------------------------------------*/
/* Private macro -------------------------------------------------------------*/
/* Private variables ---------------------------------------------------------*/
/* Private function prototypes -----------------------------------------------*/
/* Private functions ---------------------------------------------------------*/
  
static void i2c_Delay(void)
{
    uint8_t i;
    for (i = 0; i < 30; i++);
}

void i2c_Init(void)
{
    board_i2cInit();  /* i2c port init */
    i2c_Stop();
}

void i2c_Start(void)
{
    I2C_SDA_1();
    I2C_SCL_1();
    i2c_Delay();
    I2C_SDA_0();
    i2c_Delay();
    I2C_SCL_0();
    i2c_Delay();
}


void i2c_Stop(void)
{
    I2C_SDA_0();
    I2C_SCL_1();
    i2c_Delay();
    I2C_SDA_1();
}

void i2c_SendByte(uint8_t _ucByte)
{
    uint8_t i;

    for (i = 0; i < 8; i++)
    {
          if (_ucByte & 0x80)
          {
                  I2C_SDA_1();
          }
          else
          {
                  I2C_SDA_0();
          }
          i2c_Delay();
          I2C_SCL_1();
          i2c_Delay();
          I2C_SCL_0();
          if (i == 7)
          {
                   I2C_SDA_1();
          }
          _ucByte <<= 1;
          i2c_Delay();
    }
}


uint8_t i2c_ReadByte(void)
{
    uint8_t i;
    uint8_t value;

    value = 0;
    for (i = 0; i < 8; i++)
    {
        value <<= 1;
        I2C_SCL_1();
        i2c_Delay();
        if (I2C_SDA_READ())
        {
                value++;
        }
        I2C_SCL_0();
        i2c_Delay();
    }

    return value;
}

/**
  * @brief  wait for i2c ack.
* @retval result:
  */
i2c_TypeDef i2c_WaitAck(void)
{
    i2c_TypeDef re = I2C_OK;

    I2C_SDA_1();        
    i2c_Delay();
    I2C_SCL_1();        
    i2c_Delay();
    if (I2C_SDA_READ())
    {
        re = I2C_FAIL;
    }
    I2C_SCL_0();
    i2c_Delay();
   
    return re;
}

void i2c_Ack(void)
{
    I2C_SDA_0();
    i2c_Delay();
    I2C_SCL_1();
    i2c_Delay();
    I2C_SCL_0();
    i2c_Delay();
    I2C_SDA_1();
}


void i2c_NAck(void)
{
    I2C_SDA_1();        
    i2c_Delay();
    I2C_SCL_1();
    i2c_Delay();
    I2C_SCL_0();
    i2c_Delay();
}

i2c_TypeDef i2c_CheckDevice(uint8_t _Address)
{
    i2c_TypeDef ucAck = I2C_FAIL;

    if (I2C_SDA_READ() && I2C_SCL_READ())
    {
        i2c_Start();               

        i2c_SendByte(_Address | I2C_WR);
        ucAck = i2c_WaitAck();        

        i2c_Stop();
    }
   
    return ucAck;
}

/* End of this file */[/mw_shl_code]




友情提示: 此问题已得到解决,问题已经关闭,关闭后问题禁止继续编辑,回答。
该问题目前已经被作者或者管理员关闭, 无法添加新回复
8条回答
mftang2016
1楼-- · 2019-07-20 05:53
 精彩回答 2  元偷偷看……
mftang2016
2楼-- · 2019-07-20 10:45
历史帖更新:

360截图20180715194200937.jpg
mftang2016
3楼-- · 2019-07-20 12:43
 精彩回答 2  元偷偷看……
正点原子
4楼-- · 2019-07-20 12:59
谢谢分享
mftang2016
5楼-- · 2019-07-20 17:44
正点原子 发表于 2018-7-30 01:08
谢谢分享

哥们,你太拼了,晚上1点钟还在回复帖子
mftang2016
6楼-- · 2019-07-20 19:12
 精彩回答 2  元偷偷看……

一周热门 更多>