BQ76942配置:与MCU通信——软件I2C or 硬件I2C?

AFE系列文章

德州仪器TI作为AFE龙头老大,具有多款功能强大的AFE,国产AFE的设计基本也是对标TI。本系列文章旨在对TI的一款AFE BQ76942容易踩坑的地方进行总结,希望对使用这款AFE的工程师们有所帮助。

第一章 BQ76942配置:使用AFE FET寄存器来控MOS
第二章 BQ76942配置:与MCU通信——软件I2C or 硬件I2C?
第三章 BQ76942配置:电流采样配置
第四章 BQ76942配置:过压保护(SOV)配置
第五章 BQ76942配置:采样断线对MOS的影响
第六章 BQ76942配置:充电时AFE自行休眠现象



前言

BQ76952 器件集成了三个串行通信接口: I2C 总线, 其支持 100kHz 和 400kHz 模式, 可选 CRC 校验; SPI 总线, 可选 CRC 校验, 支持高达 2MHz 的时钟速率; 以及单线 HDQ 接口。 BQ76952 器件默认配置为 I2C 模式( 其他版本的器件, 例如 BQ7695201, 可能默认配置为不同的模式), 并且可以通过对寄存器或 OTP 配置进行相应编程来更改为 SPI 或 HDQ 模式。客户可以在生产线上对器件的集成 OTP 进行编程, 以设置在运行中加电时使用的所需通信速度和协议。

在这里插入图片描述


一、两种I2C的区别

我们都知道I2C分为软件I2C和硬件I2C,软件I2C是通过模拟电平的时序来实现和器件之间的通信,硬件I2C则是直接通过MCU内置的I2C模块进行通信。

BQ76942这款AFE有个问题,MCU使用软件I2C的方式与AFE进行通信时,SDA时序间需要加大量的延时否则通信失败,而硬件I2C则不需要加延时

如果大家使用STM32的硬件I2C会发现经常在while循环里进行了死锁,ST貌似在已修复这个问题,但是一些国产的MCU厂家没修复这个bug,目前使用NXP的MCU与BQ76942进行硬件I2C的通信比较合适,不存在通信方面的问题。

二、参考代码

<main.c> 代码如下:

/******************************************************************************
  * @file           : main.c
  * @brief          : Main program body 
  * (Non-USER sections generated from STM32CubeMX software)
  ******************************************************************************/
  
  
  
//  BQ76952EVM 代码例程 
//
//  引脚接线描述: The I2C SCL and SDA pins are the only pin connections required between the NUCLEO board and the BQ76952EVM for this demo code. Also a ground connection should be made between the 2 boards.The ALERT, RST_SHUT, and DFETOFF pins are also configured on the MCU and can be used as shown.
//I2C的SCL和SDA引脚是该演示代码在NUCLEO板和BQ76952EVM之间所需的唯一引脚连接。另外,两个板子之间也要接地。ALERT, RST_SHUT和DFETOFF引脚也在MCU上配置,可以如下所示使用。
//
//                                     /|\ /|\ 
//                   STM32             5k |
//                 -----------------    |  5k
//                |             PB8 |---+---|-- I2C Clock (SCL)
//                |                 |       |
//                |		        PB9 |-------+-- I2C Data (SDA)
//                |                 |
//     DFETOFF ---| PA8             |
//                |                 |
//   RST_SHUT  ---| PA9        		|--- Green LED
//                |                 |
//      ALERT  ---|	PA10            |
//                |                 |


/* Includes ------------------------------------------------------------------*/
#include "main.h"
#include <stdio.h>
#include "BQ769x2Header.h"

#define DEV_ADDR  0x10  // BQ769x2 address is 0x10 including R/W bit or 0x8 as 7-bit address
#define CRC_Mode 0  // 0 for disabled, 1 for enabled
#define MAX_BUFFER_SIZE 10
#define R 0 // Read; Used in DirectCommands and Subcommands functions
#define W 1 // Write; Used in DirectCommands and Subcommands functions
#define W2 2 // Write data with two bytes; Used in Subcommands function



/* Private variables ---------------------------------------------------------*/
I2C_HandleTypeDef hi2c1;

TIM_HandleTypeDef htim1;

UART_HandleTypeDef huart2;

/* USER CODE BEGIN PV */
uint8_t RX_data [2]    = {0x00, 0x00}; // used in several functions to store data read from BQ769x2
uint8_t RX_32Byte [32] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
	                      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
	//used in Subcommands read function
// Global Variables for cell voltages, temperatures, Stack voltage, PACK Pin voltage, LD Pin voltage, CC2 current
uint16_t CellVoltage [16] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
float Temperature [3] = {0,0,0};
uint16_t Stack_Voltage = 0x00;
uint16_t Pack_Voltage = 0x00;
uint16_t LD_Voltage = 0x00;
uint16_t Pack_Current = 0x00;

uint16_t AlarmBits = 0x00;
uint8_t value_SafetyStatusA;  // Safety Status Register A
uint8_t value_SafetyStatusB;  // Safety Status Register B
uint8_t value_SafetyStatusC;  // Safety Status Register C
uint8_t value_PFStatusA;   // Permanent Fail Status Register A
uint8_t value_PFStatusB;   // Permanent Fail Status Register B
uint8_t value_PFStatusC;   // Permanent Fail Status Register C
uint8_t FET_Status;  // FET Status register contents  - Shows states of FETs
uint16_t CB_ActiveCells;  // Cell Balancing Active Cells

uint8_t	UV_Fault = 0;   // under-voltage fault state
uint8_t	OV_Fault = 0;   // over-voltage fault state
uint8_t	SCD_Fault = 0;  // short-circuit fault state
uint8_t	OCD_Fault = 0;  // over-current fault state
uint8_t ProtectionsTriggered = 0; // Set to 1 if any protection triggers

uint8_t LD_ON = 0;	// Load Detect status bit
uint8_t DSG = 0;   // discharge FET state
uint8_t CHG = 0;   // charge FET state
uint8_t PCHG = 0;  // pre-charge FET state
uint8_t PDSG = 0;  // pre-discharge FET state

uint32_t AccumulatedCharge_Int; // in BQ769x2_READPASSQ func
uint32_t AccumulatedCharge_Frac;// in BQ769x2_READPASSQ func
uint32_t AccumulatedCharge_Time;// in BQ769x2_READPASSQ func
/* USER CODE END PV */

/* Private function prototypes -----------------------------------------------*/
void SystemClock_Config(void);
static void MX_GPIO_Init(void);
static void MX_I2C1_Init(void);
static void MX_USART2_UART_Init(void);
static void MX_TIM1_Init(void);
/* USER CODE BEGIN PFP */
void delayUS(uint32_t us) {   // Sets the delay in microseconds.
	__HAL_TIM_SET_COUNTER(&htim1,0);  // set the counter value a 0
	while (__HAL_TIM_GET_COUNTER(&htim1) < us);  // wait for the counter to reach the us input in the parameter
}

void CopyArray(uint8_t *source, uint8_t *dest, uint8_t count)
{
    uint8_t copyIndex = 0;
    for (copyIndex = 0; copyIndex < count; copyIndex++)
    {
        dest[copyIndex] = source[copyIndex];
    }
}

unsigned char Checksum(unsigned char *ptr, unsigned char len)
// Calculates the checksum when writing to a RAM register. The checksum is the inverse of the sum of the bytes.	
{
	unsigned char i;
	unsigned char checksum = 0;

	for(i=0; i<len; i++)
		checksum += ptr[i];

	checksum = 0xff & ~checksum;

	return(checksum);
}

unsigned char CRC8(unsigned char *ptr, unsigned char len)
//Calculates CRC8 for passed bytes. Used in i2c read and write functions 
{
	unsigned char i;
	unsigned char crc=0;
	while(len--!=0)
	{
		for(i=0x80; i!=0; i/=2)
		{
			if((crc & 0x80) != 0)
			{
				crc *= 2;
				crc ^= 0x107;
			}
			else
				crc *= 2;

			if((*ptr & i)!=0)
				crc ^= 0x107;
		}
		ptr++;
	}
	return(crc);
}

void I2C_WriteReg(uint8_t reg_addr, uint8_t *reg_data, uint8_t count)
{
	uint8_t TX_Buffer [MAX_BUFFER_SIZE] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
#if CRC_Mode
	{
		uint8_t crc_count = 0;
		crc_count = count * 2;
		uint8_t crc1stByteBuffer [3] = {0x10, reg_addr, reg_data[0]};
		unsigned int j;
		unsigned int i;
		uint8_t temp_crc_buffer [3];

		TX_Buffer[0] = reg_data[0];
		TX_Buffer[1] = CRC8(crc1stByteBuffer,3);

		j = 2;
		for(i=1; i<count; i++)
		{
			TX_Buffer[j] = reg_data[i];
			j = j + 1;
			temp_crc_buffer[0] = reg_data[i];
			TX_Buffer[j] = CRC8(temp_crc_buffer,1);
			j = j + 1;
		}
		HAL_I2C_Mem_Write(&hi2c1, DEV_ADDR, reg_addr, 1, TX_Buffer, crc_count, 1000);
	}
#else 
	HAL_I2C_Mem_Write(&hi2c1, DEV_ADDR, reg_addr, 1, reg_data, count, 1000);
#endif
}

