// // Created by dell on 24-12-3. // #include "ldc1612.h" /*! \brief 写入寄存器 \param[in] reg_addr: 寄存器地址 \param[in] value: 写入值 \param[out] none \retval i2c_result_t */ static i2c_result_t ldc1612_write_register(uint8_t reg_addr, uint16_t value) { uint8_t data[2]; data[0] = (value >> 8) & 0xFF; data[1] = value & 0xFF; return LDC1612_IIC_WRITE_16BITS(LDC1612_ADDR, reg_addr, data); } /*! \brief 读取寄存器 \param[in] reg_addr: 寄存器地址 \param[out] value: 读取值指针 \retval i2c_status_t */ static i2c_result_t ldc1612_read_register(uint8_t reg_addr, uint16_t *value) { uint8_t data[2]; i2c_result_t status; if (value == NULL) { return I2C_RESULT_INVALID_PARAM; } status = LDC1612_IIC_READ_16BITS(LDC1612_ADDR, reg_addr, data); if (status == I2C_RESULT_SUCCESS) { *value = ((uint16_t)data[0] << 8) | data[1]; } return status; } /*! \brief 计算并获取频率分频值 \param[in] channel: 通道号 \param[out] none \retval 计算得到的频率分频值 */ static uint16_t ldc1612_calculate_freq_divider(uint8_t channel) { uint16_t value; uint16_t fin_div, freq_div; float sensor_freq; sensor_freq = 1 / (2 * 3.14 * sqrt(COIL_L_UH * COIL_C_PF * pow(10, -18))) * pow(10, -6); fin_div = (uint16_t) (sensor_freq / 8.75 + 1); if (fin_div * 4 < 40) { freq_div = 2; } else { freq_div = 4; } value = fin_div << 12; value |= freq_div; return value; } uint16_t ldc1612_get_manufacturer_id(void) { uint8_t data[2] = {0}; LDC1612_IIC_READ_16BITS(LDC1612_ADDR, READ_MANUFACTURER_ID, data); return (data[0] << 8) | data[1]; } uint16_t ldc1612_get_deveice_id(void) { uint8_t data[2] = {0}; LDC1612_IIC_READ_16BITS(LDC1612_ADDR, READ_DEVICE_ID, data); return (data[0] << 8) | data[1]; } /** @brief reset sensor. * */ ldc1612_status_t ldc1612_reset_sensor(void) { i2c_result_t state = ldc1612_write_register(SENSOR_RESET_REG, LDC1612_RESET_DEV); return (state == I2C_RESULT_SUCCESS) ? LDC1612_STATUS_SUCCESS : LDC1612_STATUS_ERROR; } ldc1612_status_t ldc1612_init(void) { i2c_result_t i2c_status; uint16_t manufacturer_id, device_id; /* reset LDC1612 sensor */ i2c_status = ldc1612_reset_sensor(); if (i2c_status != I2C_RESULT_SUCCESS) { return LDC1612_STATUS_ERROR; } delay_ms(100); manufacturer_id = ldc1612_get_manufacturer_id(); device_id = ldc1612_get_deveice_id(); if (manufacturer_id != 0x5449 || device_id != 0x3055) { return LDC1612_STATUS_ERROR; } return LDC1612_STATUS_SUCCESS; } /*! \brief 配置单通道模式 \param[in] channel: 通道号 (0或1) \param[out] none \retval ldc1612_status_t */ ldc1612_status_t ldc1612_config_single_channel(uint8_t channel) { i2c_result_t status; if (channel > 1) { return LDC1612_STATUS_INVALID_PARAM; } /* 配置顺序严格按照TI官方文档要求 */ /* Step 1: 确保传感器处于睡眠模式 - 配置前必须 */ status = ldc1612_write_register(SENSOR_CONFIG_REG, LDC1612_SLEEP_MODE); if (status != I2C_RESULT_SUCCESS) return LDC1612_STATUS_ERROR; delay_ms(10); /* Step 2: 配置频率分频 - 必须在其他配置之前 */ uint16_t freq_divider = ldc1612_calculate_freq_divider(channel); ldc1612_write_register(SET_FREQ_REG_START + channel, freq_divider); delay_ms(5); /* Step 3: 配置LC稳定时间 - 影响测量精度 */ ldc1612_write_register(SET_LC_STABILIZE_REG_START + channel, LC_STABILIZE_TIME_CH0); /* Step 4: 配置转换时间 - 影响测量速度和精度 */ ldc1612_write_register(SET_CONVERSION_TIME_REG_START + channel, LDC1612_CONVERSION_TIME_CH0); /* Step 5: 配置转换偏移 */ ldc1612_write_register(SET_CONVERSION_OFFSET_REG_START + channel, SET_CONVERSION_OFFSET_CH0); /* Step 6: 配置驱动电流 - 影响传感器灵敏度 */ ldc1612_write_register(SET_DRIVER_CURRENT_REG + channel, LDC1612_DRIVE_CURRENT); /* Step 7: 配置多路复用器 - 设置通道选择和滤波 */ // ldc1612_configure_mux_register(LDC1612_MUX_AUTOSCAN_DISABLE, LDC1612_MUX_RR_SEQUENCE_0, LDC1612_MUX_FILTER_ALL_LOW, LDC1612_MUX_FILTER_NONE); ldc1612_write_register(MUL_CONFIG_REG, LDC1612_MUX_CONFIG); /* Step 8: 配置错误输出 */ ldc1612_write_register(ERROR_CONFIG_REG, LDC1612_ERROR_CONFIG); /* Step 9: 最后启动传感器 - 必须最后一步 */ status = ldc1612_write_register(SENSOR_CONFIG_REG, LDC1612_SENSOR_CONFIG_CH0); if (status != I2C_RESULT_SUCCESS) return LDC1612_STATUS_ERROR; /* Step 10: 等待传感器稳定 */ delay_ms(50); return LDC1612_STATUS_SUCCESS; } /** @brief read the raw channel result from register. @param channel LDC1612 has total two channels. @param result raw data * */ uint32_t ldc1612_get_raw_channel_result(uint8_t channel) { uint32_t raw_value = 0; uint8_t value[2] = {0}; /* Read MSW */ LDC1612_IIC_READ_16BITS(LDC1612_ADDR, CONVERTION_RESULT_REG_START + channel, value); raw_value |= (uint32_t)(((uint16_t)value[0] << 8) | value[1]) << 16; /* Read LSW */ LDC1612_IIC_READ_16BITS(LDC1612_ADDR, CONVERTION_RESULT_REG_START + channel + 1, value); raw_value |= (uint32_t)(((uint16_t)value[0] << 8) | value[1]); uint32_t calibration_value = raw_value & 0x0FFFFFFF; if (calibration_value == 0x0FFFFFFF) { return 0xF0000000; /* No coil */ } uint8_t error_code = (uint8_t)(raw_value >> 24); if (error_code & 0x80) return 0x80000000; /* Under range */ if (error_code & 0x40) return 0x40000000; /* Over range */ if (error_code & 0x20) return 0x20000000; /* Watchdog */ if (error_code & 0x10) return 0x10000000; /* Amplitude error */ return raw_value; } // void ldc1612_drvie_current_detect(uint8_t channel) { // uint8_t data[2] = {0}; // uint16_t init_value = 0 , drive_current = 0; // ldc1612_set_sensor_config(LDC1612_SLEEP_MODE); // ldc1612_configure_frequency(channel); // LDC1612_IIC_READ_16BITS(LDC1612_ADDR, SENSOR_CONFIG_REG, data); // ldc1612_set_sensor_config(LDC1612_SLEEP_MODE); // ldc1612_set_sensor_config(LDC1612_SENSOR_CONFIG_CH0); //0x1A --0x1601 // delay_ms(10); // LDC1612_IIC_READ_16BITS(LDC1612_ADDR, SET_DRIVER_CURRENT_REG, data); // init_value = (((data[0] << 8) | data[1]) >> 6) & 0x1F; // drive_current = (init_value << 11) | 0x0000; // printf("init value: 0x%x\tdrive current: 0x%x\n", init_value, drive_current); // } /** @brief Get sensor status register @return Status register value * */ uint16_t ldc1612_get_sensor_status(void) { uint8_t data[2] = {0}; LDC1612_IIC_READ_16BITS(LDC1612_ADDR, SENSOR_STATUS_REG, data); return (data[0] << 8) | data[1]; } /** @brief Check if data is ready for specific channel @param channel Channel to check (0 or 1) @return true if data is ready, false otherwise * */ bool ldc1612_is_data_ready(uint8_t channel) { uint16_t status = ldc1612_get_sensor_status(); if (channel == 0) { return (status & 0x0040) != 0; // DRDY_0 bit } else if (channel == 1) { return (status & 0x0080) != 0; // DRDY_1 bit } return false; }