/* * @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); }