int I2C_ReadReg(uint8_t reg_addr, uint8_t *reg_data, uint8_t count)
{
	unsigned int RX_CRC_Fail = 0;  // reset to 0. If in CRC Mode and CRC fails, this will be incremented.
	uint8_t RX_Buffer [MAX_BUFFER_SIZE] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
#if CRC_Mode
	{
		uint8_t crc_count = 0;
		uint8_t ReceiveBuffer [10] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
		crc_count = count * 2;
		unsigned int j;
		unsigned int i;
		unsigned char CRCc = 0;
		uint8_t temp_crc_buffer [3];

		HAL_I2C_Mem_Read(&hi2c1, DEV_ADDR, reg_addr, 1, ReceiveBuffer, crc_count, 1000);
		uint8_t crc1stByteBuffer [4] = {0x10, reg_addr, 0x11, ReceiveBuffer[0]};
		CRCc = CRC8(crc1stByteBuffer,4);
		if (CRCc != ReceiveBuffer[1])
		{
			RX_CRC_Fail += 1;
		}
		RX_Buffer[0] = ReceiveBuffer[0];

		j = 2;
		for (i=1; i<count; i++)
		{
			RX_Buffer[i] = ReceiveBuffer[j];
			temp_crc_buffer[0] = ReceiveBuffer[j];
			j = j + 1;
			CRCc = CRC8(temp_crc_buffer,1);
			if (CRCc != ReceiveBuffer[j])
				RX_CRC_Fail += 1;
			j = j + 1;
		}
		CopyArray(RX_Buffer, reg_data, crc_count);
	}
#else
	HAL_I2C_Mem_Read(&hi2c1, DEV_ADDR, reg_addr, 1, reg_data, count, 1000);
#endif
	return 0;
}

void BQ769x2_SetRegister(uint16_t reg_addr, uint32_t reg_data, uint8_t datalen)
{
	uint8_t TX_Buffer[2] = {0x00, 0x00};
	uint8_t TX_RegData[6] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00};

	//TX_RegData in little endian format
	TX_RegData[0] = reg_addr & 0xff; 
	TX_RegData[1] = (reg_addr >> 8) & 0xff;
	TX_RegData[2] = reg_data & 0xff; //1st byte of data

	switch(datalen)
    {
		case 1: //1 byte datalength
      		I2C_WriteReg(0x3E, TX_RegData, 3);
			delayUS(2000);
			TX_Buffer[0] = Checksum(TX_RegData, 3); 
			TX_Buffer[1] = 0x05; //combined length of register address and data
      		I2C_WriteReg(0x60, TX_Buffer, 2); // Write the checksum and length
			delayUS(2000);
			break;
		case 2: //2 byte datalength
			TX_RegData[3] = (reg_data >> 8) & 0xff;
			I2C_WriteReg(0x3E, TX_RegData, 4);
			delayUS(2000);
			TX_Buffer[0] = Checksum(TX_RegData, 4); 
			TX_Buffer[1] = 0x06; //combined length of register address and data
      		I2C_WriteReg(0x60, TX_Buffer, 2); // Write the checksum and length
			delayUS(2000);
			break;
		case 4: //4 byte datalength, Only used for CCGain and Capacity Gain
			TX_RegData[3] = (reg_data >> 8) & 0xff;
			TX_RegData[4] = (reg_data >> 16) & 0xff;
			TX_RegData[5] = (reg_data >> 24) & 0xff;
			I2C_WriteReg(0x3E, TX_RegData, 6);
			delayUS(2000);
			TX_Buffer[0] = Checksum(TX_RegData, 6); 
			TX_Buffer[1] = 0x08; //combined length of register address and data
      		I2C_WriteReg(0x60, TX_Buffer, 2); // Write the checksum and length
			delayUS(2000);
			break;
    }
}

void CommandSubcommands(uint16_t command) //For Command only Subcommands
// See the TRM or the BQ76952 header file for a full list of Command-only subcommands
{	//For DEEPSLEEP/SHUTDOWN subcommand you will need to call this function twice consecutively
	
	uint8_t TX_Reg[2] = {0x00, 0x00};

	//TX_Reg in little endian format
	TX_Reg[0] = command & 0xff;
	TX_Reg[1] = (command >> 8) & 0xff;

	I2C_WriteReg(0x3E,TX_Reg,2); 
	delayUS(2000);
}

void Subcommands(uint16_t command, uint16_t data, uint8_t type)
// See the TRM or the BQ76952 header file for a full list of Subcommands
{
	//security keys and Manu_data writes dont work with this function (reading these commands works)
	//max readback size is 32 bytes i.e. DASTATUS, CUV/COV snapshot
	uint8_t TX_Reg[4] = {0x00, 0x00, 0x00, 0x00};
	uint8_t TX_Buffer[2] = {0x00, 0x00};

	//TX_Reg in little endian format
	TX_Reg[0] = command & 0xff;
	TX_Reg[1] = (command >> 8) & 0xff; 

	if (type == R) {//read
		I2C_WriteReg(0x3E,TX_Reg,2);
		delayUS(2000);
		I2C_ReadReg(0x40, RX_32Byte, 32); //RX_32Byte is a global variable
	}
	else if (type == W) {
		//FET_Control, REG12_Control
		TX_Reg[2] = data & 0xff; 
		I2C_WriteReg(0x3E,TX_Reg,3);
		delayUS(1000);
		TX_Buffer[0] = Checksum(TX_Reg, 3);
		TX_Buffer[1] = 0x05; //combined length of registers address and data
		I2C_WriteReg(0x60, TX_Buffer, 2);
		delayUS(1000); 
	}
	else if (type == W2){ //write data with 2 bytes
		//CB_Active_Cells, CB_SET_LVL
		TX_Reg[2] = data & 0xff; 
		TX_Reg[3] = (data >> 8) & 0xff;
		I2C_WriteReg(0x3E,TX_Reg,4);
		delayUS(1000);
		TX_Buffer[0] = Checksum(TX_Reg, 4); 
		TX_Buffer[1] = 0x06; //combined length of registers address and data
		I2C_WriteReg(0x60, TX_Buffer, 2);
		delayUS(1000); 
	}
}

void DirectCommands(uint8_t command, uint16_t data, uint8_t type)
// See the TRM or the BQ76952 header file for a full list of Direct Commands
{	//type: R = read, W = write
	uint8_t TX_data[2] = {0x00, 0x00};

	//little endian format
	TX_data[0] = data & 0xff;
	TX_data[1] = (data >> 8) & 0xff;

	if (type == R) {//Read
		I2C_ReadReg(command, RX_data, 2); //RX_data is a global variable
		delayUS(2000);
	}
	if (type == W) {//write
    //Control_status, alarm_status, alarm_enable all 2 bytes long
		I2C_WriteReg(command,TX_data,2);
		delayUS(2000);
	}
}

