/***************************************************************************//**
* @file LTC681x.cpp
* @author BMS (bms.support@analog.com)
REVISION HISTORY
$Revision: 1.0 $
$Date: 2018-11 $
********************************************************************************
* Copyright 2018(c) Analog Devices, Inc.
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* - Neither the name of Analog Devices, Inc. nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
* - The use of this software may or may not infringe the patent rights
* of one or more patent holders. This license does not release you
* from the requirement that you obtain separate licenses from these
* patent holders to use this software.
* - Use of the software either in source or binary form, must be run
* on or directly connected to an Analog Devices Inc. component.
*
* THIS SOFTWARE IS PROVIDED BY ANALOG DEVICES "AS IS" AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, NON-INFRINGEMENT,
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL ANALOG DEVICES BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, INTELLECTUAL PROPERTY RIGHTS, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*******************************************************************************/
/*! @file
Library for LTC681x Multi-cell Battery Monitor
*/
#include <stdint.h>
#include "LTC681x.h"
#include "bms_hardware.h"
#ifdef LINDUINO
#include <Arduino.h>
#endif
//Wake isoSPI up from idle state
void wakeup_idle(uint8_t total_ic)
{
for (int i =0; i<total_ic; i++)
{
cs_low(CS_PIN);
spi_read_byte(0xff);//Guarantees the isoSPI will be in ready mode
cs_high(CS_PIN);
}
}
//Generic wakeup command to wake the LTC681x from sleep
void wakeup_sleep(uint8_t total_ic)
{
for (int i =0; i<total_ic; i++)
{
cs_low(CS_PIN);
delay_u(300); // Guarantees the LTC681x will be in standby
cs_high(CS_PIN);
delay_u(10);
}
}
//Generic function to write 68xx commands. Function calculated PEC for tx_cmd data
void cmd_68(uint8_t tx_cmd[2])
{
uint8_t cmd[4];
uint16_t cmd_pec;
uint8_t md_bits;
cmd[0] = tx_cmd[0];
cmd[1] = tx_cmd[1];
cmd_pec = pec15_calc(2, cmd);
cmd[2] = (uint8_t)(cmd_pec >> 8);
cmd[3] = (uint8_t)(cmd_pec);
cs_low(CS_PIN);
spi_write_array(4,cmd);
cs_high(CS_PIN);
}
//Generic function to write 68xx commands and write payload data. Function calculated PEC for tx_cmd data
void write_68(uint8_t total_ic,
uint8_t tx_cmd[2],
uint8_t data[])
{
const uint8_t BYTES_IN_REG = 6;
const uint8_t CMD_LEN = 4+(8*total_ic);
uint8_t *cmd;
uint16_t data_pec;
uint16_t cmd_pec;
uint8_t cmd_index;
cmd = (uint8_t *)malloc(CMD_LEN*sizeof(uint8_t));
cmd[0] = tx_cmd[0];
cmd[1] = tx_cmd[1];
cmd_pec = pec15_calc(2, cmd);
cmd[2] = (uint8_t)(cmd_pec >> 8);
cmd[3] = (uint8_t)(cmd_pec);
cmd_index = 4;
for (uint8_t current_ic = total_ic; current_ic > 0; current_ic--) // executes for each LTC681x, this loops starts with the last IC on the stack.
{ //The first configuration written is received by the last IC in the daisy chain
for (uint8_t current_byte = 0; current_byte < BYTES_IN_REG; current_byte++)
{
cmd[cmd_index] = data[((current_ic-1)*6)+current_byte];
cmd_index = cmd_index + 1;
}
data_pec = (uint16_t)pec15_calc(BYTES_IN_REG, &data[(current_ic-1)*6]); // calculating the PEC for each Iss configuration register data
cmd[cmd_index] = (uint8_t)(data_pec >> 8);
cmd[cmd_index + 1] = (uint8_t)data_pec;
cmd_index = cmd_index + 2;
}
cs_low(CS_PIN);
spi_write_array(CMD_LEN, cmd);
cs_high(CS_PIN);
free(cmd);
}
//Generic function to write 68xx commands and read data. Function calculated PEC for tx_cmd data
int8_t read_68( uint8_t total_ic,
uint8_t tx_cmd[2],
uint8_t *rx_data)
{
const uint8_t BYTES_IN_REG = 8;
uint8_t cmd[4];
uint8_t data[256];
int8_t pec_error = 0;
uint16_t cmd_pec;
uint16_t data_pec;
uint16_t received_pec;
cmd[0] = tx_cmd[0];
cmd[1] = tx_cmd[1];
cmd_pec = pec15_calc(2, cmd);
cmd[2] = (uint8_t)(cmd_pec >> 8);
cmd[3] = (uint8_t)(cmd_pec);
cs_low(CS_PIN);
spi_write_read(cmd, 4, data, (BYTES_IN_REG*total_ic)); //Read the configuration data of all ICs on the daisy chain into rx_data[] array
cs_high(CS_PIN);
for (uint8_t current_ic = 0; current_ic < total_ic; current_ic++) //executes for each LTC681x in the daisy chain and packs the data
{ //into the r_comm array as well as check the received data for any bit errors
for (uint8_t current_byte = 0; current_byte < BYTES_IN_REG; current_byte++)
{
rx_data[(current_ic*8)+current_byte] = data[current_byte + (current_ic*BYTES_IN_REG)];
}
received_pec = (rx_data[(current_ic*8)+6]<<8) + rx_data[(current_ic*8)+7];
data_pec = pec15_calc(6, &rx_data[current_ic*8]);
if (received_pec != data_pec)
{
pec_error = -1;
}
}
return(pec_error);
}
//Calculates and returns the CRC15
uint16_t pec15_calc(uint8_t len, //Number of bytes that will be used to calculate a PEC
uint8_t *data //Array of data that will be used to calculate a PEC
)
{
uint16_t remainder,addr;
remainder = 16;//initialize the PEC
for (uint8_t i = 0; i<len; i++) // loops for each byte in data array
{
addr = ((remainder>>7)^data[i])&0xff;//calculate PEC table address
#ifdef MBED
remainder = (remainder<<8)^crc15Table[addr];
#else
remainder = (remainder<<8)^pgm_read_word_near(crc15Table+addr);
#endif
}
return(remainder*2);//The CRC15 has a 0 in the LSB so the remainder must be multiplied by 2
}
//Helper function to initialize CFG variables.
void LTC681x_init_cfg(uint8_t total_ic,
cell_asic *ic
)
{
for (uint8_t current_ic = 0; current_ic<total_ic;current_ic++)
{
for (int j =0; j<6; j++)
{
ic[current_ic].config.tx_data[j] = 0;
}
}
}
//Helper function to set CFGR variable
void LTC681x_set_cfgr(uint8_t nIC,
cell_asic *ic,
bool refon,
bool adcopt,
bool gpio[5],
bool dcc[12],
bool dcto[4],
uint16_t uv,
uint16_t ov
)
{
LTC681x_set_cfgr_refon(nIC,ic,refon);
LTC681x_set_cfgr_adcopt(nIC,ic,adcopt);
LTC681x_set_cfgr_gpio(nIC,ic,gpio);
LTC681x_set_cfgr_dis(nIC,ic,dcc);
LTC681x_set_cfgr_dcto(nIC,ic,dcto);
LTC681x_set_cfgr_uv(nIC, ic, uv);
LTC681x_set_cfgr_ov(nIC, ic, ov);
}
//Helper function to set the REFON bit
void LTC681x_set_cfgr_refon(uint8_t nIC, cell_asic *ic, bool refon)
{
if (refon) ic[nIC].config.tx_data[0] = ic[nIC].config.tx_data[0]|0x04;
else ic[nIC].config.tx_data[0] = ic[nIC].config.tx_data[0]&0xFB;
}
//Helper function to set the adcopt bit
void LTC68
weixin_44602199
- 粉丝: 1
- 资源: 1
最新资源
- 基于Pytorch+YOLOv5+SlowFast实现的视频流实时动作检测算法-支持多目标的跟踪检测源码
- Halcon仿射变换详解
- 局部遮阴下光伏MPPT-粒子群算法,仿真模型
- GD32H7xx pack包
- Midjourney 常用参数列表
- 光伏MPPT仿真-电导增量法,仿真模型,可替自建光伏电池,有Video explanation(原创)
- Linux应用开发实训:基于51单片机的智能大棚管理系统设计与实现
- 福昕Foxit PDF语言包OCR-Lang-Chinese
- 3 Halcon基础之形态学算子
- 20230925-Halcon的3D点云筛选与切割过程详解
- 2024年大模型轻量化技术研究报告.pdf
- 电磁无损检测中扫频与脉冲涡流探伤的理论及实验研究(多层结构缺陷表征)
- 特征稀疏主子空间学习:低秩协方差矩阵全局优化算法与一般情况迭代求解的研究
- 脉冲调制涡流检测中漏斗形探头对导体内部缺陷敏感度增强的研究
- 7 【Halcon深度学习】水果分拣系统实战
- 美食点餐系-JAVA-基于微信美食点餐系统小程序的设计与实现(毕业论文)
资源上传下载、课程学习等过程中有任何疑问或建议,欢迎提出宝贵意见哦~我们会及时处理!
点击此处反馈