RRC3570 Li-ion battery charger(LTC4015) firmware
Satyabrata Senapati
Technical Content Writer , Technical Expert , Mentor , Trainer , & Embedded Software Developer
In this article we are going to implement the firmware for stm32l0 microcontroller which is interfaced through I2C port to LTC4015 charger IC to perform the basic charging functionality.The content of main.c file is given as below.
/* USER CODE BEGIN Header */
/**
******************************************************************************
* @file : main.c
* @brief : Main program body
******************************************************************************
* @attention
*
* Copyright (c) 2023 STMicroelectronics.
* All rights reserved.
*
* This software is licensed under terms that can be found in the LICENSE file
* in the root directory of this software component.
* If no LICENSE file comes with this software, it is provided AS-IS.
*
******************************************************************************
*/
/* USER CODE END Header */
/* Includes ------------------------------------------------------------------*/
#include "main.h"
/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
/* USER CODE END Includes */
/* Private typedef -----------------------------------------------------------*/
/* USER CODE BEGIN PTD */
/* USER CODE END PTD */
/* Private define ------------------------------------------------------------*/
/* USER CODE BEGIN PD */
/* USER CODE END PD */
/* Private macro -------------------------------------------------------------*/
/* USER CODE BEGIN PM */
/* USER CODE END PM */
/* Private variables ---------------------------------------------------------*/
I2C_HandleTypeDef hi2c1;
UART_HandleTypeDef huart1;
/* USER CODE BEGIN PV */
static const uint8_t PCA9546A_DEVICE_ADDRESS = 0xE0;//device address with write operation
static const uint8_t LTC4015_DEVICE_ADDRESS_READ = 0xD1;//for read operation
static const uint8_t LTC4015_DEVICE_ADDRESS_WRITE = 0xD0;//for write operation
static const uint8_t CONTROL_REG1 = 0x01;//select channel 0 of multiplexer ltc4015_1
static const uint8_t CONTROL_REG2 = 0x02;//select channel 1 of multiplexer battery_1
static const uint8_t CONTROL_REG3 = 0x04;//select channel 2 of multiplexer ltc4015_2
static const uint8_t CONTROL_REG4 = 0x08;//select channel 3 of multiplexer battery_2
/* 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_USART1_UART_Init(void);
/* USER CODE BEGIN PFP */
static void rrc3570_battery_comm_check(void);
static void ltc_4015_init(void);
static void start_charging(void);
static void stop_charging(void);
/* 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 */
HAL_StatusTypeDef ret;
uint8_t buf[1];
uint8_t read_buf_word[2];
uint16_t register_value = 0;
/* 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_USART1_UART_Init();
/* USER CODE BEGIN 2 */
rrc3570_battery_comm_check();//rrc_3570 battery communication check
HAL_UART_Transmit(&huart1,(uint8_t*) "battery Communication done\r\n", sizeof("Battery Communication done\r\n"), HAL_MAX_DELAY);
HAL_Delay(500);//wait for some time
ltc_4015_init();//ltc4015 alert limit,en_limit_alerts,en_charger_state_alerts configuration
HAL_UART_Transmit(&huart1,(uint8_t*) "ltc4015 successfully initialized\r\n", sizeof("ltc4015 sucessfully initialized\r\n"), HAL_MAX_DELAY);
HAL_Delay(500);//wait for some time
// stop_charging();//initially stop charging rrc3570 battery
// HAL_UART_Transmit(&huart1,(uint8_t*) "battery charging stopped\r\n", sizeof("battery charging stopped\r\n"), HAL_MAX_DELAY);
// HAL_Delay(2000);//wait for some time
start_charging();//start charging the rrc3570 battery
HAL_UART_Transmit(&huart1,(uint8_t*) "battery charging started\r\n", sizeof("battery charging started\r\n"), HAL_MAX_DELAY);
HAL_Delay(2000);//wait for some time
/* USER CODE END 2 */
/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1)
{
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
HAL_Delay(500);//put some delay
//step-1
HAL_GPIO_WritePin(GPIOB, GPIO_PIN_7,GPIO_PIN_RESET);//RESET PIN cleared of PCA9546A
HAL_Delay(500);//put some delay
HAL_GPIO_WritePin(GPIOB, GPIO_PIN_7,GPIO_PIN_SET);//RESET PIN set of PCA9546A
HAL_Delay(500);//put some delay
//step-2
buf[0] = CONTROL_REG1;
ret = HAL_I2C_Master_Transmit(&hi2c1,PCA9546A_DEVICE_ADDRESS,buf,1,HAL_MAX_DELAY);//select channel 0 for i2c switch
if (ret != HAL_OK)
{
Error_Handler();
}
//check charge_status
ret = HAL_I2C_Mem_Read(&hi2c1,LTC4015_DEVICE_ADDRESS_READ,0x35,I2C_MEMADD_SIZE_8BIT,read_buf_word, 2, HAL_MAX_DELAY);
if (ret != HAL_OK)
{
Error_Handler();
}
register_value = ((uint16_t)read_buf_word[0] | ((uint16_t)read_buf_word[1] << 8));
//check limit_alerts
ret = HAL_I2C_Mem_Read(&hi2c1,LTC4015_DEVICE_ADDRESS_READ,0x36,I2C_MEMADD_SIZE_8BIT,read_buf_word, 2, HAL_MAX_DELAY);
if (ret != HAL_OK)
{
Error_Handler();
}
register_value = ((uint16_t)read_buf_word[0] | ((uint16_t)read_buf_word[1] << 8));
//check charger_state_alerts
ret = HAL_I2C_Mem_Read(&hi2c1,LTC4015_DEVICE_ADDRESS_READ,0x37,I2C_MEMADD_SIZE_8BIT,read_buf_word, 2, HAL_MAX_DELAY);
if (ret != HAL_OK)
{
Error_Handler();
}
register_value = ((uint16_t)read_buf_word[0] | ((uint16_t)read_buf_word[1] << 8));
//check system_status
ret = HAL_I2C_Mem_Read(&hi2c1,LTC4015_DEVICE_ADDRESS_READ,0x39,I2C_MEMADD_SIZE_8BIT,read_buf_word, 2, HAL_MAX_DELAY);
if (ret != HAL_OK)
{
Error_Handler();
}
register_value = ((uint16_t)read_buf_word[0] | ((uint16_t)read_buf_word[1] << 8));
//read VBATSENS = 26.498v
ret = HAL_I2C_Mem_Read(&hi2c1,LTC4015_DEVICE_ADDRESS_READ,0x3A,I2C_MEMADD_SIZE_8BIT,read_buf_word, 2, HAL_MAX_DELAY);
if (ret != HAL_OK)
{
Error_Handler();
}
register_value = ((uint16_t)read_buf_word[0] | ((uint16_t)read_buf_word[1] << 8));
//read VIN = 35.621volt
ret = HAL_I2C_Mem_Read(&hi2c1,LTC4015_DEVICE_ADDRESS_READ,0x3B,I2C_MEMADD_SIZE_8BIT,read_buf_word, 2, HAL_MAX_DELAY);
if (ret != HAL_OK)
{
Error_Handler();
}
register_value = ((uint16_t)read_buf_word[0] | ((uint16_t)read_buf_word[1] << 8));
//read VSYS = 35.5volt
ret = HAL_I2C_Mem_Read(&hi2c1,LTC4015_DEVICE_ADDRESS_READ,0x3C,I2C_MEMADD_SIZE_8BIT,read_buf_word, 2, HAL_MAX_DELAY);
if (ret != HAL_OK)
{
Error_Handler();
}
register_value = ((uint16_t)read_buf_word[0] | ((uint16_t)read_buf_word[1] << 8));
//read IBAT = 0.063721845
ret = HAL_I2C_Mem_Read(&hi2c1,LTC4015_DEVICE_ADDRESS_READ,0x3D,I2C_MEMADD_SIZE_8BIT,read_buf_word, 2, HAL_MAX_DELAY);
if (ret != HAL_OK)
{
Error_Handler();
}
register_value = ((uint16_t)read_buf_word[0] | ((uint16_t)read_buf_word[1] << 8));
//read IIN = 0.01269554 amp
ret = HAL_I2C_Mem_Read(&hi2c1,LTC4015_DEVICE_ADDRESS_READ,0x3E,I2C_MEMADD_SIZE_8BIT,read_buf_word, 2, HAL_MAX_DELAY);
if (ret != HAL_OK)
{
Error_Handler();
}
register_value = ((uint16_t)read_buf_word[0] | ((uint16_t)read_buf_word[1] << 8));
//read DIE_TEMP = 41.798 degree centigrade
ret = HAL_I2C_Mem_Read(&hi2c1,LTC4015_DEVICE_ADDRESS_READ,0x3F,I2C_MEMADD_SIZE_8BIT,read_buf_word, 2, HAL_MAX_DELAY);
if (ret != HAL_OK)
{
Error_Handler();
}
register_value = ((uint16_t)read_buf_word[0] | ((uint16_t)read_buf_word[1] << 8));
//read BSR = 0ohm
ret = HAL_I2C_Mem_Read(&hi2c1,LTC4015_DEVICE_ADDRESS_READ,0x41,I2C_MEMADD_SIZE_8BIT,read_buf_word, 2, HAL_MAX_DELAY);
if (ret != HAL_OK)
{
Error_Handler();
}
register_value = ((uint16_t)read_buf_word[0] | ((uint16_t)read_buf_word[1] << 8));
//read ICHARGE_DAC = 11
ret = HAL_I2C_Mem_Read(&hi2c1,LTC4015_DEVICE_ADDRESS_READ,0x44,I2C_MEMADD_SIZE_8BIT,read_buf_word, 2, HAL_MAX_DELAY);
if (ret != HAL_OK)
{
Error_Handler();
}
register_value = ((uint16_t)read_buf_word[0] | ((uint16_t)read_buf_word[1] << 8));
//read VCHARGE_DAC=31
ret = HAL_I2C_Mem_Read(&hi2c1,LTC4015_DEVICE_ADDRESS_READ,0x45,I2C_MEMADD_SIZE_8BIT,read_buf_word, 2, HAL_MAX_DELAY);
if (ret != HAL_OK)
{
Error_Handler();
}
register_value = ((uint16_t)read_buf_word[0] | ((uint16_t)read_buf_word[1] << 8));
//VBAT_FILT=26 volt
ret = HAL_I2C_Mem_Read(&hi2c1,LTC4015_DEVICE_ADDRESS_READ,0x47,I2C_MEMADD_SIZE_8BIT,read_buf_word, 2, HAL_MAX_DELAY);
if (ret != HAL_OK)
{
Error_Handler();
}
register_value = ((uint16_t)read_buf_word[0] | ((uint16_t)read_buf_word[1] << 8));
//MEAS_SYS_VALID
ret = HAL_I2C_Mem_Read(&hi2c1,LTC4015_DEVICE_ADDRESS_READ,0x4A,I2C_MEMADD_SIZE_8BIT,read_buf_word, 2, HAL_MAX_DELAY);
if (ret != HAL_OK)
{
Error_Handler();
}
register_value = ((uint16_t)read_buf_word[0] | ((uint16_t)read_buf_word[1] << 8));
//check charger state as battery detection
if ( HAL_I2C_Mem_Read(&hi2c1,LTC4015_DEVICE_ADDRESS_READ,0x34,I2C_MEMADD_SIZE_8BIT,read_buf_word, 2, HAL_MAX_DELAY) == HAL_OK )
{
register_value = 0;
register_value = ((uint16_t)read_buf_word[0] | ((uint16_t)read_buf_word[1] << 8));
if ( ( register_value & 0x2 ) == 0 )//checking battery detection
{
HAL_UART_Transmit(&huart1,(uint8_t*) "battery is detected by ltc4015\r\n", sizeof("battery is detected by ltc4015\r\n"), HAL_MAX_DELAY);
}
else
{
//print message
HAL_UART_Transmit(&huart1, (uint8_t*) "battery is not detected by ltc4015\r\n", sizeof("battery is not detected by ltc4015\r\n"), HAL_MAX_DELAY);
}
}
else
{
Error_Handler();
}
//check charger state as cc_cv_charge state
if ( HAL_I2C_Mem_Read(&hi2c1,LTC4015_DEVICE_ADDRESS_READ,0x34,I2C_MEMADD_SIZE_8BIT,read_buf_word, 2, HAL_MAX_DELAY) == HAL_OK )
{
register_value = 0;
register_value = ((uint16_t)read_buf_word[0] | ((uint16_t)read_buf_word[1] << 8));
if ( ( register_value & 0x0040 ) != 0 )//checking CC_CV state
{
//print message
HAL_UART_Transmit(&huart1,(uint8_t*) "charger has entered into cc_cv state & battery is charging\r\n", sizeof("charger has entered into cc_cv state & battery is charging\r\n"), HAL_MAX_DELAY);
HAL_GPIO_TogglePin(GPIOA,GPIO_PIN_1);//blink led if battery is charging
}
else
{
//print message
HAL_UART_Transmit(&huart1, (uint8_t*) "charger has not entered into cc_cv state & battery is not charging\r\n", sizeof("charger has not entered into cc_cv state & battery is not charging\r\n"), HAL_MAX_DELAY);
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_1,GPIO_PIN_SET);//on the led if battery is not charging
}
}
else
{
Error_Handler();
}
// ret = HAL_I2C_Mem_Read(&hi2c1,LTC4015_DEVICE_ADDRESS_READ,0x37,I2C_MEMADD_SIZE_8BIT,(uint16_t*)(®ister_value), 2, HAL_MAX_DELAY);//checking battery missing fault alert
// if (ret != HAL_OK)
// {
// Error_Handler();
// }
}
/* 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};
/** Configure the main internal regulator output voltage
*/
__HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE1);
/** Initializes the RCC Oscillators according to the specified parameters
* in the RCC_OscInitTypeDef structure.
*/
RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI;
RCC_OscInitStruct.HSIState = RCC_HSI_ON;
RCC_OscInitStruct.HSICalibrationValue = RCC_HSICALIBRATION_DEFAULT;
RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSI;
RCC_OscInitStruct.PLL.PLLMUL = RCC_PLLMUL_4;
RCC_OscInitStruct.PLL.PLLDIV = RCC_PLLDIV_2;
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_1) != 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();
}
}
/**
* @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 = 0x00707CBB;
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 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};
/* USER CODE BEGIN MX_GPIO_Init_1 */
/* USER CODE END MX_GPIO_Init_1 */
/* GPIO Ports Clock Enable */
__HAL_RCC_GPIOA_CLK_ENABLE();
__HAL_RCC_GPIOB_CLK_ENABLE();
/*Configure GPIO pin Output Level */
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_0|GPIO_PIN_1, GPIO_PIN_RESET);
/*Configure GPIO pin Output Level */
HAL_GPIO_WritePin(GPIOB, GPIO_PIN_4|GPIO_PIN_7, GPIO_PIN_RESET);
/*Configure GPIO pins : PA0 PA1 */
GPIO_InitStruct.Pin = GPIO_PIN_0|GPIO_PIN_1;
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);
/*Configure GPIO pins : PB4 PB7 */
GPIO_InitStruct.Pin = GPIO_PIN_4|GPIO_PIN_7;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
/*Configure GPIO pin : PB5 */
GPIO_InitStruct.Pin = GPIO_PIN_5;
GPIO_InitStruct.Mode = GPIO_MODE_IT_FALLING;
GPIO_InitStruct.Pull = GPIO_NOPULL;
HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
/* EXTI interrupt init*/
HAL_NVIC_SetPriority(EXTI4_15_IRQn, 0, 0);
领英推荐
HAL_NVIC_EnableIRQ(EXTI4_15_IRQn);
/* USER CODE BEGIN MX_GPIO_Init_2 */
/* USER CODE END MX_GPIO_Init_2 */
}
/* USER CODE BEGIN 4 */
// External Interrupt ISR Handler CallBackFun
//SMBALERT interrupt input pin from ltc4015 to stm32l0
void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
{
//if(GPIO_Pin == GPIO_PIN_5) // INT Source is pin B5
//{
//HAL_Delay(100);
//HAL_GPIO_TogglePin(GPIOA,GPIO_PIN_1);//do some task
// }
}
//rrc3570_battery_comm_check function
static void rrc3570_battery_comm_check(void)
{
HAL_StatusTypeDef ret;
uint8_t buf[1];
uint8_t read_buf_block[10];
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_0,GPIO_PIN_RESET);//initially Disable the battery
HAL_Delay(500);//wait for 500ms
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_0,GPIO_PIN_SET);//Enable the battery
//step-1
HAL_GPIO_WritePin(GPIOB, GPIO_PIN_7,GPIO_PIN_RESET);//RESET PIN cleared of PCA9546A
HAL_Delay(500);//put some delay
HAL_GPIO_WritePin(GPIOB, GPIO_PIN_7,GPIO_PIN_SET);//RESET PIN set of PCA9546A
HAL_Delay(500);//put some delay
//step-2
buf[0] = CONTROL_REG2;
ret = HAL_I2C_Master_Transmit(&hi2c1,PCA9546A_DEVICE_ADDRESS,buf,1,HAL_MAX_DELAY);//select channel 1 for battery
if (ret != HAL_OK)
{
Error_Handler();
}
//read battery chemistry as LION for checking battery communication
ret = HAL_I2C_Mem_Read(&hi2c1,0x17,0x22,I2C_MEMADD_SIZE_8BIT,read_buf_block,5,HAL_MAX_DELAY);
if (ret != HAL_OK)
{
Error_Handler();
}
else
{
HAL_UART_Transmit(&huart1,read_buf_block,5, HAL_MAX_DELAY);
HAL_UART_Transmit(&huart1,(uint8_t *)" ",sizeof(" "), HAL_MAX_DELAY);
HAL_UART_Transmit(&huart1,(uint8_t *)"chemistry\r\n",sizeof("chemistry\r\n"), HAL_MAX_DELAY);
}
}//end of rrc3570_battery_comm_check function
//ltc_4015_init function
static void ltc_4015_init(void)
{
HAL_StatusTypeDef ret;
uint8_t buf[1];
uint8_t read_buf_word[2];
uint16_t register_value = 0;
//(ltc4015 section)
//PB5 ALERT pin is configured as interrupt
// HAL_GPIO_WritePin(GPIOB, GPIO_PIN_4,GPIO_PIN_RESET);//EQ1 pin is low as unused
//ntc pin is grounded & unused
//step-1
HAL_GPIO_WritePin(GPIOB, GPIO_PIN_7,GPIO_PIN_RESET);//RESET PIN cleared of PCA9546A
HAL_Delay(500);//put some delay
HAL_GPIO_WritePin(GPIOB, GPIO_PIN_7,GPIO_PIN_SET);//RESET PIN set of PCA9546A
HAL_Delay(500);//put some delay
//step-2
buf[0] = CONTROL_REG1;
ret = HAL_I2C_Master_Transmit(&hi2c1,PCA9546A_DEVICE_ADDRESS,buf,1,HAL_MAX_DELAY);//select channel 0 for i2c switch
if (ret != HAL_OK)
{
Error_Handler();
}
//Configure alert limit registers
//VBAT_LO_ALERT_LIMIT=2.50v*7=17.5v
//first send lower byte & then send higher byte
uint8_t dataBuffer1[2] = {0xcb,0x32};
ret = HAL_I2C_Mem_Write(&hi2c1, LTC4015_DEVICE_ADDRESS_WRITE, 0x01, I2C_MEMADD_SIZE_8BIT, dataBuffer1, 2, HAL_MAX_DELAY);
if (ret != HAL_OK)
{
Error_Handler();
}
ret = HAL_I2C_Mem_Read(&hi2c1,LTC4015_DEVICE_ADDRESS_READ,0x01,I2C_MEMADD_SIZE_8BIT,read_buf_word, 2, HAL_MAX_DELAY);
if (ret != HAL_OK)
{
Error_Handler();
}
register_value = ((uint16_t)read_buf_word[0] | ((uint16_t)read_buf_word[1] << 8));
//VBAT_HI_ALERT_LIMIT=4.2*7 = 29.4v
//send low byte then send high byte
uint8_t dataBuffer2[2] = {0x55,0x55};
ret = HAL_I2C_Mem_Write(&hi2c1, LTC4015_DEVICE_ADDRESS_WRITE, 0x02, I2C_MEMADD_SIZE_8BIT, dataBuffer2, 2, HAL_MAX_DELAY);
if (ret != HAL_OK)
{
Error_Handler();
}
ret = HAL_I2C_Mem_Read(&hi2c1,LTC4015_DEVICE_ADDRESS_READ,0x02,I2C_MEMADD_SIZE_8BIT,read_buf_word, 2, HAL_MAX_DELAY);
if (ret != HAL_OK)
{
Error_Handler();
}
register_value = ((uint16_t)read_buf_word[0] | ((uint16_t)read_buf_word[1] << 8));
//VIN_LO_ALERT_LIMIT 2.8v
//send low then high byte
uint8_t dataBuffer3[2] = {0xa3,0x06};
ret = HAL_I2C_Mem_Write(&hi2c1, LTC4015_DEVICE_ADDRESS_WRITE, 0x03, I2C_MEMADD_SIZE_8BIT, dataBuffer3, 2, HAL_MAX_DELAY);
if (ret != HAL_OK)
{
Error_Handler();
}
ret = HAL_I2C_Mem_Read(&hi2c1,LTC4015_DEVICE_ADDRESS_READ,0x03,I2C_MEMADD_SIZE_8BIT,read_buf_word,2, HAL_MAX_DELAY);
if (ret != HAL_OK)
{
Error_Handler();
}
register_value = ((uint16_t)read_buf_word[0] | ((uint16_t)read_buf_word[1] << 8));
//VIN_HI_ALERT_LIMIT 35v
//send low byte then high byte
uint8_t dataBuffer4[2] = {0xf6,0x52};
ret = HAL_I2C_Mem_Write(&hi2c1, LTC4015_DEVICE_ADDRESS_WRITE, 0x04, I2C_MEMADD_SIZE_8BIT, dataBuffer4, 2, HAL_MAX_DELAY);
if (ret != HAL_OK)
{
Error_Handler();
}
ret = HAL_I2C_Mem_Read(&hi2c1,LTC4015_DEVICE_ADDRESS_READ,0x04,I2C_MEMADD_SIZE_8BIT,read_buf_word,2, HAL_MAX_DELAY);
if (ret != HAL_OK)
{
Error_Handler();
}
register_value = ((uint16_t)read_buf_word[0] | ((uint16_t)read_buf_word[1] << 8));
//VSYS_LO_ALERT_LIMIT 2.8v
//send low then send high byte
uint8_t dataBuffer5[2] = {0xa3,0x06};
ret = HAL_I2C_Mem_Write(&hi2c1, LTC4015_DEVICE_ADDRESS_WRITE, 0x05, I2C_MEMADD_SIZE_8BIT, dataBuffer5, 2, HAL_MAX_DELAY);
if (ret != HAL_OK)
{
Error_Handler();
}
ret = HAL_I2C_Mem_Read(&hi2c1,LTC4015_DEVICE_ADDRESS_READ,0x05,I2C_MEMADD_SIZE_8BIT,read_buf_word,2, HAL_MAX_DELAY);
if (ret != HAL_OK)
{
Error_Handler();
}
register_value = ((uint16_t)read_buf_word[0] | ((uint16_t)read_buf_word[1] << 8));
//VSYS_HI_ALERT_LIMIT 35v
//send low then send high byte
uint8_t dataBuffer6[2] = {0xf6,0x52};
ret = HAL_I2C_Mem_Write(&hi2c1, LTC4015_DEVICE_ADDRESS_WRITE, 0x06, I2C_MEMADD_SIZE_8BIT, dataBuffer6, 2, HAL_MAX_DELAY);
if (ret != HAL_OK)
{
Error_Handler();
}
ret = HAL_I2C_Mem_Read(&hi2c1,LTC4015_DEVICE_ADDRESS_READ,0x06,I2C_MEMADD_SIZE_8BIT,read_buf_word,2, HAL_MAX_DELAY);
if (ret != HAL_OK)
{
Error_Handler();
}
register_value = ((uint16_t)read_buf_word[0] | ((uint16_t)read_buf_word[1] << 8));
//IN_HI_ALERT_LIMIT 3Amp
//send low then send high byte
uint8_t dataBuffer7[2] = {0x00,0x18};
ret = HAL_I2C_Mem_Write(&hi2c1, LTC4015_DEVICE_ADDRESS_WRITE, 0x07, I2C_MEMADD_SIZE_8BIT, dataBuffer7, 2, HAL_MAX_DELAY);
if (ret != HAL_OK)
{
Error_Handler();
}
ret = HAL_I2C_Mem_Read(&hi2c1,LTC4015_DEVICE_ADDRESS_READ,0x07,I2C_MEMADD_SIZE_8BIT,read_buf_word,2, HAL_MAX_DELAY);
if (ret != HAL_OK)
{
Error_Handler();
}
register_value = ((uint16_t)read_buf_word[0] | ((uint16_t)read_buf_word[1] << 8));
//IBAT_LO_ALERT_LIMIT 0amp
//send low then send high byte
uint8_t dataBuffer8[2] = {0x00,0x00};
ret = HAL_I2C_Mem_Write(&hi2c1, LTC4015_DEVICE_ADDRESS_WRITE,0x08, I2C_MEMADD_SIZE_8BIT, dataBuffer8, 2, HAL_MAX_DELAY);
if (ret != HAL_OK)
{
Error_Handler();
}
ret = HAL_I2C_Mem_Read(&hi2c1,LTC4015_DEVICE_ADDRESS_READ,0x08,I2C_MEMADD_SIZE_8BIT,read_buf_word,2, HAL_MAX_DELAY);
if (ret != HAL_OK)
{
Error_Handler();
}
register_value = ((uint16_t)read_buf_word[0] | ((uint16_t)read_buf_word[1] << 8));
//DIE_TEMP_HI_ALERT_LIMIT 60 degree can be changed as per requirement
//send low then send high byte
uint8_t dataBuffer9[2] = {0x9a,0x39};
ret = HAL_I2C_Mem_Write(&hi2c1, LTC4015_DEVICE_ADDRESS_WRITE,0x09, I2C_MEMADD_SIZE_8BIT, dataBuffer9, 2, HAL_MAX_DELAY);
if (ret != HAL_OK)
{
Error_Handler();
}
ret = HAL_I2C_Mem_Read(&hi2c1,LTC4015_DEVICE_ADDRESS_READ,0x09,I2C_MEMADD_SIZE_8BIT,read_buf_word,2, HAL_MAX_DELAY);
if (ret != HAL_OK)
{
Error_Handler();
}
register_value = ((uint16_t)read_buf_word[0] | ((uint16_t)read_buf_word[1] << 8));
//BSR_HI_ALERT_LIMIT 100milliohm & can be changed as per requirement
//send low then send high byte
uint8_t dataBuffer10[2] = {0xfa,0x06};
ret = HAL_I2C_Mem_Write(&hi2c1, LTC4015_DEVICE_ADDRESS_WRITE,0x0A, I2C_MEMADD_SIZE_8BIT, dataBuffer10, 2, HAL_MAX_DELAY);
if (ret != HAL_OK)
{
Error_Handler();
}
ret = HAL_I2C_Mem_Read(&hi2c1,LTC4015_DEVICE_ADDRESS_READ,0x0A,I2C_MEMADD_SIZE_8BIT,read_buf_word,2, HAL_MAX_DELAY);
if (ret != HAL_OK)
{
Error_Handler();
}
register_value = ((uint16_t)read_buf_word[0] | ((uint16_t)read_buf_word[1] << 8));
//ntc is not used here
//NTC_RATIO_HI_ALERT_LIMIT (Sub-Address 0x0B, Bits 15:0,R/W)
//NTC_RATIO_LO_ALERT_LIMIT (Sub-Address 0x0C, Bits 15:0, R/W)
//Enable limit alerts
//send lower byte then send higher byte
uint8_t dataBuffer11[2] = {0xfc,0xbf};
ret = HAL_I2C_Mem_Write(&hi2c1, LTC4015_DEVICE_ADDRESS_WRITE,0x0D, I2C_MEMADD_SIZE_8BIT, dataBuffer11,2, HAL_MAX_DELAY);
if (ret != HAL_OK)
{
Error_Handler();
}
ret = HAL_I2C_Mem_Read(&hi2c1,LTC4015_DEVICE_ADDRESS_READ,0x0D,I2C_MEMADD_SIZE_8BIT,read_buf_word,2, HAL_MAX_DELAY);
if (ret != HAL_OK)
{
Error_Handler();
}
register_value = ((uint16_t)read_buf_word[0] | ((uint16_t)read_buf_word[1] << 8));
//Enable charger state alerts
//send lower byte then send higher byte
uint8_t dataBuffer12[2] = {0xdf,0x01};
ret = HAL_I2C_Mem_Write(&hi2c1, LTC4015_DEVICE_ADDRESS_WRITE,0x0E, I2C_MEMADD_SIZE_8BIT, dataBuffer12,2, HAL_MAX_DELAY);
if (ret != HAL_OK)
{
Error_Handler();
}
ret = HAL_I2C_Mem_Read(&hi2c1,LTC4015_DEVICE_ADDRESS_READ,0x0E,I2C_MEMADD_SIZE_8BIT,read_buf_word,2, HAL_MAX_DELAY);
if (ret != HAL_OK)
{
Error_Handler();
}
register_value = ((uint16_t)read_buf_word[0] | ((uint16_t)read_buf_word[1] << 8));
//Enable charge status alert
//send lower byte then send higher byte
uint8_t dataBuffer13[2] = {0x0f,0x00};
ret = HAL_I2C_Mem_Write(&hi2c1, LTC4015_DEVICE_ADDRESS_WRITE,0x0F, I2C_MEMADD_SIZE_8BIT, dataBuffer13,2, HAL_MAX_DELAY);
if (ret != HAL_OK)
{
Error_Handler();
}
ret = HAL_I2C_Mem_Read(&hi2c1,LTC4015_DEVICE_ADDRESS_READ,0x0F,I2C_MEMADD_SIZE_8BIT,read_buf_word,2, HAL_MAX_DELAY);
if (ret != HAL_OK)
{
Error_Handler();
}
register_value = ((uint16_t)read_buf_word[0] | ((uint16_t)read_buf_word[1] << 8));
//state of charge function is not required as it is indicated in battery leds
//QCOUNT_LO_ALERT_LIMIT register is not required to configure
//QCOUNT_HI_ALERT_LIMIT register is not required to configure
//QCOUNT_PRESCALE_FACTOR register is not required to configure
//QCOUNT register is not required to configure
//CONFIG_BITS only suspend_charger bit is required for setting & resetting
//IN_LIMIT_SETTING 3 amp
//send lower byte then send higher byte
uint8_t dataBuffer14[2] = {0x11,0x00};
ret = HAL_I2C_Mem_Write(&hi2c1, LTC4015_DEVICE_ADDRESS_WRITE,0x15, I2C_MEMADD_SIZE_8BIT, dataBuffer14,2, HAL_MAX_DELAY);
if (ret != HAL_OK)
{
Error_Handler();
}
ret = HAL_I2C_Mem_Read(&hi2c1,LTC4015_DEVICE_ADDRESS_READ,0x15,I2C_MEMADD_SIZE_8BIT,read_buf_word,2, HAL_MAX_DELAY);
if (ret != HAL_OK)
{
Error_Handler();
}
register_value = ((uint16_t)read_buf_word[0] | ((uint16_t)read_buf_word[1] << 8));
//VIN_UVCL_SETTING not req as its used for solar panel and default value is 0xff
//ICHARGE_TARGET 3amp
uint8_t dataBuffer15[2] = {0x0b,0x00};
ret = HAL_I2C_Mem_Write(&hi2c1, LTC4015_DEVICE_ADDRESS_WRITE,0x1A, I2C_MEMADD_SIZE_8BIT, dataBuffer15,2, HAL_MAX_DELAY);
if (ret != HAL_OK)
{
Error_Handler();
}
ret = HAL_I2C_Mem_Read(&hi2c1,LTC4015_DEVICE_ADDRESS_READ,0x1A,I2C_MEMADD_SIZE_8BIT,read_buf_word,2, HAL_MAX_DELAY);
if (ret != HAL_OK)
{
Error_Handler();
}
register_value = ((uint16_t)read_buf_word[0] | ((uint16_t)read_buf_word[1] << 8));
//VCHARGE_SETTING 4.2v/cell
uint8_t dataBuffer16[2] = {0x1f,0x00};
ret = HAL_I2C_Mem_Write(&hi2c1, LTC4015_DEVICE_ADDRESS_WRITE,0x1B, I2C_MEMADD_SIZE_8BIT, dataBuffer16,2, HAL_MAX_DELAY);
if (ret != HAL_OK)
{
Error_Handler();
}
ret = HAL_I2C_Mem_Read(&hi2c1,LTC4015_DEVICE_ADDRESS_READ,0x1B,I2C_MEMADD_SIZE_8BIT,read_buf_word,2, HAL_MAX_DELAY);
if (ret != HAL_OK)
{
Error_Handler();
}
register_value = ((uint16_t)read_buf_word[0] | ((uint16_t)read_buf_word[1] << 8));
//C_OVER_X_THRESHOLD default value is set = 2184
//ret = HAL_I2C_Mem_Read(&hi2c1,LTC4015_DEVICE_ADDRESS_READ,0x1C,I2C_MEMADD_SIZE_8BIT,read_buf_word,2, HAL_MAX_DELAY);
//if (ret != HAL_OK)
//{
// Error_Handler();
//}
//register_value = ((uint16_t)read_buf_word[0] | ((uint16_t)read_buf_word[1] << 8));
//MAX_CV_TIME default value = 14,400 i.e 4 hours for lion chemistry
//ret = HAL_I2C_Mem_Read(&hi2c1,LTC4015_DEVICE_ADDRESS_READ,0x1D,I2C_MEMADD_SIZE_8BIT,read_buf_word,2, HAL_MAX_DELAY);
//if (ret != HAL_OK)
//{
// Error_Handler();
//}
//register_value = ((uint16_t)read_buf_word[0] | ((uint16_t)read_buf_word[1] << 8));
//MAX_CHARGE_TIME default value = 18.2 hours (65535)for lion chemistry
//ret = HAL_I2C_Mem_Read(&hi2c1,LTC4015_DEVICE_ADDRESS_READ,0x1E,I2C_MEMADD_SIZE_8BIT,read_buf_word,2, HAL_MAX_DELAY);
//if (ret != HAL_OK)
//{
// Error_Handler();
//}
//register_value = ((uint16_t)read_buf_word[0] | ((uint16_t)read_buf_word[1] << 8));
//CHARGER_CONFIG_BITS only bit 2 en_c_over_x_term will be set
uint8_t dataBuffer17[2] = {0x04,0x00};
ret = HAL_I2C_Mem_Write(&hi2c1, LTC4015_DEVICE_ADDRESS_WRITE,0x29, I2C_MEMADD_SIZE_8BIT, dataBuffer17,2, HAL_MAX_DELAY);
if (ret != HAL_OK)
{
Error_Handler();
}
ret = HAL_I2C_Mem_Read(&hi2c1,LTC4015_DEVICE_ADDRESS_READ,0x29,I2C_MEMADD_SIZE_8BIT,read_buf_word,2, HAL_MAX_DELAY);
if (ret != HAL_OK)
{
Error_Handler();
}
register_value = ((uint16_t)read_buf_word[0] | ((uint16_t)read_buf_word[1] << 8));
}//end of function ltc_4015_init()
//start charging function
static void start_charging(void)
{
HAL_StatusTypeDef ret;
uint16_t temp;
uint16_t read_data;
uint8_t read_buf_word_data[2];
uint8_t write_buf_word_data[2];
// ret = HAL_I2C_Mem_Read(&hi2c1,LTC4015_DEVICE_ADDRESS_READ,0x14,I2C_MEMADD_SIZE_8BIT,read_buf_word_data,2, HAL_MAX_DELAY);
// if (ret != HAL_OK)
// {
// Error_Handler();
// }
// read_data = ((uint16_t)read_buf_word_data[0] | ((uint16_t)read_buf_word_data[1] << 8));
// temp = read_data | (0x0001<<8);//suspend_charger bit is high
// write_buf_word_data[0] = (uint8_t)(temp & 0x00ff);
// write_buf_word_data[1] =(uint8_t)((temp & 0xff00)>>8);
//
// ret = HAL_I2C_Mem_Write(&hi2c1, LTC4015_DEVICE_ADDRESS_WRITE,0x14, I2C_MEMADD_SIZE_8BIT,write_buf_word_data,2, HAL_MAX_DELAY);
// if (ret != HAL_OK)
// {
// Error_Handler();
// }
//
// HAL_Delay(500);
ret = HAL_I2C_Mem_Read(&hi2c1,LTC4015_DEVICE_ADDRESS_READ,0x14,I2C_MEMADD_SIZE_8BIT,read_buf_word_data,2, HAL_MAX_DELAY);
if (ret != HAL_OK)
{
Error_Handler();
}
read_data = ((uint16_t)read_buf_word_data[0] | ((uint16_t)read_buf_word_data[1] << 8));
temp = read_data &(~(0x0001<<8));////suspend_charger bit is low
write_buf_word_data[0] = (uint8_t)(temp & 0x00ff);
write_buf_word_data[1] =(uint8_t)((temp & 0xff00)>>8);
ret = HAL_I2C_Mem_Write(&hi2c1, LTC4015_DEVICE_ADDRESS_WRITE,0x14, I2C_MEMADD_SIZE_8BIT,write_buf_word_data,2, HAL_MAX_DELAY);
if (ret != HAL_OK)
{
Error_Handler();
}
}//end of function start_charging()
//stop charging function
static void stop_charging(void)
{
HAL_StatusTypeDef ret;
uint16_t temp;
uint16_t read_data;
uint8_t read_buf_word_data[2];
uint8_t write_buf_word_data[2];
ret = HAL_I2C_Mem_Read(&hi2c1,LTC4015_DEVICE_ADDRESS_READ,0x14,I2C_MEMADD_SIZE_8BIT,read_buf_word_data,2, HAL_MAX_DELAY);
if (ret != HAL_OK)
{
Error_Handler();
}
read_data = ((uint16_t)read_buf_word_data[0] | ((uint16_t)read_buf_word_data[1] << 8));
temp = read_data | (0x0001<<8);//suspend_charger bit is high
write_buf_word_data[0] = (uint8_t)(temp & 0x00ff);
write_buf_word_data[1] =(uint8_t)((temp & 0xff00)>>8);
ret = HAL_I2C_Mem_Write(&hi2c1, LTC4015_DEVICE_ADDRESS_WRITE,0x14, I2C_MEMADD_SIZE_8BIT,write_buf_word_data,2, HAL_MAX_DELAY);
if (ret != HAL_OK)
{
Error_Handler();
}
}//end of function stop_charging()
/* 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();
HAL_UART_Transmit(&huart1,(uint8_t*) "I2C communication error\r\n", sizeof("I2C communication error\r\n"), HAL_MAX_DELAY);
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 */
Note :- This program can be easily modified for more advanced applications.
IDE - STM32cubeide
Microcontroller - STM32L0
CTO LikeAbird Ltd and Unmanned Systems Consulting Expert
9 个月Interesting project. are you open to migrate the same over to microcontrollers?
Technical Content Writer , Technical Expert , Mentor , Trainer , & Embedded Software Developer
1 年Please comment if you find any mistakes.