void BQ769x2_Init() {
	// Configures all parameters in device RAM

	// Enter CONFIGUPDATE mode (Subcommand 0x0090) - It is required to be in CONFIG_UPDATE mode to program the device RAM settings
	CommandSubcommands(SET_CFGUPDATE);

	// 'Power Config' - 0x9234 = 0x2D80
	// 置位DPSLP_LDO :进入休眠模式,让LDOs保持激活状态
  	// 设置 wake speed bits to 00 : 全速模式
	BQ769x2_SetRegister(PowerConfig, 0x2D80, 2);

	// 'REG0 Config' - set REG0_EN bit : 启用前置稳压器
	BQ769x2_SetRegister(REG0Config, 0x01, 1);

	// 'REG12 Config' - 使能 REG1 输出3.3V
	BQ769x2_SetRegister(REG12Config, 0x0D, 1);

	// Set DFETOFF pin to control BOTH CHG and DSG FET 输出 - 0x92FB = 0x42 (set to 0x00 to disable)
	BQ769x2_SetRegister(DFETOFFPinConfig, 0x42, 1);

	// Set up ALERT Pin - 0x92FC = 0x2A
	// This configures the ALERT pin to drive high (REG1 voltage) when enabled.
	//在 ALERT 引脚上生成警报信号的功能, 该信号可用作主机处理器的中断。
	BQ769x2_SetRegister(ALERTPinConfig, 0x2A, 1);

	// Set TS1 to measure Cell Temperature - 0x92FD = 0x07
	BQ769x2_SetRegister(TS1Config, 0x07, 1);

	// Set TS3 to measure FET Temperature - 0x92FF = 0x0F
	BQ769x2_SetRegister(TS3Config, 0x0F, 1);

	// Set HDQ to measure Cell Temperature - 0x9300 = 0x07
	BQ769x2_SetRegister(HDQPinConfig, 0x00, 1);  // No thermistor热敏电阻 installed on EVM评估版 HDQ pin, so set to 0x00

	// 'VCell Mode' - Enable 16 cells - 0x9304 = 0x0000; Writing 0x0000 sets the default of 16 cells
	BQ769x2_SetRegister(VCellMode, 0x0000, 2);

	// 使能保护功能: 'Enabled Protections A' 0x9261 = 0xBC
	// Enables SCD (short-circuit), OCD1 (over-current in discharge), OCC (over-current in charge),
	// COV (over-voltage), CUV (under-voltage)
	BQ769x2_SetRegister(EnabledProtectionsA, 0xBC, 1);

	// 使能所有保护: 'Enabled Protections B' 0x9262 = 0xF7
	// Enables OTF (over-temperature FET), OTINT (internal over-temperature), OTD (over-temperature in discharge),
	// OTC (over-temperature in charge), UTINT (internal under-temperature), UTD (under-temperature in discharge), UTC (under-temperature in charge)
	BQ769x2_SetRegister(EnabledProtectionsB, 0xF7, 1);

	// 'Default Alarm Mask' - 0x..82 Enables the FullScan and ADScan bits, default value = 0xF800
	BQ769x2_SetRegister(DefaultAlarmMask, 0xF882, 2);

	//设置 Balancing Configuration - 0x9335 = 0x03   -  Automated balancing while in Relax or Charge modes
	// Also see "Cell Balancing with BQ769x2 Battery Monitors" document on ti.com
	BQ769x2_SetRegister(BalancingConfiguration, 0x03, 1);

	// Set up CUV (under-voltage) Threshold - 0x9275 = 0x31 (2479 mV)
	// CUV Threshold is this value multiplied by 50.6mV
	BQ769x2_SetRegister(CUVThreshold, 0x31, 1);

	// Set up COV (over-voltage) Threshold - 0x9278 = 0x55 (4301 mV)
	// COV Threshold is this value multiplied by 50.6mV
	BQ769x2_SetRegister(COVThreshold, 0x55, 1);

	// Set up OCC (over-current in charge) Threshold - 0x9280 = 0x05 (10 mV = 10A across 1mOhm sense resistor) Units in 2mV
	BQ769x2_SetRegister(OCCThreshold, 0x05, 1);

	// Set up OCD1 Threshold - 0x9282 = 0x0A (20 mV = 20A across 1mOhm sense resistor) units of 2mV
	BQ769x2_SetRegister(OCD1Threshold, 0x0A, 1);

	// Set up SCD Threshold - 0x9286 = 0x05 (100 mV = 100A across 1mOhm sense resistor)  0x05=100mV
	BQ769x2_SetRegister(SCDThreshold, 0x05, 1);

	// Set up SCD Delay - 0x9287 = 0x03 (30 us) Enabled with a delay of (value - 1) * 15 µs; min value of 1    
	BQ769x2_SetRegister(SCDDelay, 0x03, 1);

	// Set up SCDL Latch Limit to 1 to set SCD recovery only with load removal 0x9295 = 0x01
	// If this is not set, then SCD will recover based on time (SCD Recovery Time parameter).
	BQ769x2_SetRegister(SCDLLatchLimit, 0x01, 1);

	// Exit CONFIGUPDATE mode  - Subcommand 0x0092
	CommandSubcommands(EXIT_CFGUPDATE);
}

//  ********************************* FET Control Commands  ***************************************

void BQ769x2_BOTHOFF () {
	// Disables all FETs using the DFETOFF (BOTHOFF) pin
	// The DFETOFF pin on the BQ76952EVM should be connected to the MCU board to use this function
	HAL_GPIO_WritePin(GPIOA, GPIO_PIN_8, GPIO_PIN_SET);  // DFETOFF pin (BOTHOFF) set high
}

void BQ769x2_RESET_BOTHOFF () {
	// Resets DFETOFF (BOTHOFF) pin
	// The DFETOFF pin on the BQ76952EVM should be connected to the MCU board to use this function
	HAL_GPIO_WritePin(GPIOA, GPIO_PIN_8, GPIO_PIN_RESET);  // DFETOFF pin (BOTHOFF) set low
}

void BQ769x2_ReadFETStatus() { 
	// Read FET Status to see which FETs are enabled
	DirectCommands(FETStatus, 0x00, R);
	FET_Status = (RX_data[1]*256 + RX_data[0]);
	DSG = ((0x4 & RX_data[0])>>2);// discharge FET state
  	CHG = (0x1 & RX_data[0]);// charge FET state
  	PCHG = ((0x2 & RX_data[0])>>1);// pre-charge FET state
  	PDSG = ((0x8 & RX_data[0])>>3);// pre-discharge FET state
}

// ********************************* End of FET Control Commands *********************************

// ********************************* BQ769x2 Power Commands   *****************************************

void BQ769x2_ShutdownPin() {
	// Puts the device into SHUTDOWN mode using the RST_SHUT pin
	// The RST_SHUT pin on the BQ76952EVM should be connected to the MCU board to use this function	
	HAL_GPIO_WritePin(GPIOA, GPIO_PIN_9, GPIO_PIN_SET);  // Sets RST_SHUT pin
}

void BQ769x2_ReleaseShutdownPin() {
	// Releases the RST_SHUT pin
	// The RST_SHUT pin on the BQ76952EVM should be connected to the MCU board to use this function	
	HAL_GPIO_WritePin(GPIOA, GPIO_PIN_9, GPIO_PIN_RESET);  // Resets RST_SHUT pin
}

// ********************************* End of BQ769x2 Power Commands   *****************************************


// ********************************* BQ769x2 Status and Fault Commands   *****************************************

uint16_t BQ769x2_ReadAlarmStatus() { 
	// Read this register to find out why the ALERT pin was asserted
	DirectCommands(AlarmStatus, 0x00, R);
	return (RX_data[1]*256 + RX_data[0]);
}

void BQ769x2_ReadSafetyStatus() { //good example functions
	// Read Safety Status A/B/C and find which bits are set
	// This shows which primary protections have been triggered
	DirectCommands(SafetyStatusA, 0x00, R);
	value_SafetyStatusA = (RX_data[1]*256 + RX_data[0]);
	//Example Fault Flags
	UV_Fault = ((0x4 & RX_data[0])>>2); 
	OV_Fault = ((0x8 & RX_data[0])>>3);
	SCD_Fault = ((0x8 & RX_data[1])>>3);
	OCD_Fault = ((0x2 & RX_data[1])>>1);
	DirectCommands(SafetyStatusB, 0x00, R);
	value_SafetyStatusB = (RX_data[1]*256 + RX_data[0]);
	DirectCommands(SafetyStatusC, 0x00, R);
	value_SafetyStatusC = (RX_data[1]*256 + RX_data[0]);
	if ((value_SafetyStatusA + value_SafetyStatusB + value_SafetyStatusC) > 1) {
		ProtectionsTriggered = 1; }
	else {
		ProtectionsTriggered = 0; }
}

void BQ769x2_ReadPFStatus() {
	// Read Permanent Fail Status A/B/C and find which bits are set
	// This shows which permanent failures have been triggered
	DirectCommands(PFStatusA, 0x00, R);
	value_PFStatusA = (RX_data[1]*256 + RX_data[0]);
	DirectCommands(PFStatusB, 0x00, R);
	value_PFStatusB = (RX_data[1]*256 + RX_data[0]);
	DirectCommands(PFStatusC, 0x00, R);
	value_PFStatusC = (RX_data[1]*256 + RX_data[0]);
}

// ********************************* End of BQ769x2 Status and Fault Commands   *****************************************


// ********************************* BQ769x2 Measurement Commands   *****************************************


uint16_t BQ769x2_ReadVoltage(uint8_t command)
// This function can be used to read a specific cell voltage or stack / pack / LD voltage
{
	//RX_data is global var
	DirectCommands(command, 0x00, R);
	if(command >= Cell1Voltage && command <= Cell16Voltage) {//Cells 1 through 16 (0x14 to 0x32)
		return (RX_data[1]*256 + RX_data[0]); //voltage is reported in mV
	}
	else {//stack, Pack, LD
		return 10 * (RX_data[1]*256 + RX_data[0]); //voltage is reported in 0.01V units
	}

}
void BQ769x2_ReadAllVoltages()
// Reads all cell voltages, Stack voltage, PACK pin voltage, and LD pin voltage
{
  int cellvoltageholder = Cell1Voltage; //Cell1Voltage is 0x14
  for (int x = 0; x < 16; x++){//Reads all cell voltages
    CellVoltage[x] = BQ769x2_ReadVoltage(cellvoltageholder);
    cellvoltageholder = cellvoltageholder + 2;
  }
  Stack_Voltage = BQ769x2_ReadVoltage(StackVoltage);
  Pack_Voltage = BQ769x2_ReadVoltage(PACKPinVoltage);
  LD_Voltage = BQ769x2_ReadVoltage(LDPinVoltage);
}

uint16_t BQ769x2_ReadCurrent() 
// Reads PACK current 
{
	DirectCommands(CC2Current, 0x00, R);
	return (RX_data[1]*256 + RX_data[0]);  // current is reported in mA
}

float BQ769x2_ReadTemperature(uint8_t command) 
{
	DirectCommands(command, 0x00, R);
	//RX_data is a global var
	return (0.1 * (float)(RX_data[1]*256 + RX_data[0])) - 273.15;  // converts from 0.1K to Celcius
}

