/*!
General BMS Library
@verbatim
@endverbatim
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.
Copyright 2017 Linear Technology Corp. (LTC)
***********************************************************/
#include <stdint.h>
#include "LTC681x.h"
#include "bms_hardware.h"
#ifdef LINDUINO
#include <Arduino.h>
#endif
void wakeup_idle(uint8_t total_ic)
{
for (int i =0; i<total_ic; i++)
{
cs_low(CS_PIN);
//delayMicroseconds(2); //Guarantees the isoSPI will be in ready mode
spi_read_byte(0xff);
cs_high(CS_PIN);
}
}
//Generic wakeup commannd to wake the LTC6813 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 LTC6813 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 in daisy chain, 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;
// data = (uint8_t *) malloc((8*total_ic)*sizeof(uint8_t)); // This is a problem because it can fail
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
cs_high(CS_PIN); //rx_data[] array
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 Config 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
}
//Starts cell voltage conversion
void LTC681x_adcv(
uint8_t MD, //ADC Mode
uint8_t DCP, //Discharge Permit
uint8_t CH //Cell Channels to be measured
)
{
uint8_t cmd[4];
uint8_t md_bits;
md_bits = (MD & 0x02) >> 1;
cmd[0] = md_bits + 0x02;
md_bits = (MD & 0x01) << 7;
cmd[1] = md_bits + 0x60 + (DCP<<4) + CH;
cmd_68(cmd);
}
//Starts cell voltage and SOC conversion
void LTC681x_adcvsc(
uint8_t MD, //ADC Mode
uint8_t DCP //Discharge Permit
)
{
uint8_t cmd[4];
uint8_t md_bits;
md_bits = (MD & 0x02) >> 1;
cmd[0] = md_bits | 0x04;
md_bits = (MD & 0x01) << 7;
cmd[1] = md_bits | 0x60 | (DCP<<4) | 0x07;
cmd_68(cmd);
}
// Starts cell voltage and GPIO 1&2 conversion
void LTC681x_adcvax(
uint8_t MD, //ADC Mode
uint8_t DCP //Discharge Permit
)
{
uint8_t cmd[4];
uint8_t md_bits;
md_bits = (MD & 0x02) >> 1;
cmd[0] = md_bits | 0x04;
md_bits = (MD & 0x01) << 7;
cmd[1] = md_bits | ((DCP&0x01)<<4) + 0x6F;
cmd_68(cmd);
}
//Starts cell voltage overlap conversion
void LTC681x_adol(
uint8_t MD, //ADC Mode
uint8_t DCP //Discharge Permit
)
{
uint8_t cmd[4];
uint8_t md_bits;
md_bits = (MD & 0x02) >> 1;
cmd[0] = md_bits + 0x02;
md_bits = (MD & 0x01) << 7;
cmd[1] = md
LTC681x Driver
需积分: 50 59 浏览量
2018-09-13
22:05:07
上传
评论 1
收藏 17KB RAR 举报
chentengkui
- 粉丝: 84
- 资源: 9
最新资源
- Screenshot_20240427_031602.jpg
- 网页PDF_2024年04月26日 23-46-14_QQ浏览器网页保存_QQ浏览器转格式(6).docx
- 直接插入排序,冒泡排序,直接选择排序.zip
- 在排序2的基础上,再次对快排进行优化,其次增加快排非递归,归并排序,归并排序非递归版.zip
- 实现了7种排序算法.三种复杂度排序.三种nlogn复杂度排序(堆排序,归并排序,快速排序)一种线性复杂度的排序.zip
- 冒泡排序 直接选择排序 直接插入排序 随机快速排序 归并排序 堆排序.zip
- 课设-内部排序算法比较 包括冒泡排序、直接插入排序、简单选择排序、快速排序、希尔排序、归并排序和堆排序.zip
- Python排序算法.zip
- C语言实现直接插入排序、希尔排序、选择排序、冒泡排序、堆排序、快速排序、归并排序、计数排序,并带图详解.zip
- 常用工具集参考用于图像等数据处理
资源上传下载、课程学习等过程中有任何疑问或建议,欢迎提出宝贵意见哦~我们会及时处理!
点击此处反馈