TLSR8258——IIC驱动SHT31温湿度传感器
I2C,由数据线 SDA 和时钟 SCL 构成的串⾏总线,可发送和接收数据,是半双⼯通信⽅式。时钟是由 master端提供控制的。
TLSR8258驱动SHT31温湿度传感器时,TLSR8258做主机端使用 i2c_master_init()函数 进行IIC初始化配置从机地址和时钟频率。
i2c_set_id(0函数:用于设置I2C模块的从机地址。
reset_i2c_moudle()函数:用于复位I2C模块。
i2c_write_series()函数:用于将数据包写入从属设备的指定地址。
i2c_read_series()函数:用于在从属设备的指定地址读取数据包。
温湿度传感器SHT31的地址字节,高7位是地址位,最后低1位是读写位。0 写;1 读
具体源码如下:
/*
* sht31_iic.c
*
* Created on: 2023-10-7
* Author: ZJ
* 温湿度传感器SHT31驱动
*/
#include "sht31_iic.h"
static float SHT3X_CalcHumidity(uint16_t rawValue);
static float SHT3X_CalcTemperature(uint16_t rawValue);
static etError SHT3X_CheckCrc(uint8_t data[], uint8_t nbrOfBytes, uint8_t checksum);
/*
* @brief:硬件IIC初始化
* */
void IIC_master_init(void)
{
i2c_gpio_set(I2C_GPIO_SDA_SCL);
i2c_master_init(SHT31_ADDRESS, (unsigned char)(CLOCK_SYS_CLOCK_HZ/(4*I2C_CLK_SPEED)) ); // 200KHz
}
/*
* @brief:IIC复位
* */
void IIC_master_RESET(void)
{
reset_i2c_moudle();
}
/*
* @brief:向SHT31写命令
* */
static etError SHT3x_WriteCommand(uint8_t device_id, uint16_t cmd)
{
static uint8_t tx_buf[2];
tx_buf[0] = (uint8_t)(cmd>>8);
tx_buf[1] = (uint8_t)(cmd & 0xFF);
i2c_set_id(device_id);
i2c_write_series(0, 0, (uint8_t*)tx_buf,sizeof(tx_buf));
return NO_ERROR;
}
/*
* @brief:读取单次测量模式温湿度数据,函数中会校验数据
* */
etError SHT3X_ReadSingleMeasurementBuffer(uint8_t *readbuff)
{
etError error;
float temperature;
float humidity;
static uint8_t bytes[6];
uint16_t t1,h1;
SHT3x_WriteCommand(SHT31_ADDRESS|0,CMD_MEAS_CLOCKSTR_H);
reg_i2c_mode |= FLD_I2C_HOLD_MASTER;// Enable clock stretching for Sensor
i2c_set_id(SHT31_ADDRESS);
i2c_read_series(SHT31_ADDRESS|1,1,(uint8_t*)bytes,6);
reg_i2c_mode &= ~FLD_I2C_HOLD_MASTER;// Disable clock stretching for Sensor
error = SHT3X_CheckCrc(bytes, 2, bytes[2]);
if(error == NO_ERROR)SHT3X_CheckCrc(&bytes[3], 2, bytes[5]);
if(error == NO_ERROR)
{
temperature = SHT3X_CalcTemperature((bytes[0] << 8) | bytes[1]); //计算温度
humidity = SHT3X_CalcHumidity((bytes[3] << 8) | bytes[4]); //计算湿度
t1 = (uint16_t)(temperature*100);
h1 = (uint16_t)(humidity*100);
// printf("t1:%d\r\n",t1);
// printf("h1:%d\r\n",h1);
readbuff[0] = (t1>>8)&0xff;
readbuff[1] = t1&0xff;
readbuff[2] = (h1>>8)&0xff;
readbuff[3] = h1&0xff;
}
return NO_ERROR;
}
/*
* @brief:CRC校验
* */
static uint8_t SHT3X_CalcCrc(uint8_t data[], uint8_t nbrOfBytes)
{
uint8_t bit; // bit mask
uint8_t crc = 0xFF; // calculated checksum
uint8_t byteCtr; // byte counter
for(byteCtr = 0; byteCtr < nbrOfBytes; byteCtr++)
{
crc ^= (data[byteCtr]);
for(bit = 8; bit > 0; --bit)
{
if(crc & 0x80) crc = (crc << 1) ^ POLYNOMIALSHT;
else crc = (crc << 1);
}
}
return crc;
}
/*
* @brief:检查校验是否正确
* */
static etError SHT3X_CheckCrc(uint8_t data[], uint8_t nbrOfBytes, uint8_t checksum)
{
uint8_t crc; // calculated checksum
crc = SHT3X_CalcCrc(data, nbrOfBytes);
if(crc != checksum) return CHECKSUM_ERROR;
else return NO_ERROR;
}
/*
* @brief:计算温度
* */
static float SHT3X_CalcTemperature(uint16_t rawValue)
{
return 175.0f * (float)rawValue / 65535.0f - 45.0f;
}
/*
* @brief:计算湿度
* */
static float SHT3X_CalcHumidity(uint16_t rawValue)
{
return 100.0f * (float)rawValue / 65535.0f;
}
/*
* sht31_iic.h
*
* Created on: 2023-10-7
* Author: ZJ
*/
#ifndef SHT31_IIC_H_
#define SHT31_IIC_H_
#include "global.h"
#define I2C_GPIO_SDA_SCL I2C_GPIO_GROUP_C0C1
#define I2C_CLK_SPEED 200000
#define SHT31_ADDRESS 0x44<<1
//CRC多项式
#define POLYNOMIALSHT 0x131 // P(x) = x^8 + x^5 + x^4 + 1 = 100110001
typedef enum{
NO_ERROR = 0x00, // no error
ACK_ERROR = 0x01, // no acknowledgment error
CHECKSUM_ERROR = 0x02, // checksum mismatch error
TIMEOUT_ERROR = 0x04, // timeout error
PARM_ERROR = 0x80, // parameter out of range error
}etError;
typedef enum{
CMD_READ_SERIALNBR = 0x3780, // read serial number
CMD_READ_STATUS = 0xF32D, // read status register
CMD_CLEAR_STATUS = 0x3041, // clear status register ?
CMD_HEATER_ENABLE = 0x306D, // enabled heater
CMD_HEATER_DISABLE = 0x3066, // disable heater
CMD_SOFT_RESET = 0x30A2, // soft reset ?
CMD_MEAS_CLOCKSTR_H = 0x2C06, // meas. clock stretching, high rep.
CMD_MEAS_CLOCKSTR_M = 0x2C0D, // meas. clock stretching, medium rep.
CMD_MEAS_CLOCKSTR_L = 0x2C10, // meas. clock stretching, low rep.
CMD_MEAS_POLLING_H = 0x2400, // meas. no clock stretching, high rep.
CMD_MEAS_POLLING_M = 0x240B, // meas. no clock stretching, medium rep.
CMD_MEAS_POLLING_L = 0x2416, // meas. no clock stretching, low rep.
CMD_MEAS_PERI_05_H = 0x2032, // meas. periodic 0.5 mps, high rep.
CMD_MEAS_PERI_05_M = 0x2024, // meas. periodic 0.5 mps, medium rep.
CMD_MEAS_PERI_05_L = 0x202F, // meas. periodic 0.5 mps, low rep.
CMD_MEAS_PERI_1_H = 0x2130, // meas. periodic 1 mps, high rep.
CMD_MEAS_PERI_1_M = 0x2126, // meas. periodic 1 mps, medium rep.
CMD_MEAS_PERI_1_L = 0x212D, // meas. periodic 1 mps, low rep.
CMD_MEAS_PERI_2_H = 0x2236, // meas. periodic 2 mps, high rep.
CMD_MEAS_PERI_2_M = 0x2220, // meas. periodic 2 mps, medium rep.
CMD_MEAS_PERI_2_L = 0x222B, // meas. periodic 2 mps, low rep.
CMD_MEAS_PERI_4_H = 0x2334, // meas. periodic 4 mps, high rep.
CMD_MEAS_PERI_4_M = 0x2322, // meas. periodic 4 mps, medium rep.
CMD_MEAS_PERI_4_L = 0x2329, // meas. periodic 4 mps, low rep.
CMD_MEAS_PERI_10_H = 0x2737, // meas. periodic 10 mps, high rep.
CMD_MEAS_PERI_10_M = 0x2721, // meas. periodic 10 mps, medium rep.
CMD_MEAS_PERI_10_L = 0x272A, // meas. periodic 10 mps, low rep.
CMD_FETCH_DATA = 0xE000, // readout measurements for periodic mode
CMD_R_AL_LIM_LS = 0xE102, // read alert limits, low set
CMD_R_AL_LIM_LC = 0xE109, // read alert limits, low clear
CMD_R_AL_LIM_HS = 0xE11F, // read alert limits, high set
CMD_R_AL_LIM_HC = 0xE114, // read alert limits, high clear
CMD_W_AL_LIM_LS = 0x6100, // write alert limits, low set
CMD_W_AL_LIM_LC = 0x610B, // write alert limits, low clear
CMD_W_AL_LIM_HS = 0x611D, // write alert limits, high set
CMD_W_AL_LIM_HC = 0x6116, // write alert limits, high clear
CMD_NO_SLEEP = 0x303E,
}etCommands;
void IIC_master_init(void);
void IIC_master_RESET(void);
etError SHT3X_ReadSingleMeasurementBuffer(uint8_t *readbuff);
#endif /* SHT31_IIC_H_ */