void BQ769x2_ReadPassQ(){ // Read Accumulated Charge and Time from DASTATUS6 
	Subcommands(DASTATUS6, 0x00, R);
	AccumulatedCharge_Int = ((RX_32Byte[3]<<24) + (RX_32Byte[2]<<16) + (RX_32Byte[1]<<8) + RX_32Byte[0]); //Bytes 0-3
	AccumulatedCharge_Frac = ((RX_32Byte[7]<<24) + (RX_32Byte[6]<<16) + (RX_32Byte[5]<<8) + RX_32Byte[4]); //Bytes 4-7
	AccumulatedCharge_Time = ((RX_32Byte[11]<<24) + (RX_32Byte[10]<<16) + (RX_32Byte[9]<<8) + RX_32Byte[8]); //Bytes 8-11
}

// ********************************* End of BQ769x2 Measurement Commands   *****************************************


/* USER CODE END PFP */

/* Private user code ---------------------------------------------------------*/
/* USER CODE BEGIN 0 */
/* USER CODE END 0 */

/**
  * @brief  The application entry point.
  * @retval int
  */
int main(void)
{
  /* USER CODE BEGIN 1 */

  /* USER CODE END 1 */

  /* MCU Configuration--------------------------------------------------------*/

  /* Reset of all peripherals外设, Initializes the Flash interface and the Systick. */
  	HAL_Init();

  /* USER CODE BEGIN Init */

  /* USER CODE END Init */

  /* Configure the system clock */
  	SystemClock_Config();

  /* USER CODE BEGIN SysInit */

  /* USER CODE END SysInit */

  /* Initialize all configured peripherals */
  	MX_GPIO_Init();
  	MX_I2C1_Init();
  	MX_USART2_UART_Init();
  	MX_TIM1_Init();
  /* USER CODE BEGIN 2 */
	// Start timer
	HAL_TIM_Base_Start(&htim1);

	HAL_GPIO_WritePin(GPIOA, GPIO_PIN_9, GPIO_PIN_RESET);  // RST_SHUT复位引脚 pin set low
	//主机可以通过使 CFETOFF 或 DFETOFF 引脚生效或发送 FET 控制子命令来禁用 FET( 表5-8) 。
	HAL_GPIO_WritePin(GPIOA, GPIO_PIN_8, GPIO_PIN_RESET);  // DFETOFF pin (BOTHOFF) set low
  	delayUS(10000);

	CommandSubcommands(BQ769x2_RESET);  // Resets the BQ769x2 registers
	delayUS(60000);
	BQ769x2_Init();  // Configure all of the BQ769x2 register settings
	delayUS(10000);
	CommandSubcommands(FET_ENABLE); // Enable the CHG and DSG FETs
	delayUS(10000);
	CommandSubcommands(SLEEP_DISABLE); // Sleep mode is enabled by default. For this example, Sleep is disabled to 
									   // demonstrate full-speed measurements in Normal mode. 

	delayUS(60000); delayUS(60000); delayUS(60000); delayUS(60000);  //wait to start measurements after FETs close

  /* USER CODE END 2 */

  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
  while (1)
  {
    /* USER CODE END WHILE */

    /* USER CODE BEGIN 3 */
	
    //Reads Cell, Stack, Pack, LD Voltages, Pack Current and TS1/TS3 Temperatures in a loop
	//This basic example polls the Alarm Status register to see if protections have triggered or new measurements are ready
	//The ALERT pin can also be used as an interrupt to the microcontroller for fastest response time instead of polling
	//In this example the LED on the microcontroller board will be turned on to indicate a protection has triggered and will 
	//be turned off if the protection condition has cleared.

		AlarmBits = BQ769x2_ReadAlarmStatus();
		if (AlarmBits & 0x80)   // Check if FULLSCAN is complete. If set, new measurements are available
		{  
      		BQ769x2_ReadAllVoltages();
      		Pack_Current = BQ769x2_ReadCurrent();
      		Temperature[0] = BQ769x2_ReadTemperature(TS1Temperature);
      		Temperature[1] = BQ769x2_ReadTemperature(TS3Temperature);
			DirectCommands(AlarmStatus, 0x0080, W);  // Clear the FULLSCAN bit
		}
				
		if (AlarmBits & 0xC000) // If Safety Status bits are showing in AlarmStatus register
		{  
			BQ769x2_ReadSafetyStatus(); // Read the Safety Status registers to find which protections have triggered
			if (ProtectionsTriggered & 1) 
			{
				// Turn on the LED to indicate Protection has triggered
				HAL_GPIO_WritePin(GPIOA, LD2_Pin, GPIO_PIN_SET); 
			}
			DirectCommands(AlarmStatus, 0xF800, W); // Clear the Safety Status Alarm bits.
		}
		else
		{
			if (ProtectionsTriggered & 1) 
			{
				BQ769x2_ReadSafetyStatus();
				if (!(ProtectionsTriggered & 1)) 
				{
					// Turn off the LED if Safety Status has cleared which means the protection condition is no longer present
					HAL_GPIO_WritePin(GPIOA, LD2_Pin, GPIO_PIN_RESET);
				} 
			} 
		}
		delayUS(20000);  // repeat loop every 20 ms
  }
  /* USER CODE END 3 */
}

/**
  * @brief System Clock Configuration
  * @retval None
  */
void SystemClock_Config(void)
{
  RCC_OscInitTypeDef RCC_OscInitStruct = {0};
  RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};

  /** Initializes the RCC Oscillators according to the specified parameters
  * in the RCC_OscInitTypeDef structure.
  */
  RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;
  RCC_OscInitStruct.HSEState = RCC_HSE_ON;
  RCC_OscInitStruct.HSEPredivValue = RCC_HSE_PREDIV_DIV1;
  RCC_OscInitStruct.HSIState = RCC_HSI_ON;
  RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
  RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
  RCC_OscInitStruct.PLL.PLLMUL = RCC_PLL_MUL8;
  if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
  {
    Error_Handler();
  }
  /** Initializes the CPU, AHB and APB buses clocks
  */
  RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
                              |RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;
  RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
  RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
  RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV2;
  RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;

  if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_2) != HAL_OK)
  {
    Error_Handler();
  }
}

/**
  * @brief I2C1 Initialization Function
  * @param None
  * @retval None
  */
static void MX_I2C1_Init(void)
{

  /* USER CODE BEGIN I2C1_Init 0 */

  /* USER CODE END I2C1_Init 0 */

  /* USER CODE BEGIN I2C1_Init 1 */

  /* USER CODE END I2C1_Init 1 */
  hi2c1.Instance = I2C1;
  hi2c1.Init.ClockSpeed = 400000;
  hi2c1.Init.DutyCycle = I2C_DUTYCYCLE_2;
  hi2c1.Init.OwnAddress1 = 0;
  hi2c1.Init.AddressingMode = I2C_ADDRESSINGMODE_7BIT;
  hi2c1.Init.DualAddressMode = I2C_DUALADDRESS_DISABLE;
  hi2c1.Init.OwnAddress2 = 0;
  hi2c1.Init.GeneralCallMode = I2C_GENERALCALL_DISABLE;
  hi2c1.Init.NoStretchMode = I2C_NOSTRETCH_DISABLE;
  if (HAL_I2C_Init(&hi2c1) != HAL_OK)
  {
    Error_Handler();
  }
  /* USER CODE BEGIN I2C1_Init 2 */

  /* USER CODE END I2C1_Init 2 */

}

/**
  * @brief TIM1 Initialization Function
  * @param None
  * @retval None
  */
static void MX_TIM1_Init(void)
{

  /* USER CODE BEGIN TIM1_Init 0 */

  /* USER CODE END TIM1_Init 0 */

  TIM_ClockConfigTypeDef sClockSourceConfig = {0};
  TIM_MasterConfigTypeDef sMasterConfig = {0};

  /* USER CODE BEGIN TIM1_Init 1 */

  /* USER CODE END TIM1_Init 1 */
  htim1.Instance = TIM1;
  htim1.Init.Prescaler = 63;
  htim1.Init.CounterMode = TIM_COUNTERMODE_UP;
  htim1.Init.Period = 65535;
  htim1.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
  htim1.Init.RepetitionCounter = 0;
  htim1.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE;
  if (HAL_TIM_Base_Init(&htim1) != HAL_OK)
  {
    Error_Handler();
  }
  sClockSourceConfig.ClockSource = TIM_CLOCKSOURCE_INTERNAL;
  if (HAL_TIM_ConfigClockSource(&htim1, &sClockSourceConfig) != HAL_OK)
  {
    Error_Handler();
  }
  sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET;
  sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;
  if (HAL_TIMEx_MasterConfigSynchronization(&htim1, &sMasterConfig) != HAL_OK)
  {
    Error_Handler();
  }
  /* USER CODE BEGIN TIM1_Init 2 */

  /* USER CODE END TIM1_Init 2 */

}

/**
  * @brief USART2 Initialization Function
  * @param None
  * @retval None
  */
static void MX_USART2_UART_Init(void)
{

  /* USER CODE BEGIN USART2_Init 0 */

  /* USER CODE END USART2_Init 0 */

  /* USER CODE BEGIN USART2_Init 1 */

  /* USER CODE END USART2_Init 1 */
  huart2.Instance = USART2;
  huart2.Init.BaudRate = 115200;
  huart2.Init.WordLength = UART_WORDLENGTH_8B;
  huart2.Init.StopBits = UART_STOPBITS_1;
  huart2.Init.Parity = UART_PARITY_NONE;
  huart2.Init.Mode = UART_MODE_TX_RX;
  huart2.Init.HwFlowCtl = UART_HWCONTROL_NONE;
  huart2.Init.OverSampling = UART_OVERSAMPLING_16;
  if (HAL_UART_Init(&huart2) != HAL_OK)
  {
    Error_Handler();
  }
  /* USER CODE BEGIN USART2_Init 2 */

  /* USER CODE END USART2_Init 2 */

}

/**
  * @brief GPIO Initialization Function
  * @param None
  * @retval None
  */
static void MX_GPIO_Init(void)
{
  GPIO_InitTypeDef GPIO_InitStruct = {0};

  /* GPIO Ports Clock Enable */
  __HAL_RCC_GPIOC_CLK_ENABLE();
  __HAL_RCC_GPIOD_CLK_ENABLE();
  __HAL_RCC_GPIOA_CLK_ENABLE();
  __HAL_RCC_GPIOB_CLK_ENABLE();

  /*Configure GPIO pin Output Level */
  HAL_GPIO_WritePin(GPIOA, LD2_Pin|GPIO_PIN_8|GPIO_PIN_9|GPIO_PIN_10, GPIO_PIN_RESET);

  /*Configure GPIO pin : B1_Pin */
  GPIO_InitStruct.Pin = B1_Pin;
  GPIO_InitStruct.Mode = GPIO_MODE_IT_RISING;
  GPIO_InitStruct.Pull = GPIO_NOPULL;
  HAL_GPIO_Init(B1_GPIO_Port, &GPIO_InitStruct);

  /*Configure GPIO pins : LD2_Pin PA8 PA9 PA10 */
  GPIO_InitStruct.Pin = LD2_Pin|GPIO_PIN_8|GPIO_PIN_9|GPIO_PIN_10;
  GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
  GPIO_InitStruct.Pull = GPIO_NOPULL;
  GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
  HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);

  /* EXTI interrupt init*/
  HAL_NVIC_SetPriority(EXTI15_10_IRQn, 0, 0);
  HAL_NVIC_EnableIRQ(EXTI15_10_IRQn);

}

/* USER CODE BEGIN 4 */

/* USER CODE END 4 */

/**
  * @brief  This function is executed in case of error occurrence.
  * @retval None
  */
void Error_Handler(void)
{
  /* USER CODE BEGIN Error_Handler_Debug */
  /* User can add his own implementation to report the HAL error return state */

  /* USER CODE END Error_Handler_Debug */
}

#ifdef  USE_FULL_ASSERT
/**
  * @brief  Reports the name of the source file and the source line number
  *         where the assert_param error has occurred.
  * @param  file: pointer to the source file name
  * @param  line: assert_param error line source number
  * @retval None
  */
void assert_failed(uint8_t *file, uint32_t line)
{
  /* USER CODE BEGIN 6 */
  /* User can add his own implementation to report the file name and line number,
     tex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */
  /* USER CODE END 6 */
}
#endif /* USE_FULL_ASSERT */

/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/

<BQ769x2Header.h> 代码如下:

//BQ769x2 General Program Header File
typedef unsigned char		uint8_t;
typedef unsigned short int  uint16_t;
typedef unsigned long int   uint32_t;

//Data	Memory	registers	Name in TRM
#define Cell1Gain 0x9180      //Calibration:Voltage:Cell 1 Gain			
#define Cell2Gain 0x9182      //Calibration:Voltage:Cell 2 Gain			
#define Cell3Gain 0x9184      //Calibration:Voltage:Cell 3 Gain			
#define Cell4Gain 0x9186      //Calibration:Voltage:Cell 4 Gain			
#define Cell5Gain 0x9188      //Calibration:Voltage:Cell 5 Gain			
#define Cell6Gain 0x918A      //Calibration:Voltage:Cell 6 Gain			
#define Cell7Gain 0x918C      //Calibration:Voltage:Cell 7 Gain			
#define Cell8Gain 0x918E      //Calibration:Voltage:Cell 8 Gain			
#define Cell9Gain 0x9190      //Calibration:Voltage:Cell 9 Gain			
#define Cell10Gain 0x9192      //Calibration:Voltage:Cell 10 Gain			
#define Cell11Gain 0x9194      //Calibration:Voltage:Cell 11 Gain			
#define Cell12Gain 0x9196      //Calibration:Voltage:Cell 12 Gain			
#define Cell13Gain 0x9198      //Calibration:Voltage:Cell 13 Gain			
#define Cell14Gain 0x919A      //Calibration:Voltage:Cell 14 Gain			
#define Cell15Gain 0x919C      //Calibration:Voltage:Cell 15 Gain			
#define Cell16Gain 0x919E      //Calibration:Voltage:Cell 16 Gain			
#define PackGain 0x91A0      //Calibration:Voltage:Pack Gain			
#define TOSGain 0x91A2      //Calibration:Voltage:TOS Gain			
#define LDGain 0x91A4      //Calibration:Voltage:LD Gain			
#define ADCGain 0x91A6      //Calibration:Voltage:ADC Gain			
#define CCGain 0x91A8      //Calibration:Current:CC Gain			
#define CapacityGain 0x91AC      //Calibration:Current:Capacity Gain			
#define VcellOffset 0x91B0      //Calibration:Vcell Offset:Vcell Offset			
#define VdivOffset 0x91B2      //Calibration:V Divider Offset:Vdiv Offset			
#define CoulombCounterOffsetSamples 0x91C6      //Calibration:Current Offset:Coulomb Counter Offset Samples			
#define BoardOffset 0x91C8      //Calibration:Current Offset:Board Offset			
#define InternalTempOffset 0x91CA      //Calibration:Temperature:Internal Temp Offset			
#define CFETOFFTempOffset 0x91CB      //Calibration:Temperature:CFETOFF Temp Offset			
#define DFETOFFTempOffset 0x91CC      //Calibration:Temperature:DFETOFF Temp Offset			
#define ALERTTempOffset 0x91CD      //Calibration:Temperature:ALERT Temp Offset			
#define TS1TempOffset 0x91CE      //Calibration:Temperature:TS1 Temp Offset			
#define TS2TempOffset 0x91CF      //Calibration:Temperature:TS2 Temp Offset			
#define TS3TempOffset 0x91D0      //Calibration:Temperature:TS3 Temp Offset			
#define HDQTempOffset 0x91D1      //Calibration:Temperature:HDQ Temp Offset			
#define DCHGTempOffset 0x91D2      //Calibration:Temperature:DCHG Temp Offset			
#define DDSGTempOffset 0x91D3      //Calibration:Temperature:DDSG Temp Offset			
#define IntGain 0x91E2      //Calibration:Internal Temp Model:Int Gain			
#define Intbaseoffset 0x91E4      //Calibration:Internal Temp Model:Int base offset			
#define IntMaximumAD 0x91E6      //Calibration:Internal Temp Model:Int Maximum AD			
#define IntMaximumTemp 0x91E8      //Calibration:Internal Temp Model:Int Maximum Temp			
#define T18kCoeffa1 0x91EA      //Calibration:18K Temperature Model:Coeff a1			
#define T18kCoeffa2 0x91EC      //Calibration:18K Temperature Model:Coeff a2			
#define T18kCoeffa3 0x91EE      //Calibration:18K Temperature Model:Coeff a3			
#define T18kCoeffa4 0x91F0      //Calibration:18K Temperature Model:Coeff a4			
#define T18kCoeffa5 0x91F2      //Calibration:18K Temperature Model:Coeff a5			
#define T18kCoeffb1 0x91F4      //Calibration:18K Temperature Model:Coeff b1			
#define T18kCoeffb2 0x91F6      //Calibration:18K Temperature Model:Coeff b2			
#define T18kCoeffb3 0x91F8      //Calibration:18K Temperature Model:Coeff b3			
#define T18kCoeffb4 0x91FA      //Calibration:18K Temperature Model:Coeff b4			
#define T18kAdc0 0x91FE      //Calibration:18K Temperature Model:Adc0			
#define T180kCoeffa1 0x9200      //Calibration:180K Temperature Model:Coeff a1			
#define T180kCoeffa2 0x9202      //Calibration:180K Temperature Model:Coeff a2			
#define T180kCoeffa3 0x9204      //Calibration:180K Temperature Model:Coeff a3			
#define T180kCoeffa4 0x9206      //Calibration:180K Temperature Model:Coeff a4			
#define T180kCoeffa5 0x9208      //Calibration:180K Temperature Model:Coeff a5			
#define T180kCoeffb1 0x920A      //Calibration:180K Temperature Model:Coeff b1			
#define T180kCoeffb2 0x920C      //Calibration:180K Temperature Model:Coeff b2			
#define T180kCoeffb3 0x920E      //Calibration:180K Temperature Model:Coeff b3			
#define T180kCoeffb4 0x9210      //Calibration:180K Temperature Model:Coeff b4			
#define T180kAdc0 0x9214      //Calibration:180K Temperature Model:Adc0			
#define CustomCoeffa1 0x9216      //Calibration:Custom Temperature Model:Coeff a1			
#define CustomCoeffa2 0x9218      //Calibration:Custom Temperature Model:Coeff a2			
#define CustomCoeffa3 0x921A      //Calibration:Custom Temperature Model:Coeff a3			
#define CustomCoeffa4 0x921C      //Calibration:Custom Temperature Model:Coeff a4			
#define CustomCoeffa5 0x921E      //Calibration:Custom Temperature Model:Coeff a5			
#define CustomCoeffb1 0x9220      //Calibration:Custom Temperature Model:Coeff b1			
#define CustomCoeffb2 0x9222      //Calibration:Custom Temperature Model:Coeff b2			
#define CustomCoeffb3 0x9224      //Calibration:Custom Temperature Model:Coeff b3			
#define CustomCoeffb4 0x9226      //Calibration:Custom Temperature Model:Coeff b4			
#define CustomRc0 0x9228      //Calibration:Custom Temperature Model:Rc0			
#define CustomAdc0 0x922A      //Calibration:Custom Temperature Model:Adc0			
#define CoulombCounterDeadband 0x922D      //Calibration:Current Deadband:Coulomb Counter Deadband			
#define CUVThresholdOverride 0x91D4      //Calibration:CUV:CUV Threshold Override			
#define COVThresholdOverride 0x91D6      //Calibration:COV:COV Threshold Override			
#define MinBlowFuseVoltage 0x9231      //Settings:Fuse:Min Blow Fuse Voltage			
#define FuseBlowTimeout 0x9233      //Settings:Fuse:Fuse Blow Timeout			
#define PowerConfig 0x9234      //Settings:Configuration:Power Config			
#define REG12Config 0x9236      //Settings:Configuration:REG12 Config			
#define REG0Config 0x9237      //Settings:Configuration:REG0 Config			
#define HWDRegulatorOptions 0x9238      //Settings:Configuration:HWD Regulator Options			
#define CommType 0x9239      //Settings:Configuration:Comm Type			
#define I2CAddress 0x923A      //Settings:Configuration:I2C Address			
#define SPIConfiguration 0x923C      //Settings:Configuration:SPI Configuration			
#define CommIdleTime 0x923D      //Settings:Configuration:Comm Idle Time			
#define CFETOFFPinConfig 0x92FA      //Settings:Configuration:CFETOFF Pin Config			
#define DFETOFFPinConfig 0x92FB      //Settings:Configuration:DFETOFF Pin Config			
#define ALERTPinConfig 0x92FC      //Settings:Configuration:ALERT Pin Config			
#define TS1Config 0x92FD      //Settings:Configuration:TS1 Config			
#define TS2Config 0x92FE      //Settings:Configuration:TS2 Config			
#define TS3Config 0x92FF      //Settings:Configuration:TS3 Config			
#define HDQPinConfig 0x9300      //Settings:Configuration:HDQ Pin Config			
#define DCHGPinConfig 0x9301      //Settings:Configuration:DCHG Pin Config			
#define DDSGPinConfig 0x9302      //Settings:Configuration:DDSG Pin Config			
#define DAConfiguration 0x9303      //Settings:Configuration:DA Configuration			
#define VCellMode 0x9304      //Settings:Configuration:Vcell Mode			
#define CC3Samples 0x9307      //Settings:Configuration:CC3 Samples			
#define ProtectionConfiguration 0x925F      //Settings:Protection:Protection Configuration			
#define EnabledProtectionsA 0x9261      //Settings:Protection:Enabled Protections A			
#define EnabledProtectionsB 0x9262      //Settings:Protection:Enabled Protections B			
#define EnabledProtectionsC 0x9263      //Settings:Protection:Enabled Protections C			
#define CHGFETProtectionsA 0x9265      //Settings:Protection:CHG FET Protections A			
#define CHGFETProtectionsB 0x9266      //Settings:Protection:CHG FET Protections B			
#define CHGFETProtectionsC 0x9267      //Settings:Protection:CHG FET Protections C			
#define DSGFETProtectionsA 0x9269      //Settings:Protection:DSG FET Protections A			
#define DSGFETProtectionsB 0x926A      //Settings:Protection:DSG FET Protections B			
#define DSGFETProtectionsC 0x926B      //Settings:Protection:DSG FET Protections C			
#define BodyDiodeThreshold 0x9273      //Settings:Protection:Body Diode Threshold			
#define DefaultAlarmMask 0x926D      //Settings:Alarm:Default Alarm Mask			
#define SFAlertMaskA 0x926F      //Settings:Alarm:SF Alert Mask A			
#define SFAlertMaskB 0x9270      //Settings:Alarm:SF Alert Mask B			
#define SFAlertMaskC 0x9271      //Settings:Alarm:SF Alert Mask C			
#define PFAlertMaskA 0x92C4      //Settings:Alarm:PF Alert Mask A			
#define PFAlertMaskB 0x92C5      //Settings:Alarm:PF Alert Mask B			
#define PFAlertMaskC 0x92C6      //Settings:Alarm:PF Alert Mask C			
#define PFAlertMaskD 0x92C7      //Settings:Alarm:PF Alert Mask D			
#define EnabledPFA 0x92C0      //Settings:Permanent Failure:Enabled PF A			
#define EnabledPFB 0x92C1      //Settings:Permanent Failure:Enabled PF B			
#define EnabledPFC 0x92C2      //Settings:Permanent Failure:Enabled PF C			
#define EnabledPFD 0x92C3      //Settings:Permanent Failure:Enabled PF D			
#define FETOptions 0x9308      //Settings:FET:FET Options			
#define ChgPumpControl 0x9309      //Settings:FET:Chg Pump Control			
#define PrechargeStartVoltage 0x930A      //Settings:FET:Precharge Start Voltage			
#define PrechargeStopVoltage 0x930C      //Settings:FET:Precharge Stop Voltage			
#define PredischargeTimeout 0x930E      //Settings:FET:Predischarge Timeout			
#define PredischargeStopDelta 0x930F      //Settings:FET:Predischarge Stop Delta			
#define DsgCurrentThreshold 0x9310      //Settings:Current Thresholds:Dsg Current Threshold			
#define ChgCurrentThreshold 0x9312      //Settings:Current Thresholds:Chg Current Threshold			
#define CheckTime 0x9314      //Settings:Cell Open-Wire:Check Time			
#define Cell1Interconnect 0x9315      //Settings:Interconnect Resistances:Cell 1 Interconnect			
#define Cell2Interconnect 0x9317      //Settings:Interconnect Resistances:Cell 2 Interconnect			
#define Cell3Interconnect 0x9319      //Settings:Interconnect Resistances:Cell 3 Interconnect			
#define Cell4Interconnect 0x931B      //Settings:Interconnect Resistances:Cell 4 Interconnect			
#define Cell5Interconnect 0x931D      //Settings:Interconnect Resistances:Cell 5 Interconnect			
#define Cell6Interconnect 0x931F      //Settings:Interconnect Resistances:Cell 6 Interconnect			
#define Cell7Interconnect 0x9321      //Settings:Interconnect Resistances:Cell 7 Interconnect			
#define Cell8Interconnect 0x9323      //Settings:Interconnect Resistances:Cell 8 Interconnect			
#define Cell9Interconnect 0x9325      //Settings:Interconnect Resistances:Cell 9 Interconnect			
#define Cell10Interconnect 0x9327      //Settings:Interconnect Resistances:Cell 10 Interconnect			
#define Cell11Interconnect 0x9329      //Settings:Interconnect Resistances:Cell 11 Interconnect			
#define Cell12Interconnect 0x932B      //Settings:Interconnect Resistances:Cell 12 Interconnect			
#define Cell13Interconnect 0x932D      //Settings:Interconnect Resistances:Cell 13 Interconnect			
#define Cell14Interconnect 0x932F      //Settings:Interconnect Resistances:Cell 14 Interconnect			
#define Cell15Interconnect 0x9331      //Settings:Interconnect Resistances:Cell 15 Interconnect			
#define Cell16Interconnect 0x9333      //Settings:Interconnect Resistances:Cell 16 Interconnect			
#define MfgStatusInit 0x9343      //Settings:Manufacturing:Mfg Status Init			
#define BalancingConfiguration 0x9335      //Settings:Cell Balancing Config:Balancing Configuration			
#define MinCellTemp 0x9336      //Settings:Cell Balancing Config:Min Cell Temp			
#define MaxCellTemp 0x9337      //Settings:Cell Balancing Config:Max Cell Temp			
#define MaxInternalTemp 0x9338      //Settings:Cell Balancing Config:Max Internal Temp			
#define CellBalanceInterval 0x9339      //Settings:Cell Balancing Config:Cell Balance Interval			
#define CellBalanceMaxCells 0x933A      //Settings:Cell Balancing Config:Cell Balance Max Cells			
#define CellBalanceMinCellVCharge 0x933B      //Settings:Cell Balancing Config:Cell Balance Min Cell V (Charge)			
#define CellBalanceMinDeltaCharge 0x933D      //Settings:Cell Balancing Config:Cell Balance Min Delta (Charge)			
#define CellBalanceStopDeltaCharge 0x933E      //Settings:Cell Balancing Config:Cell Balance Stop Delta (Charge)			
#define CellBalanceMinCellVRelax 0x933F      //Settings:Cell Balancing Config:Cell Balance Min Cell V (Relax)			
#define CellBalanceMinDeltaRelax 0x9341      //Settings:Cell Balancing Config:Cell Balance Min Delta (Relax)			
#define CellBalanceStopDeltaRelax 0x9342      //Settings:Cell Balancing Config:Cell Balance Stop Delta (Relax)			
#define ShutdownCellVoltage 0x923F      //Power:Shutdown:Shutdown Cell Voltage			
#define ShutdownStackVoltage 0x9241      //Power:Shutdown:Shutdown Stack Voltage			
#define LowVShutdownDelay 0x9243      //Power:Shutdown:Low V Shutdown Delay			
#define ShutdownTemperature 0x9244      //Power:Shutdown:Shutdown Temperature			
#define ShutdownTemperatureDelay 0x9245      //Power:Shutdown:Shutdown Temperature Delay			
#define FETOffDelay 0x9252      //Power:Shutdown:FET Off Delay			
#define ShutdownCommandDelay 0x9253      //Power:Shutdown:Shutdown Command Delay			
#define AutoShutdownTime 0x9254      //Power:Shutdown:Auto Shutdown Time			
#define RAMFailShutdownTime 0x9255      //Power:Shutdown:RAM Fail Shutdown Time			
#define SleepCurrent 0x9248      //Power:Sleep:Sleep Current			
#define VoltageTime 0x924A      //Power:Sleep:Voltage Time			
#define WakeComparatorCurrent 0x924B      //Power:Sleep:Wake Comparator Current			
#define SleepHysteresisTime 0x924D      //Power:Sleep:Sleep Hysteresis Time			
#define SleepChargerVoltageThreshold 0x924E      //Power:Sleep:Sleep Charger Voltage Threshold			
#define SleepChargerPACKTOSDelta 0x9250      //Power:Sleep:Sleep Charger PACK-TOS Delta			
#define ConfigRAMSignature 0x91E0      //System Data:Integrity:Config RAM Signature			
#define CUVThreshold 0x9275      //Protections:CUV:Threshold			
#define CUVDelay 0x9276      //Protections:CUV:Delay			
#define CUVRecoveryHysteresis 0x927B      //Protections:CUV:Recovery Hysteresis			
#define COVThreshold 0x9278      //Protections:COV:Threshold			
#define COVDelay 0x9279      //Protections:COV:Delay			
#define COVRecoveryHysteresis 0x927C      //Protections:COV:Recovery Hysteresis			
#define COVLLatchLimit 0x927D      //Protections:COVL:Latch Limit			
#define COVLCounterDecDelay 0x927E      //Protections:COVL:Counter Dec Delay			
#define COVLRecoveryTime 0x927F      //Protections:COVL:Recovery Time			
#define OCCThreshold 0x9280      //Protections:OCC:Threshold			
#define OCCDelay 0x9281      //Protections:OCC:Delay			
#define OCCRecoveryThreshold 0x9288      //Protections:OCC:Recovery Threshold			
#define OCCPACKTOSDelta 0x92B0      //Protections:OCC:PACK-TOS Delta			
#define OCD1Threshold 0x9282      //Protections:OCD1:Threshold			
#define OCD1Delay 0x9283      //Protections:OCD1:Delay			
#define OCD2Threshold 0x9284      //Protections:OCD2:Threshold			
#define OCD2Delay 0x9285      //Protections:OCD2:Delay			
#define SCDThreshold 0x9286      //Protections:SCD:Threshold			
#define SCDDelay 0x9287      //Protections:SCD:Delay			
#define SCDRecoveryTime 0x9294      //Protections:SCD:Recovery Time			
#define OCD3Threshold 0x928A      //Protections:OCD3:Threshold			
#define OCD3Delay 0x928C      //Protections:OCD3:Delay			
#define OCDRecoveryThreshold 0x928D      //Protections:OCD:Recovery Threshold			
#define OCDLLatchLimit 0x928F      //Protections:OCDL:Latch Limit			
#define OCDLCounterDecDelay 0x9290      //Protections:OCDL:Counter Dec Delay			
#define OCDLRecoveryTime 0x9291      //Protections:OCDL:Recovery Time			
#define OCDLRecoveryThreshold 0x9292      //Protections:OCDL:Recovery Threshold			
#define SCDLLatchLimit 0x9295      //Protections:SCDL:Latch Limit			
#define SCDLCounterDecDelay 0x9296      //Protections:SCDL:Counter Dec Delay			
#define SCDLRecoveryTime 0x9297      //Protections:SCDL:Recovery Time			
#define SCDLRecoveryThreshold 0x9298      //Protections:SCDL:Recovery Threshold			
#define OTCThreshold 0x929A      //Protections:OTC:Threshold			
#define OTCDelay 0x920B      //Protections:OTC:Delay			
#define OTCRecovery 0x929C      //Protections:OTC:Recovery			
#define OTDThreshold 0x929D      //Protections:OTD:Threshold			
#define OTDDelay 0x929E      //Protections:OTD:Delay			
#define OTDRecovery 0x929F      //Protections:OTD:Recovery			
#define OTFThreshold 0x92A0      //Protections:OTF:Threshold			
#define OTFDelay 0x92A1      //Protections:OTF:Delay			
#define OTFRecovery 0x92A2      //Protections:OTF:Recovery			
#define OTINTThreshold 0x92A3      //Protections:OTINT:Threshold			
#define OTINTDelay 0x92A4      //Protections:OTINT:Delay			
#define OTINTRecovery 0x92A5      //Protections:OTINT:Recovery			
#define UTCThreshold 0x92A6      //Protections:UTC:Threshold			
#define UTCDelay 0x92A7      //Protections:UTC:Delay			
#define UTCRecovery 0x92A8      //Protections:UTC:Recovery			
#define UTDThreshold 0x92A9      //Protections:UTD:Threshold			
#define UTDDelay 0x92AA      //Protections:UTD:Delay			
#define UTDRecovery 0x92AB      //Protections:UTD:Recovery			
#define UTINTThreshold 0x92AC      //Protections:UTINT:Threshold			
#define UTINTDelay 0x92AD      //Protections:UTINT:Delay			
#define UTINTRecovery 0x92AE      //Protections:UTINT:Recovery			
#define ProtectionsRecoveryTime 0x92AF      //Protections:Recovery:Time			
#define HWDDelay 0x92B2      //Protections:HWD:Delay			
#define LoadDetectActiveTime 0x92B4      //Protections:Load Detect:Active Time			
#define LoadDetectRetryDelay 0x92B5      //Protections:Load Detect:Retry Delay			
#define LoadDetectTimeout 0x92B6      //Protections:Load Detect:Timeout			
#define PTOChargeThreshold 0x92BA      //Protections:PTO:Charge Threshold			
#define PTODelay 0x92BC      //Protections:PTO:Delay			
#define PTOReset 0x92BE      //Protections:PTO:Reset			
#define CUDEPThreshold 0x92C8      //Permanent Fail:CUDEP:Threshold			
#define CUDEPDelay 0x92CA      //Permanent Fail:CUDEP:Delay			
#define SUVThreshold 0x92CB      //Permanent Fail:SUV:Threshold			
#define SUVDelay 0x92CD      //Permanent Fail:SUV:Delay			
#define SOVThreshold 0x92CE      //Permanent Fail:SOV:Threshold			
#define SOVDelay 0x92D0      //Permanent Fail:SOV:Delay			
#define TOSSThreshold 0x92D1      //Permanent Fail:TOS:Threshold			
#define TOSSDelay 0x92D3      //Permanent Fail:TOS:Delay			
#define SOCCThreshold 0x92D4      //Permanent Fail:SOCC:Threshold			
#define SOCCDelay 0x92D6      //Permanent Fail:SOCC:Delay			
#define SOCDThreshold 0x92D7      //Permanent Fail:SOCD:Threshold			
#define SOCDDelay 0x92D9      //Permanent Fail:SOCD:Delay			
#define SOTThreshold 0x92DA      //Permanent Fail:SOT:Threshold			
#define SOTDelay 0x92DB      //Permanent Fail:SOT:Delay			
#define SOTFThreshold 0x92DC      //Permanent Fail:SOTF:Threshold			
#define SOTFDelay 0x92DD      //Permanent Fail:SOTF:Delay			
#define VIMRCheckVoltage 0x92DE      //Permanent Fail:VIMR:Check Voltage			
#define VIMRMaxRelaxCurrent 0x92E0      //Permanent Fail:VIMR:Max Relax Current			
#define VIMRThreshold 0x92E2      //Permanent Fail:VIMR:Threshold			
#define VIMRDelay 0x92E4      //Permanent Fail:VIMR:Delay			
#define VIMRRelaxMinDuration 0x92E5      //Permanent Fail:VIMR:Relax Min Duration			
#define VIMACheckVoltage 0x92E7      //Permanent Fail:VIMA:Check Voltage			
#define VIMAMinActiveCurrent 0x92E9      //Permanent Fail:VIMA:Min Active Current			
#define VIMAThreshold 0x92EB      //Permanent Fail:VIMA:Threshold			
#define VIMADelay 0x92ED      //Permanent Fail:VIMA:Delay			
#define CFETFOFFThreshold 0x92EE      //Permanent Fail:CFETF:OFF Threshold			
#define CFETFOFFDelay 0x92F0      //Permanent Fail:CFETF:OFF Delay			
#define DFETFOFFThreshold 0x92F1      //Permanent Fail:DFETF:OFF Threshold			
#define DFETFOFFDelay 0x92F3      //Permanent Fail:DFETF:OFF Delay			
#define VSSFFailThreshold 0x92F4      //Permanent Fail:VSSF:Fail Threshold			
#define VSSFDelay 0x92F6      //Permanent Fail:VSSF:Delay			
#define PF2LVLDelay 0x92F7      //Permanent Fail:2LVL:Delay			
#define LFOFDelay 0x92F8      //Permanent Fail:LFOF:Delay			
#define HWMXDelay 0x92F9      //Permanent Fail:HWMX:Delay			
#define SecuritySettings 0x9256      //Security:Settings:Security Settings			
#define UnsealKeyStep1 0x9257      //Security:Keys:Unseal Key Step 1			
#define UnsealKeyStep2 0x9259      //Security:Keys:Unseal Key Step 2			
#define FullAccessKeyStep1 0x925B      //Security:Keys:Full Access Key Step 1			
#define FullAccessKeyStep2 0x925D      //Security:Keys:Full Access Key Step 2			

