目录
概述
1 硬件接口介绍
2 SHT20模块
2.1 SHT20简介
2.2 SHT-20模块电路
3 I2C接口实现
3.1 FSP配置I2C
3.2 I2C驱动程序实现
4 SHT20驱动程序
4.1 SHT20驱动代码结构
4.2 源代码文件
5 测试
5.1 测试功能介绍
5.2 测试代码实现
5.3 运行代码
概述
本文主要介绍使用Renesas R7FA8D1BH (Cortex®-M85)控制SHT20的相关内容,包括SHT20的特性,使用FSP配置Renesas R7FA8D1BH的I2C接口,i2c驱动程序,还介绍了一个简单的应用案例:实时读取SHT20的温湿度数据,显示在OLED上。
1 硬件接口介绍
SHT2X与Renesas R7FA8D1BH通过I2C接口连接起来,其接口关系如下:
2 SHT20模块
2.1 SHT20简介
SHT20是由Sensirion公司推出的一款数字温湿度传感器。它采用先进的CMOSens®技术,具有高精度、低功耗和长期稳定性的特点。
SHT20的测量范围涵盖了-40℃至125℃的温度和0%至100%的湿度,精确度分别为±0.3℃和±3%RH。它使用了数字式输出接口,可以通过I2C总线进行数据通信,并支持温度和湿度的实时测量。
SHT20的封装形式小巧,尺寸为3x3x1.1mm,适合各种应用场景。它具有低功耗特性,工作电压范围为2.1V至3.6V,供电电流在典型条件下为1.2mA。此外,SHT20还具有快速响应时间和强大的抗干扰能力。
2.2 SHT-20模块电路
1)SHT20硬件接口图
2) sensor模块电路
SHT-20实物图:
3 I2C接口实现
3.1 FSP配置I2C
1) 在Pins面板上配置I2C IO port
2) 创建Stack对象
3)配置Stack的参数
3.2 I2C驱动程序实现
使用FSP完成参数配置后,生成硬件相关的配置代码,接下来需要实现I2C相关的驱动接口
1)创建bsp_i2c.c文件,编写如下代码
/*
FILE NAME : bsp_i2c.c
Description: user i2c interface
Author : tangmingfei2013@126.com
Date : 2024/06/03
*/
#include "bsp_i2c.h"
#include "hal_data.h"
#define TIME_OUT 10000
i2c_master_event_t g_i2c_callback_event;
void sci_b_i2c_master_callback (i2c_master_callback_args_t * p_args)
{
if (NULL != p_args)
{
g_i2c_callback_event = p_args->event;
}
}
void i2c2_init_para( uint32_t const slaveAddress )
{
fsp_err_t err;
err = R_SCI_B_I2C_Open(&g_i2c0_ctrl, &g_i2c0_cfg);
assert(FSP_SUCCESS == err);
err = R_SCI_B_I2C_SlaveAddressSet(&g_i2c0_ctrl, slaveAddress, I2C_MASTER_ADDR_MODE_7BIT);
assert(FSP_SUCCESS == err);
}
void i2c2_write_bytes(uint8_t *pbuff, uint16_t length )
{
unsigned int timeout_ms = TIME_OUT;
fsp_err_t err;
err = R_SCI_B_I2C_Write(&g_i2c0_ctrl, pbuff, length, false);
assert(FSP_SUCCESS == err);
g_i2c_callback_event = I2C_MASTER_EVENT_ABORTED;
/* Since there is nothing else to do, block until Callback triggers*/
while ((I2C_MASTER_EVENT_TX_COMPLETE != g_i2c_callback_event) && timeout_ms)
{
R_BSP_SoftwareDelay(1U, BSP_DELAY_UNITS_MILLISECONDS);
timeout_ms--;;
}
}
void i2c2_read_bytes(uint8_t *pbuff, uint16_t length )
{
unsigned int timeout_ms = TIME_OUT;
fsp_err_t err;
g_i2c_callback_event = I2C_MASTER_EVENT_ABORTED;
err = R_SCI_B_I2C_Read(&g_i2c0_ctrl, pbuff, length, false);
assert(FSP_SUCCESS == err);
/* Since there is nothing else to do, block until Callback triggers*/
while ((I2C_MASTER_EVENT_RX_COMPLETE != g_i2c_callback_event) && timeout_ms)
{
R_BSP_SoftwareDelay(1U, BSP_DELAY_UNITS_MILLISECONDS);
timeout_ms--;;
}
}
/* End of this file */
2)创建bsp_i2c.h文件,编写如下代码:
/*
FILE NAME : bsp_i2c.h
Description: user i2c interface
Author : tangmingfei2013@126.com
Date : 2024/06/03
*/
#ifndef BSP_I2C_H
#define BSP_I2C_H
#include "hal_data.h"
void i2c2_init_para( uint32_t const slaveAddress );
void i2c2_write_bytes(uint8_t *pbuff, uint16_t length );
void i2c2_read_bytes(uint8_t *pbuff, uint16_t length );
#endif /* BSP_I2C_H */
4 SHT20驱动程序
4.1 SHT20驱动代码结构
1)写寄存器函数
2)读寄存器函数
3)sensor初始化函数
4)获取温度值函数
5) 获取湿度值函数
4.2 源代码文件
1)创建sht2x.c文件,编写如下代码
/*
FILE NAME : sht2x.c
Description: user sht20 interface
Author : tangmingfei2013@126.com
Date : 2024/06/03
*/
#include "hal_data.h"
#include "sht2x.h"
/******************************************************************************
* LOCAL MACROS AND DEFINITIONS
******************************************************************************/
#define SHT2X_ADDR 0x40
#define POLY 0x131 //P(x)=x^8+x^5+x^4+1 = 100110001
#define DELAY_CNT 4500 //for N32G45, sleep time is 6.4 ms
#define QUERY_TEMP_CMD TRIG_T_MEASUREMENT_HM
#define QUERY_HUMIDY_CMD TRIG_RH_MEASUREMENT_HM
static void msleep(unsigned int time)
{
uint16_t i;
for (i = 0; i < time; i++);
}
static int sht2xdrv_CheckCrc(unsigned char data[], unsigned char nbrOfBytes, unsigned char checksum)
{
uint16_t res = 0;
uint16_t crc = 0;
uint16_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 int sht2xdrv_CalcTemperatureC(int u16sT)
{
int 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 = ((17572 * u16sT) >> 16) - 4685;
return temperatureC;
}
static int sht2xdrv_CalcRH(int u16sRH)
{
int 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 = ((12500 * u16sRH) >> 16) - 600;
return humidityRH;
}
static uint8_t write_reg( uint8_t *buff, uint8_t len )
{
fsp_err_t err;
err = R_SCI_B_I2C_SlaveAddressSet( &g_i2c0_ctrl,
SHT2X_ADDR,
I2C_MASTER_ADDR_MODE_7BIT);
assert(FSP_SUCCESS == err);
i2c2_write_bytes(buff, len);
return 0;
}
static uint8_t read_regs(uint8_t reg, uint8_t *buf, uint8_t len)
{
fsp_err_t err;
uint8_t msgs[2];
err = R_SCI_B_I2C_SlaveAddressSet( &g_i2c0_ctrl,
SHT2X_ADDR,
I2C_MASTER_ADDR_MODE_7BIT);
assert(FSP_SUCCESS == err);
msgs[0] = reg;
i2c2_write_bytes(msgs, 1);
i2c2_read_bytes( buf, len);
return 0;
}
int sht2x_softreset( void )
{
int ret = -1;
unsigned char buf[2] = {0};
unsigned char cmd = SOFT_RESET;
buf[0] = cmd;
ret = write_reg(buf, 1);
if( ret < 0 )
{
printf("%s %s write softrest cmd to sht2x failure \n", __FILE__, __FUNCTION__);
return -1;
}
msleep(50);
return 0;
}
int sht2x_get_temperature( float *temper)
{
unsigned char buf[4] = {0}, checksum;
int ret = -1;
int tempval;
ret = read_regs(QUERY_TEMP_CMD, buf, 3);
if( ret < 0 )
{
printf("get the temper failure.\n");
return -1;
}
// match crc here
checksum = buf[2];
ret = sht2xdrv_CheckCrc(buf, 2, checksum);
if( ret < 0 )
{
printf("match check sum error.\n");
return -1;
}
tempval = (buf[0] << 8) | buf[1];
*temper = (float)sht2xdrv_CalcTemperatureC( tempval );
return 0;
}
int sht2x_get_humidy( float *humidy )
{
unsigned char buf[4] = {0}, checksum;
int ret = -1;
int tempval;
ret = read_regs(QUERY_HUMIDY_CMD, buf, 3);
if( ret < 0 )
{
printf("get the humidy failure.\n");
return -1;
}
// match crc here
checksum = buf[2];
ret = sht2xdrv_CheckCrc(buf, 2, checksum);
if( ret < 0 )
{
printf("match check sum error.\n");
return -1;
}
tempval = (buf[0] << 8) | buf[1];
*humidy = (float)sht2xdrv_CalcRH( tempval );
return 0;
}
void sht2x_Init( void )
{
fsp_err_t err;
err = R_SCI_B_I2C_SlaveAddressSet( &g_i2c0_ctrl,
SHT2X_ADDR,
I2C_MASTER_ADDR_MODE_7BIT);
assert(FSP_SUCCESS == err);
sht2x_softreset();
}
2)创建sht2x.h文件,编写如下代码
/*
FILE NAME : sht2x.h
Description: user sht20 interface
Author : tangmingfei2013@126.com
Date : 2024/06/03
*/
#ifndef __SHT20_H
#define __SHT20_H
#ifdef __cplusplus
extern "C" {
#endif
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <errno.h>
#include <assert.h>
#include <string.h>
#include <time.h>
typedef enum sht2xOptErrorCode
{
SHT2x_RES_I2C_ERR = 0X01,
}sht2xOptErrorCode;
/******************************************************************************
* EXPORTED MACROS AND DEFINITIONS
******************************************************************************/
typedef enum sht2xResolution_t
{
SHT2x_RES_12_14BIT = 0x00, // RH=12bit, T=14bit
SHT2x_RES_8_12BIT = 0x01, // RH= 8bit, T=12bit
SHT2x_RES_10_13BIT = 0x80, // RH=10bit, T=13bit
SHT2x_RES_11_11BIT = 0x81, // RH=11bit, T=11bit
SHT2x_RES_MASK = 0x81 // Mask for res. bits (7,0) in user reg.
} sht2xResolution_t;
typedef enum sht2xStatusCode {
SHT2x_STATUS_OK = 0x00,
SHT2x_STATUS_VALID_DATA = 0x01,
SHT2x_STATUS_NO_CHANGE = 0x02,
SHT2x_STATUS_ABORTED = 0x03,
SHT2x_STATUS_BUSY = 0x04,
SHT2x_STATUS_SUSPEND = 0x05,
SHT2x_STATUS_ERR_IO = 0x06,
SHT2x_STATUS_ERR_BAD_DATA = 0x07,
SHT2x_STATUS_ERR_TIMEOUT = 0x08
}sht2xStatusCode;
// sensor command
typedef enum{
TRIG_T_MEASUREMENT_HM = 0xE3, // command trig. temp meas. hold master
TRIG_RH_MEASUREMENT_HM = 0xE5, // command trig. humidity meas. hold master
TRIG_T_MEASUREMENT_POLL = 0xF3, // command trig. temp meas. no hold master
TRIG_RH_MEASUREMENT_POLL = 0xF5, // command trig. humidity meas. no hold master
USER_REG_W = 0xE6, // command writing user register
USER_REG_R = 0xE7, // command reading user register
SOFT_RESET = 0xFE // command soft reset
}sht2xCommand_t;
typedef enum {
SHT2x_EOB_ON = 0x40, // end of battery
SHT2x_EOB_MASK = 0x40, // Mask for EOB bit(6) in user reg.
} sht2xEob_t;
typedef enum {
SHT2x_HEATER_ON = 0x04, // heater on
SHT2x_HEATER_OFF = 0x00, // heater off
SHT2x_HEATER_MASK = 0x04, // Mask for Heater bit(2) in user reg.
} etSHT2xHeater;
// measurement signal selection
typedef enum{
HUMIDITY,
TEMP
}etSHT2xMeasureType;
typedef enum{
I2C_ADR_W = 128, // sensor I2C address + write bit
I2C_ADR_R = 129 // sensor I2C address + read bit
}etI2cHeader;
typedef struct {
unsigned char _step;
unsigned char ret;
unsigned char finish; //1: finished, 0: idle
unsigned char dataValid; //1: valid, 0: invalid
int _tryCnt;
int _binValue; // primordial value from sht20 register
int outValue; // true temperature or humidity
} shtdrv;
typedef struct {
shtdrv st_Temp;
shtdrv st_RH;
int errorCode;
}shtOpt;
void sht2x_Init( void );
int sht2x_get_humidy( float *humidy );
int sht2x_get_temperature( float *temper);
#ifdef __cplusplus
}
#endif
#endif /* __SHT20_H */
5 测试
5.1 测试功能介绍
1) 实时读取SHT2X的数据,并将数据转换为温度和湿度值
2)采样间隔为1 second
3) 在OLED上实时显示温度和湿度数据
5.2 测试代码实现
代码189行: 获取RTC时间值
代码190行:判断1s时间间隔
代码193行:获取湿度数据
代码194行:获取温度数据
代码198~209: 在OLED上实时显示温度和湿度数据
5.3 运行代码
测试环境如下:
编译代码,并将代码下载到板卡中,其运行结果如下: