Backup before error handling refactoring
This commit is contained in:
1428
HARDWARE/Old/ltc6813-1.c
Normal file
1428
HARDWARE/Old/ltc6813-1.c
Normal file
File diff suppressed because it is too large
Load Diff
196
HARDWARE/can.c
Normal file
196
HARDWARE/can.c
Normal file
@@ -0,0 +1,196 @@
|
||||
#include "sys.h"
|
||||
#include "delay.h"
|
||||
#include "can.h"
|
||||
#include "includes.h" //ucos Use
|
||||
//////////////////////////////////////////////////////////////////////////////////
|
||||
//This program is for educational purposes only, without the author's permission, may not be used for any other purpose
|
||||
//ALIENTEK STM32F4 Explorer Board
|
||||
//Initialize serial port 2
|
||||
//Hot Atomic @ALIENTEK
|
||||
//Forum: www.openedv.com
|
||||
//Date modified: 2015/9/12
|
||||
//Version: V1.0
|
||||
//All rights reserved pirated reserved.
|
||||
//Copyright(C) Guangzhou wing electronic technology limited company 2009-2019
|
||||
//All rights reserved
|
||||
//********************************************************************************
|
||||
//////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/* Defines -------------------------------------------------------------------*/
|
||||
#define RX_BUFFER_SIZE 10
|
||||
|
||||
/* Type declarations ---------------------------------------------------------*/
|
||||
typedef struct
|
||||
{
|
||||
CAN_TypeDef *can;
|
||||
u16 RxInPos, RxOutPos;
|
||||
u16 TxInPos, TxOutPos;
|
||||
CanRxMsg RxBuf[RX_BUFFER_SIZE];
|
||||
} CAN_Info;
|
||||
|
||||
/* Exported macro ------------------------------------------------------------*/
|
||||
CAN_Info Can;
|
||||
|
||||
uint32_t can_speed = 500000;
|
||||
|
||||
//Initializes CAN Port
|
||||
//Bound: baud rate
|
||||
void can1_init(u32 buadrate)
|
||||
{
|
||||
//GPIO port settings
|
||||
GPIO_InitTypeDef GPIO_InitStructure;
|
||||
CAN_InitTypeDef CAN_InitStructure;
|
||||
CAN_FilterInitTypeDef CAN_FilterInitStructure;
|
||||
|
||||
Can.can = CAN1;
|
||||
|
||||
/* GPIO clock enable */
|
||||
RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE);
|
||||
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); //Enable GPIOA clock
|
||||
RCC_APB1PeriphClockCmd(RCC_APB1Periph_CAN1, ENABLE); //Enable CAN1 clock
|
||||
|
||||
//CAN1 pins reuse maps
|
||||
// GPIO_PinRemapConfig(GPIO_Remapping_CAN , ENABLE);
|
||||
|
||||
/* Configure CAN pin: RX */
|
||||
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11;
|
||||
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
|
||||
GPIO_Init(GPIOA, &GPIO_InitStructure);
|
||||
|
||||
/* Configure CAN pin: TX */
|
||||
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12;
|
||||
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
|
||||
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
|
||||
GPIO_Init(GPIOA, &GPIO_InitStructure);
|
||||
|
||||
//CAN1 Initialization settings
|
||||
CAN_DeInit(Can.can);
|
||||
|
||||
CAN_InitStructure.CAN_Mode = CAN_Mode_Normal;
|
||||
CAN_InitStructure.CAN_SJW = CAN_SJW_1tq;
|
||||
|
||||
// switch (buadrate)
|
||||
// {
|
||||
// case 125000:
|
||||
// CAN_InitStructure.CAN_BS1 = CAN_BS1_2tq;
|
||||
// CAN_InitStructure.CAN_BS2 = CAN_BS2_5tq;
|
||||
// CAN_InitStructure.CAN_Prescaler = 42;
|
||||
// break;
|
||||
// case 250000:
|
||||
// CAN_InitStructure.CAN_BS1 = CAN_BS1_3tq;
|
||||
// CAN_InitStructure.CAN_BS2 = CAN_BS2_4tq;
|
||||
// CAN_InitStructure.CAN_Prescaler = 16;
|
||||
// break;
|
||||
// case 500000:
|
||||
CAN_InitStructure.CAN_BS1 = CAN_BS1_3tq;
|
||||
CAN_InitStructure.CAN_BS2 = CAN_BS2_4tq;
|
||||
CAN_InitStructure.CAN_Prescaler = 8;
|
||||
// break;
|
||||
// case 1000000:
|
||||
// /* CAN Baudrate = 1MBps*/
|
||||
// CAN_InitStructure.CAN_BS1 = CAN_BS1_3tq;
|
||||
// CAN_InitStructure.CAN_BS2 = CAN_BS2_4tq;
|
||||
// CAN_InitStructure.CAN_Prescaler = 4;
|
||||
// break;
|
||||
// }
|
||||
CAN_InitStructure.CAN_TTCM = DISABLE; //
|
||||
CAN_InitStructure.CAN_ABOM = DISABLE; //
|
||||
CAN_InitStructure.CAN_AWUM = DISABLE; //
|
||||
CAN_InitStructure.CAN_NART = DISABLE; //
|
||||
CAN_InitStructure.CAN_RFLM = DISABLE; //
|
||||
CAN_InitStructure.CAN_TXFP = ENABLE; //
|
||||
|
||||
/* CAN filter init */
|
||||
CAN_FilterInitStructure.CAN_FilterNumber = 0;
|
||||
CAN_FilterInitStructure.CAN_FilterMode = CAN_FilterMode_IdMask;
|
||||
CAN_FilterInitStructure.CAN_FilterScale = CAN_FilterScale_32bit;
|
||||
CAN_FilterInitStructure.CAN_FilterIdHigh = 0x0000;
|
||||
CAN_FilterInitStructure.CAN_FilterIdLow = 0x0000;
|
||||
CAN_FilterInitStructure.CAN_FilterMaskIdHigh = 0x0000;
|
||||
CAN_FilterInitStructure.CAN_FilterMaskIdLow = 0x0000;
|
||||
CAN_FilterInitStructure.CAN_FilterFIFOAssignment = 0;
|
||||
CAN_FilterInitStructure.CAN_FilterActivation = ENABLE;
|
||||
|
||||
CAN_FilterInit(&CAN_FilterInitStructure);
|
||||
|
||||
CAN_Init(Can.can, &CAN_InitStructure); //Initialize CAN1 port
|
||||
|
||||
CAN_ITConfig(Can.can, CAN_IT_FMP0, ENABLE);
|
||||
}
|
||||
|
||||
void USB_LP_CAN1_RX0_IRQHandler(void) //CAN 1 interrupt service routine
|
||||
{
|
||||
CanRxMsg RxMessage;
|
||||
|
||||
CAN_ClearITPendingBit(Can.can, CAN_IT_FMP0);
|
||||
|
||||
CAN_Receive(Can.can, CAN_FIFO0, &RxMessage);
|
||||
|
||||
memcpy(&Can.RxBuf[Can.RxInPos++], &RxMessage, sizeof(CanRxMsg));
|
||||
Can.RxInPos %= RX_BUFFER_SIZE;
|
||||
|
||||
if (Can.RxInPos == Can.RxOutPos)
|
||||
{
|
||||
Can.RxOutPos++;
|
||||
Can.RxOutPos %= RX_BUFFER_SIZE;
|
||||
}
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* Function Name : u8 CAN_GetPacket(CanRxMsg *packet)
|
||||
* Description : CAN Port로 수신버퍼에서 데이타(1 Pakcet) 가져오기
|
||||
* Parameters : none
|
||||
* Return : 데이타 수신 여부(0: 수신버퍼가 비었음, 1: 수신버퍼에 데이타가 있음)
|
||||
*******************************************************************************/
|
||||
u8 CAN_GetPacket(CanRxMsg *packet)
|
||||
{
|
||||
if (Can.RxInPos != Can.RxOutPos)
|
||||
{
|
||||
memcpy(packet, &Can.RxBuf[Can.RxOutPos], sizeof(CanRxMsg));
|
||||
Can.RxOutPos++;
|
||||
Can.RxOutPos %= RX_BUFFER_SIZE;
|
||||
return SUCCESS;
|
||||
}
|
||||
else
|
||||
return ERROR;
|
||||
}
|
||||
|
||||
void CAN_SendPacket(CanTxMsg *packet)
|
||||
{
|
||||
u8 retMsgBox;
|
||||
uint8_t result;
|
||||
int i;
|
||||
|
||||
retMsgBox = CAN_Transmit(Can.can, packet);
|
||||
|
||||
i = 0;
|
||||
|
||||
if (retMsgBox != CAN_TxStatus_NoMailBox)
|
||||
{
|
||||
result = CAN_TransmitStatus(CAN1, retMsgBox);
|
||||
|
||||
// while (((result == CAN_TxStatus_Failed) || (result == CAN_TxStatus_Pending))&&(i < 0xFFF))
|
||||
while (((result == CAN_TxStatus_Failed) )&&(i < 0xFF))
|
||||
{
|
||||
result = CAN_TransmitStatus(CAN1, retMsgBox);
|
||||
i++;
|
||||
}
|
||||
if(i >= 0xFF)
|
||||
{
|
||||
// if (result == CAN_TxStatus_Pending)
|
||||
// CAN_CancelTransmit(CAN1, retMsgBox);
|
||||
|
||||
// delay_os_ms(100);
|
||||
//
|
||||
// if (screenmode == DIAG_MODE)
|
||||
// printf("\r\n Tx Error (%d)", retMsgBox);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
can1_init(250000);
|
||||
delay_os_ms(10);
|
||||
retMsgBox = CAN_Transmit(CAN1, packet);
|
||||
}
|
||||
}
|
||||
|
||||
26
HARDWARE/can.h
Normal file
26
HARDWARE/can.h
Normal file
@@ -0,0 +1,26 @@
|
||||
#ifndef __UART3_H
|
||||
#define __UART3_H
|
||||
#include "stdio.h"
|
||||
#include "stm32f10x_conf.h"
|
||||
#include "sys.h"
|
||||
//////////////////////////////////////////////////////////////////////////////////
|
||||
//This program is for educational purposes only, without the author's permission, may not be used for any other purpose
|
||||
//ALIENTEK STM32F4 Explorer Board
|
||||
//Initialize serial port 3
|
||||
//Hot Atomic @ALIENTEK
|
||||
//Forum: www.openedv.com
|
||||
//Date modified: 2014/6/10
|
||||
//Version: V1.4
|
||||
//All rights reserved pirated reserved.
|
||||
//Copyright(C) Guangzhou wing electronic technology limited company 2009-2019
|
||||
//All rights reserved
|
||||
//********************************************************************************
|
||||
//////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void can1_init(u32 buadrate);
|
||||
u8 CAN_GetPacket(CanRxMsg *packet);
|
||||
void CAN_SendPacket(CanTxMsg *packet);
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
55
HARDWARE/iwdg.c
Normal file
55
HARDWARE/iwdg.c
Normal file
@@ -0,0 +1,55 @@
|
||||
#include "iwdg.h"
|
||||
#include "stm32f10x_iwdg.h"
|
||||
//////////////////////////////////////////////////////////////////////////////////
|
||||
//This program is for educational purposes only, without the author's permission, may not be used for any other purpose
|
||||
//ALIENTEK STM32F407 Development Board
|
||||
//Independent watch-dog driver code
|
||||
//Hot Atomic @ALIENTEK
|
||||
//Forum: www.openedv.com
|
||||
//Date created: 2015/9/1
|
||||
//Version: V1.0
|
||||
//All rights reserved pirated reserved.
|
||||
//Copyright(C) Guangzhou wing electronic technology limited company 2014-2024
|
||||
//All rights reserved
|
||||
//////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
//Initialize watch-dog
|
||||
void IWDG_Init(void)
|
||||
{
|
||||
/* IWDG timeout equal to 250 ms (the timeout may varies due to LSI frequency
|
||||
dispersion) */
|
||||
/* Enable write access to IWDG_PR and IWDG_RLR registers */
|
||||
IWDG_WriteAccessCmd(IWDG_WriteAccess_Enable);
|
||||
|
||||
/* IWDG counter clock: 40KHz(LSI) / 128 = 312.5 Hz : 3.2ms */
|
||||
/* 0.8ms ~ 3276.8ms */
|
||||
// IWDG_Prescaler_4, 0, 0.1, 409.6
|
||||
// IWDG_Prescaler_8, 1, 0.2, 819.2
|
||||
// IWDG_Prescaler_16, 2, 0.4, 1638.4
|
||||
// IWDG_Prescaler_32, 3, 0.8, 3276.8
|
||||
// IWDG_Prescaler_64, 4, 1.6, 6553.6
|
||||
// IWDG_Prescaler_128 5, 3.2, 13107.2
|
||||
// IWDG_Prescaler_256 6, 6.4, 26214.4
|
||||
|
||||
/* IWDG counter clock: LSI/128 */
|
||||
IWDG_SetPrescaler(IWDG_Prescaler_128);
|
||||
|
||||
/* Set counter reload value to obtain 250ms IWDG TimeOut.
|
||||
Counter Reload Value = 1000ms / IWDG counter clock period
|
||||
= 1000ms / (LSI/128)
|
||||
=
|
||||
|
||||
Counter Reload Value = 250ms/IWDG counter clock period
|
||||
= 250ms / (LSI/32)
|
||||
= 0.25s / (LsiFreq/32)
|
||||
= LsiFreq/(32 * 4)
|
||||
= LsiFreq/128
|
||||
*/
|
||||
IWDG_SetReload(1000);
|
||||
|
||||
/* Reload IWDG counter */
|
||||
IWDG_ReloadCounter();
|
||||
|
||||
/* Enable IWDG (the LSI oscillator will be enabled by hardware) */
|
||||
IWDG_Enable();
|
||||
}
|
||||
17
HARDWARE/iwdg.h
Normal file
17
HARDWARE/iwdg.h
Normal file
@@ -0,0 +1,17 @@
|
||||
#ifndef _IWDG_H
|
||||
#define _IWDG_H
|
||||
//////////////////////////////////////////////////////////////////////////////////
|
||||
//This program is for educational purposes only, without the author's permission, may not be used for any other purpose
|
||||
//ALIENTEK STM32F407 Development Board
|
||||
//Independent watch-dog driver code
|
||||
//Hot Atomic @ALIENTEK
|
||||
//Forum: www.openedv.com
|
||||
//Date created: 2015/9/1
|
||||
//Version: V1.0
|
||||
//All rights reserved pirated reserved.
|
||||
//Copyright(C) Guangzhou wing electronic technology limited company 2014-2024
|
||||
//All rights reserved
|
||||
//////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void IWDG_Init(void); //Initialize
|
||||
#endif
|
||||
66
HARDWARE/led.c
Normal file
66
HARDWARE/led.c
Normal file
@@ -0,0 +1,66 @@
|
||||
#include "led.h"
|
||||
//////////////////////////////////////////////////////////////////////////////////
|
||||
//This program is for educational purposes only, without the author's permission, may not be used for any other purpose
|
||||
//ALIENTEK STM32F407 Development Board
|
||||
//LED driver code
|
||||
//Hot Atomic @ALIENTEK
|
||||
//Forum: www.openedv.com
|
||||
//Date created: 2014/6/10
|
||||
//Version: V1.0
|
||||
//All rights reserved pirated reserved.
|
||||
//Copyright(C) Guangzhou wing electronic technology limited company 2014-2024
|
||||
//All rights reserved
|
||||
//////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
//Initialize the PF9 and PF10 outlet. and to enable these two clocks
|
||||
//LED class IO
|
||||
void DIO_Init(void)
|
||||
{
|
||||
GPIO_InitTypeDef GPIO_InitStructure;
|
||||
|
||||
/* GPIO clock enable */
|
||||
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
|
||||
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
|
||||
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC, ENABLE);
|
||||
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOD, ENABLE);
|
||||
RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE);
|
||||
|
||||
//Serial port 1 pins reuse maps
|
||||
GPIO_PinRemapConfig(GPIO_Remap_SWJ_Disable, ENABLE);
|
||||
GPIO_PinRemapConfig(GPIO_Remap_PD01, ENABLE);
|
||||
|
||||
/* Safety Signal Output */
|
||||
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4;
|
||||
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
|
||||
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
|
||||
GPIO_Init(GPIOA, &GPIO_InitStructure);
|
||||
|
||||
/* Board Run Led Output */
|
||||
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_13;
|
||||
GPIO_Init(GPIOA, &GPIO_InitStructure);
|
||||
|
||||
/* Board External Led Output (PB8: GREEN, PB9: RED) */
|
||||
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8 | GPIO_Pin_9;
|
||||
GPIO_Init(GPIOB, &GPIO_InitStructure);
|
||||
|
||||
/* MP2642 Enable Output - GPIOA (PA0,1,2,3,5,6,7) */
|
||||
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1 | GPIO_Pin_2 | GPIO_Pin_3 | GPIO_Pin_5 | GPIO_Pin_6 | GPIO_Pin_7;
|
||||
GPIO_Init(GPIOA, &GPIO_InitStructure);
|
||||
|
||||
/* MP2642 Enable Output - GPIOB (PB0,1,2,3,4,5,6,7,10,11) */
|
||||
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1 | GPIO_Pin_2 | GPIO_Pin_3 | GPIO_Pin_4 | GPIO_Pin_5 | GPIO_Pin_6 | GPIO_Pin_7 | GPIO_Pin_10 | GPIO_Pin_11;
|
||||
GPIO_Init(GPIOB, &GPIO_InitStructure);
|
||||
|
||||
/* MP2642 Enable Output - GPIOC (PC13,14,15) */
|
||||
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_13 | GPIO_Pin_14 | GPIO_Pin_15;
|
||||
GPIO_Init(GPIOC, &GPIO_InitStructure);
|
||||
|
||||
/* MP2642 Enable Output - GPIOD (PD1) */
|
||||
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1;
|
||||
GPIO_Init(GPIOD, &GPIO_InitStructure);
|
||||
|
||||
GPIO_ResetBits(GPIOA, GPIO_Pin_4 | GPIO_Pin_13 | GPIO_Pin_0 | GPIO_Pin_1 | GPIO_Pin_2 | GPIO_Pin_3 | GPIO_Pin_5 | GPIO_Pin_6 | GPIO_Pin_7);
|
||||
GPIO_ResetBits(GPIOB, GPIO_Pin_8 | GPIO_Pin_9 | GPIO_Pin_0 | GPIO_Pin_1 | GPIO_Pin_2 | GPIO_Pin_3 | GPIO_Pin_4 | GPIO_Pin_5 | GPIO_Pin_6 | GPIO_Pin_7 | GPIO_Pin_10 | GPIO_Pin_11);
|
||||
GPIO_ResetBits(GPIOC, GPIO_Pin_13 | GPIO_Pin_14 | GPIO_Pin_15);
|
||||
GPIO_ResetBits(GPIOD, GPIO_Pin_1);
|
||||
}
|
||||
51
HARDWARE/led.h
Normal file
51
HARDWARE/led.h
Normal file
@@ -0,0 +1,51 @@
|
||||
#ifndef _LED_H
|
||||
#define _LED_H
|
||||
#include "sys.h"
|
||||
//////////////////////////////////////////////////////////////////////////////////
|
||||
//This program is for educational purposes only, without the author's permission, may not be used for any other purpose
|
||||
//ALIENTEK STM32F407 Development Board
|
||||
//LED driver code
|
||||
//Hot Atomic @ALIENTEK
|
||||
//Forum: www.openedv.com
|
||||
//Date created: 2014/6/10
|
||||
//Version: V1.0
|
||||
//All rights reserved pirated reserved.
|
||||
//Copyright(C) Guangzhou wing electronic technology limited company 2014-2024
|
||||
//All rights reserved
|
||||
//////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
//LED port definitions
|
||||
#define BD_RUN_LED PAout(13)
|
||||
|
||||
#define GREEN_LED PBout(8)
|
||||
#define RED_LED PBout(9)
|
||||
|
||||
#define SAFETY_SIGNAL PAout(4)
|
||||
|
||||
// Active Balancing Enable Pins (Mapped from Schematic)
|
||||
#define MP2642_ENABLE_01 PBout(3)
|
||||
#define MP2642_ENABLE_02 PBout(4)
|
||||
#define MP2642_ENABLE_03 PBout(5)
|
||||
#define MP2642_ENABLE_04 PBout(6)
|
||||
#define MP2642_ENABLE_05 PBout(7)
|
||||
#define MP2642_ENABLE_06 PCout(13)
|
||||
#define MP2642_ENABLE_07 PCout(14)
|
||||
#define MP2642_ENABLE_08 PCout(15)
|
||||
#define MP2642_ENABLE_09 PDout(1)
|
||||
#define MP2642_ENABLE_10 PAout(0)
|
||||
#define MP2642_ENABLE_11 PAout(1)
|
||||
#define MP2642_ENABLE_12 PAout(2)
|
||||
#define MP2642_ENABLE_13 PAout(3)
|
||||
#define MP2642_ENABLE_14 PAout(5)
|
||||
#define MP2642_ENABLE_15 PAout(6)
|
||||
#define MP2642_ENABLE_16 PAout(7)
|
||||
#define MP2642_ENABLE_17 PBout(0)
|
||||
#define MP2642_ENABLE_18 PBout(1)
|
||||
#define MP2642_ENABLE_19 PBout(10)
|
||||
#define MP2642_ENABLE_20 PBout(11)
|
||||
|
||||
#define MD_BALANCE PBout(2) // PB2 is typically used or left as placeholder if not defined
|
||||
|
||||
void DIO_Init(void); //Initialize
|
||||
|
||||
#endif
|
||||
812
HARDWARE/ltc6813.c
Normal file
812
HARDWARE/ltc6813.c
Normal file
@@ -0,0 +1,812 @@
|
||||
/*! LTC6813: Multicell Battery Monitors
|
||||
*
|
||||
*@verbatim
|
||||
*The LTC6813 is multicell battery stack monitor that measures up to 18 series
|
||||
*connected battery cells with a total measurement error of less than 2.2mV.
|
||||
*The cell measurement range of 0V to 5V makes the LTC6813 suitable for most
|
||||
*battery chemistries. All 18 cell voltages can be captured in 290uS, and lower
|
||||
*data acquisition rates can be selected for high noise reduction.
|
||||
*Using the LTC6813-1, multiple devices are connected in a daisy-chain with one
|
||||
*host processor connection for all devices, permitting simultaneous cell monitoring
|
||||
*of long, high voltage battery strings.
|
||||
*@endverbatim
|
||||
*
|
||||
* https://www.analog.com/en/products/ltc6813-1.html
|
||||
* https://www.analog.com/en/design-center/evaluation-hardware-and-software/evaluation-boards-kits/dc2350a-b.html
|
||||
*
|
||||
*********************************************************************************
|
||||
* Copyright 2019(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.
|
||||
*******************************************************************************/
|
||||
|
||||
//! @ingroup BMS
|
||||
//! @{
|
||||
//! @defgroup LTC6813-1 LTC6813-1: Multicell Battery Monitor
|
||||
//! @}
|
||||
|
||||
/*! @file
|
||||
@ingroup LTC6813-1
|
||||
Library for LTC6813-1 Multicell Battery Monitor
|
||||
*/
|
||||
|
||||
#include <includes.h>
|
||||
#include "stdint.h"
|
||||
#include "LTC681x.h"
|
||||
#include "LTC6813.h"
|
||||
|
||||
//Helper function to initialize CFG variables.
|
||||
void LTC6811_init_cfg(uint8_t icNo, cell_asic *ic)
|
||||
{
|
||||
for (int j =0; j < 6; j++)
|
||||
{
|
||||
ic[icNo].config.tx_data[j] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
//Helper function to set CFGR variable
|
||||
void LTC6811_set_cfgr(uint8_t icNo, cell_asic *ic, bool refon, bool adcopt, uint8_t gpio, uint16_t dcc, uint8_t dcto, uint16_t uv, uint16_t ov)
|
||||
{
|
||||
LTC6811_set_cfgr_refon (icNo, ic, refon );
|
||||
LTC6811_set_cfgr_adcopt(icNo, ic, adcopt);
|
||||
LTC6811_set_cfgr_gpio (icNo, ic, gpio );
|
||||
LTC6811_set_cfgr_dis (icNo, ic, dcc );
|
||||
LTC6811_set_cfgr_dcto (icNo, ic, dcto );
|
||||
LTC6811_set_cfgr_uv (icNo, ic, uv );
|
||||
LTC6811_set_cfgr_ov (icNo, ic, ov );
|
||||
}
|
||||
|
||||
//Helper function to set the REFON bit
|
||||
void LTC6811_set_cfgr_refon(uint8_t icNo, cell_asic *ic, bool refon)
|
||||
{
|
||||
if (refon) ic[icNo].config.tx_data[0] = ic[icNo].config.tx_data[0] | 0x04;
|
||||
else ic[icNo].config.tx_data[0] = ic[icNo].config.tx_data[0] & 0xFB;
|
||||
}
|
||||
|
||||
//Helper function to set the adcopt bit
|
||||
void LTC6811_set_cfgr_adcopt(uint8_t icNo, cell_asic *ic, bool adcopt)
|
||||
{
|
||||
if (adcopt) ic[icNo].config.tx_data[0] = ic[icNo].config.tx_data[0] | 0x01;
|
||||
else ic[icNo].config.tx_data[0] = ic[icNo].config.tx_data[0] & 0xFE;
|
||||
}
|
||||
|
||||
//Helper function to set GPIO bits
|
||||
void LTC6811_set_cfgr_gpio(uint8_t icNo, cell_asic *ic, uint8_t gpio)
|
||||
{
|
||||
for (int i = 0; i < 5; i++)
|
||||
{
|
||||
if ((gpio >> i) & 0x01) ic[icNo].config.tx_data[0] = ic[icNo].config.tx_data[0] | ( 0x01 << (i + 3));
|
||||
else ic[icNo].config.tx_data[0] = ic[icNo].config.tx_data[0] & (~(0x01 << (i + 3)));
|
||||
}
|
||||
}
|
||||
|
||||
//Helper function to control discharge
|
||||
void LTC6811_set_cfgr_dis(uint8_t icNo, cell_asic *ic, uint16_t dcc)
|
||||
{
|
||||
for (int i = 0; i < 8; i++)
|
||||
{
|
||||
if ((dcc >> i) & 0x0001) ic[icNo].config.tx_data[4] = ic[icNo].config.tx_data[4] | (0x01 << i);
|
||||
else ic[icNo].config.tx_data[4] = ic[icNo].config.tx_data[4] & (~(0x01 << i));
|
||||
}
|
||||
for (int i = 0; i < 4; i++)
|
||||
{
|
||||
if ((dcc >> (8 + i)) & 0x0001) ic[icNo].config.tx_data[5] = ic[icNo].config.tx_data[5] | (0x01 << i);
|
||||
else ic[icNo].config.tx_data[5] = ic[icNo].config.tx_data[5] & (~(0x01 << i));
|
||||
}
|
||||
}
|
||||
|
||||
//Helper Function to set dcto value in CFG register
|
||||
void LTC6811_set_cfgr_dcto(uint8_t icNo, cell_asic *ic, uint8_t dcto)
|
||||
{
|
||||
ic[icNo].config.tx_data[5] &= 0x0F;
|
||||
ic[icNo].config.tx_data[5] |= (uint8_t)((dcto << 4) & 0xF0);
|
||||
}
|
||||
|
||||
//Helper Function to set uv value in CFG register
|
||||
void LTC6811_set_cfgr_uv(uint8_t icNo, cell_asic *ic,uint16_t uv)
|
||||
{
|
||||
ic[icNo].config.tx_data[1] = (uint8_t)((uv >> 0) & 0xFF);
|
||||
ic[icNo].config.tx_data[2] &= 0xF0;
|
||||
ic[icNo].config.tx_data[2] |= (uint8_t)((uv >> 8) & 0x0F);
|
||||
}
|
||||
|
||||
//Helper function to set OV value in CFG register
|
||||
void LTC6811_set_cfgr_ov(uint8_t icNo, cell_asic *ic, uint16_t ov)
|
||||
{
|
||||
ic[icNo].config.tx_data[2] &= 0x0F;
|
||||
ic[icNo].config.tx_data[2] |= (uint8_t)((ov << 4) & 0xF0);
|
||||
ic[icNo].config.tx_data[3] = (uint8_t)((ov >> 4) & 0xFF);
|
||||
}
|
||||
|
||||
/***************************** CFGRB *********************************/
|
||||
|
||||
/*
|
||||
This command will write the configuration registers of the LTC6813-1s
|
||||
connected in a daisy chain stack. The configuration is written in descending
|
||||
order so the last device's configuration is written first.
|
||||
*/
|
||||
void LTC6811_wrcfg(uint8_t icNo, //The number of ICs being written to
|
||||
cell_asic *ic //A two dimensional array of the configuration data that will be written
|
||||
)
|
||||
{
|
||||
LTC681x_wrcfg(icNo, ic);
|
||||
}
|
||||
|
||||
|
||||
// Reads configuration registers of a LTC6813 daisy chain
|
||||
int8_t LTC6811_rdcfg(uint8_t icNo, //Number of ICs in the system
|
||||
cell_asic *ic //A two dimensional array that the function stores the read configuration data.
|
||||
)
|
||||
{
|
||||
uint8_t cmd[2] = {0x00, 0x02};
|
||||
uint8_t read_buffer[10];
|
||||
int8_t pec_error = 0;
|
||||
uint16_t data_pec;
|
||||
uint16_t calc_pec;
|
||||
|
||||
pec_error = read_68(icNo, cmd, read_buffer);
|
||||
|
||||
for (int i = 0; i < 8; i++)
|
||||
{
|
||||
ic[icNo].config.rx_data[i] = read_buffer[i];
|
||||
}
|
||||
calc_pec = pec15_calc(6,&read_buffer[0]);
|
||||
data_pec = read_buffer[7] | (read_buffer[6] << 8);
|
||||
|
||||
if (calc_pec != data_pec )
|
||||
ic[icNo].config.rx_pec_match = 1;
|
||||
else
|
||||
ic[icNo].config.rx_pec_match = 0;
|
||||
|
||||
LTC681x_check_pec(icNo, CFGR, ic);
|
||||
|
||||
return(pec_error);
|
||||
}
|
||||
|
||||
//Starts cell voltage conversion
|
||||
void LTC6811_adcv(uint8_t icNo,
|
||||
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;
|
||||
cmd[0] |= (0x80 | (icNo << 3)); // IC Address
|
||||
md_bits = (MD & 0x01) << 7;
|
||||
cmd[1] = md_bits + 0x60 + (DCP << 4) + CH;
|
||||
cmd_68(cmd);
|
||||
}
|
||||
|
||||
// Reads and parses the LTC6813 cell voltage registers.
|
||||
uint8_t LTC6811_rdcv(uint8_t reg, // Controls which cell voltage register is read back.
|
||||
uint8_t icNo, // the number of ICs in the system
|
||||
cell_asic *ic // Array of the parsed cell codes
|
||||
)
|
||||
{
|
||||
int8_t pec_error = 0;
|
||||
pec_error = LTC681x_rdcv(reg, icNo, ic);
|
||||
return(pec_error);
|
||||
}
|
||||
|
||||
//Start a Status ADC Conversion
|
||||
void LTC6811_adstat(uint8_t icNo,
|
||||
uint8_t MD, //ADC Mode
|
||||
uint8_t CHST //GPIO Channels to be measured)
|
||||
)
|
||||
{
|
||||
uint8_t cmd[4];
|
||||
uint8_t md_bits;
|
||||
|
||||
md_bits = (MD & 0x02) >> 1;
|
||||
cmd[0] = md_bits + 0x04;
|
||||
cmd[0] |= (0x80 | (icNo << 3)); // IC Address
|
||||
md_bits = (MD & 0x01) << 7;
|
||||
cmd[1] = md_bits + 0x68 + CHST;
|
||||
|
||||
cmd_68(cmd);
|
||||
}
|
||||
|
||||
//Start a GPIO and Vref2 Conversion
|
||||
void LTC6811_adax(uint8_t icNo,
|
||||
uint8_t MD, //ADC Mode
|
||||
uint8_t CHG //GPIO Channels to be measured)
|
||||
)
|
||||
{
|
||||
uint8_t cmd[4];
|
||||
uint8_t md_bits;
|
||||
|
||||
md_bits = (MD & 0x02) >> 1;
|
||||
cmd[0] = md_bits + 0x04;
|
||||
cmd[0] |= (0x80 | (icNo << 3)); // IC Address
|
||||
md_bits = (MD & 0x01) << 7;
|
||||
cmd[1] = md_bits + 0x60 + CHG;
|
||||
|
||||
cmd_68(cmd);
|
||||
}
|
||||
|
||||
/*
|
||||
The function is used
|
||||
to read the parsed GPIO codes of the LTC6813. This function will send the requested
|
||||
read commands parse the data and store the gpio voltages in aux_codes variable
|
||||
*/
|
||||
int8_t LTC6811_rdaux(uint8_t reg, //Determines which GPIO voltage register is read back.
|
||||
uint8_t icNo,//the number of ICs in the system
|
||||
cell_asic *ic//A two dimensional array of the gpio voltage codes.
|
||||
)
|
||||
{
|
||||
uint8_t *data;
|
||||
int8_t pec_error = 0;
|
||||
data = (uint8_t *) malloc(NUM_RX_BYT * sizeof(uint8_t));
|
||||
|
||||
if (reg == 0)
|
||||
{
|
||||
for (uint8_t gpio_reg = 1; gpio_reg < ic[icNo].ic_reg.num_gpio_reg + 1; gpio_reg++) //executes once for each of the LTC6813 aux voltage registers
|
||||
{
|
||||
LTC681x_rdaux_reg(gpio_reg, icNo, data); //Reads the raw auxiliary register data into the data[] array
|
||||
// printf("\r\n (%d)GPIO-%d:\r\n Data: ", icNo, gpio_reg);
|
||||
// for (int i = 0; i < 8; i++)
|
||||
// printf("%02X ", data[i]);
|
||||
pec_error = parse_auxs(gpio_reg, data,
|
||||
&ic[icNo].aux.a_codes[0],
|
||||
&ic[icNo].aux.pec_match[0]);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
LTC681x_rdaux_reg(reg, icNo, data);
|
||||
|
||||
pec_error = parse_auxs(reg, data,
|
||||
&ic[icNo].aux.a_codes[0],
|
||||
&ic[icNo].aux.pec_match[0]);
|
||||
}
|
||||
LTC681x_check_pec(icNo, AUX, ic);
|
||||
free(data);
|
||||
return (pec_error);
|
||||
}
|
||||
|
||||
//Start a Status ADC Conversion
|
||||
void LTC6813_adstat(uint8_t MD, //ADC Mode
|
||||
uint8_t CHST //GPIO Channels to be measured
|
||||
)
|
||||
{
|
||||
LTC681x_adstat(MD,CHST);
|
||||
}
|
||||
|
||||
// Reads and parses the LTC6813 cell voltage registers.
|
||||
uint8_t LTC6811_rdstat(uint8_t reg, // Controls which cell voltage register is read back.
|
||||
uint8_t icNo, // the number of ICs in the system
|
||||
cell_asic *ic // Array of the parsed cell codes
|
||||
)
|
||||
{
|
||||
int8_t pec_error = 0;
|
||||
pec_error = LTC681x_rdstatA(reg, icNo, ic);
|
||||
return(pec_error);
|
||||
}
|
||||
|
||||
int8_t LTC6811_rdstat1(uint8_t reg, //Determines which Stat register is read back.
|
||||
uint8_t icNo,//the number of ICs in the system
|
||||
cell_asic *ic
|
||||
)
|
||||
{
|
||||
const uint8_t BYT_IN_REG = 6;
|
||||
const uint8_t GPIO_IN_REG = 3;
|
||||
|
||||
uint8_t *data;
|
||||
uint8_t data_counter = 0;
|
||||
int8_t pec_error = 0;
|
||||
uint16_t parsed_stat;
|
||||
uint16_t received_pec;
|
||||
uint16_t data_pec;
|
||||
uint8_t c_ic = 0;
|
||||
data = (uint8_t *) malloc((NUM_RX_BYT) * sizeof(uint8_t));
|
||||
|
||||
if (reg == 0)
|
||||
{
|
||||
for (uint8_t stat_reg = 1; stat_reg< 3; stat_reg++) //executes once for each of the LTC6811 stat voltage registers
|
||||
{
|
||||
data_counter = 0;
|
||||
LTC681x_rdstat_reg(stat_reg, icNo, data); //Reads the raw statiliary register data into the data[] array
|
||||
|
||||
if (ic->isospi_reverse == false)
|
||||
{
|
||||
c_ic = icNo;
|
||||
}
|
||||
else
|
||||
{
|
||||
c_ic = 2 - icNo - 1;
|
||||
}
|
||||
// current_ic is used as the IC counter
|
||||
if (stat_reg ==1)
|
||||
{
|
||||
for (uint8_t current_gpio = 0; current_gpio< GPIO_IN_REG; current_gpio++) // This loop parses the read back data into GPIO voltages, it
|
||||
{
|
||||
// loops once for each of the 3 gpio voltage codes in the register
|
||||
|
||||
parsed_stat = data[data_counter] + (data[data_counter+1]<<8); //Each gpio codes is received as two bytes and is combined to
|
||||
ic[c_ic].stat.stat_codes[current_gpio] = parsed_stat;
|
||||
data_counter=data_counter+2; //Because gpio voltage codes are two bytes the data counter
|
||||
|
||||
}
|
||||
}
|
||||
else if (stat_reg == 2)
|
||||
{
|
||||
parsed_stat = data[data_counter] + (data[data_counter+1]<<8); //Each gpio codes is received as two bytes and is combined to
|
||||
data_counter = data_counter +2;
|
||||
ic[c_ic].stat.stat_codes[3] = parsed_stat;
|
||||
ic[c_ic].stat.flags[0] = data[data_counter++];
|
||||
ic[c_ic].stat.flags[1] = data[data_counter++];
|
||||
ic[c_ic].stat.flags[2] = data[data_counter++];
|
||||
ic[c_ic].stat.mux_fail[0] = (data[data_counter] & 0x02)>>1;
|
||||
ic[c_ic].stat.thsd[0] = data[data_counter++] & 0x01;
|
||||
}
|
||||
|
||||
received_pec = (data[data_counter]<<8)+ data[data_counter+1]; //The received PEC for the current_ic is transmitted as the 7th and 8th
|
||||
//after the 6 gpio voltage data bytes
|
||||
data_pec = pec15_calc(BYT_IN_REG, &data[0]);
|
||||
|
||||
if (received_pec != data_pec)
|
||||
{
|
||||
pec_error = -1; //The pec_error variable is simply set negative if any PEC errors
|
||||
ic[c_ic].stat.pec_match[stat_reg-1]=1;
|
||||
//are detected in the received serial data
|
||||
}
|
||||
else
|
||||
{
|
||||
ic[c_ic].stat.pec_match[stat_reg-1]=0;
|
||||
}
|
||||
|
||||
data_counter=data_counter+2; //Because the transmitted PEC code is 2 bytes long the data_counter
|
||||
//must be incremented by 2 bytes to point to the next ICs gpio voltage data
|
||||
}
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
LTC681x_rdstat_reg(reg, icNo, data);
|
||||
// current_ic is used as an IC counter
|
||||
if (ic->isospi_reverse == false)
|
||||
{
|
||||
c_ic = icNo;
|
||||
}
|
||||
else
|
||||
{
|
||||
c_ic = 2 - icNo - 1;
|
||||
}
|
||||
if (reg ==1)
|
||||
{
|
||||
for (uint8_t current_gpio = 0; current_gpio< GPIO_IN_REG; current_gpio++) // This loop parses the read back data into GPIO voltages, it
|
||||
{
|
||||
// loops once for each of the 3 gpio voltage codes in the register
|
||||
parsed_stat = data[data_counter] + (data[data_counter+1]<<8); //Each gpio codes is received as two bytes and is combined to
|
||||
// create the parsed gpio voltage code
|
||||
|
||||
ic[c_ic].stat.stat_codes[current_gpio] = parsed_stat;
|
||||
data_counter=data_counter+2; //Because gpio voltage codes are two bytes the data counter
|
||||
//must increment by two for each parsed gpio voltage code
|
||||
|
||||
}
|
||||
}
|
||||
else if (reg == 2)
|
||||
{
|
||||
parsed_stat = data[data_counter++] + (data[data_counter++]<<8); //Each gpio codes is received as two bytes and is combined to
|
||||
ic[c_ic].stat.stat_codes[3] = parsed_stat;
|
||||
ic[c_ic].stat.flags[0] = data[data_counter++];
|
||||
ic[c_ic].stat.flags[1] = data[data_counter++];
|
||||
ic[c_ic].stat.flags[2] = data[data_counter++];
|
||||
ic[c_ic].stat.mux_fail[0] = (data[data_counter] & 0x02)>>1;
|
||||
ic[c_ic].stat.thsd[0] = data[data_counter++] & 0x01;
|
||||
}
|
||||
|
||||
received_pec = (data[data_counter]<<8)+ data[data_counter+1]; //The received PEC for the current_ic is transmitted as the 7th and 8th
|
||||
//after the 6 gpio voltage data bytes
|
||||
data_pec = pec15_calc(BYT_IN_REG, &data[0]);
|
||||
if (received_pec != data_pec)
|
||||
{
|
||||
pec_error = -1; //The pec_error variable is simply set negative if any PEC errors
|
||||
ic[c_ic].stat.pec_match[reg-1]=1;
|
||||
|
||||
}
|
||||
|
||||
data_counter=data_counter+2;
|
||||
}
|
||||
LTC681x_check_pec(icNo, STAT, ic);
|
||||
free(data);
|
||||
return (pec_error);
|
||||
}
|
||||
|
||||
/*
|
||||
Reads and parses the LTC6813 stat registers.
|
||||
The function is used
|
||||
to read the parsed stat codes of the LTC6813. This function will send the requested
|
||||
read commands parse the data and store the stat voltages in stat_codes variable
|
||||
*/
|
||||
int8_t LTC6813_rdstat(uint8_t reg, //Determines which Stat register is read back.
|
||||
uint8_t total_ic,//the number of ICs in the system
|
||||
cell_asic *ic
|
||||
)
|
||||
{
|
||||
int8_t pec_error = 0;
|
||||
pec_error = LTC681x_rdstat(reg,total_ic,ic);
|
||||
return (pec_error);
|
||||
}
|
||||
|
||||
// Starts cell voltage and GPIO 1&2 conversion
|
||||
void LTC6813_adcvax(uint8_t MD, //ADC Mode
|
||||
uint8_t DCP //Discharge Permit
|
||||
)
|
||||
{
|
||||
// LTC681x_adcvax(MD,DCP);
|
||||
}
|
||||
|
||||
//Starts cell voltage and SOC conversion
|
||||
void LTC6813_adcvsc( uint8_t MD, //ADC Mode
|
||||
uint8_t DCP //Discharge Permit
|
||||
)
|
||||
{
|
||||
// LTC681x_adcvsc(MD,DCP);
|
||||
}
|
||||
|
||||
//Starts the Mux Decoder diagnostic self test
|
||||
void LTC6813_diagn()
|
||||
{
|
||||
LTC681x_diagn();
|
||||
}
|
||||
|
||||
//Starts cell voltage self test conversion
|
||||
void LTC6813_cvst(uint8_t MD, //ADC Mode
|
||||
uint8_t ST //Self Test
|
||||
)
|
||||
{
|
||||
LTC681x_cvst(MD,ST);
|
||||
}
|
||||
|
||||
//Start an Auxiliary Register Self Test Conversion
|
||||
void LTC6813_axst(uint8_t MD, //ADC Mode
|
||||
uint8_t ST //Self Test
|
||||
)
|
||||
{
|
||||
LTC681x_axst(MD,ST);
|
||||
}
|
||||
|
||||
//Start a Status Register Self Test Conversion
|
||||
void LTC6813_statst(uint8_t MD, //ADC Mode
|
||||
uint8_t ST //Self Test
|
||||
)
|
||||
{
|
||||
LTC681x_statst(MD,ST);
|
||||
}
|
||||
|
||||
// Runs the Digital Filter Self Test
|
||||
int16_t LTC6813_run_cell_adc_st(uint8_t adc_reg,uint8_t total_ic, cell_asic *ic,uint8_t md,bool adcopt)
|
||||
{
|
||||
int16_t error = 0;
|
||||
// error = LTC681x_run_cell_adc_st(adc_reg,total_ic,ic,md,adcopt);
|
||||
return(error);
|
||||
}
|
||||
|
||||
//Starts cell voltage overlap conversion
|
||||
void LTC6813_adol(uint8_t MD, //ADC Mode
|
||||
uint8_t DCP //Discharge Permit
|
||||
)
|
||||
{
|
||||
LTC681x_adol(MD,DCP);
|
||||
}
|
||||
|
||||
// Runs the ADC overlap test for the IC
|
||||
uint16_t LTC6813_run_adc_overlap(uint8_t total_ic, cell_asic *ic)
|
||||
{
|
||||
uint16_t error = 0;
|
||||
int32_t measure_delta =0;
|
||||
int16_t failure_pos_limit = 20;
|
||||
int16_t failure_neg_limit = -20;
|
||||
uint32_t conv_time=0;
|
||||
wakeup_idle(total_ic);
|
||||
LTC681x_adol(MD_7KHZ_3KHZ,DCP_DISABLED);
|
||||
conv_time = LTC6811_pollAdc(0);
|
||||
conv_time = conv_time;
|
||||
|
||||
wakeup_idle(total_ic);
|
||||
error = LTC681x_rdcv(0, total_ic,ic);
|
||||
for (int cic = 0; cic<total_ic; cic++)
|
||||
{
|
||||
|
||||
|
||||
measure_delta = (int32_t)ic[cic].cells.c_codes[6]-(int32_t)ic[cic].cells.c_codes[7];
|
||||
if ((measure_delta>failure_pos_limit) || (measure_delta<failure_neg_limit))
|
||||
{
|
||||
error = error | (1<<(cic-1));
|
||||
}
|
||||
measure_delta = (int32_t)ic[cic].cells.c_codes[12]-(int32_t)ic[cic].cells.c_codes[13];
|
||||
if ((measure_delta>failure_pos_limit) || (measure_delta<failure_neg_limit))
|
||||
{
|
||||
error = error | (1<<(cic-1));
|
||||
}
|
||||
}
|
||||
return(error);
|
||||
}
|
||||
|
||||
//Start GPIOs open wire ADC conversion
|
||||
void LTC6813_axow(uint8_t MD, //ADC Mode
|
||||
uint8_t PUP //Discharge Permit
|
||||
)
|
||||
{
|
||||
// LTC681x_axow(MD, PUP);
|
||||
}
|
||||
|
||||
// Start an open wire Conversion
|
||||
void LTC6813_adow(uint8_t MD,uint8_t PUP,uint8_t CH,uint8_t DCP)
|
||||
{
|
||||
// LTC681x_adow(MD,PUP,CH,DCP);
|
||||
}
|
||||
|
||||
//Runs open wire for GPIOs
|
||||
void LTC6813_run_gpio_openwire(uint8_t total_ic,
|
||||
cell_asic *ic
|
||||
)
|
||||
{
|
||||
// LTC681x_run_gpio_openwire(total_ic, ic);
|
||||
}
|
||||
|
||||
//Runs the data sheet algorithm for open wire for single cell detection
|
||||
void LTC6813_run_openwire_single(uint8_t total_ic, cell_asic *ic)
|
||||
{
|
||||
// LTC681x_run_openwire_single(total_ic, ic);
|
||||
}
|
||||
|
||||
//Runs the data sheet algorithm for open wire for multiple cell and two consecutive cells detection
|
||||
void LTC6813_run_openwire_multi(uint8_t total_ic, cell_asic *ic)
|
||||
{
|
||||
// LTC681x_run_openwire_multi( total_ic, ic);
|
||||
}
|
||||
|
||||
//Start an GPIO Redundancy test
|
||||
void LTC6813_adaxd(uint8_t MD, //ADC Mode
|
||||
uint8_t CHG //GPIO Channels to be measured)
|
||||
)
|
||||
{
|
||||
LTC681x_adaxd(MD,CHG);
|
||||
}
|
||||
|
||||
// Start a Status register redundancy test Conversion
|
||||
void LTC6813_adstatd(uint8_t MD, //ADC Mode
|
||||
uint8_t CHST //GPIO Channels to be measured
|
||||
)
|
||||
{
|
||||
LTC681x_adstatd(MD,CHST);
|
||||
}
|
||||
|
||||
//Runs the redundancy self test
|
||||
int16_t LTC6813_run_adc_redundancy_st(uint8_t adc_mode, uint8_t adc_reg, uint8_t total_ic, cell_asic *ic)
|
||||
{
|
||||
int16_t error = 0;
|
||||
LTC681x_run_adc_redundancy_st(adc_mode,adc_reg,total_ic,ic);
|
||||
return(error);
|
||||
}
|
||||
|
||||
//Sends the poll ADC command
|
||||
uint8_t LTC6813_pladc()
|
||||
{
|
||||
// return(LTC681x_pladc());
|
||||
return(0);
|
||||
}
|
||||
|
||||
#include "delay.h"
|
||||
|
||||
//This function will block operation until the ADC has finished it's conversion
|
||||
uint32_t LTC6811_pollAdc(uint8_t icNo)
|
||||
{
|
||||
uint32_t counter = 0;
|
||||
uint8_t finished = 0;
|
||||
uint8_t current_time = 0;
|
||||
uint8_t cmd[4];
|
||||
uint16_t cmd_pec;
|
||||
|
||||
cmd[0] = 0x07 | (0x80 | (icNo << 3));
|
||||
cmd[1] = 0x14;
|
||||
cmd_pec = pec15_calc(2, cmd);
|
||||
cmd[2] = (uint8_t)(cmd_pec >> 8);
|
||||
cmd[3] = (uint8_t)(cmd_pec);
|
||||
|
||||
CS_PIN = 0;
|
||||
spi_write_array(4,cmd);
|
||||
|
||||
while ((counter < 2000) && (finished == 0))
|
||||
{
|
||||
current_time = spi_read_byte(0xff);
|
||||
if (current_time > 0)
|
||||
finished = 1;
|
||||
else
|
||||
counter++;
|
||||
|
||||
delay_os_ms(1);
|
||||
}
|
||||
CS_PIN = 1;
|
||||
|
||||
return(counter);
|
||||
}
|
||||
|
||||
/*
|
||||
The command clears the cell voltage registers and initializes
|
||||
all values to 1. The register will read back hexadecimal 0xFF
|
||||
after the command is sent.
|
||||
*/
|
||||
void LTC6813_clrcell()
|
||||
{
|
||||
LTC681x_clrcell();
|
||||
}
|
||||
|
||||
/*
|
||||
The command clears the Auxiliary registers and initializes
|
||||
all values to 1. The register will read back hexadecimal 0xFF
|
||||
after the command is sent.
|
||||
*/
|
||||
void LTC6813_clraux()
|
||||
{
|
||||
LTC681x_clraux();
|
||||
}
|
||||
|
||||
/*
|
||||
The command clears the Stat registers and initializes
|
||||
all values to 1. The register will read back hexadecimal 0xFF
|
||||
after the command is sent.
|
||||
*/
|
||||
void LTC6813_clrstat()
|
||||
{
|
||||
LTC681x_clrstat();
|
||||
}
|
||||
|
||||
//Writes the pwm registers of a LTC6813 daisy chain
|
||||
void LTC6813_wrpwm(uint8_t total_ic,
|
||||
uint8_t pwmReg, //The number of ICs being written to
|
||||
cell_asic *ic //A two dimensional array of the configuration data that will be written
|
||||
)
|
||||
{
|
||||
// LTC681x_wrpwm(total_ic,pwmReg,ic);
|
||||
}
|
||||
|
||||
//Reads pwm registers of a LTC6813 daisy chain
|
||||
int8_t LTC6813_rdpwm(uint8_t total_ic, //Number of ICs in the system
|
||||
uint8_t pwmReg,
|
||||
cell_asic *ic //A two dimensional array that the function stores the read configuration data.
|
||||
)
|
||||
{
|
||||
int8_t pec_error =0;
|
||||
// pec_error = LTC681x_rdpwm(total_ic,pwmReg,ic);
|
||||
return(pec_error);
|
||||
}
|
||||
|
||||
//Writes data in S control register the ltc6813-1 connected in a daisy chain stack.
|
||||
void LTC6813_wrsctrl(uint8_t total_ic, //< number of ICs in the daisy chain
|
||||
uint8_t sctrl_reg,
|
||||
cell_asic *ic
|
||||
)
|
||||
{
|
||||
// LTC681x_wrsctrl(total_ic, sctrl_reg, ic);
|
||||
}
|
||||
|
||||
// Reads sctrl registers of a ltc6812 daisy chain
|
||||
int8_t LTC6813_rdsctrl(uint8_t total_ic, //< number of ICs in the daisy chain
|
||||
uint8_t sctrl_reg,
|
||||
cell_asic *ic //< a two dimensional array that the function stores the read pwm data
|
||||
)
|
||||
{
|
||||
// LTC681x_rdsctrl( total_ic, sctrl_reg,ic );
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Start Sctrl data communication
|
||||
This command will start the sctrl pulse communication over the spins
|
||||
*/
|
||||
void LTC6813_stsctrl()
|
||||
{
|
||||
// LTC681x_stsctrl();
|
||||
}
|
||||
|
||||
/*
|
||||
The command clears the Sctrl registers and initializes
|
||||
all values to 0. The register will read back hexadecimal 0x00
|
||||
after the command is sent.
|
||||
*/
|
||||
void LTC6813_clrsctrl()
|
||||
{
|
||||
// LTC681x_clrsctrl();
|
||||
}
|
||||
|
||||
//Writes the COMM registers of a LTC6813 daisy chain
|
||||
void LTC6813_wrcomm(uint8_t total_ic, //The number of ICs being written to
|
||||
cell_asic *ic //A two dimensional array of the comm data that will be written
|
||||
)
|
||||
{
|
||||
// LTC681x_wrcomm(total_ic,ic);
|
||||
}
|
||||
|
||||
// Reads COMM registers of a LTC6813 daisy chain
|
||||
int8_t LTC6813_rdcomm(uint8_t total_ic, //Number of ICs in the system
|
||||
cell_asic *ic //A two dimensional array that the function stores the read configuration data.
|
||||
)
|
||||
{
|
||||
int8_t pec_error = 0;
|
||||
// LTC681x_rdcomm(total_ic, ic);
|
||||
return(pec_error);
|
||||
}
|
||||
|
||||
// Shifts data in COMM register out over LTC6813 SPI/I2C port
|
||||
void LTC6813_stcomm()
|
||||
{
|
||||
// LTC681x_stcomm();
|
||||
}
|
||||
|
||||
//Clears all of the DCC bits in the configuration registers
|
||||
void LTC6813_clear_discharge(uint8_t total_ic,
|
||||
cell_asic *ic)
|
||||
{
|
||||
// LTC681x_clear_discharge(total_ic,ic);
|
||||
|
||||
}
|
||||
|
||||
//Helper function that increments PEC counters
|
||||
void LTC6813_check_pec(uint8_t total_ic,uint8_t reg, cell_asic *ic)
|
||||
{
|
||||
LTC681x_check_pec(total_ic,reg,ic);
|
||||
}
|
||||
|
||||
//Helper Function to reset PEC counters
|
||||
void LTC6811_reset_crc_count(uint8_t icNo, cell_asic *ic)
|
||||
{
|
||||
LTC681x_reset_crc_count(icNo, ic);
|
||||
}
|
||||
|
||||
//Mutes the LTC6813 discharge transistors
|
||||
void LTC6813_mute()
|
||||
{
|
||||
uint8_t cmd[2];
|
||||
|
||||
cmd[0] = 0x00;
|
||||
cmd[1] = 0x28;
|
||||
|
||||
cmd_68(cmd);
|
||||
}
|
||||
|
||||
//Clears the LTC6813 Mute Discharge
|
||||
void LTC6813_unmute()
|
||||
{
|
||||
uint8_t cmd[2];
|
||||
|
||||
cmd[0] = 0x00;
|
||||
cmd[1] = 0x29;
|
||||
cmd_68(cmd);
|
||||
}
|
||||
474
HARDWARE/ltc6813.h
Normal file
474
HARDWARE/ltc6813.h
Normal file
@@ -0,0 +1,474 @@
|
||||
/*! LTC6813: Multicell Battery Monitors
|
||||
*
|
||||
*@verbatim
|
||||
*The LTC6813 is multicell battery stack monitor that measures up to 18 series
|
||||
*connected battery cells with a total measurement error of less than 2.2mV.
|
||||
*The cell measurement range of 0V to 5V makes the LTC6813 suitable for most
|
||||
*battery chemistries. All 18 cell voltages can be captured in 290uS, and lower
|
||||
*data acquisition rates can be selected for high noise reduction.
|
||||
*Using the LTC6813-1, multiple devices are connected in a daisy-chain with one
|
||||
*host processor connection for all devices, permitting simultaneous cell monitoring
|
||||
*of long, high voltage battery strings.
|
||||
*@endverbatim
|
||||
*
|
||||
* https://www.analog.com/en/products/ltc6813-1.html
|
||||
* https://www.analog.com/en/design-center/evaluation-hardware-and-software/evaluation-boards-kits/dc2350a-b.html
|
||||
*
|
||||
*********************************************************************************
|
||||
* Copyright 2019(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
|
||||
@ingroup LTC6813-1
|
||||
Header for LTC6813-1 Multicell Battery Monitor
|
||||
*/
|
||||
|
||||
#ifndef LTC6813_H
|
||||
#define LTC6813_H
|
||||
|
||||
#include "stdint.h"
|
||||
#include "LTC681x.h"
|
||||
|
||||
#define CELL 1
|
||||
#define AUX 2
|
||||
#define STAT 3
|
||||
|
||||
/*! Helper Function to initialize the CFGR data structures*/
|
||||
//!@return void
|
||||
void LTC6811_init_cfg(uint8_t icNo, //!< Number of ICs in the system
|
||||
cell_asic *ic //!< A two dimensional array that will store the data
|
||||
);
|
||||
|
||||
/*! Helper function to set appropriate bits in CFGR register based on bit function*/
|
||||
//!@return void
|
||||
void LTC6811_set_cfgr(uint8_t icNO, //!< the number of ICs in the daisy chain
|
||||
cell_asic *ic, //!< A two dimensional array that will store the data
|
||||
bool refon, //!< the REFON bit
|
||||
bool adcopt, //!< the ADCOPT bit
|
||||
uint8_t gpio, //!< the GPIO bits
|
||||
uint16_t dcc, //!< the DCC bits
|
||||
uint8_t dcto, //!< the Dcto bits
|
||||
uint16_t uv, //!< the UV value
|
||||
uint16_t ov //!< the OV value
|
||||
);
|
||||
|
||||
/*! Helper function to turn the refon bit HIGH or LOW*/
|
||||
//!@return void
|
||||
void LTC6811_set_cfgr_refon(uint8_t icNo, //!< the number of ICs in the daisy chain
|
||||
cell_asic *ic, //!< A two dimensional array that will store the data
|
||||
bool refon //!< the REFON bit
|
||||
);
|
||||
|
||||
/*! Helper function to turn the ADCOPT bit HIGH or LOW*/
|
||||
//!@return void
|
||||
void LTC6811_set_cfgr_adcopt(uint8_t icNo, //!< the number of ICs in the daisy chain
|
||||
cell_asic *ic, //!< A two dimensional array that will store the data
|
||||
bool adcopt //!< the ADCOPT bit
|
||||
);
|
||||
|
||||
/*! Helper function to turn the GPIO bits HIGH or LOW*/
|
||||
//!@return void
|
||||
void LTC6811_set_cfgr_gpio(uint8_t icNo, //!< the number of ICs in the daisy chain
|
||||
cell_asic *ic, //!< A two dimensional array that will store the data
|
||||
uint8_t gpio //!< the GPIO bits
|
||||
);
|
||||
|
||||
/*! Helper function to turn the DCC bits HIGH or LOW*/
|
||||
//!@return void
|
||||
void LTC6811_set_cfgr_dis(uint8_t icNo, //!< the number of ICs in the daisy chain
|
||||
cell_asic *ic, //!< A two dimensional array that will store the data
|
||||
uint16_t dcc //!< the DCC bits
|
||||
);
|
||||
|
||||
/*! Helper function to set uv field in CFGRA register*/
|
||||
//!@return void
|
||||
void LTC6811_set_cfgr_uv(uint8_t icNo, //!< the number of ICs in the daisy chain
|
||||
cell_asic *ic, //!< A two dimensional array that will store the data
|
||||
uint16_t uv //!< the UV value
|
||||
);
|
||||
|
||||
/*! Helper function to set DCTO field in CFGRA register*/
|
||||
//!@return void
|
||||
void LTC6811_set_cfgr_dcto(uint8_t icNo, //!< the number of ICs in the daisy chain
|
||||
cell_asic *ic, //!< A two dimensional array that will store the data
|
||||
uint8_t dcto //!< the Dcto bits
|
||||
);
|
||||
|
||||
/*! Helper function to set ov field in CFGRA register*/
|
||||
//!@return void
|
||||
void LTC6811_set_cfgr_ov(uint8_t icNo, //!< the number of ICs in the daisy chain
|
||||
cell_asic *ic, //!< A two dimensional array that will store the data
|
||||
uint16_t ov //!< the OV value
|
||||
);
|
||||
|
||||
|
||||
/*! Write the LTC6813 configuration register A*/
|
||||
//!@return void
|
||||
void LTC6811_wrcfg(uint8_t icNo, //!< Number of ICs in the system
|
||||
cell_asic *ic //!< a two dimensional array of the configuration data that will be written
|
||||
);
|
||||
|
||||
|
||||
/*! Reads configuration register A of a LTC6813 daisy chain
|
||||
@return int8_t, PEC Status.
|
||||
0: Data read back has matching PEC
|
||||
-1: Data read back has incorrect PEC */
|
||||
int8_t LTC6811_rdcfg(uint8_t icNo, //!< Number of ICs in the system
|
||||
cell_asic *ic //!< a two dimensional array that the function stores the read configuration data
|
||||
);
|
||||
|
||||
/*! Reads configuration register B of a LTC6813 daisy chain
|
||||
@return int8_t, PEC Status.
|
||||
0: Data read back has matching PEC
|
||||
-1: Data read back has incorrect PEC */
|
||||
int8_t LTC6813_rdcfgb(uint8_t nIC, //!< Number of ICs in the system
|
||||
cell_asic *ic //!< a two dimensional array that the function stores the read configuration data
|
||||
);
|
||||
|
||||
/*! Starts cell voltage conversion */
|
||||
//!@return void
|
||||
void LTC6811_adcv(uint8_t icNo,
|
||||
uint8_t MD, //!< ADC Conversion Mode
|
||||
uint8_t DCP, //!< Controls if Discharge is permitted during conversion
|
||||
uint8_t CH //!< Sets which Cell channels are converted
|
||||
);
|
||||
|
||||
/*! Reads and parses the LTC6813 cell voltage registers.
|
||||
@return uint8_t, PEC Status.
|
||||
0: No PEC error detected
|
||||
-1: PEC error detected, retry read
|
||||
*/
|
||||
uint8_t LTC6811_rdcv(uint8_t reg, //!< controls which cell voltage register is read back.
|
||||
uint8_t icNo, //!< the number of ICs in the daisy chain(-1 only)
|
||||
cell_asic *ic //!< array of the parsed cell codes from lowest to highest.
|
||||
);
|
||||
|
||||
/*! Start a GPIO and Vref2 Conversion */
|
||||
//!@return void
|
||||
void LTC6811_adax(uint8_t icNo,
|
||||
uint8_t MD, //!< ADC Conversion Mode
|
||||
uint8_t CHG //!< Sets which GPIO channels are converted
|
||||
);
|
||||
|
||||
/*! Reads and parses the LTC6813 auxiliary registers.
|
||||
@return int8_t, PEC Status
|
||||
0: No PEC error detected
|
||||
-1: PEC error detected, retry read
|
||||
*/
|
||||
int8_t LTC6811_rdaux(uint8_t reg, //!< controls which GPIO voltage register is read back
|
||||
uint8_t icNo, //!< the number of ICs in the daisy chain
|
||||
cell_asic *ic //!< A two dimensional array of the parsed gpio voltage codes
|
||||
);
|
||||
|
||||
/*! Start a Status ADC Conversion */
|
||||
//!@return void
|
||||
void LTC6811_adstat(uint8_t icNo,
|
||||
uint8_t MD, //ADC Mode
|
||||
uint8_t CHST //GPIO Channels to be measured)
|
||||
);
|
||||
|
||||
// Reads and parses the LTC6813 cell voltage registers.
|
||||
uint8_t LTC6811_rdstat(uint8_t reg, // Controls which cell voltage register is read back.
|
||||
uint8_t total_ic, // the number of ICs in the system
|
||||
cell_asic *ic // Array of the parsed cell codes
|
||||
);
|
||||
|
||||
int8_t LTC6811_rdstat1(uint8_t reg, //Determines which Stat register is read back.
|
||||
uint8_t icNo,//the number of ICs in the system
|
||||
cell_asic *ic
|
||||
);
|
||||
|
||||
/*! Start a Status ADC Conversion */
|
||||
//!@return void
|
||||
void LTC6813_adstat( uint8_t MD, //!< ADC Conversion Mode
|
||||
uint8_t CHST //!< Sets which Stat channels are converted
|
||||
);
|
||||
|
||||
/*! Reads and parses the LTC6813 stat registers.
|
||||
@return int8_t, PEC Status
|
||||
0: No PEC error detected
|
||||
-1: PEC error detected, retry read
|
||||
*/
|
||||
int8_t LTC6813_rdstat(uint8_t reg, //!< Determines which Stat register is read back.
|
||||
uint8_t total_ic,//!< Number of ICs in the system
|
||||
cell_asic *ic //!< A two dimensional array that will store the data
|
||||
);
|
||||
|
||||
/*! Starts cell voltage and GPIO 1&2 conversion */
|
||||
//!@return void
|
||||
void LTC6813_adcvax(uint8_t MD, //!< ADC Conversion Mode
|
||||
uint8_t DCP //!< Controls if Discharge is permitted during conversion
|
||||
);
|
||||
|
||||
/*! Starts cell voltage and SOC conversion */
|
||||
//!@return void
|
||||
void LTC6813_adcvsc(uint8_t MD, //!< ADC Conversion Mode
|
||||
uint8_t DCP //!< Controls if Discharge is permitted during conversion
|
||||
);
|
||||
|
||||
/*! Starts the Mux Decoder diagnostic self test
|
||||
Running this command will start the Mux Decoder Diagnostic Self Test
|
||||
This test takes roughly 1mS to complete. The MUXFAIL bit will be updated,
|
||||
the bit will be set to 1 for a failure and 0 if the test has been passed.
|
||||
*/
|
||||
//!@return void
|
||||
void LTC6813_diagn(void);
|
||||
|
||||
/*! Starts cell voltage self test conversion */
|
||||
//!@return void
|
||||
void LTC6813_cvst(uint8_t MD, //!< ADC Conversion Mode
|
||||
uint8_t ST //!< Self Test Mode
|
||||
);
|
||||
|
||||
/*! Start an Auxiliary Register Self Test Conversion */
|
||||
//!@return void
|
||||
void LTC6813_axst(uint8_t MD, //!< ADC Conversion Mode
|
||||
uint8_t ST //!< Sets if self test 1 or 2 is run
|
||||
);
|
||||
|
||||
/*! Start a Status Register Self Test Conversion */
|
||||
//!@return void
|
||||
void LTC6813_statst(uint8_t MD, //!< ADC Conversion Mode
|
||||
uint8_t ST //!< Sets if self test 1 or 2 is run
|
||||
);
|
||||
|
||||
/*! Helper function that runs the ADC Self Tests*/
|
||||
//!@return int16_t, error
|
||||
//! Number of errors detected.
|
||||
int16_t LTC6813_run_cell_adc_st(uint8_t adc_reg, //!< Type of register
|
||||
uint8_t total_ic, //!< Number of ICs in the system
|
||||
cell_asic *ic, //!< A two dimensional array that will store the data
|
||||
uint8_t md, //!< ADC Mode
|
||||
bool adcopt //!< the adcopt bit in the configuration register
|
||||
);
|
||||
|
||||
/*! Starts cell voltage overlap conversion */
|
||||
//!@return void
|
||||
void LTC6813_adol(uint8_t MD, //!< ADC Conversion Mode
|
||||
uint8_t DCP //!< Discharge permitted during conversion
|
||||
);
|
||||
|
||||
/*! Helper Function that runs the ADC Overlap test*/
|
||||
//!@return uint16_t, error
|
||||
//! 0: Pass
|
||||
//!-1: False, Error detected
|
||||
uint16_t LTC6813_run_adc_overlap(uint8_t total_ic, //!< Number of ICs in the system
|
||||
cell_asic *ic //!< A two dimensional array that will store the data
|
||||
);
|
||||
|
||||
/*! Start an open wire Conversion
|
||||
*/
|
||||
//!@return void
|
||||
void LTC6813_adow(uint8_t MD, //!< ADC Conversion Mode
|
||||
uint8_t PUP,//!< Controls if Discharge is permitted during
|
||||
uint8_t CH, //!< Sets which Cell channels are converted
|
||||
uint8_t DCP //!< Discharge permitted during conversion
|
||||
);
|
||||
|
||||
/*! start GPIOs open wire ADC conversion */
|
||||
//!@return void
|
||||
void LTC6813_axow(uint8_t MD, //!< ADC Mode
|
||||
uint8_t PUP //!< Discharge Permit
|
||||
);
|
||||
|
||||
/*! Runs open wire for GPIOs*/
|
||||
//!@return void
|
||||
void LTC6813_run_gpio_openwire(uint8_t total_ic, //!< Number of ICs in the system
|
||||
cell_asic *ic //!< A two dimensional array that will store the data
|
||||
);
|
||||
|
||||
/*! Helper function that runs the data sheet algorithm for open wire for single cell detection*/
|
||||
//!@return void
|
||||
void LTC6813_run_openwire_single(uint8_t total_ic, //!< Number of ICs in the system
|
||||
cell_asic *ic //!< A two dimensional array that will store the data
|
||||
);
|
||||
|
||||
/*! Helper function that runs open wire for multiple cell and two consecutive cells detection*/
|
||||
//!@return void
|
||||
void LTC6813_run_openwire_multi(uint8_t total_ic, //!< Number of ICs in the system
|
||||
cell_asic *ic //!< A two dimensional array that will store the data
|
||||
);
|
||||
|
||||
/*! Start an GPIO Redundancy test */
|
||||
//!@return void
|
||||
void LTC6813_adaxd(uint8_t MD, //!< ADC Conversion Mode
|
||||
uint8_t CHG //!< Sets which GPIO channels are converted
|
||||
);
|
||||
|
||||
/*! Start a Status register redundancy test Conversion */
|
||||
//!@return void
|
||||
void LTC6813_adstatd(uint8_t MD, //!< ADC Mode
|
||||
uint8_t CHST //!< Sets which Status channels are converted
|
||||
);
|
||||
|
||||
/*! Helper function that runs the ADC Digital Redundancy commands and checks output for errors*/
|
||||
//!@return int16_t, error
|
||||
int16_t LTC6813_run_adc_redundancy_st(uint8_t adc_mode, //!< ADC Mode
|
||||
uint8_t adc_reg, //!< Type of register
|
||||
uint8_t total_ic, //!< Number of ICs in the system
|
||||
cell_asic *ic //!< A two dimensional array that will store the data
|
||||
);
|
||||
|
||||
//! Sends the poll ADC command
|
||||
//! @returns 1 byte read back after a pladc command. If the byte is not 0xFF ADC conversion has completed
|
||||
uint8_t LTC6813_pladc(void);
|
||||
|
||||
//! This function will block operation until the ADC has finished it's conversion
|
||||
//! @returns the approximate time it took for the ADC function to complete.
|
||||
uint32_t LTC6811_pollAdc(uint8_t icNo);
|
||||
|
||||
/*! Clears the LTC6813 cell voltage registers */
|
||||
//!@return void
|
||||
void LTC6813_clrcell(void);
|
||||
|
||||
/*! Clears the LTC6813 Auxiliary registers */
|
||||
//!@return void
|
||||
void LTC6813_clraux(void);
|
||||
|
||||
/*! Clears the LTC6813 Stat registers */
|
||||
//!@return void
|
||||
void LTC6813_clrstat(void);
|
||||
|
||||
/*! Write the LTC6813 PWM register */
|
||||
//!@return void
|
||||
void LTC6813_wrpwm(uint8_t nIC, //!< number of ICs in the daisy chain
|
||||
uint8_t pwmReg, //!< PWM Register A or B
|
||||
cell_asic *ic //!< A two dimensional array that will store the data
|
||||
);
|
||||
|
||||
/*! Reads pwm registers of a LTC6813 daisy chain */
|
||||
//!@return int8_t, PEC Status.
|
||||
//! 0: Data read back has matching PEC
|
||||
//! -1: Data read back has incorrect PEC
|
||||
int8_t LTC6813_rdpwm(uint8_t nIC, //!< number of ICs in the daisy chain
|
||||
uint8_t pwmReg, //! PWM Register A or B
|
||||
cell_asic *ic //!< A two dimensional array that will store the data
|
||||
);
|
||||
|
||||
/*! Write the LTC6813 Sctrl register */
|
||||
//!@return void
|
||||
void LTC6813_wrsctrl(uint8_t nIC, //!< number of ICs in the daisy chain
|
||||
uint8_t sctrl_reg,//! SCTRL Register A or B
|
||||
cell_asic *ic //!< A two dimensional array that will store the data
|
||||
);
|
||||
|
||||
/*! Reads sctrl registers of a LTC6813 daisy chain
|
||||
@return int8_t, PEC Status.
|
||||
0: Data read back has matching PEC
|
||||
-1: Data read back has incorrect PEC
|
||||
*/
|
||||
int8_t LTC6813_rdsctrl(uint8_t nIC, //!< number of ICs in the daisy chain
|
||||
uint8_t sctrl_reg,//! SCTRL Register A or B
|
||||
cell_asic *ic //!< A two dimensional array that will store the data
|
||||
);
|
||||
|
||||
/*! Start Sctrl data communication
|
||||
This command will start the sctrl pulse communication over the spins
|
||||
*/
|
||||
//!@return void
|
||||
void LTC6813_stsctrl(void);
|
||||
|
||||
/*! Clears the LTC6813 Sctrl registers */
|
||||
//!@return void
|
||||
void LTC6813_clrsctrl(void);
|
||||
|
||||
/*! Write the LTC6813 COMM register */
|
||||
//!@return void
|
||||
void LTC6813_wrcomm(uint8_t total_ic, //!< Number of ICs in the daisy chain
|
||||
cell_asic *ic //!< A two dimensional array of the comm data that will be written
|
||||
);
|
||||
|
||||
/*! Reads comm registers of a LTC6813 daisy chain
|
||||
@return int8_t, PEC Status.
|
||||
0: Data read back has matching PEC
|
||||
-1: Data read back has incorrect PEC
|
||||
*/
|
||||
int8_t LTC6813_rdcomm(uint8_t total_ic, //!< number of ICs in the daisy chain
|
||||
cell_asic *ic //!< Two dimensional array that the function stores the read comm data.
|
||||
);
|
||||
|
||||
/*! Issues a stcomm command and clocks data out of the COMM register */
|
||||
//!@return void
|
||||
void LTC6813_stcomm(void);
|
||||
|
||||
/*! Helper Function to Set DCC bits in the CFGR Registers*/
|
||||
//!@return void
|
||||
void LTC6813_set_discharge(int Cell, //!< The cell to be discharged
|
||||
uint8_t total_ic, //!< Number of ICs in the system
|
||||
cell_asic *ic //!< A two dimensional array that will store the data
|
||||
);
|
||||
|
||||
/*! Helper Function to clear DCC bits in the CFGR Registers*/
|
||||
//!@return void
|
||||
void LTC6813_clear_discharge(uint8_t total_ic, //!< Number of ICs in the system
|
||||
cell_asic *ic //!< A two dimensional array that will store the data
|
||||
);
|
||||
|
||||
/*! Helper Function that counts overall PEC errors and register/IC PEC errors*/
|
||||
//!@return void
|
||||
void LTC6813_check_pec(uint8_t total_ic, //!< Number of ICs in the system
|
||||
uint8_t reg, //!< Type of register
|
||||
cell_asic *ic //!< A two dimensional array that will store the data
|
||||
);
|
||||
|
||||
/*! Helper Function that resets the PEC error counters */
|
||||
//!@return void
|
||||
void LTC6811_reset_crc_count(uint8_t icNo, //!< Number of ICs in the system
|
||||
cell_asic *ic //!< A two dimensional array that will store the data
|
||||
);
|
||||
|
||||
/*! Write the 6813 PWM/Sctrl Register B */
|
||||
//!@return void
|
||||
void LTC6813_wrpsb(uint8_t total_ic, //!< Number of ICs in the system
|
||||
cell_asic *ic //!< A two dimensional array that will store the data
|
||||
);
|
||||
|
||||
/*! Reading pwm/s control register B
|
||||
@return uint8_t, PEC Status.
|
||||
0: Data read back has matching PEC
|
||||
-1: Data read back has incorrect PEC
|
||||
*/
|
||||
uint8_t LTC6813_rdpsb(uint8_t total_ic, //!< number of ICs in the daisy chain
|
||||
cell_asic *ic //!< a two dimensional array that the function stores the read pwm data
|
||||
);
|
||||
|
||||
/*! Mutes the LTC6813 discharge transistors */
|
||||
//!@return void
|
||||
void LTC6813_mute(void);
|
||||
|
||||
/*! Clears the LTC6813 Mute Discharge */
|
||||
//!@return void
|
||||
void LTC6813_unmute(void);
|
||||
|
||||
#endif
|
||||
1303
HARDWARE/ltc681x.c
Normal file
1303
HARDWARE/ltc681x.c
Normal file
File diff suppressed because it is too large
Load Diff
521
HARDWARE/ltc681x.h
Normal file
521
HARDWARE/ltc681x.h
Normal file
@@ -0,0 +1,521 @@
|
||||
#ifndef bms_master_H
|
||||
#define bms_master_H
|
||||
|
||||
#include "sys.h"
|
||||
|
||||
#define IC_LTC6813
|
||||
|
||||
#define MD_422HZ_1KHZ 0
|
||||
#define MD_27KHZ_14KHZ 1
|
||||
#define MD_7KHZ_3KHZ 2
|
||||
#define MD_26HZ_2KHZ 3
|
||||
|
||||
#define ADC_OPT_ENABLED 1
|
||||
#define ADC_OPT_DISABLED 0
|
||||
|
||||
#define CELL_CH_ALL 0
|
||||
#define CELL_CH_1and7 1
|
||||
#define CELL_CH_2and8 2
|
||||
#define CELL_CH_3and9 3
|
||||
#define CELL_CH_4and10 4
|
||||
#define CELL_CH_5and11 5
|
||||
#define CELL_CH_6and12 6
|
||||
|
||||
#define SELFTEST_1 1
|
||||
#define SELFTEST_2 2
|
||||
|
||||
#define AUX_CH_ALL 0
|
||||
#define AUX_CH_GPIO1 1
|
||||
#define AUX_CH_GPIO2 2
|
||||
#define AUX_CH_GPIO3 3
|
||||
#define AUX_CH_GPIO4 4
|
||||
#define AUX_CH_GPIO5 5
|
||||
#define AUX_CH_VREF2 6
|
||||
|
||||
#define STAT_CH_ALL 0
|
||||
#define STAT_CH_SOC 1
|
||||
#define STAT_CH_ITEMP 2
|
||||
#define STAT_CH_VREGA 3
|
||||
#define STAT_CH_VREGD 4
|
||||
|
||||
#define DCP_DISABLED 0
|
||||
#define DCP_ENABLED 1
|
||||
|
||||
#define PULL_UP_CURRENT 1
|
||||
#define PULL_DOWN_CURRENT 0
|
||||
|
||||
#define NUM_RX_BYT 8
|
||||
#define CELL 1
|
||||
#define AUX 2
|
||||
#define STAT 3
|
||||
#define CFGR 0
|
||||
#define CFGRB 4
|
||||
|
||||
#define CS_PIN PBout(12) //The chip select signals
|
||||
|
||||
//! Cell Voltage data structure.
|
||||
typedef struct
|
||||
{
|
||||
uint16_t c_codes[18]; //!< Cell Voltage Codes
|
||||
uint8_t pec_match[6]; //!< If a PEC error was detected during most recent read cmd
|
||||
uint8_t reserved[2];
|
||||
} cv;
|
||||
|
||||
//! AUX Reg Voltage Data
|
||||
typedef struct
|
||||
{
|
||||
uint16_t a_codes[12]; //!< Aux Voltage Codes
|
||||
uint8_t pec_match[4]; //!< If a PEC error was detected during most recent read cmd
|
||||
} ax;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint16_t stat_codes[4]; //!< A two dimensional array of the stat voltage codes.
|
||||
uint8_t flags[3]; //!< byte array that contains the uv/ov flag data
|
||||
uint8_t mux_fail[1]; //!< Mux self test status flag
|
||||
uint8_t thsd[1]; //!< Thermal shutdown status
|
||||
uint8_t pec_match[2]; //!< If a PEC error was detected during most recent read cmd
|
||||
uint8_t reserved;
|
||||
} st;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint8_t tx_data[6];
|
||||
uint8_t rx_data[8];
|
||||
uint8_t rx_pec_match; //!< If a PEC error was detected during most recent read cmd
|
||||
uint8_t reserved;
|
||||
} ic_register;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint16_t pec_count;
|
||||
uint16_t cfgr_pec;
|
||||
uint16_t cell_pec[6];
|
||||
uint16_t aux_pec[4];
|
||||
uint16_t stat_pec[2];
|
||||
} pec_counter;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint8_t cell_channels;
|
||||
uint8_t stat_channels;
|
||||
uint8_t aux_channels;
|
||||
uint8_t num_cv_reg;
|
||||
uint8_t num_gpio_reg;
|
||||
uint8_t num_stat_reg;
|
||||
uint8_t reserved[2];
|
||||
} register_cfg;
|
||||
|
||||
typedef uint8_t bool;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
ic_register config;
|
||||
cv cells;
|
||||
ax aux;
|
||||
st stat;
|
||||
ic_register com;
|
||||
ic_register pwm;
|
||||
ic_register sctrl;
|
||||
pec_counter crc_count;
|
||||
register_cfg ic_reg;
|
||||
long system_open_wire;
|
||||
bool isospi_reverse;
|
||||
uint8_t reserved[3];
|
||||
} cell_asic;
|
||||
|
||||
/*! calculates and returns the CRC15
|
||||
@returns The calculated pec15 as an unsigned int
|
||||
*/
|
||||
uint16_t pec15_calc(uint8_t len, //!< the length of the data array being passed to the function
|
||||
uint8_t *data //!< the array of data that the PEC will be generated from
|
||||
);
|
||||
|
||||
/*! Wake isoSPI up from idle state */
|
||||
void wakeup_idle(uint8_t total_ic);//!< number of ICs in the daisy chain
|
||||
|
||||
/*! Wake the LTC6813 from the sleep state */
|
||||
void wakeup_sleep(uint8_t total_ic); //!< number of ICs in the daisy chain
|
||||
|
||||
/*! Sense a command to the bms IC. This code will calculate the PEC code for the transmitted command*/
|
||||
void cmd_68(uint8_t tx_cmd[2]); //!< 2 Byte array containing the BMS command to be sent
|
||||
|
||||
//! Writes an array of data to the daisy chain
|
||||
void write_68(uint8_t icNo, //!< number of ICs in the daisy chain
|
||||
uint8_t tx_cmd[2], //!< 2 Byte array containing the BMS command to be sent
|
||||
uint8_t data[] //!< Array containing the data to be written to the BMS ICs
|
||||
);
|
||||
//! Issues a command onto the daisy chain and reads back 6*total_ic data in the rx_data array
|
||||
int8_t read_68( uint8_t icNo, //!< number of ICs in the daisy chain
|
||||
uint8_t tx_cmd[2], //!< 2 Byte array containing the BMS command to be sent
|
||||
uint8_t *rx_data); //!< Array that the read back data will be stored.
|
||||
|
||||
/*! Starts the Mux Decoder diagnostic self test
|
||||
|
||||
Running this command will start the Mux Decoder Diagnostic Self Test
|
||||
This test takes roughly 1mS to complete. The MUXFAIL bit will be updated,
|
||||
the bit will be set to 1 for a failure and 0 if the test has been passed.
|
||||
*/
|
||||
void LTC681x_diagn(void);
|
||||
|
||||
/*! Starts cell voltage conversion
|
||||
|
||||
Starts ADC conversions of the LTC6811 Cpin inputs.
|
||||
The type of ADC conversion executed can be changed by setting the following parameters:
|
||||
*/
|
||||
void LTC681x_adcv(uint8_t MD, //!< ADC Conversion Mode
|
||||
uint8_t DCP, //!< Controls if Discharge is permitted during conversion
|
||||
uint8_t CH //!< Sets which Cell channels are converted
|
||||
);
|
||||
|
||||
/*! Starts cell voltage and GPIO 1&2 conversion
|
||||
*/
|
||||
void LTC681x_adcvax(
|
||||
uint8_t MD, //!< ADC Conversion Mode
|
||||
uint8_t DCP //!< Controls if Discharge is permitted during conversion
|
||||
);
|
||||
|
||||
|
||||
/*! Starts cell voltage self test conversion
|
||||
*/
|
||||
void LTC681x_cvst(
|
||||
uint8_t MD, //!< ADC Conversion Mode
|
||||
uint8_t ST //!< Self Test Mode
|
||||
);
|
||||
|
||||
/*! Starts cell voltage and SOC conversion
|
||||
*/
|
||||
void LTC681x_adcvsc(
|
||||
uint8_t MD, //!< ADC Conversion Mode
|
||||
uint8_t DCP //!< Controls if Discharge is permitted during conversion
|
||||
);
|
||||
/*! Starts cell voltage overlap conversion
|
||||
*/
|
||||
void LTC681x_adol(
|
||||
uint8_t MD, //!< ADC Conversion Mode
|
||||
uint8_t DCP //!< Discharge permitted during conversion
|
||||
);
|
||||
|
||||
/*! Start an open wire Conversion
|
||||
*/
|
||||
void LTC681x_adow(
|
||||
uint8_t MD, //!< ADC Conversion Mode
|
||||
uint8_t PUP //!< Controls if Discharge is permitted during conversion
|
||||
);
|
||||
|
||||
|
||||
/*! Start a GPIO and Vref2 Conversion
|
||||
*/
|
||||
void LTC681x_adax(
|
||||
uint8_t MD, //!< ADC Conversion Mode
|
||||
uint8_t CHG //!< Sets which GPIO channels are converted
|
||||
);
|
||||
|
||||
/*! Start an GPIO Redundancy test
|
||||
*/
|
||||
void LTC681x_adaxd(
|
||||
uint8_t MD, //!< ADC Conversion Mode
|
||||
uint8_t CHG //!< Sets which GPIO channels are converted
|
||||
);
|
||||
|
||||
/*! Start an Auxiliary Register Self Test Conversion
|
||||
*/
|
||||
void LTC681x_axst(
|
||||
uint8_t MD, //!< ADC Conversion Mode
|
||||
uint8_t ST //!< Sets if self test 1 or 2 is run
|
||||
);
|
||||
|
||||
|
||||
|
||||
/*! Start a Status ADC Conversion
|
||||
*/
|
||||
void LTC681x_adstat(
|
||||
uint8_t MD, //!< ADC Conversion Mode
|
||||
uint8_t CHST //!< Sets which Stat channels are converted
|
||||
);
|
||||
|
||||
/*! Start a Status register redundancy test Conversion
|
||||
*/
|
||||
void LTC681x_adstatd(
|
||||
uint8_t MD, //!< ADC Mode
|
||||
uint8_t CHST //!< Sets which Status channels are converted
|
||||
);
|
||||
|
||||
|
||||
/*! Start a Status Register Self Test Conversion
|
||||
*/
|
||||
void LTC681x_statst(
|
||||
uint8_t MD, //!< ADC Conversion Mode
|
||||
uint8_t ST //!< Sets if self test 1 or 2 is run
|
||||
);
|
||||
|
||||
void LTC681x_rdcv_reg(uint8_t reg, //!<Determines which cell voltage register is read back
|
||||
uint8_t icNo, //!<the number of ICs in the
|
||||
uint8_t *data //!<An array of the unparsed cell codes
|
||||
);
|
||||
/*! helper function that parses voltage measurement registers
|
||||
*/
|
||||
int8_t parse_cells(uint8_t cell_reg,
|
||||
uint8_t cell_data[],
|
||||
uint16_t *cell_codes,
|
||||
uint8_t *ic_pec);
|
||||
|
||||
/*! helper function that parses voltage measurement registers
|
||||
*/
|
||||
int8_t parse_stats(uint8_t stat_reg,
|
||||
uint8_t stat_data[],
|
||||
uint16_t *stat_codes,
|
||||
uint8_t *ic_pec);
|
||||
|
||||
/*! helper function that parses aux volatge measurement registers
|
||||
*/
|
||||
int8_t parse_auxs(uint8_t aux_reg,
|
||||
uint8_t aux_data[],
|
||||
uint16_t *aux_codes,
|
||||
uint8_t *ic_pec
|
||||
);
|
||||
|
||||
/*! Read the raw data from the LTC681x auxiliary register
|
||||
|
||||
The function reads a single GPIO voltage register and stores thre read data
|
||||
in the *data point as a byte array. This function is rarely used outside of
|
||||
the LTC681x_rdaux(void) command.
|
||||
*/
|
||||
void LTC681x_rdaux_reg( uint8_t reg, //Determines which GPIO voltage register is read back
|
||||
uint8_t icNo, //The number of ICs in the system
|
||||
uint8_t *data //Array of the unparsed auxiliary codes
|
||||
);
|
||||
/*! Read the raw data from the LTC681x stat register
|
||||
|
||||
The function reads a single GPIO voltage register and stores thre read data
|
||||
in the *data point as a byte array. This function is rarely used outside of
|
||||
the LTC681x_rdstat(void) command.
|
||||
*/
|
||||
void LTC681x_rdstat_reg(uint8_t reg, //Determines which stat register is read back
|
||||
uint8_t icNo, //The number of ICs in the system
|
||||
uint8_t *data //Array of the unparsed stat codes
|
||||
);
|
||||
uint8_t LTC681x_rdstatA(uint8_t reg, // Controls which state register is read back.
|
||||
uint8_t icNo, // the number of ICs in the system
|
||||
cell_asic ic[] // Array of the parsed cell codes
|
||||
);
|
||||
|
||||
/*! Clears the LTC681x cell voltage registers
|
||||
|
||||
The command clears the cell voltage registers and initializes
|
||||
all values to 1. The register will read back hexadecimal 0xFF
|
||||
after the command is sent.
|
||||
*/
|
||||
void LTC681x_clrcell(void);
|
||||
/*! Clears the LTC681x Auxiliary registers
|
||||
|
||||
The command clears the Auxiliary registers and initializes
|
||||
all values to 1. The register will read back hexadecimal 0xFF
|
||||
after the command is sent.
|
||||
*/
|
||||
void LTC681x_clraux(void);
|
||||
|
||||
/*! Clears the LTC681x Stat registers
|
||||
|
||||
The command clears the Stat registers and initializes
|
||||
all values to 1. The register will read back hexadecimal 0xFF
|
||||
after the command is sent.
|
||||
*/
|
||||
void LTC681x_clrstat(void);
|
||||
|
||||
/*! Clears the LTC681x SCTRL registers
|
||||
|
||||
The command clears the SCTRL registers and initializes
|
||||
all values to 0. The register will read back hexadecimal 0x00
|
||||
after the command is sent.
|
||||
*/
|
||||
void LTC681x_clrsctrl(void);
|
||||
|
||||
/*! Starts the Mux Decoder diagnostic self test
|
||||
|
||||
Running this command will start the Mux Decoder Diagnostic Self Test
|
||||
This test takes roughly 1mS to complete. The MUXFAIL bit will be updated,
|
||||
the bit will be set to 1 for a failure and 0 if the test has been passed.
|
||||
*/
|
||||
void LTC681x_diagn(void);
|
||||
|
||||
/*! Reads and parses the LTC681x cell voltage registers.
|
||||
|
||||
The function is used to read the cell codes of the LTC6811.
|
||||
This function will send the requested read commands parse the data
|
||||
and store the cell voltages in the cell_asic structure.
|
||||
*/
|
||||
uint8_t LTC681x_rdcv(uint8_t reg, // Controls which cell voltage register is read back.
|
||||
uint8_t icNo, // the number of ICs in the system
|
||||
cell_asic ic[] // Array of the parsed cell codes
|
||||
);
|
||||
|
||||
/*! Reads and parses the LTC681x auxiliary registers.
|
||||
|
||||
The function is used to read the parsed GPIO codes of the LTC6811. This function will send the requested
|
||||
read commands parse the data and store the gpio voltages in the cell_asic structure.
|
||||
*/
|
||||
int8_t LTC681x_rdaux(uint8_t reg, //Determines which GPIO voltage register is read back.
|
||||
uint8_t icNo,//the number of ICs in the system
|
||||
cell_asic ic[]//!< Measurement Data Structure
|
||||
);
|
||||
|
||||
/*! Reads and parses the LTC681x stat registers.
|
||||
|
||||
The function is used to read the parsed status codes of the LTC6811. This function will send the requested
|
||||
read commands parse the data and store the status voltages in the cell_asic structure
|
||||
*/
|
||||
int8_t LTC681x_rdstat( uint8_t reg, //!<Determines which Stat register is read back.
|
||||
uint8_t total_ic,//!<the number of ICs in the system
|
||||
cell_asic ic[]//!< Measurement Data Structure
|
||||
);
|
||||
/*! Write the LTC681x CFGRA
|
||||
|
||||
This command will write the configuration registers of the LTC681xs
|
||||
connected in a daisy chain stack. The configuration is written in descending
|
||||
order so the last device's configuration is written first.
|
||||
*/
|
||||
void LTC681x_wrcfg(uint8_t icNo, //The number of ICs being written to
|
||||
cell_asic ic[] //A two dimensional array of the configuration data that will be written
|
||||
);
|
||||
|
||||
/*! Reads the LTC681x CFGRA register
|
||||
*/
|
||||
int8_t LTC681x_rdcfg(uint8_t total_ic, //Number of ICs in the system
|
||||
cell_asic ic[] //A two dimensional array that the function stores the read configuration data.
|
||||
);
|
||||
|
||||
/*! Selft Test Helper Function*/
|
||||
uint16_t LTC681x_st_lookup(
|
||||
uint8_t MD, //ADC Mode
|
||||
uint8_t ST //Self Test
|
||||
);
|
||||
|
||||
/*! Helper Function to clear DCC bits in the CFGR Registers*/
|
||||
void clear_discharge(uint8_t total_ic,
|
||||
cell_asic ic[]);
|
||||
|
||||
/*! Helper function that runs the ADC Self Tests*/
|
||||
int16_t LTC681x_run_cell_adc_st(uint8_t adc_reg,
|
||||
uint8_t total_ic,
|
||||
cell_asic ic[]);
|
||||
|
||||
/*! Helper function that runs the ADC Digital Redudancy commands and checks output for errors*/
|
||||
int16_t LTC681x_run_adc_redundancy_st(uint8_t adc_mode,
|
||||
uint8_t adc_reg,
|
||||
uint8_t total_ic,
|
||||
cell_asic ic[]);
|
||||
|
||||
/*! Helper function that runs the datasheet open wire algorithm*/
|
||||
void LTC681x_run_openwire(uint8_t total_ic,
|
||||
cell_asic ic[]);
|
||||
|
||||
/*! Helper Function that runs the ADC Overlap test*/
|
||||
uint16_t LTC681x_run_adc_overlap(uint8_t total_ic,
|
||||
cell_asic ic[]);
|
||||
/*! Helper Function that counts overall PEC errors and register/IC PEC errors*/
|
||||
void LTC681x_check_pec(uint8_t icNo,
|
||||
uint8_t reg,
|
||||
cell_asic ic[]);
|
||||
|
||||
/*! Helper Function that resets the PEC error counters */
|
||||
void LTC681x_reset_crc_count(uint8_t icNo,
|
||||
cell_asic ic[]);
|
||||
|
||||
/*! Helper Function to initialize the CFGR data structures*/
|
||||
void LTC681x_init_cfg(uint8_t total_ic,
|
||||
cell_asic ic[]);
|
||||
|
||||
/*! Helper function to set appropriate bits in CFGR register based on bit function*/
|
||||
void LTC681x_set_cfgr(uint8_t nIC,
|
||||
cell_asic ic[],
|
||||
bool refon,
|
||||
bool adcopt,
|
||||
bool gpio[5],
|
||||
uint16_t dcc);
|
||||
|
||||
/*! Helper function to turn the refon bit HIGH or LOW*/
|
||||
void LTC681x_set_cfgr_refon(uint8_t nIC,
|
||||
cell_asic ic[],
|
||||
bool refon);
|
||||
|
||||
/*! Helper function to turn the ADCOPT bit HIGH or LOW*/
|
||||
void LTC681x_set_cfgr_adcopt(uint8_t nIC,
|
||||
cell_asic ic[],
|
||||
bool adcopt);
|
||||
|
||||
/*! Helper function to turn the GPIO bits HIGH or LOW*/
|
||||
void LTC681x_set_cfgr_gpio(uint8_t nIC,
|
||||
cell_asic ic[],
|
||||
bool gpio[]);
|
||||
|
||||
/*! Helper function to turn the DCC bits HIGH or LOW*/
|
||||
void LTC681x_set_cfgr_dis(uint8_t nIC,
|
||||
cell_asic ic[],
|
||||
uint16_t dcc);
|
||||
/*! Helper function to turn the DCC bits HIGH or LOW*/
|
||||
void LTC681x_set_cfgr_dcto(uint8_t nIC,
|
||||
cell_asic ic[],
|
||||
uint8_t dcto);
|
||||
/*! Helper function to turn the DCC bits HIGH or LOW*/
|
||||
void LTC681x_set_cfgr_uv(uint8_t nIC,
|
||||
cell_asic ic[],
|
||||
uint16_t UV);
|
||||
|
||||
|
||||
|
||||
////This needs a PROGMEM = when using with a LINDUINO
|
||||
//const uint16_t crc15Table[256] = {
|
||||
// 0x0000, 0xc599, 0xceab, 0x0b32, 0xd8cf, 0x1d56, 0x1664, 0xd3fd, 0xf407, 0x319e, 0x3aac, //!<precomputed CRC15 Table
|
||||
// 0xff35, 0x2cc8, 0xe951, 0xe263, 0x27fa, 0xad97, 0x680e, 0x633c, 0xa6a5, 0x7558, 0xb0c1,
|
||||
// 0xbbf3, 0x7e6a, 0x5990, 0x9c09, 0x973b, 0x52a2, 0x815f, 0x44c6, 0x4ff4, 0x8a6d, 0x5b2e,
|
||||
// 0x9eb7, 0x9585, 0x501c, 0x83e1, 0x4678, 0x4d4a, 0x88d3, 0xaf29, 0x6ab0, 0x6182, 0xa41b,
|
||||
// 0x77e6, 0xb27f, 0xb94d, 0x7cd4, 0xf6b9, 0x3320, 0x3812, 0xfd8b, 0x2e76, 0xebef, 0xe0dd,
|
||||
// 0x2544, 0x02be, 0xc727, 0xcc15, 0x098c, 0xda71, 0x1fe8, 0x14da, 0xd143, 0xf3c5, 0x365c,
|
||||
// 0x3d6e, 0xf8f7, 0x2b0a, 0xee93, 0xe5a1, 0x2038, 0x07c2, 0xc25b, 0xc969, 0x0cf0, 0xdf0d,
|
||||
// 0x1a94, 0x11a6, 0xd43f, 0x5e52, 0x9bcb, 0x90f9, 0x5560, 0x869d, 0x4304, 0x4836, 0x8daf,
|
||||
// 0xaa55, 0x6fcc, 0x64fe, 0xa167, 0x729a, 0xb703, 0xbc31, 0x79a8, 0xa8eb, 0x6d72, 0x6640,
|
||||
// 0xa3d9, 0x7024, 0xb5bd, 0xbe8f, 0x7b16, 0x5cec, 0x9975, 0x9247, 0x57de, 0x8423, 0x41ba,
|
||||
// 0x4a88, 0x8f11, 0x057c, 0xc0e5, 0xcbd7, 0x0e4e, 0xddb3, 0x182a, 0x1318, 0xd681, 0xf17b,
|
||||
// 0x34e2, 0x3fd0, 0xfa49, 0x29b4, 0xec2d, 0xe71f, 0x2286, 0xa213, 0x678a, 0x6cb8, 0xa921,
|
||||
// 0x7adc, 0xbf45, 0xb477, 0x71ee, 0x5614, 0x938d, 0x98bf, 0x5d26, 0x8edb, 0x4b42, 0x4070,
|
||||
// 0x85e9, 0x0f84, 0xca1d, 0xc12f, 0x04b6, 0xd74b, 0x12d2, 0x19e0, 0xdc79, 0xfb83, 0x3e1a, 0x3528,
|
||||
// 0xf0b1, 0x234c, 0xe6d5, 0xede7, 0x287e, 0xf93d, 0x3ca4, 0x3796, 0xf20f, 0x21f2, 0xe46b, 0xef59,
|
||||
// 0x2ac0, 0x0d3a, 0xc8a3, 0xc391, 0x0608, 0xd5f5, 0x106c, 0x1b5e, 0xdec7, 0x54aa, 0x9133, 0x9a01,
|
||||
// 0x5f98, 0x8c65, 0x49fc, 0x42ce, 0x8757, 0xa0ad, 0x6534, 0x6e06, 0xab9f, 0x7862, 0xbdfb, 0xb6c9,
|
||||
// 0x7350, 0x51d6, 0x944f, 0x9f7d, 0x5ae4, 0x8919, 0x4c80, 0x47b2, 0x822b, 0xa5d1, 0x6048, 0x6b7a,
|
||||
// 0xaee3, 0x7d1e, 0xb887, 0xb3b5, 0x762c, 0xfc41, 0x39d8, 0x32ea, 0xf773, 0x248e, 0xe117, 0xea25,
|
||||
// 0x2fbc, 0x0846, 0xcddf, 0xc6ed, 0x0374, 0xd089, 0x1510, 0x1e22, 0xdbbb, 0x0af8, 0xcf61, 0xc453,
|
||||
// 0x01ca, 0xd237, 0x17ae, 0x1c9c, 0xd905, 0xfeff, 0x3b66, 0x3054, 0xf5cd, 0x2630, 0xe3a9, 0xe89b,
|
||||
// 0x2d02, 0xa76f, 0x62f6, 0x69c4, 0xac5d, 0x7fa0, 0xba39, 0xb10b, 0x7492, 0x5368, 0x96f1, 0x9dc3,
|
||||
// 0x585a, 0x8ba7, 0x4e3e, 0x450c, 0x8095
|
||||
// };
|
||||
|
||||
//********************************** LTC6811 ******************************************//
|
||||
void LTC6811_init_reg_limits(uint8_t icNo, cell_asic ic[]);
|
||||
|
||||
void LTC6811_set_discharge(int Cell,
|
||||
uint8_t total_ic,
|
||||
cell_asic ic[]);
|
||||
|
||||
//********************************** SPI ******************************************//
|
||||
/*
|
||||
Writes an array of bytes out of the SPI port
|
||||
*/
|
||||
void spi_write_array(uint8_t len, // Option: Number of bytes to be written on the SPI port
|
||||
uint8_t data[] //Array of bytes to be written on the SPI port
|
||||
);
|
||||
/*
|
||||
Writes and read a set number of bytes using the SPI port.
|
||||
|
||||
*/
|
||||
|
||||
void spi_write_read(uint8_t tx_Data[],//array of data to be written on SPI port
|
||||
uint8_t tx_len, //length of the tx data arry
|
||||
uint8_t *rx_data,//Input: array that will store the data read by the SPI port
|
||||
uint8_t rx_len //Option: number of bytes to be read from the SPI port
|
||||
);
|
||||
|
||||
uint8_t spi_read_byte(uint8_t tx_dat);//name conflicts with linduino also needs to take a byte as a parameter
|
||||
|
||||
#endif
|
||||
78
HARDWARE/spi.c
Normal file
78
HARDWARE/spi.c
Normal file
@@ -0,0 +1,78 @@
|
||||
#include "spi.h"
|
||||
//////////////////////////////////////////////////////////////////////////////////
|
||||
//This program is for educational purposes only, without the author's permission, may not be used for any other purpose
|
||||
//ALIENTEK STM32F4 Explorer Board
|
||||
//SPI Driver code
|
||||
//Hot Atomic @ALIENTEK
|
||||
//Forum: www.openedv.com
|
||||
//Date modified: 2014/5/6
|
||||
//Version: V1.0
|
||||
//All rights reserved pirated reserved.
|
||||
//Copyright(C) Guangzhou wing electronic technology limited company 2009-2019
|
||||
//All rights reserved
|
||||
//////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
//Following is the SPI module initialization code, and configured to master mode
|
||||
//SPI port initialization
|
||||
//Needle is SPI1 initialization
|
||||
void SPI2_Init(void)
|
||||
{
|
||||
GPIO_InitTypeDef GPIO_InitStructure;
|
||||
SPI_InitTypeDef SPI_InitStructure;
|
||||
|
||||
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE); // Enable GPIOB clock
|
||||
RCC_APB1PeriphClockCmd(RCC_APB1Periph_SPI2 , ENABLE); // Enable SPI2 clock
|
||||
|
||||
//GPIO B13, B14, B15 initialization settings
|
||||
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_13
|
||||
| GPIO_Pin_14
|
||||
| GPIO_Pin_15
|
||||
; // PB13~15 reuse function output
|
||||
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; // Multiplexing function
|
||||
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; // 100MHz
|
||||
GPIO_Init(GPIOB, &GPIO_InitStructure); // Initialize
|
||||
|
||||
GPIO_SetBits(GPIOB, GPIO_Pin_13 | GPIO_Pin_14 | GPIO_Pin_15);
|
||||
|
||||
//Here only for the SPI port initialization
|
||||
SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex; // Set SPI unidirectional or bi-directional data modes: SPI is set to two-lane bi-directional full-duplex
|
||||
SPI_InitStructure.SPI_Mode = SPI_Mode_Master; // Set SPI mode: set master SPI
|
||||
SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b; // Set SPI data size: send receive 8-bit SPI frame structure
|
||||
SPI_InitStructure.SPI_CPOL = SPI_CPOL_High; // Serial synchronous clock idle high
|
||||
SPI_InitStructure.SPI_CPHA = SPI_CPHA_2Edge; // Serial synchronous clocks second jump (increase or decrease) the data is sampled
|
||||
SPI_InitStructure.SPI_NSS = SPI_NSS_Soft; // NSS is set by hardware (NSS pins) or software (using SSI) management: internal NSS SSI signal level control
|
||||
SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_256; // Define baud rate predissociation spectrum of values: baud rate predissociation spectrum value of 256
|
||||
SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB; // Specifies the data transmission starting from MSB or LSB bit: data transmission starting from the MSB
|
||||
SPI_InitStructure.SPI_CRCPolynomial = 7; // CRC calculate polynomials
|
||||
SPI_Init(SPI2, &SPI_InitStructure); // According to the parameters specified in SPI_InitStruct to initialize peripherals SPIx register
|
||||
|
||||
SPI_Cmd(SPI2, ENABLE); // Make SPI peripherals
|
||||
|
||||
SPI2_ReadWriteByte(0xff); // To start the transfer
|
||||
}
|
||||
|
||||
//SPI1 speed setting function
|
||||
//SpeedSet:0~7
|
||||
//SPI speed =fAPB2/2^ (SpeedSet+1)
|
||||
//FAPB2 84Mhz
|
||||
void SPI2_SetSpeed(u8 SPI_BaudRatePrescaler)
|
||||
{
|
||||
assert_param(IS_SPI_BAUDRATE_PRESCALER(SPI_BaudRatePrescaler));
|
||||
SPI2->CR1 &= 0XFFC7;
|
||||
SPI2->CR1 |= SPI_BaudRatePrescaler; //Set SPI1 speed
|
||||
SPI_Cmd(SPI2, ENABLE);
|
||||
}
|
||||
//SPI1 read and write bytes
|
||||
//TxData: the bytes to write
|
||||
//Return value: reads a byte
|
||||
u8 SPI2_ReadWriteByte(u8 TxData)
|
||||
{
|
||||
while (SPI_I2S_GetFlagStatus(SPI2, SPI_I2S_FLAG_TXE) == RESET){}//Waiting to be sent
|
||||
|
||||
SPI_I2S_SendData(SPI2, TxData); //Send a byte data through peripheral SPIx
|
||||
|
||||
while (SPI_I2S_GetFlagStatus(SPI2, SPI_I2S_FLAG_RXNE) == RESET){} //Wait to receive a one byte
|
||||
|
||||
return SPI_I2S_ReceiveData(SPI2); //Returned by SPIx recently received data
|
||||
}
|
||||
24
HARDWARE/spi.h
Normal file
24
HARDWARE/spi.h
Normal file
@@ -0,0 +1,24 @@
|
||||
#ifndef __SPI_H
|
||||
#define __SPI_H
|
||||
#include "sys.h"
|
||||
//////////////////////////////////////////////////////////////////////////////////
|
||||
//This program is for educational purposes only, without the author's permission, may not be used for any other purpose
|
||||
//ALIENTEK STM32F4 Explorer Board
|
||||
//SPI Driver code
|
||||
//Hot Atomic @ALIENTEK
|
||||
//Forum: www.openedv.com
|
||||
//Date modified: 2014/5/6
|
||||
//Version: V1.0
|
||||
//All rights reserved pirated reserved.
|
||||
//Copyright(C) Guangzhou wing electronic technology limited company 2009-2019
|
||||
//All rights reserved
|
||||
//////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
|
||||
void SPI2_Init(void); //Initialize SPI1
|
||||
void SPI2_SetSpeed(u8 SpeedSet); //Set SPI1 speed
|
||||
u8 SPI2_ReadWriteByte(u8 TxData); //SPI1 bus read/write bytes
|
||||
|
||||
#endif
|
||||
|
||||
Reference in New Issue
Block a user