//Direct Commands 
#define ControlStatus 0x00
#define SafetyAlertA 0x02
#define SafetyStatusA 0x03
#define SafetyAlertB 0x04
#define SafetyStatusB 0x05
#define SafetyAlertC 0x06
#define SafetyStatusC 0x07
#define PFAlertA 0x0A
#define PFStatusA 0x0B
#define PFAlertB 0x0C
#define PFStatusB 0x0D
#define PFAlertC 0x0E
#define PFStatusC 0x0F
#define PFAlertD 0x10
#define PFStatusD 0x11
#define BatteryStatus 0x12
#define Cell1Voltage 0x14
#define Cell2Voltage 0x16
#define Cell3Voltage 0x18
#define Cell4Voltage 0x1A
#define Cell5Voltage 0x1C
#define Cell6Voltage 0x1E
#define Cell7Voltage 0x20
#define Cell8Voltage 0x22
#define Cell9Voltage 0x24
#define Cell10Voltage 0x26
#define Cell11Voltage 0x28
#define Cell12Voltage 0x2A
#define Cell13Voltage 0x2C
#define Cell14Voltage 0x2E
#define Cell15Voltage 0x30
#define Cell16Voltage 0x32
#define StackVoltage 0x34
#define PACKPinVoltage 0x36
#define LDPinVoltage 0x38
#define CC2Current 0x3A
#define AlarmStatus 0x62
#define AlarmRawStatus 0x64
#define AlarmEnable 0x66
#define IntTemperature 0x68
#define CFETOFFTemperature 0x6A
#define DFETOFFTemperature 0x6C
#define ALERTTemperature 0x6E
#define TS1Temperature 0x70
#define TS2Temperature 0x72
#define TS3Temperature 0x74
#define HDQTemperature 0x76
#define DCHGTemperature 0x78
#define DDSGTemperature 0x7A
#define FETStatus 0x7F

