This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

[参考译文] BQ76952:电荷泵和 MOSFET 开关问题

Guru**** 2589245 points
Other Parts Discussed in Thread: BQ76952, BQSTUDIO

请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

https://e2e.ti.com/support/power-management-group/power-management/f/power-management-forum/1013992/bq76952-issues-on-charge-pump-and-mosfet-switching

器件型号:BQ76952
主题中讨论的其他器件: BQSTUDIO

您好!

我使用 的是具有 Bq76952 IC 的 STM32L431RC 微控制    器、并尝试通过将 Mfg 状态初始化寄存器中的[FET_EN]位写入0x50来在测试模式下控制 MOSFET。 使用测试代码

void AFE_ManufacturingStatus (){

TX_4Byte[0]= 0x43;TX_4Byte[1]= 0x93;TX_4Byte[2]= 0x50;TX_4Byte[3]= 0x00;
I2C_WriteReg (0x3E、TX_4Byte、4);


TX_2Byte[0]=校验和(TX_4Byte、4);TX_2Byte[1]= 0x06;//校验和和长度
I2C_WriteReg (0x60、TX_2Byte、2);

并使用测试代码在 FET 选项中启用 sllep_CHG 位

void AFE_FETOptions(){
TX_3Byte[0]= 0x08;TX_3Byte[1]= 0x93;TX_3Byte[2]= 0x1F;
I2C_WriteReg (0x3E、TX_3Byte、3);

TX_2Byte[0]=校验和(TX_3Byte、3);TX_2Byte[1]= 0x05;
I2C_WriteReg (0x60、TX_2Byte、2);

提供 FET_CONTROL (0x00)后、预放电、充电和放电 MOSFET 会导通、当它单步执行时、预放电 MOSFET 会关断。 当在没有 CHARGE_PUMP 的情况下打开充电和放电 MOSFET 时、我还将使用该函数手动打开 CHARGE_PUMP。

void charge pump(){
TX_3Byte[0]= 0x09;TX_3Byte[1]= 0x93;TX_3Byte[2]= 0x01;
I2C_WriteReg (0x3E、TX_3Byte、3);
delayUS(1000);
TX_2Byte[0]=校验和(TX_3Byte、3);TX_2Byte[1]= 0x05;
I2C_WriteReg (0x60、TX_2Byte、2);

  • 我是否需要考虑其他配置? 或者、我编写的代码是否需要修改?
  • 在没有测试模式的情况下、启用所有具有电荷泵的 MOSFET 需要满足哪些条件? 而默认条件也是如此设置。
  • 如果我配置任何额外的东西、使 MOSFET 通过 CHARGE_PUMP 在正常模式下打开 、以及为什么前置 MOSFET 关闭

2) 2) 我还在使用 BQ7695202 IC、如果我无法使用与 BQ76952相同的代码执行任何操作、我需要进行哪些更改

请帮帮我。

谢谢、此致、

罗希思西

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    您好、Rohith、

    我不确定我是否理解您在代码中尝试执行的操作。 您说您正在尝试同时打开所有 FET。 器件通常不允许这样做-例如、PDSG FET 或 DSG FET 可以导通。 PCHG FET 或 CHG FET 可以导通。 FET_Control 命令可以单独禁用 FET、但器件仍需要确保启用 FET 时条件安全。

    您正在设置的某些寄存器(如启用充电 FET 和设置 SLEEPCHG 位)默认已启用。 我注意到、前两个重要的函数缺少一些延迟时间。 在使用 MCU 之前、最容易尝试在 BQStudio 中执行的操作。

    BQ7695202使用 CRC。 我共享的示例代码有一个预定义的变量、需要更新该变量才能启用 CRC 代码:

    #define CRC_Mode 0 // 0表示禁用、1表示启用

    此致、

    Matt

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    您好

    感谢您的回复、我附上了我的 C 文件供您参考。

    正如您之前所说的、我禁用了睡眠模式、启用了 SLEEP_CHG 位、启用 了函数之间的延迟。希望 CHG_PUMP 和 FET_EN ()默认处于打开状态。

    分别提出了以下意见:

    • 当 FET_ENABLE()(0x0022)被打开时、充电、放电和预放电 FET 在没有电荷泵电压的情况下被打开。
    • 当通过在寄存器地址0x9343中将0x0050作为数据写入来调用由我编写的 Manfacinging_Init()函数时,FET 未打开。

    查询:

    • 我在 C 文件中调用和编写的函数是否顺序正确?
    •  独立启用和禁用充电、放电、预放电和预充电 FET 需要调用哪些函数?
    • 在打开主 FET 的同时单独调用电荷泵功能。  

    注:

    • 我的电池组电压为59V
    • 在 CHG 和 DSG 引脚上进行探测时、出现61V、但电荷泵未打开。
    • 在 CP1引脚上进行探测时、该引脚上会出现70V 电压。

    请浏览我的 C 文件。

    /* USER CODE BEGIN Header */
    /**
      ******************************************************************************
      * @file           : main.c
      * @brief          : Main program body
      ******************************************************************************
      * @attention
      *
      * <h2><center>Copyright Copyright (c) 2021 STMicroelectronics.
      * All rights reserved.</center></h2>
      *
      * This software component is licensed by ST under BSD 3-Clause license,
      * the "License"; You may not use this file except in compliance with the
      * License. You may obtain a copy of the License at:
      *                        opensource.org/licenses/BSD-3-Clause
      *
      ******************************************************************************
      */
    /* USER CODE END Header */
    /* Includes ------------------------------------------------------------------*/
    #include "main.h"
    
    /* Private includes ----------------------------------------------------------*/
    /* USER CODE BEGIN Includes */
    #include<stdio.h>
    /* USER CODE END Includes */
    
    /* Private typedef -----------------------------------------------------------*/
    /* USER CODE BEGIN PTD */
    
    /* USER CODE END PTD */
    
    /* Private define ------------------------------------------------------------*/
    /* USER CODE BEGIN PD */
    #define DEV_ADDR 0x10    // Device address
    #define CRC_Mode  0  // 0 for disabled, 1 for enabled
    #define MAX_BUFFER_SIZE     10  //Max buffer size
    //#define DEBUG_RX_DO_Pin GPIO_PIN_10
    //#define DEBUG_RX_DO_GPIO_Port GPIOA
    /* USER CODE END PD */
    
    /* Private macro -------------------------------------------------------------*/
    /* USER CODE BEGIN PM */
    
    /* USER CODE END PM */
    
    /* Private variables ---------------------------------------------------------*/
    I2C_HandleTypeDef hi2c1;
    
    TIM_HandleTypeDef htim1;
    TIM_HandleTypeDef htim2;
    
    UART_HandleTypeDef huart1;
    
    /* USER CODE BEGIN PV */
    uint8_t spiData [2];
    uint8_t spiRxData [2];
    uint8_t rxdata [2];
    uint8_t busyData [2] = {0xFF, 0xFF};
    
    uint8_t TX_2Byte [2] = {0x00, 0x00};
    uint8_t TX_3Byte [3] = {0x00, 0x00, 0x00};
    uint8_t TX_4Byte [4] = {0x00, 0x00, 0x00, 0x00};
    uint8_t TX_Buffer [MAX_BUFFER_SIZE] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
    
    uint8_t RX_2Byte [2] = {0x00, 0x00};
    uint8_t RX_3Byte [3] = {0x00, 0x00, 0x00};
    uint8_t RX_4Byte [4] = {0x00, 0x00, 0x00, 0x00};
    uint8_t RX_12Byte [12] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
    uint8_t RX_Buffer [MAX_BUFFER_SIZE] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
    unsigned int RX_CRC_Check = 0;
    // Variables for cell voltages, temperatures, CC2 current, Stack voltage, PACK Pin voltage, LD Pin voltage
    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};
    float FET_Temperature = 0;
    uint16_t Stack_Voltage = 0x00;
    uint16_t LD_Voltage = 0x00;
    uint16_t PACK_Voltage = 0x00;
    uint16_t PACK_Current = 0x00;
    uint16_t AlarmBits = 0x00;
    
    uint8_t SafetyStatusA;  // Safety Status Register A
    uint8_t SafetyStatusB;  // Safety Status Register B
    uint8_t SafetyStatusC;  // Safety Status Register C
    uint8_t PFStatusA;   // Permanent Fail Status Register A
    uint8_t PFStatusB;   // Permanent Fail Status Register B
    uint8_t PFStatusC;   // Permanent Fail Status Register C
    uint8_t FET_Status;  // FET Status register contents See TRM Section 12.2.20  - Shows states of FETs
    
    uint16_t CB_ActiveCells;  // Cell Balancing Active Cells
    uint16_t DEVICE_NUMBER;
    
    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 LD_ON = 0;							// Load Detect status bit
    uint8_t DCHG = 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;
    uint32_t AccumulatedCharge_Frac;
    uint32_t AccumulatedCharge_Time;
    /* 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_TIM1_Init(void);
    static void MX_USART1_UART_Init(void);
    static void MX_TIM2_Init(void);
    /* USER CODE BEGIN PFP */
    void delayUS(uint32_t us) {   // Sets the delay in microseconds.
    	//uint8_t tim = 0;
    	__HAL_TIM_SET_COUNTER(&htim1,0);  // set the counter value a 0
    	while (__HAL_TIM_GET_COUNTER(&htim1) < us);
    }
    
    void delay_ticks(uint32_t ticks)
    {
        SysTick->LOAD = ticks;
        SysTick->VAL = 0;
        SysTick->CTRL = SysTick_CTRL_ENABLE_Msk;
        // COUNTFLAG is a bit that is set to 1 when counter reaches 0.
        // It's automatically cleared when read.
        while ((SysTick->CTRL & SysTick_CTRL_COUNTFLAG_Msk) == 0);
        SysTick->CTRL = 0;
    }
    
    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)
    {
    	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)
    {
    		#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, count, 1000);
    		}
    		#endif
    
    		#if CRC_Mode < 1
    		 HAL_StatusTypeDef state = HAL_OK;
    		state=HAL_I2C_Mem_Write(&hi2c1, DEV_ADDR, reg_addr, 1, reg_data, count, 1000);
    		if(state != HAL_OK)
    				{
    
    				}
    		#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.
    
    	#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);
    	}
    	#endif
    
    	#if CRC_Mode < 1
    	// HAL_StatusTypeDef state = HAL_OK;
    		 HAL_I2C_Mem_Read(&hi2c1, DEV_ADDR, reg_addr, 1, reg_data, count, 1000);
    		//if(state != HAL_OK)
    		//{
    
    		//}
    	#endif
    
    	  return 0;
    }
    
    
    void AFE_Reset() {
    	// Reset command. Resets all registers to default values or the values programmed in OTP.
    	TX_2Byte[0] = 0x12; TX_2Byte[1] = 0x00;
    	I2C_WriteReg(0x3E,TX_2Byte,2);
    }
    
    void AFE_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
    	// See TRM Section 7.6 for full description of CONFIG_UPDATE mode
    	TX_2Byte[0] = 0x90; TX_2Byte[1] = 0x00;
    	I2C_WriteReg(0x3E,TX_2Byte,2);
    
    	delayUS(2000);
    
    	// After entering CONFIG_UPDATE mode, RAM registers can be programmed. When programming RAM, checksum and length must also be
    	// programmed for the change to take effect. All of the RAM registers are described in detail in Chapter 13 of the BQ76952 TRM.
    	// An easier way to find the descriptions is in the BQStudio Data Memory screen. When you move the mouse over the register name,
    	// a full description of the register and the bits will pop up on the screen.
    	// A summary of the Data Memory is also in Section 13.9 of the TRM.
    
    	// 'Power Config' - Set DSLP_LDO  - 0x9234 = 0x2D82  (See TRM section 13.3.2)
    	// Setting the DSLP_LDO bit allows the LDOs to remain active when the device goes into Deep Sleep mode
      TX_4Byte[0] = 0x34; TX_4Byte[1] = 0x92; TX_4Byte[2] = 0x82; TX_4Byte[3] = 0x2D;
      I2C_WriteReg(0x3E, TX_4Byte, 4);
    	delayUS(1000);
    	TX_2Byte[0] = Checksum(TX_4Byte, 4); TX_2Byte[1] = 0x06;  // Checksum and Length
      I2C_WriteReg(0x60, TX_2Byte, 2);
    	delayUS(1000);
    
    	// 'REG0 Config' - set REG0_EN bit to enable pre-regulator
    	TX_3Byte[0] = 0x37; TX_3Byte[1] = 0x92; TX_3Byte[2] = 0x01;
      I2C_WriteReg(0x3E, TX_3Byte, 3);
    	delayUS(1000);
    	TX_2Byte[0] = Checksum(TX_3Byte, 3); TX_2Byte[1] = 0x05;
      I2C_WriteReg(0x60, TX_2Byte, 2);
    	delayUS(1000);
    
    	// 'REG12 Config' - Enable REG1 with 3.3V output
    	TX_3Byte[0] = 0x36; TX_3Byte[1] = 0x92; TX_3Byte[2] = 0x0D;
      I2C_WriteReg(0x3E, TX_3Byte, 3);
    	delayUS(1000);
    	TX_2Byte[0] = Checksum(TX_3Byte, 3); TX_2Byte[1] = 0x05;
      I2C_WriteReg(0x60, TX_2Byte, 2);
    	delayUS(1000);
    
    	// 'VCell Mode' - Enable 16 cells - 0x9304 = 0x0000  (See TRM section 13.3.2.19)
    	// 0x0000 sets the default value of 16 cells.
      TX_4Byte[0] = 0x04; TX_4Byte[1] = 0x93; TX_4Byte[2] = 0x00; TX_4Byte[3] = 0x00;
      I2C_WriteReg(0x3E, TX_4Byte, 4);
    	delayUS(1000);
    	TX_2Byte[0] = Checksum(TX_4Byte, 4); TX_2Byte[1] = 0x06;  // Checksum and Length
      I2C_WriteReg(0x60, TX_2Byte, 2);
    	delayUS(1000);
    
    	// 'Default Alarm Mask' - Enable FullScan and ADScan bits
    	// 0xF882
      TX_4Byte[0] = 0x6D; TX_4Byte[1] = 0x92; TX_4Byte[2] = 0x82; TX_4Byte[3] = 0xF8;
      I2C_WriteReg(0x3E, TX_4Byte, 4);
    	delayUS(1000);
    	TX_2Byte[0] = Checksum(TX_4Byte, 4); TX_2Byte[1] = 0x06;  // Checksum and Length
      I2C_WriteReg(0x60, TX_2Byte, 2);
    	delayUS(1000);
    
    	// Enable protections in 'Enabled Protections A' 0x9261 = 0xBC (See TRM section 13.3.3.2)
    	// Enables SCD (short-circuit), OCD1 (over-current in discharge), OCC (over-current in charge),
    	// COV (over-voltage), CUV (under-voltage)
    	TX_3Byte[0] = 0x61; TX_3Byte[1] = 0x92; TX_3Byte[2] = 0xFC;
      I2C_WriteReg(0x3E, TX_3Byte, 3);
    	delayUS(1000);
    	TX_2Byte[0] = Checksum(TX_3Byte, 3); TX_2Byte[1] = 0x05;
      I2C_WriteReg(0x60, TX_2Byte, 2);
    	delayUS(1000);
    
    	// Enable all protections in 'Enabled Protections B' 0x9262 = 0xF7 (See TRM section 13.3.3.3)
    	// 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)
    	TX_3Byte[0] = 0x62; TX_3Byte[1] = 0x92; TX_3Byte[2] = 0xF7;
      I2C_WriteReg(0x3E, TX_3Byte, 3);
    	delayUS(1000);
    	TX_2Byte[0] = Checksum(TX_3Byte, 3); TX_2Byte[1] = 0x05;
      I2C_WriteReg(0x60, TX_2Byte, 2);
    	delayUS(1000);
    
    
    	// Set TS1 to measure Cell Temperature - 0x92FD = 0x07   (See TRM Section 13.3.2.12)
    	TX_3Byte[0] = 0xFD; TX_3Byte[1] = 0x92; TX_3Byte[2] = 0x07;
      I2C_WriteReg(0x3E, TX_3Byte, 3);
    	//delayUS(1000);
    	TX_2Byte[0] = Checksum(TX_3Byte, 3); TX_2Byte[1] = 0x05;
      I2C_WriteReg(0x60, TX_2Byte, 2);
    	//delayUS(1000);
    
    	// Set TS3 to measure FET Temperature - 0x92FF = 0x0F   (See TRM Section 13.3.2.14)
    	TX_3Byte[0] = 0xFF; TX_3Byte[1] = 0x92; TX_3Byte[2] = 0x0F;
      I2C_WriteReg(0x3E, TX_3Byte, 3);
    	//delayUS(1000);
    	TX_2Byte[0] = Checksum(TX_3Byte, 3); TX_2Byte[1] = 0x05;
      I2C_WriteReg(0x60, TX_2Byte, 2);
    	//delayUS(1000);
    
    
    	// Set DFETOFF pin to control BOTH CHG and DSG FET - 0x92FB = 0x42 (set to 0x00 to disable)
    	// See TRM section 13.3.2.10, Table 13-7
    	TX_3Byte[0] = 0xFB; TX_3Byte[1] = 0x92; TX_3Byte[2] = 0x42;
      I2C_WriteReg(0x3E, TX_3Byte, 3);
    	//delayUS(1000);
    	TX_2Byte[0] = Checksum(TX_3Byte, 3); TX_2Byte[1] = 0x05;
      I2C_WriteReg(0x60, TX_2Byte, 2);
    	//delayUS(1000);
    
    	// Set up Alert Pin - 0x92FC = 0x2A  - See TRM Section 13.3.2.11, Table 13-8
    	// This configures the Alert pin to drive high (REG1 voltage) when enabled.
    	// Other options available include active-low, drive HiZ, drive using REG18 (1.8V), weak internal pull-up and pull-down
    	TX_3Byte[0] = 0xFC; TX_3Byte[1] = 0x92; TX_3Byte[2] = 0x2A;
      I2C_WriteReg(0x3E, TX_3Byte, 3);
    	delayUS(1000);
    	TX_2Byte[0] = Checksum(TX_3Byte, 3); TX_2Byte[1] = 0x05;
      I2C_WriteReg(0x60, TX_2Byte, 2);
    	delayUS(1000);
    
    
    	// Set up Cell Balancing Configuration - 0x9335 = 0x03   -  Automated balancing while in Relax or Charge modes
    	// See TRM Section 13.3.11. Chapter 10 of TRM describes Cell Balancing in detail
    	// Also see "Cell Balancing with BQ76952, BQ76942 Battery Monitors" document on ti.com
    	TX_3Byte[0] = 0x35; TX_3Byte[1] = 0x93; TX_3Byte[2] = 0x03;
      I2C_WriteReg(0x3E, TX_3Byte, 3);
    	delayUS(1000);
    	TX_2Byte[0] = Checksum(TX_3Byte, 3); TX_2Byte[1] = 0x05;
      I2C_WriteReg(0x60, TX_2Byte, 2);
    	delayUS(1000);
    
    	// Set up COV (over-voltage) Threshold - 0x9278 = 0x55 (4301 mV)
    	// COV Threshold is this value multiplied by 50.6mV  See TRM section 13.6.2
    	TX_3Byte[0] = 0x78; TX_3Byte[1] = 0x92; TX_3Byte[2] = 0x55;
      I2C_WriteReg(0x3E, TX_3Byte, 3);
    	delayUS(1000);
    	TX_2Byte[0] = Checksum(TX_3Byte, 3); TX_2Byte[1] = 0x05;
      I2C_WriteReg(0x60, TX_2Byte, 2);
    	delayUS(1000);
    
    	// Set up SCD Threshold - 0x9286 = 0x05 (100 mV = 100A across 1mOhm sense resistor)
    	// See TRM section 13.6.7    0x05=100mV
    	TX_3Byte[0] = 0x86; TX_3Byte[1] = 0x92; TX_3Byte[2] = 0x05;
      I2C_WriteReg(0x3E, TX_3Byte, 3);
    	delayUS(1000);
    	TX_2Byte[0] = Checksum(TX_3Byte, 3); TX_2Byte[1] = 0x05;
      I2C_WriteReg(0x60, TX_2Byte, 2);
    	delayUS(1000);
    
    	// Set up SCD Delay - 0x9287 = 0x03 (30 us)    See TRM section 13.6.7
    	// Units of 15us
    	TX_3Byte[0] = 0x87; TX_3Byte[1] = 0x92; TX_3Byte[2] = 0x03;
      I2C_WriteReg(0x3E, TX_3Byte, 3);
    	delayUS(1000);
    	TX_2Byte[0] = Checksum(TX_3Byte, 3); TX_2Byte[1] = 0x05;
      I2C_WriteReg(0x60, TX_2Byte, 2);
    	delayUS(1000);
    
    	// 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).
    	// See TRM section 13.6.11.1
    	TX_3Byte[0] = 0x95; TX_3Byte[1] = 0x92; TX_3Byte[2] = 0x01;
      I2C_WriteReg(0x3E, TX_3Byte, 3);
    	delayUS(1000);
    	TX_2Byte[0] = Checksum(TX_3Byte, 3); TX_2Byte[1] = 0x05;
      I2C_WriteReg(0x60, TX_2Byte, 2);
    	delayUS(1000);
    
    
    	// Exit CONFIGUPDATE mode  - Subcommand 0x0092
    	TX_2Byte[0] = 0x92; TX_2Byte[1] = 0x00;
    	I2C_WriteReg(0x3E,TX_2Byte,2);
    	delayUS(1000);
    }
    
    void Enable_REG1()
    {
    	TX_2Byte[0] = 0x90; TX_2Byte[1] = 0x00;
    		I2C_WriteReg(0x3E,TX_2Byte,2);
    		// 'REG0 Config' - set REG0_EN bit to enable pre-regulator
    			TX_3Byte[0] = 0x37; TX_3Byte[1] = 0x92; TX_3Byte[2] = 0x01;
    		  I2C_WriteReg(0x3E, TX_3Byte, 3);
    			delayUS(1000);
    			TX_2Byte[0] = Checksum(TX_3Byte, 3); TX_2Byte[1] = 0x05;
    		  I2C_WriteReg(0x60, TX_2Byte, 2);
    			delayUS(1000);
    
    			// 'REG12 Config' - Enable REG1 with 3.3V output
    			TX_3Byte[0] = 0x36; TX_3Byte[1] = 0x92; TX_3Byte[2] = 0x0D;
    		  I2C_WriteReg(0x3E, TX_3Byte, 3);
    			delayUS(1000);
    			TX_2Byte[0] = Checksum(TX_3Byte, 3); TX_2Byte[1] = 0x05;
    		  I2C_WriteReg(0x60, TX_2Byte, 2);
    			delayUS(1000);
    		  // Exit CONFIGUPDATE mode  - Subcommand 0x0092
    		  	TX_2Byte[0] = 0x92; TX_2Byte[1] = 0x00;
    		  	I2C_WriteReg(0x3E,TX_2Byte,2);
    		  	//delayUS(1000);
    
    }
    
    // ************************** Functions Written by Rohith********************//
    void AFE_FETOptions(){
    	TX_3Byte[0] = 0x08; TX_3Byte[1] = 0x93; TX_3Byte[2] = 0x1F;
    	  I2C_WriteReg(0x3E, TX_3Byte, 3);
    		delayUS(1000);
    		TX_2Byte[0] = Checksum(TX_3Byte, 3); TX_2Byte[1] = 0x05;
    	  I2C_WriteReg(0x60, TX_2Byte, 2);
    	  delayUS(1000);
    }
    
    void AFE_ManufacturingStatus(){
    
    	 TX_4Byte[0] = 0x43; TX_4Byte[1] = 0x93; TX_4Byte[2] = 0x50; TX_4Byte[3] = 0x00;
    	  I2C_WriteReg(0x3E, TX_4Byte, 4);
    		delayUS(1000);
    	 // HAL_Delay(1);
    		TX_2Byte[0] = Checksum(TX_4Byte, 4); TX_2Byte[1] = 0x06;  // Checksum and Length
    	  I2C_WriteReg(0x61, TX_2Byte, 2);
    	  delayUS(1000);
    
    }
    void Manufacturing_Status_Read(){
    
    }
    void PDSG_TEST(){
    	TX_2Byte[0] = 0x1C; TX_2Byte[1] = 0x00;
    		I2C_WriteReg(0x3E,TX_2Byte,2);
    }
    void PCHG_TEST(){
    	TX_2Byte[0] = 0x1E; TX_2Byte[1] = 0x00;
    		I2C_WriteReg(0x3E,TX_2Byte,2);
    }
    void CHG_TEST(){
    	TX_2Byte[0] = 0x1F; TX_2Byte[1] = 0x00;
    		I2C_WriteReg(0x3E,TX_2Byte,2);
    }
    void DSG_TEST(){
    	TX_2Byte[0] = 0x20; TX_2Byte[1] = 0x00;
    		I2C_WriteReg(0x3E,TX_2Byte,2);
    }
    void Charge_Pump(){
    	TX_3Byte[0] = 0x09; TX_3Byte[1] = 0x93; TX_3Byte[2] = 0x01;
    		  I2C_WriteReg(0x3E, TX_3Byte, 3);
    			delayUS(1000);
    			TX_2Byte[0] = Checksum(TX_3Byte, 3); TX_2Byte[1] = 0x05;
    		  I2C_WriteReg(0x60, TX_2Byte, 2);
    		  delayUS(1000);
    }
    
    void Comm_Type(){
    	TX_3Byte[0] = 0x39; TX_3Byte[1] = 0x92; TX_3Byte[2] = 0x12;
    			  I2C_WriteReg(0x3E, TX_3Byte, 3);
    				delayUS(1000);
    				TX_2Byte[0] = Checksum(TX_3Byte, 3); TX_2Byte[1] = 0x05;
    			  I2C_WriteReg(0x60, TX_2Byte, 2);
    }
    
    void Swap_Comm_Mode(){
    	TX_2Byte[0] = 0x90; TX_2Byte[1] = 0x00;
    	I2C_WriteReg(0x3E,TX_2Byte,2);
    
    
    	TX_3Byte[0] = 0x39; TX_3Byte[1] = 0x92; TX_3Byte[2] = 0x12;
    	I2C_WriteReg(0x3E, TX_3Byte, 3);
    	//delayUS(1000);
    	TX_2Byte[0] = Checksum(TX_3Byte, 3); TX_2Byte[1] = 0x05;
    	I2C_WriteReg(0x60, TX_2Byte, 2);
    
    	TX_2Byte[0] = 0xBC; TX_2Byte[1] = 0x29;
    	I2C_WriteReg(0x3E,TX_2Byte,2);
    
    	TX_2Byte[0] = 0x92; TX_2Byte[1] = 0x00;
    	I2C_WriteReg(0x3E,TX_2Byte,2);
    }
    void Dfet_off(){
    
    	TX_3Byte[0] = 0xFB; TX_3Byte[1] = 0x92; TX_3Byte[2] = 0x00;
    	I2C_WriteReg(0x3E, TX_3Byte, 3);
    	delayUS(1000);
    	TX_2Byte[0] = Checksum(TX_3Byte, 3); TX_2Byte[1] = 0x05;
    	I2C_WriteReg(0x60, TX_2Byte, 2);
    
    }
    
    void Cfet_off(){
    
    	TX_3Byte[0] = 0xFA; TX_3Byte[1] = 0x92; TX_3Byte[2] = 0x00;
    	I2C_WriteReg(0x3E, TX_3Byte, 3);
    	delayUS(1000);
    	TX_2Byte[0] = Checksum(TX_3Byte, 3); TX_2Byte[1] = 0x05;
    	I2C_WriteReg(0x60, TX_2Byte, 2);
    
    }
    void Status_Read(){
    	uint8_t rd_data;
    	TX_2Byte[0] = 0x57; TX_2Byte[1] = 0x00;
    		I2C_WriteReg(0x3E,TX_2Byte,2);
    		delayUS(2000);
    		I2C_ReadReg(0x40, RX_2Byte, 2);
    		rd_data = (RX_2Byte[1]*256 + RX_2Byte[0]);
    }
    void Vcell(){
    	 TX_4Byte[0] = 0x04; TX_4Byte[1] = 0x93; TX_4Byte[2] = 0x00; TX_4Byte[3] = 0x00;
    	  I2C_WriteReg(0x3E, TX_4Byte, 4);
    		delayUS(1000);
    		TX_2Byte[0] = Checksum(TX_4Byte, 4); TX_2Byte[1] = 0x06;  // Checksum and Length
    	  I2C_WriteReg(0x60, TX_2Byte, 2);
    }
    //******(********** End *************//
    //  ********************************* FET Control Commands  ***************************************
    
    void AFE_FET_ENABLE() {
    	// Toggles the FET_EN bit in the Manufacturing Status register. So this command can be used to enable or disable the FETs.
    	TX_2Byte[0] = 0x22; TX_2Byte[1] = 0x00;   //0x22
    	I2C_WriteReg(0x3E,TX_2Byte,2);
    }
    
    void AFE_FET_Control(uint8_t FET_states) {  // Bit3 = PCHG_OFF, Bit 2 = CHG_OFF, Bit1 = PDSG_OFF, Bit 0 = DSG_OFF
    	TX_3Byte[0] = 0x97; TX_3Byte[1] = 0x00; TX_3Byte[2] = FET_states;
    	I2C_WriteReg(0x3E,TX_3Byte,3);
    	delayUS(1000);
    	TX_2Byte[0] = Checksum(TX_3Byte, 3); TX_2Byte[1] = 0x05;
      I2C_WriteReg(0x60, TX_2Byte, 2);
    }
    
    void DSG_PDSG_OFF() {
    	// Disable discharge (and pre-discharge) FETs
    	// Subcommand 0x0093  See TRM Table 5-8  (DSG_PDSG_OFF())
    	TX_2Byte[0] = 0x93; TX_2Byte[1] = 0x00;
    	I2C_WriteReg(0x3E,TX_2Byte,2);
    }
    
    void CHG_PCHG_OFF() {
    	// Disable charge (and pre-charge) FETs
    	// Subcommand 0x0094  See TRM Table 5-8  (CHG_PCHG_OFF())
    	TX_2Byte[0] = 0x94; TX_2Byte[1] = 0x00;
    	I2C_WriteReg(0x3E,TX_2Byte,2);
    }
    
    void AFE_ALL_FETS_OFF() {
    	// Disable all FETs with command 0x0095  See TRM Table 5-8
    	TX_2Byte[0] = 0x95; TX_2Byte[1] = 0x00;
    	I2C_WriteReg(0x3E,TX_2Byte,2);
    }
    
    void AFE_ALL_FETS_ON() {
    	// All all FETs to be enabled with command 0x0096  See TRM Table 5-8
    	TX_2Byte[0] = 0x96; TX_2Byte[1] = 0x00;
    	I2C_WriteReg(0x3E,TX_2Byte,2);
    }
    
    void AFE_BOTHOFF () {
    	// Disables all FETs using the DFETOFF (BOTHOFF) pin
    	HAL_GPIO_WritePin(GPIOA, GPIO_PIN_8, GPIO_PIN_SET);  // DFETOFF pin (BOTHOFF) set low
    }
    
    void AFE_RESET_BOTHOFF () {
    	// Resets DFETOFF (BOTHOFF) pin
    	HAL_GPIO_WritePin(GPIOA, GPIO_PIN_8, GPIO_PIN_RESET);  // DFETOFF pin (BOTHOFF) set low
    }
    
    void AFE_ReadFETStatus() {
    	// Read FET Status to see which FETs are enabled
    	I2C_ReadReg(0x7F, RX_2Byte, 2);
      FET_Status = (RX_2Byte[1]*256 + RX_2Byte[0]);
    	DCHG = 0x4 & RX_2Byte[0];   // discharge FET state
    	CHG = 0x1 & RX_2Byte[0];   // charge FET state
    	PCHG = 0x2 & RX_2Byte[0];  // pre-charge FET state
    	PDSG = 0x8 & RX_2Byte[0];  // pre-discharge FET state
    }
    
    
    // ********************************* End of FET Control Commands *********************************
    
    
    // ********************************* AFE Cell Balancing Commands   *****************************************
    
    void CB_ACTIVE_CELLS() {
    	// Check status of which cells are balancing
    	TX_2Byte[0] = 0x83; TX_2Byte[1] = 0x00;
    	I2C_WriteReg(0x3E,TX_2Byte,2);
    	I2C_ReadReg(0x40, RX_2Byte, 2);
      CB_ActiveCells = (RX_2Byte[1]*256 + RX_2Byte[0]);
    }
    
    void CFET_OFF_LO(){
    	TX_2Byte[0] = 0x28; TX_2Byte[1] = 0x00;
    	I2C_WriteReg(0x3E, TX_2Byte, 2);
    }
    void DFET_OFF_LO(){
    	TX_2Byte[0] = 0x28; TX_2Byte[1] = 0x01;
    		I2C_WriteReg(0x3E, TX_2Byte, 2);
    }
    // ********************************* End of AFE Cell Balancing Commands   *****************************************
    
    
    // ********************************* AFE Power Commands   *****************************************
    void AFE_DeepSleep() {
    	// Puts the device into DEEPSLEEP mode. See TRM section 7.4
    	TX_2Byte[0] = 0x0F; TX_2Byte[1] = 0x00;
    	I2C_WriteReg(0x3E,TX_2Byte,2);
    	I2C_WriteReg(0x3E,TX_2Byte,2);
    }
    
    void AFE_ExitDeepSleep() {
    	// Exits DEEPSLEEP mode. See TRM section 7.4
    	TX_2Byte[0] = 0x0E; TX_2Byte[1] = 0x00;
    	I2C_WriteReg(0x3E,TX_2Byte,2);
    }
    
    void AFE_ShutdownCommand() {
    	// Puts the device into SHUTDOWN mode. See TRM section 7.5
    	TX_2Byte[0] = 0x10; TX_2Byte[1] = 0x00;
    	I2C_WriteReg(0x3E,TX_2Byte,2);
    }
    
    void AFE_ShutdownPin() {
    	// Puts the device into SHUTDOWN mode using the RST_SHUT pin
    	HAL_GPIO_WritePin(GPIOA, GPIO_PIN_9, GPIO_PIN_SET);  // Sets RST_SHUT pin
    }
    
    void AFE_ReleaseShutdownPin() {
    	// Releases the RST_SHUT pin
    	HAL_GPIO_WritePin(GPIOA, GPIO_PIN_9, GPIO_PIN_RESET);  // Resets RST_SHUT pin
    }
    
    void AFE_SLEEP_ENABLE() { // SLEEP_ENABLE 0x0099
    	// Allows the device to enter Sleep mode if current is below Sleep Current. See TRM section 7.3
    	TX_2Byte[0] = 0x99; TX_2Byte[1] = 0x00;
    	I2C_WriteReg(0x3E,TX_2Byte,2);
    }
    
    void AFE_SLEEP_DISABLE() { // SLEEP_DISABLE 0x009A
    	// Takes the device out of sleep mode. See TRM section 7.3
    	TX_2Byte[0] = 0x9A; TX_2Byte[1] = 0x00;
    	I2C_WriteReg(0x3E,TX_2Byte,2);
    }
    
    // ********************************* End of AFE Power Commands   *****************************************
    
    
    // ********************************* AFE Status and Fault Commands   *****************************************
    
    uint16_t AFE_ReadAlarmStatus() {
    	// Read this register to find out why the Alert pin was asserted. See section 6.6 of the TRM for full description.
    	I2C_ReadReg(0x62, RX_2Byte, 2);
    	return (RX_2Byte[1]*256 + RX_2Byte[0]);
    }
    
    void AFE_ReadSafetyStatus() {
    	// Read Safety Status A/B/C and find which bits are set
    	// This shows which primary protections have been triggered
    	I2C_ReadReg(0x03, RX_2Byte, 2);
    	SafetyStatusA = (RX_2Byte[1]*256 + RX_2Byte[0]);
    	UV_Fault = 0x4 & RX_2Byte[0];
    	OV_Fault = 0x8 & RX_2Byte[0];
    	SCD_Fault = 0x8 & RX_2Byte[1];
    	OCD_Fault = 0x2 & RX_2Byte[1];
    	I2C_ReadReg(0x05, RX_2Byte, 2);
    	SafetyStatusB = (RX_2Byte[1]*256 + RX_2Byte[0]);
    	I2C_ReadReg(0x07, RX_2Byte, 2);
    	SafetyStatusC = (RX_2Byte[1]*256 + RX_2Byte[0]);
    }
    
    void AFE_ReadPFStatus() {
    	// Read Permanent Fail Status A/B/C and find which bits are set
    	// This shows which permanent failures have been triggered
    	I2C_ReadReg(0x0B, RX_2Byte, 2);
    	PFStatusA = (RX_2Byte[1]*256 + RX_2Byte[0]);
    	I2C_ReadReg(0x0D, RX_2Byte, 2);
    	PFStatusB = (RX_2Byte[1]*256 + RX_2Byte[0]);
    	I2C_ReadReg(0x0F, RX_2Byte, 2);
    	PFStatusC = (RX_2Byte[1]*256 + RX_2Byte[0]);
    }
    
    
    void AFE_ControlStatus() {
    	// Control status register - Bit0 - LD_ON (load detected)
    	// See TRM Table 6-1
    	I2C_ReadReg(0x00, RX_2Byte, 2);
      LD_ON = 0x1 & RX_2Byte[0];
    }
    
    void AFE_BatteryStatus() {
    	// Battery status register - See TRM Table 6-2
    	I2C_ReadReg(0x12, RX_2Byte, 2);
    }
    
    void AFE_ClearFaults() {
    	TX_2Byte[0] = 0x00; TX_2Byte[1] = 0xF8;
    	I2C_WriteReg(0x62,TX_2Byte,2);
    }
    
    void AFE_ClearScanBits() {
    	TX_2Byte[0] = 0x82; TX_2Byte[1] = 0x00;
    	I2C_WriteReg(0x62,TX_2Byte,2);
    }
    
    void AFE_PFReset() {
    	TX_2Byte[0] = 0x29; TX_2Byte[1] = 0x00;
    	I2C_WriteReg(0x3E,TX_2Byte,2);
    }
    
    uint16_t AFE_DeviceID() {
    	// Read Device ID using Subcommand 0x0001
    	TX_2Byte[0] = 0x01; TX_2Byte[1] = 0x00;
    	I2C_WriteReg(0x3E,TX_2Byte,2);
    	delayUS(500);
    	I2C_ReadReg(0x40, RX_2Byte, 2);
    	return (RX_2Byte[1]*256 + RX_2Byte[0]);
    }
    // ********************************* End of AFE Status and Fault Commands   *****************************************
    
    
    // ********************************* AFE Measurement Commands   *****************************************
    
    uint16_t AFE_ReadCellVoltage(uint8_t channel) {
    	I2C_ReadReg(channel*2+0x14, RX_2Byte, 2);
    	return (RX_2Byte[1]*256 + RX_2Byte[0]);     // cell voltage is reported in mV
    }
    
    uint16_t AFE_ReadStackVoltage() {
    	I2C_ReadReg(0x34, RX_2Byte, 2);
    	return 10 * (RX_2Byte[1]*256 + RX_2Byte[0]);  // voltage is reported in 0.01V units
    }
    
    uint16_t AFE_ReadPackVoltage() {
    	I2C_ReadReg(0x36, RX_2Byte, 2);
    	return 10 * (RX_2Byte[1]*256 + RX_2Byte[0]);  // voltage is reported in 0.01V units
    }
    
    uint16_t AFE_ReadLDVoltage() {
    	I2C_ReadReg(0x38, RX_2Byte, 2);
    	return 10 * (RX_2Byte[1]*256 + RX_2Byte[0]);  // voltage is reported in 0.01V units
    }
    
    uint16_t AFE_ReadCurrent() {
    	//uint8_t cure = 0;
    	I2C_ReadReg(0x3A, RX_2Byte, 2);
    	return (RX_2Byte[1]*256 + RX_2Byte[0]);  // current is reported in mA
    }
    
    
    
    float AFE_ReadTemperature(uint8_t channel) {
    	switch(channel)
    	{
    		case 0:
    			I2C_ReadReg(0x70, RX_2Byte, 2);  // TS1 pin
    			break;
    		case 1:
    			I2C_ReadReg(0x74, RX_2Byte, 2);  // TS3 pin, FET temperature
    			break;
    		default: break;
    	}
    	return (0.1 * (float)(RX_2Byte[1]*256 + RX_2Byte[0])) - 273.15;  // convert from 0.1K to Celcius
    }
    
    
    void AFE_ReadPassQ() {
    	// Read Accumulated Charge and Time from DASTATUS6 (See TRM Table 4-6)
    	TX_2Byte[0] = 0x76; TX_2Byte[1] = 0x00;
    	I2C_WriteReg(0x3E,TX_2Byte,2);
    	delayUS(1000);
    	I2C_ReadReg(0x40, RX_12Byte, 12);
    	AccumulatedCharge_Int = ((RX_12Byte[3]<<24) + (RX_12Byte[2]<<16) + (RX_12Byte[1]<<8) + RX_12Byte[0]);
    	AccumulatedCharge_Frac = ((RX_12Byte[7]<<24) + (RX_12Byte[6]<<16) + (RX_12Byte[5]<<8) + RX_12Byte[4]);
    	AccumulatedCharge_Time = ((RX_12Byte[11]<<24) + (RX_12Byte[10]<<16) + (RX_12Byte[9]<<8) + RX_12Byte[8]);
    }
    
    void AFE_ClearPassQ() {
    	// Clear Accumulated Charge and Time, command 0x0082
    	TX_2Byte[0] = 0x82; TX_2Byte[1] = 0x00;
    	I2C_WriteReg(0x3E,TX_2Byte,2);
    }
    
    void config_mode(){
    	TX_2Byte[0] = 0x90; TX_2Byte[1] = 0x00;
    		I2C_WriteReg(0x3E,TX_2Byte,2);
    
    }
    void Exit_config_mode(){
    	TX_2Byte[0] = 0x92; TX_2Byte[1] = 0x00;
    		I2C_WriteReg(0x3E,TX_2Byte,2);
    
    }
    // ********************************* End of AFE 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 */
    	volatile int i = 0;
    	char uart_buf[50];
    	int uart_buf_len;
    
      /* 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_TIM1_Init();
      MX_USART1_UART_Init();
      MX_TIM2_Init();
      /* USER CODE BEGIN 2 */
      HAL_TIM_Base_Start(&htim1);
    
    
      AFE_SLEEP_DISABLE();
      AFE_ManufacturingStatus();
      Charge_Pump();
      AFE_FETOptions();
      AFE_FET_ENABLE();
      AFE_FET_Control(0x00);
      AFE_ReadFETStatus();
      AFE_ALL_FETS_ON();
      AFE_ReadFETStatus();
    
    
    
    
      HAL_StatusTypeDef stat = HAL_OK;
      	stat = HAL_I2C_IsDeviceReady(&hi2c1,0x10,2,10);
      	if(stat == HAL_OK)
      	{
    
    
      	}
      /* USER CODE END 2 */
    
      /* Infinite loop */
      /* USER CODE BEGIN WHILE */
      while (1)
      {
        /* USER CODE END WHILE */
    
        /* USER CODE BEGIN 3 */
    	  AFE_ReadFETStatus();
    	  HAL_GPIO_WritePin(RDE_DO_GPIO_Port, RDE_DO_Pin, 1);  //Enable uart2
    	 		HAL_GPIO_WritePin(DEBUG_RX_DO_GPIO_Port, DEBUG_RDE_DO_Pin, 1); // Enable UART1
    	 	  for(int i = 0 ;i <=15; i++)
    	 	  {
    	 			CellVoltage[i] = AFE_ReadCellVoltage(i);
    	 			printf("cell voltages [%d] =  %d",i,CellVoltage);
    
    	 	  }
    	 	  HAL_GPIO_WritePin(RDE_DO_GPIO_Port, RDE_DO_Pin, 0);  //Disable uart2
    	 	  	HAL_GPIO_WritePin(DEBUG_RX_DO_GPIO_Port, DEBUG_RDE_DO_Pin, 1); //Disable UART1
      }
      /* USER CODE END 3 */
    }
    
    /**
      * @brief System Clock Configuration
      * @retval None
      */
    void SystemClock_Config(void)
    {
      RCC_OscInitTypeDef RCC_OscInitStruct = {0};
      RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};
      RCC_PeriphCLKInitTypeDef PeriphClkInit = {0};
    
      /** Initializes the RCC Oscillators according to the specified parameters
      * in the RCC_OscInitTypeDef structure.
      */
      RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_MSI;
      RCC_OscInitStruct.MSIState = RCC_MSI_ON;
      RCC_OscInitStruct.MSICalibrationValue = 0;
      RCC_OscInitStruct.MSIClockRange = RCC_MSIRANGE_6;
      RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
      RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_MSI;
      RCC_OscInitStruct.PLL.PLLM = 1;
      RCC_OscInitStruct.PLL.PLLN = 36;
      RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV7;
      RCC_OscInitStruct.PLL.PLLQ = RCC_PLLQ_DIV2;
      RCC_OscInitStruct.PLL.PLLR = RCC_PLLR_DIV2;
      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_DIV1;
      RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;
    
      if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_4) != HAL_OK)
      {
        Error_Handler();
      }
      PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_USART1|RCC_PERIPHCLK_I2C1;
      PeriphClkInit.Usart1ClockSelection = RCC_USART1CLKSOURCE_PCLK2;
      PeriphClkInit.I2c1ClockSelection = RCC_I2C1CLKSOURCE_PCLK1;
      if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInit) != HAL_OK)
      {
        Error_Handler();
      }
      /** Configure the main internal regulator output voltage
      */
      if (HAL_PWREx_ControlVoltageScaling(PWR_REGULATOR_VOLTAGE_SCALE1) != 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.Timing = 0x10808DD3;
      hi2c1.Init.OwnAddress1 = 0;
      hi2c1.Init.AddressingMode = I2C_ADDRESSINGMODE_7BIT;
      hi2c1.Init.DualAddressMode = I2C_DUALADDRESS_DISABLE;
      hi2c1.Init.OwnAddress2 = 0;
      hi2c1.Init.OwnAddress2Masks = I2C_OA2_NOMASK;
      hi2c1.Init.GeneralCallMode = I2C_GENERALCALL_DISABLE;
      hi2c1.Init.NoStretchMode = I2C_NOSTRETCH_DISABLE;
      if (HAL_I2C_Init(&hi2c1) != HAL_OK)
      {
        Error_Handler();
      }
      /** Configure Analogue filter
      */
      if (HAL_I2CEx_ConfigAnalogFilter(&hi2c1, I2C_ANALOGFILTER_ENABLE) != HAL_OK)
      {
        Error_Handler();
      }
      /** Configure Digital filter
      */
      if (HAL_I2CEx_ConfigDigitalFilter(&hi2c1, 0) != 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.MasterOutputTrigger2 = TIM_TRGO2_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 TIM2 Initialization Function
      * @param None
      * @retval None
      */
    static void MX_TIM2_Init(void)
    {
    
      /* USER CODE BEGIN TIM2_Init 0 */
    
      /* USER CODE END TIM2_Init 0 */
    
      TIM_ClockConfigTypeDef sClockSourceConfig = {0};
      TIM_MasterConfigTypeDef sMasterConfig = {0};
      TIM_OC_InitTypeDef sConfigOC = {0};
    
      /* USER CODE BEGIN TIM2_Init 1 */
    
      /* USER CODE END TIM2_Init 1 */
      htim2.Instance = TIM2;
      htim2.Init.Prescaler = 63;
      htim2.Init.CounterMode = TIM_COUNTERMODE_UP;
      htim2.Init.Period = 65535;
      htim2.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
      htim2.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE;
      if (HAL_TIM_Base_Init(&htim2) != HAL_OK)
      {
        Error_Handler();
      }
      sClockSourceConfig.ClockSource = TIM_CLOCKSOURCE_INTERNAL;
      if (HAL_TIM_ConfigClockSource(&htim2, &sClockSourceConfig) != HAL_OK)
      {
        Error_Handler();
      }
      if (HAL_TIM_OC_Init(&htim2) != HAL_OK)
      {
        Error_Handler();
      }
      sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET;
      sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;
      if (HAL_TIMEx_MasterConfigSynchronization(&htim2, &sMasterConfig) != HAL_OK)
      {
        Error_Handler();
      }
      sConfigOC.OCMode = TIM_OCMODE_TIMING;
      sConfigOC.Pulse = 0;
      sConfigOC.OCPolarity = TIM_OCPOLARITY_HIGH;
      sConfigOC.OCFastMode = TIM_OCFAST_DISABLE;
      if (HAL_TIM_OC_ConfigChannel(&htim2, &sConfigOC, TIM_CHANNEL_1) != HAL_OK)
      {
        Error_Handler();
      }
      if (HAL_TIM_OC_ConfigChannel(&htim2, &sConfigOC, TIM_CHANNEL_2) != HAL_OK)
      {
        Error_Handler();
      }
      if (HAL_TIM_OC_ConfigChannel(&htim2, &sConfigOC, TIM_CHANNEL_3) != HAL_OK)
      {
        Error_Handler();
      }
      if (HAL_TIM_OC_ConfigChannel(&htim2, &sConfigOC, TIM_CHANNEL_4) != HAL_OK)
      {
        Error_Handler();
      }
      /* USER CODE BEGIN TIM2_Init 2 */
    
      /* USER CODE END TIM2_Init 2 */
    
    }
    
    /**
      * @brief USART1 Initialization Function
      * @param None
      * @retval None
      */
    static void MX_USART1_UART_Init(void)
    {
    
      /* USER CODE BEGIN USART1_Init 0 */
    
      /* USER CODE END USART1_Init 0 */
    
      /* USER CODE BEGIN USART1_Init 1 */
    
      /* USER CODE END USART1_Init 1 */
      huart1.Instance = USART1;
      huart1.Init.BaudRate = 115200;
      huart1.Init.WordLength = UART_WORDLENGTH_8B;
      huart1.Init.StopBits = UART_STOPBITS_1;
      huart1.Init.Parity = UART_PARITY_NONE;
      huart1.Init.Mode = UART_MODE_TX_RX;
      huart1.Init.HwFlowCtl = UART_HWCONTROL_NONE;
      huart1.Init.OverSampling = UART_OVERSAMPLING_16;
      huart1.Init.OneBitSampling = UART_ONE_BIT_SAMPLE_DISABLE;
      huart1.AdvancedInit.AdvFeatureInit = UART_ADVFEATURE_NO_INIT;
      if (HAL_UART_Init(&huart1) != HAL_OK)
      {
        Error_Handler();
      }
      /* USER CODE BEGIN USART1_Init 2 */
    
      /* USER CODE END USART1_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_GPIOA_CLK_ENABLE();
      __HAL_RCC_GPIOD_CLK_ENABLE();
      __HAL_RCC_GPIOB_CLK_ENABLE();
    
      /*Configure GPIO pin Output Level */
      HAL_GPIO_WritePin(DEBUG_RDE_DO_GPIO_Port, DEBUG_RDE_DO_Pin, GPIO_PIN_RESET);
    
      /*Configure GPIO pin Output Level */
      HAL_GPIO_WritePin(RDE_DO_GPIO_Port, RDE_DO_Pin, GPIO_PIN_RESET);
    
      /*Configure GPIO pin : DEBUG_RDE_DO_Pin */
      GPIO_InitStruct.Pin = DEBUG_RDE_DO_Pin;
      GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
      GPIO_InitStruct.Pull = GPIO_NOPULL;
      GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
      HAL_GPIO_Init(DEBUG_RDE_DO_GPIO_Port, &GPIO_InitStruct);
    
      /*Configure GPIO pin : RDE_DO_Pin */
      GPIO_InitStruct.Pin = RDE_DO_Pin;
      GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
      GPIO_InitStruct.Pull = GPIO_NOPULL;
      GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
      HAL_GPIO_Init(RDE_DO_GPIO_Port, &GPIO_InitStruct);
    
    }
    
    /* 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 */
      __disable_irq();
      while (1)
      {
      }
      /* 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,
         ex: 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****/
    

    谢谢、此致、

    罗希思西

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    您好、Rohith、

    一个问题是、当您不处于 CONFIG_UPDATE 模式时、您正在尝试设置 RAM 寄存器值。 在 AFE_Init()过程中,第一步是进入 CONFIG_UPDATE 模式,然后写入所有寄存器,最后退出 CONFIG_UPDATE 模式。 您应该在该函数内设置所有寄存器设置。 您不应在 CONFIG_UPDATE 模式之外修改寄存器。

    此致、

    Matt