单片机: STM32L476
库: HAL库
通讯: 硬件I2C,直接用STM32CubeMX生成
目标: 实现读写LTC2943库仑计芯片,采集温度、库伦、电压、电流等。
硬件参考电路
ws_drive_ltc2943.h
驱动程序
/*! @file
@ingroup LTC2943
Header for LTC2943: Multicell Battery Gas Gauge with Temperature, Voltage and Current Measurement
*/
#ifndef WS_DRIVE_LTC2943_H
#define WS_DRIVE_LTC2943_H
#include "stm32l4xx_hal.h"
/*! @name LTC2943 I2C Address
@{ */
#define LTC2943_I2C_ADDRESS 0xC8
#define LTC2943_I2C_ALERT_RESPONSE 0x0C
//! @}
#define I2C_READ_BIT 0x01
#define I2C_WRITE_BIT 0x00
#define WITH_ACK 0 //!< Use with i2c_read(WITH_ACK) to read with an acknowledge
#define WITH_NACK 1
/*!
| Name | Value |
| :------------------------------------------------ | :---: |
| LTC2943_STATUS_REG | 0x00 |
| LTC2943_CONTROL_REG | 0x01 |
| LTC2943_ACCUM_CHARGE_MSB_REG | 0x02 |
| LTC2943_ACCUM_CHARGE_LSB_REG | 0x03 |
| LTC2943_CHARGE_THRESH_HIGH_MSB_REG | 0x04 |
| LTC2943_CHARGE_THRESH_HIGH_LSB_REG | 0x05 |
| LTC2943_CHARGE_THRESH_LOW_MSB_REG | 0x06 |
| LTC2943_CHARGE_THRESH_LOW_LSB_REG | 0x07 |
| LTC2943_VOLTAGE_MSB_REG | 0x08 |
| LTC2943_VOLTAGE_LSB_REG | 0x09 |
| LTC2943_VOLTAGE_THRESH_HIGH_MSB_REG | 0x0A |
| LTC2943_VOLTAGE_THRESH_HIGH_LSB_REG | 0x0B |
| LTC2943_VOLTAGE_THRESH_LOW_MSB_REG | 0x0C |
| LTC2943_VOLTAGE_THRESH_LOW_LSB_REG | 0x0D |
| LTC2943_CURRENT_MSB_REG | 0x0E |
| LTC2943_CURRENT_LSB_REG | 0x0F |
| LTC2943_CURRENT_THRESH_HIGH_MSB_REG | 0x10 |
| LTC2943_CURRENT_THRESH_HIGH_LSB_REG | 0x11 |
| LTC2943_CURRENT_THRESH_LOW_MSB_REG | 0x12 |
| LTC2943_CURRENT_THRESH_LOW_LSB_REG | 0x13 |
| LTC2943_TEMPERATURE_MSB_REG | 0x14 |
| LTC2943_TEMPERATURE_LSB_REG | 0x15 |
| LTC2943_TEMPERATURE_THRESH_HIGH_REG | 0x16 |
| LTC2943_TEMPERATURE_THRESH_LOW_REG | 0x17 |
*/
/*! @name Registers
@{ */
// Registers
#define LTC2943_STATUS_REG 0x00
#define LTC2943_CONTROL_REG 0x01
#define LTC2943_ACCUM_CHARGE_MSB_REG 0x02
#define LTC2943_ACCUM_CHARGE_LSB_REG 0x03
#define LTC2943_CHARGE_THRESH_HIGH_MSB_REG 0x04
#define LTC2943_CHARGE_THRESH_HIGH_LSB_REG 0x05
#define LTC2943_CHARGE_THRESH_LOW_MSB_REG 0x06
#define LTC2943_CHARGE_THRESH_LOW_LSB_REG 0x07
#define LTC2943_VOLTAGE_MSB_REG 0x08
#define LTC2943_VOLTAGE_LSB_REG 0x09
#define LTC2943_VOLTAGE_THRESH_HIGH_MSB_REG 0x0A
#define LTC2943_VOLTAGE_THRESH_HIGH_LSB_REG 0x0B
#define LTC2943_VOLTAGE_THRESH_LOW_MSB_REG 0x0C
#define LTC2943_VOLTAGE_THRESH_LOW_LSB_REG 0x0D
#define LTC2943_CURRENT_MSB_REG 0x0E
#define LTC2943_CURRENT_LSB_REG 0x0F
#define LTC2943_CURRENT_THRESH_HIGH_MSB_REG 0x10
#define LTC2943_CURRENT_THRESH_HIGH_LSB_REG 0x11
#define LTC2943_CURRENT_THRESH_LOW_MSB_REG 0x12
#define LTC2943_CURRENT_THRESH_LOW_LSB_REG 0x13
#define LTC2943_TEMPERATURE_MSB_REG 0x14
#define LTC2943_TEMPERATURE_LSB_REG 0x15
#define LTC2943_TEMPERATURE_THRESH_HIGH_REG 0x16
#define LTC2943_TEMPERATURE_THRESH_LOW_REG 0x17
//! @}
/*!
| Command Codes | Value |
| :-------------------------------------------- | :-------: |
| LTC2943_AUTOMATIC_MODE | 0xC0 |
| LTC2943_SCAN_MODE | 0x80 |
| LTC2943_MANUAL_MODE | 0x40 |
| LTC2943_SLEEP_MODE | 0x00 |
| LTC2943_PRESCALAR_M_1 | 0x00 |
| LTC2943_PRESCALAR_M_4 | 0x08 |
| LTC2943_PRESCALAR_M_16 | 0x10 |
| LTC2943_PRESCALAR_M_64 | 0x18 |
| LTC2943_PRESCALAR_M_256 | 0x20 |
| LTC2943_PRESCALAR_M_1024 | 0x28 |
| LTC2943_PRESCALAR_M_4096 | 0x30 |
| LTC2943_PRESCALAR_M_4096_2 | 0x31 |
| LTC2943_ALERT_MODE | 0x04 |
| LTC2943_CHARGE_COMPLETE_MODE | 0x02 |
| LTC2943_DISABLE_ALCC_PIN | 0x00 |
| LTC2943_SHUTDOWN_MODE | 0x01 |
*/
/*! @name Command Codes
@{ */
// Command Codes
#define LTC2943_AUTOMATIC_MODE 0xC0
#define LTC2943_SCAN_MODE 0x80
#define LTC2943_MANUAL_MODE 0x40
#define LTC2943_SLEEP_MODE 0x00
#define LTC2943_PRESCALAR_M_1 0x00
#define LTC2943_PRESCALAR_M_4 0x08
#define LTC2943_PRESCALAR_M_16 0x10
#define LTC2943_PRESCALAR_M_64 0x18
#define LTC2943_PRESCALAR_M_256 0x20
#define LTC2943_PRESCALAR_M_1024 0x28
#define LTC2943_PRESCALAR_M_4096 0x30
#define LTC2943_PRESCALAR_M_4096_2 0x31
#define LTC2943_ALERT_MODE 0x04
#define LTC2943_CHARGE_COMPLETE_MODE 0x02
#define LTC2943_DISABLE_ALCC_PIN 0x00
#define LTC2943_SHUTDOWN_MODE 0x01
//! @}
/*!
| Conversion Constants | Value |
| :------------------------------------------------ | :------: |
| LTC2943_CHARGE_lsb | 0.34 mAh|
| LTC2943_VOLTAGE_lsb | 1.44 mV|
| LTC2943_CURRENT_lsb | 29.3 uV|
| LTC2943_TEMPERATURE_lsb | 0.25 C|
| LTC2943_FULLSCALE_VOLTAGE | 23.6 V|
| LTC2943_FULLSCALE_CURRENT | 60 mV|
| LTC2943_FULLSCALE_TEMPERATURE | 510 K|
*/
/*! @name Conversion Constants
@{ */
//! @}
//! @}
void LTC2943_Init(void);
//! Write an 8-bit code to the LTC2943.
//! @return The function returns the state of the acknowledge bit after the I2C address write. 0=acknowledge, 1=no acknowledge.
int8_t LTC2943_write(uint8_t i2c_address, //!< Register address for the LTC2943
uint8_t adc_command, //!< The "command byte" for the LTC2943
uint8_t code //!< Value that will be written to the register.
);
//! Write a 16-bit code to the LTC2943.
//! @return The function returns the state of the acknowledge bit after the I2C address write. 0=acknowledge, 1=no acknowledge.
int8_t LTC2943_write_16_bits(uint8_t i2c_address, //!< Register address for the LTC2943
uint8_t adc_command, //!< The "command byte" for the LTC2943
uint16_t code //!< Value that will be written to the register.
);
//! Reads an 8-bit adc_code from LTC2943
//! @return The function returns the state of the acknowledge bit after the I2C address write. 0=acknowledge, 1=no acknowledge.
int8_t LTC2943_read(uint8_t i2c_address, //!< Register address for the LTC2943
uint8_t adc_command, //!< The "command byte" for the LTC2943
uint8_t *adc_code //!< Value that will be read from the register.
);
//! Reads a 16-bit adc_code from LTC2943
//! @return The function returns the state of the acknowledge bit after the I2C address write. 0=acknowledge, 1=no acknowledge.
int8_t LTC2943_read_16_bits(uint8_t i2c_address, //!< Register address for the LTC2943
uint8_t adc_command, //!< The "command byte" for the LTC2943
uint16_t *adc_code //!< Value that will be read from the register.
);
//! Calculate the LTC2943 charge in Coulombs
//! @return Returns the Coulombs of charge in the ACR register.
float LTC2943_code_to_coulombs(uint16_t adc_code, //!< The RAW ADC value
float resistor, //!< The sense resistor value
uint16_t prescalar //!< The prescalar value
);
//! Calculate the LTC2943 charge in mAh
//! @return Returns the Coulombs of charge in the ACR register.
float LTC2943_code_to_mAh(uint16_t adc_code, //!< The RAW ADC value
float resistor, //!< The sense resistor value
uint16_t prescalar //!< The prescalar value
);
//! Calculate the LTC2943 SENSE+ voltage
//! @return Returns the SENSE+ Voltage in Volts
float LTC2943_code_to_voltage(uint16_t adc_code //!< The RAW ADC value
);
//! Calculate the LTC2943 current with a sense resistor
//! @return Returns the current through the sense resisor
float LTC2943_code_to_current(uint16_t adc_code, //!< The RAW ADC value
float resistor //!< The sense resistor value
);
//! Calculate the LTC2943 temperature
//! @return Returns the temperature in Kelvin
float LTC2943_code_to_kelvin_temperature(uint16_t adc_code //!< The RAW ADC value
);
//! Calculate the LTC2943 temperature
//! @return Returns the temperature in Celcius
float LTC2943_code_to_celcius_temperature(uint16_t adc_code //!< The RAW ADC value
);
#endif // LTC2943_H
ws_drive_ltc2943.c
驱动程序
#include "ws_drive_ltc2943.h"
#include "i2c.h"
//! @defgroup LTC2943 LTC2943: Multicell Battery Gas Gauge with Temperature, Voltage and Current Measurement
/*! @file
@ingroup LTC2943
Library for LTC2943 Multicell Battery Gas Gauge with Temperature, Voltage and Current Measurement
*/
const float LTC2943_CHARGE_lsb = 0.34E-3;
const float LTC2943_VOLTAGE_lsb = 1.44E-3;
const float LTC2943_CURRENT_lsb = 29.3E-6;
const float LTC2943_TEMPERATURE_lsb = 0.25;
const float LTC2943_FULLSCALE_VOLTAGE = 23.6;
const float LTC2943_FULLSCALE_CURRENT = 60E-3;
const float LTC2943_FULLSCALE_TEMPERATURE = 510;
// Write an 8-bit code to the LTC2943.
int8_t LTC2943_write(uint8_t i2c_address, uint8_t adc_command, uint8_t code)
// The function returns the state of the acknowledge bit after the I2C address write. 0=acknowledge, 1=no acknowledge.
{
HAL_I2C_Mem_Write(&hi2c1, i2c_address, adc_command, I2C_MEMADD_SIZE_8BIT, (uint8_t *)&code, 1, 0x100);
return 0;
}
// Write a 16-bit code to the LTC2943.
int8_t LTC2943_write_16_bits(uint8_t i2c_address, uint8_t adc_command, uint16_t code)
// The function returns the state of the acknowledge bit after the I2C address write. 0=acknowledge, 1=no acknowledge.
{
HAL_I2C_Mem_Write(&hi2c1, i2c_address, adc_command, I2C_MEMADD_SIZE_8BIT, (uint8_t *)&code, 2, 0x100);
return 0;
}
// Reads an 8-bit adc_code from LTC2943
int8_t LTC2943_read(uint8_t i2c_address, uint8_t adc_command, uint8_t *adc_code)
// The function returns the state of the acknowledge bit after the I2C address write. 0=acknowledge, 1=no acknowledge.
{
HAL_I2C_Mem_Read(&hi2c1, i2c_address, adc_command, I2C_MEMADD_SIZE_8BIT, adc_code, 1, 0x100);
return 0;
}
// Reads a 16-bit adc_code from LTC2943
int8_t LTC2943_read_16_bits(uint8_t i2c_address, uint8_t adc_command, uint16_t *adc_code)
// The function returns the state of the acknowledge bit after the I2C address write. 0=acknowledge, 1=no acknowledge.
{
HAL_I2C_Mem_Read(&hi2c1, i2c_address, adc_command, I2C_MEMADD_SIZE_8BIT, (uint8_t *)adc_code, 2, 0x100);
return 0;
}
float LTC2943_code_to_coulombs(uint16_t adc_code, float resistor, uint16_t prescalar)
// The function converts the 16-bit RAW adc_code to Coulombs
{
float coulomb_charge;
coulomb_charge = 1000*(float)(adc_code*LTC2943_CHARGE_lsb*prescalar*50E-3)/(resistor*4096);
coulomb_charge = coulomb_charge*3.6f;
return(coulomb_charge);
}
float LTC2943_code_to_mAh(uint16_t adc_code, float resistor, uint16_t prescalar )
// The function converts the 16-bit RAW adc_code to mAh
{
float mAh_charge;
mAh_charge = 100*(float)(adc_code*LTC2943_CHARGE_lsb*prescalar*50E-3)/(resistor*4096);
return(mAh_charge);
}
float LTC2943_code_to_voltage(uint16_t adc_code)
// The function converts the 16-bit RAW adc_code to Volts
{
float voltage;
voltage = ((float)adc_code/(65535))*LTC2943_FULLSCALE_VOLTAGE;
return(voltage);
}
float LTC2943_code_to_current(uint16_t adc_code, float resistor)
// The function converts the 16-bit RAW adc_code to Amperes
{
float current;
current = (((float)adc_code-32767)/(32767))*((float)(LTC2943_FULLSCALE_CURRENT)/resistor);
return(current);
}
float LTC2943_code_to_kelvin_temperature(uint16_t adc_code)
// The function converts the 16-bit RAW adc_code to Kelvin
{
float temperature;
temperature = adc_code*((float)(LTC2943_FULLSCALE_TEMPERATURE)/65535);
return(temperature);
}
float LTC2943_code_to_celcius_temperature(uint16_t adc_code)
// The function converts the 16-bit RAW adc_code to Celcius
{
float temperature;
temperature = adc_code*((float)(LTC2943_FULLSCALE_TEMPERATURE)/65535) - 273.15;
return(temperature);
}
ws_app_power.c
调用驱动程序,读写转换参数
#include "ws_drive_ltc2943.h"
const float resistor = .050;
int8_t ack = 0; //! I2C acknowledge indicator
static uint8_t mAh_or_Coulombs = 0;
static uint8_t celcius_or_kelvin = 0;
static uint16_t prescalar_mode = LTC2943_PRESCALAR_M_4096;
static uint16_t prescalarValue = 4096;
static uint16_t alcc_mode = LTC2943_ALERT_MODE;
float charge = 0, current = 0, voltage = 0, temperature = 0;
void read_power_data(void)
{
menu_1_automatic_mode(mAh_or_Coulombs, celcius_or_kelvin, prescalar_mode, prescalarValue, alcc_mode);
}
int8_t menu_1_automatic_mode(int8_t mAh_or_Coulombs, int8_t celcius_or_kelvin, uint16_t prescalar_mode, uint16_t prescalarValue, uint16_t alcc_modes)
{
int8_t LTC2943_mode, ii;
int8_t ack = 0;
LTC2943_mode = LTC2943_AUTOMATIC_MODE | prescalar_mode | alcc_modes ;
ack |= LTC2943_write(LTC2943_I2C_ADDRESS, LTC2943_CONTROL_REG, LTC2943_mode); //! Writes the set mode to the LTC2943 control register
uint8_t status_code = 0;
uint16_t charge_code = 0, current_code = 0, voltage_code = 0, temperature_code = 0;
uint16_t charge_l2b = 0, current_l2b = 0, voltage_l2b = 0, temperature_l2b = 0;
ack |= LTC2943_read_16_bits(LTC2943_I2C_ADDRESS, LTC2943_ACCUM_CHARGE_MSB_REG, &charge_code); //! Read MSB and LSB Accumulated Charge Registers for 16 bit charge code
ack |= LTC2943_read_16_bits(LTC2943_I2C_ADDRESS, LTC2943_VOLTAGE_MSB_REG, &voltage_code); //! Read MSB and LSB Voltage Registers for 16 bit voltage code
ack |= LTC2943_read_16_bits(LTC2943_I2C_ADDRESS, LTC2943_CURRENT_MSB_REG, ¤t_code); //! Read MSB and LSB Current Registers for 16 bit current code
ack |= LTC2943_read(LTC2943_I2C_ADDRESS, LTC2943_STATUS_REG, &status_code);
ack |= LTC2943_read_16_bits(LTC2943_I2C_ADDRESS, LTC2943_TEMPERATURE_MSB_REG, &temperature_code);
charge_l2b = (((charge_code & 0x00ff) << 8) | ((charge_code & 0xff00) >> 8));
current_l2b = (((current_code & 0x00ff) << 8) | ((current_code & 0xff00) >> 8));
voltage_l2b = (((voltage_code & 0x00ff) << 8) | ((voltage_code & 0xff00) >> 8));
temperature_l2b = (((temperature_code & 0x00ff) << 8) | ((temperature_code & 0xff00) >> 8));
charge = LTC2943_code_to_mAh(charge_l2b, resistor, prescalarValue); //! Convert charge code to mAh if mAh units are desired.
current = LTC2943_code_to_current(current_l2b, resistor); //! Convert current code to Amperes
voltage = LTC2943_code_to_voltage(voltage_l2b); //! Convert voltage code to Volts
temperature = LTC2943_code_to_celcius_temperature(temperature_l2b);
return ack;
}
注意:LTC2943地址为0xC8