//Subcommands 
#define DEVICE_NUMBER 0x0001
#define FW_VERSION 0x0002
#define HW_VERSION 0x0003
#define IROM_SIG 0x0004
#define STATIC_CFG_SIG 0x0005
#define PREV_MACWRITE 0x0007
#define DROM_SIG 0x0009
#define SECURITY_KEYS 0x0035
#define SAVED_PF_STATUS 0x0053
#define MANUFACTURINGSTATUS 0x0057
#define MANU_DATA 0x0070
#define DASTATUS1 0x0071
#define DASTATUS2 0x0072
#define DASTATUS3 0x0073
#define DASTATUS4 0x0074
#define DASTATUS5 0x0075
#define DASTATUS6 0x0076
#define DASTATUS7 0x0077
#define CUV_SNAPSHOT 0x0080
#define COV_SNAPSHOT 0X0081
#define CB_ACTIVE_CELLS 0x0083
#define CB_SET_LVL 0x0084
#define CBSTATUS1 0x0085
#define CBSTATUS2 0x0086
#define CBSTATUS3 0x0087
#define FET_CONTROL 0x0097
#define REG12_CONTROL 0x0098
#define OTP_WR_CHECK 0x00A0
#define OTP_WRITE 0x00A1
#define READ_CAL1 0xF081
#define CAL_CUV 0xF090
#define CAL_COV 0xF091

// Command Only Subcommands 
#define EXIT_DEEPSLEEP 0x000E
#define DEEPSLEEP 0x000F
#define SHUTDOWN 0x0010
#define BQ769x2_RESET 0x0012 //"RESET" in documentation
#define PDSGTEST 0x001C
#define FUSE_TOGGLE 0x001D
#define PCHGTEST 0x001E
#define CHGTEST 0x001F
#define DSGTEST 0x0020
#define FET_ENABLE 0x0022
#define PF_ENABLE 0x0024
#define PF_RESET 0x0029
#define SEAL 0x0030
#define RESET_PASSQ 0x0082
#define PTO_RECOVER 0x008A
#define SET_CFGUPDATE 0x0090
#define EXIT_CFGUPDATE 0x0092
#define DSG_PDSG_OFF 0x0093
#define CHG_PCHG_OFF 0x0094
#define ALL_FETS_OFF 0x0095
#define ALL_FETS_ON 0x0096
#define SLEEP_ENABLE 0x0099
#define SLEEP_DISABLE 0x009A
#define OCDL_RECOVER 0x009B
#define SCDL_RECOVER 0x009C
#define LOAD_DETECT_RESTART 0x009D
#define LOAD_DETECT_ON 0x009E
#define LOAD_DETECT_OFF 0x009F
#define CFETOFF_LO 0x2800
#define DFETOFF_LO 0x2801
#define ALERT_LO 0x2802
#define HDQ_LO 0x2806
#define DCHG_LO 0x2807
#define DDSG_LO 0x2808
#define CFETOFF_HI 0x2810
#define DFETOFF_HI 0x2811
#define ALERT_HI 0x2812
#define HDQ_HI 0x2816
#define DCHG_HI 0x2817
#define DDSG_HI 0x2818
#define PF_FORCE_A 0x2857
#define PF_FORCE_B 0x29A3
#define SWAP_COMM_MODE 0x29BC
#define SWAP_TO_I2C 0x29E7
#define SWAP_TO_SPI 0x7C35
#define SWAP_TO_HDQ 0x7C40
  • 19
    点赞
  • 28
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
本应用报告包含多种信息,可帮助用户配置 BQ769x2 系列电池监控器(包括 BQ76942 和 BQ76952)。为帮助用户熟悉器件设置,此文档提供了多个常用配置示例。 1 引言 BQ769x2 电池监控器系列包括许多配置选项,可满足各种应用的需求。本文档使用 BQ76942 评估模块和 Battery Management Studio 演示了多个不同的配置示例。这些示例还可应用于 BQ769x2 系列中的所有器件。本文档还包含一个示例 .gg 文件,可使用 Battery Management Studio 将其加载到评估模块上。BQ76942 评估模块用户指南 包含有关设置器件的基本信息,本文档应与该指南一同使用。 2 基本配置 浏览 BQ76942 评估模块用户指南 的“快速入门”部分后,请参阅以下部分,了解配置器件的后续步骤。器件数据表和 TRM(技术参考手册)中提供了有关每个特性的更多详细信息。Battery Management Studio 还包括工具提示,当鼠标指针在不同字段上移动时,这些提示会提供不同设置的详细说明。 2.1 稳压器设置 BQ769x2 包含一个 1.8V 稳压器 (REG18) 和两个具有多种电压选项的 LDO(REG1 和 REG2)。REG18 电源不可配置,仅用于内部电路,而 REG1 和 REG2 是可配置的,可用于为外部电路供电。多个器件特性可引用 REG1,因此为这些特性启用 REG1 非常重要。评估模块还使用 REG1 作为多个引脚的上拉电压,因此建议启用前置稳压器 (REG0) 和 REG1。以下示例显示了如何启用 REG0、REG1 和 REG2。REG1 和 REG2 可设置为 1.8V、2.5V、3.0V、3.3V 或 5.0V。以下示例将 REG1 设为 3.3V,将 REG2 设为 2.5V。用于配置 REG1 和 REG2 的选项也显示在图 2-1 中。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

-今晚打老虎-

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值