BLE_DCF_TYQ_CH592F/BSP/src/bsp_gxhtc3c.c

207 lines
5.0 KiB
C
Raw Normal View History

2025-06-04 12:54:03 +08:00
/*
* @Author : stark1898y 1658608470@qq.com
* @Date : 2025-06-04 11:18:42
* @LastEditors : stark1898y 1658608470@qq.com
* @LastEditTime : 2025-06-04 12:16:03
* @FilePath : \BLE_TYQ_CH584M\BSP\src\bsp_gxhtc3c.c
* @Description :
*
* Copyright (c) 2025 by yzy, All Rights Reserved.
*/
#include "bsp_gxhtc3c.h"
#include "bsp_soft_i2c.h"
#include "bsp_uart.h"
#include "log.h"
#undef LOG_ENABLE
#define LOG_ENABLE 1
#define LOG_LVL LOG_DEBUG
#undef LOG_TAG
#define LOG_TAG "gxhtc3c"
// GXHTC3C_CMD_LOW_CLK_STRE_OFF_HUMI_FRONT
void _GXHTC3C_SendCmd(uint16_t cmd)
{
int ret;
uint8_t i2c_tx_data[2];
i2c_tx_data[0] = HI_UINT16(cmd);
i2c_tx_data[1] = LO_UINT16(cmd);
// ret = I2C_Write(GXHTC3C_ADDR, (const uint8_t *)&i2c_tx_data, 2, true, true);
// logDebug("_GXHTC3C_SendCmd %s", ret ? "failed" : "success");
IIC_Init();
// 发送测量命令
IIC_Start();
IIC_Send_Byte(GXHTC3C_ADDR << 1); // 发送写命令(设备地址 + 写位)
if (IIC_Wait_Ack())
{
IIC_Stop();
return; // 如果没有收到应答,停止
}
IIC_Send_Byte(i2c_tx_data[0]); // 发送测量命令
if (IIC_Wait_Ack())
{
IIC_Stop();
return; // 如果没有收到应答,停止
}
IIC_Send_Byte(i2c_tx_data[1]); // 发送测量命令
if (IIC_Wait_Ack())
{
IIC_Stop();
return; // 如果没有收到应答,停止
}
IIC_Stop();
}
void _GXHTC3C_Sleep(void)
{
_GXHTC3C_SendCmd(GXHTC3C_CMD_SLEEP);
IIC_Deinit();
}
void _GXHTC3C_Wakeup(void)
{
_GXHTC3C_SendCmd(GXHTC3C_CMD_WAKEUP);
}
void _GXHTC3C_GetStart(void)
{
// 低功耗、Clock stretching关闭、湿度在前
_GXHTC3C_SendCmd(GXHTC3C_CMD_LOW_CLK_STRE_OFF_HUMI_FRONT);
}
// 定义CRC-8参数
#define POLYNOMIAL 0x31 // 生成多项式x8+x5+x4+1 (省略最高位1)
#define INIT_VALUE 0xFF // 初始化值
#define REFLECT_IN false // 不反射输入
#define REFLECT_OUT false // 不反射输出
uint8_t _GXHTC3C_CRC_8(uint8_t *p_crc, uint8_t len)
{
uint8_t crc = INIT_VALUE;
for (size_t i = 0; i < len; ++i)
{
crc ^= p_crc[i]; // 异或当前字节
for (uint8_t j = 0; j < 8; ++j)
{
if (crc & 0x80)
{ // 如果最高位是1
crc = (crc << 1) ^ POLYNOMIAL; // 左移一位并异或多相式
}
else
{
crc <<= 1; // 否则只左移一位
}
// 确保crc保持在8位内
crc &= 0xFF;
}
}
// 最终返回CRC值
return crc;
}
// GXHTC3C_CMD_LOW_CLK_STRE_OFF_HUMI_FRONT
uint8_t GXHTC3C_GetTempHumi(float *humi, float *temp)
{
int ret;
uint8_t i2c_rx_data[6];
// 重新启动I2C并设置为读模式
IIC_Start();
IIC_Send_Byte((GXHTC3C_ADDR << 1) | 1); // 设备地址 + 读位
if (IIC_Wait_Ack())
{
IIC_Stop();
logError("read failed");
return 1; // 如果没有收到应答,停止
}
for (uint8_t i = 0; i < 6; i++)
{
i2c_rx_data[i] = IIC_Read_Byte(i != 5); // 读取6个字节
}
IIC_Stop();
IIC_Deinit();
// logHexDumpAll(i2c_rx_data, 6);
// 低功耗、Clock stretching关闭、湿度在前
uint8_t humi_raw_data[2];
uint8_t temp_raw_data[2];
humi_raw_data[0] = i2c_rx_data[0];
humi_raw_data[1] = i2c_rx_data[1];
uint16_t raw_humi = (humi_raw_data[0] << 8) | humi_raw_data[1];
uint8_t crc_humi = _GXHTC3C_CRC_8(humi_raw_data, 2);
temp_raw_data[0] = i2c_rx_data[3];
temp_raw_data[1] = i2c_rx_data[4];
uint16_t raw_temp = (temp_raw_data[0] << 8) | temp_raw_data[1];
uint8_t crc_temp = _GXHTC3C_CRC_8(temp_raw_data, 2);
if ((crc_humi == i2c_rx_data[2]) && (crc_temp == i2c_rx_data[5]))
{
// logDebug("crc ok");
// logHexDumpAll(i2c_rx_data, 6);
*humi = (100.0 * raw_humi) / 65536.0; // 湿度真实值
*temp = (175.0 * raw_temp) / 65536.0 - 45.0; // 温度真实值
// logDebug("humi %f, temp %f", *humi, *temp);
}
else
{
logHexDumpAll(i2c_rx_data, 6);
logError("crc_temp 0x%02x, crc_humi 0x%02x", crc_temp, crc_humi);
logError("crc error");
return 2;
}
// logDebug("0 success");
return 0;
}
int BSP_ReadTempHumi(float *humi, float *temp)
{
int ret;
_GXHTC3C_Wakeup();
DelayMs(1);
_GXHTC3C_GetStart();
DelayMs(3);
float _humi, _temp;
ret = GXHTC3C_GetTempHumi(&_humi, &_temp);
if (ret == 0)
{
*humi = _humi;
*temp = _temp;
// gValveData.temp = (int8_t)temp;
// gValveData.humi = (uint8_t)humi;
// logDebug("humi %.2f %, temp %.2f C", *humi, *temp);
}
_GXHTC3C_Sleep();
return ret;
}
void GXHTC3C_Init(void)
{
// IIC_Init();
_GXHTC3C_Sleep();
float _humi, _temp;
BSP_ReadTempHumi(&_humi, &_temp);
logDebug("humi = %.1f %%, temp = %.1f C", _humi, _temp);
}