1147 lines
38 KiB
C
1147 lines
38 KiB
C
/**
|
|
******************************************************************************
|
|
* File Name : pl455_comm.c
|
|
* Description : This file provides code for the configuration
|
|
* of CAN communication.
|
|
******************************************************************************
|
|
* @attention
|
|
*
|
|
* <h2><center>© Copyright (c) 2019 STMicroelectronics.
|
|
* All rights reserved.</center></h2>
|
|
*
|
|
* This software component is licensed by ST under Ultimate Liberty license
|
|
* SLA0044, the "License"; You may not use this file except in compliance with
|
|
* the License. You may obtain a copy of the License at:
|
|
* www.st.com/SLA0044
|
|
*
|
|
******************************************************************************
|
|
*/
|
|
|
|
/* Includes ------------------------------------------------------------------*/
|
|
#include <includes.h>
|
|
#include "pl455.h"
|
|
#include "uart2.h"
|
|
#include "pl455_comm.h"
|
|
#include "asutil.h"
|
|
#include "malloc.h"
|
|
#include "delay.h"
|
|
#include "device_param.h"
|
|
#include "brtc.h"
|
|
#include "console.h"
|
|
|
|
/* Private define ------------------------------------------------------------*/
|
|
#define PL455_COMM_TASK_TIME 5 // 5ms TASK
|
|
#define PL455_COMM_RX_TIMEOUT 500 // 500ms TimeOut
|
|
#define PL455_COMM_RX_DELAY 5
|
|
#define PL455_COMM_TX_DELAY 50
|
|
#define PL455_COMM_MAX_TIMEOUT 10
|
|
|
|
#define PL455_COMM_MAX_BUFFER_SIZE 512
|
|
#define PACK_BUF_MAX 50
|
|
|
|
#define PL455_VREF 2.5 // VREF 2.5V
|
|
/* Private typedef -----------------------------------------------------------*/
|
|
typedef struct
|
|
{
|
|
uint8_t *Buffer;
|
|
u16 Tick;
|
|
u16 Position;
|
|
u8 BufferStart;
|
|
u8 TxFlag;
|
|
u8 TxDetail;
|
|
u8 RxFlag;
|
|
u8 MsgPrint;
|
|
u8 DataPrint;
|
|
u8 BakMsgPrint;
|
|
u8 BakDataPrint;
|
|
} TPl455CommConfig, *PPl455CommConfig;
|
|
|
|
typedef struct
|
|
{
|
|
u32 Tick;
|
|
u16 Timeout;
|
|
u8 Commfail;
|
|
u8 Init;
|
|
} TPl455CommState, *PPl455CommState;
|
|
|
|
typedef struct
|
|
{
|
|
s16 cvolt[16];
|
|
} TPackBuf, *PPackBuf;
|
|
|
|
typedef struct
|
|
{
|
|
u16 cell_fail : 1;
|
|
u16 ocv_alarm : 1;
|
|
u16 ocv_shutdown : 1;
|
|
u16 odv_alarm : 1;
|
|
u16 odv_shutdown : 1;
|
|
u16 cell_balance : 1;
|
|
u16 reserved : 10;
|
|
} TCellAlarm, *PCellAlarm;
|
|
|
|
typedef struct _TCellData
|
|
{
|
|
u16 volt;
|
|
TCellAlarm alarm;
|
|
} TCellData, *PCellData;
|
|
|
|
typedef struct _TPack
|
|
{
|
|
TCellData cell[16];
|
|
} TPack, *PPack;
|
|
|
|
/* Private macro -------------------------------------------------------------*/
|
|
const uint16_t emptyNo = 7;
|
|
|
|
/* Private variables ---------------------------------------------------------*/
|
|
TPl455CommConfig Pl455Config;
|
|
TPl455CommState Pl455CommState;
|
|
|
|
uint16_t PackBufCh = 0;
|
|
TPackBuf PackBuf[PACK_BUF_MAX];
|
|
TPack PackData;
|
|
|
|
u16 CellVoltSum, disCellVoltSum;
|
|
|
|
u32 Balance_Avg, disBalance_Avg;
|
|
u8 CellBalancingFlag = false, disCellBalancingFlag;
|
|
u8 CellBalancingOff = false;
|
|
|
|
u8 CB_Rest = false;
|
|
u32 CB_Tick = 0;
|
|
u32 disCB_Tick = 0;
|
|
|
|
u16 ManualBalValue = 0;
|
|
u8 ManualBalFlag = 0;
|
|
|
|
/* Private function prototypes -----------------------------------------------*/
|
|
void Pl455CommProcess(void);
|
|
void Pl455PacketInit(void);
|
|
void Pl455UpdateData(void);
|
|
|
|
void SendDataToPl455(uint8_t *data, u16 len);
|
|
u8 GetPl455CommPacket(uint8_t *rdata, uint16_t len);
|
|
|
|
void Pl455_commfail_clear(void);
|
|
void Pl455_commfail_check(void);
|
|
|
|
void CellVoltagePutBuf(uint8_t *pdata);
|
|
void MakeCellAvgData(void);
|
|
|
|
void PL455_Cell_AutoBalancing(uint32_t rBal);
|
|
void PL455_Cell_ManualBalancing(uint32_t rBal);
|
|
|
|
/* Private functions ---------------------------------------------------------*/
|
|
|
|
void Pl455CommInit(void)
|
|
{
|
|
pl455_gpio_Init();
|
|
pl455_wakeup();
|
|
|
|
CommClear();
|
|
|
|
CommReset();
|
|
|
|
setSendFunc(&SendDataToPl455);
|
|
setRecvFunc(&GetPl455CommPacket);
|
|
|
|
memset(&Pl455Config, 0x00, sizeof(TPl455CommConfig));
|
|
memset(&Pl455CommState, 0x00, sizeof(TPl455CommState));
|
|
|
|
Pl455Config.Buffer = mymalloc(sizeof(PL455_COMM_MAX_BUFFER_SIZE));
|
|
|
|
device_status.battery_status.bit.ACB = true;
|
|
}
|
|
|
|
void Pl455DeviceInit(void)
|
|
{
|
|
int nSent, nRead = 0;
|
|
int nDev_ID;
|
|
uint32_t wTemp = 0;
|
|
|
|
nSent = nSent;
|
|
nRead = nRead;
|
|
|
|
nDev_ID = 0;
|
|
// Wake all devices
|
|
// The wake tone will awaken any device that is already in shutdown and the pwrdown will shutdown any device
|
|
// that is already awake. The least number of times to sequence wake and pwrdown will be half the number of
|
|
// boards to cover the worst case combination of boards already awake or shutdown.
|
|
nSent = WriteReg(nDev_ID, 12, 0x40, 1, FRMWRT_ALL_NR); // send out broadcast pwrdown command
|
|
delay_os_ms(5); //~5ms
|
|
|
|
pl455_wakeup();
|
|
delay_os_ms(5); //~5ms
|
|
|
|
// Mask Customer Checksum Fault bit - [15] USER_CKSUM_MSK
|
|
nSent = WriteReg(0, 107, 0x8000, 2, FRMWRT_ALL_NR); // clear all fault summary flags
|
|
|
|
// Clear all faults
|
|
nSent = WriteReg(0, 82, 0xFFC0, 2, FRMWRT_ALL_NR); // clear all fault summary flags - 7.6.3.27 FAULT_SUM 0x52-53 (82-83) Fault Summary
|
|
nSent = WriteReg(0, 81, 0x38, 1, FRMWRT_ALL_NR); // clear fault flags in the system status register
|
|
|
|
// Auto-address all boards (section 1.2.2)
|
|
nSent = WriteReg(0, 14, 0x19, 1, FRMWRT_ALL_NR); // set auto-address mode on all boards - 7.6.3.9 DEVCONFIG 0x0E (14) Device Configuration
|
|
nSent = WriteReg(0, 12, 0x08, 1, FRMWRT_ALL_NR); // enter auto address mode on all boards, the next write to this ID will be its address
|
|
|
|
// Set addresses for all boards in daisy-chain (section 1.2.3)
|
|
nSent = WriteReg(nDev_ID, 10, nDev_ID, 1, FRMWRT_ALL_NR); // send address to each board
|
|
|
|
// Enable all communication interfaces on all boards in the stack (section 1.2.1)
|
|
// nSent = WriteReg(0, 16, 0x10F8, 2, FRMWRT_ALL_NR); // set communications baud rate and enable all interfaces on all boards in stack
|
|
nSent = WriteReg(0, 16, 0x1080, 2, FRMWRT_ALL_NR); // set communications baud rate and disable all interfaces on all boards in stack - only enable uart
|
|
|
|
/* Change to final baud rate used in the application (set by BAUDRATE define in pl455.h).
|
|
* Up to this point, all communication is at 250Kb, as the COMM_RESET done at the initial
|
|
* startup resets the bq76PL455A-Q1 UART to 250Kb. */
|
|
switch(BAUDRATE)
|
|
{
|
|
case 125000:
|
|
nSent = WriteReg(0, 16, 0x00F8, 2, FRMWRT_ALL_NR); // set communications baud rate and enable all interfaces
|
|
delay_os_ms(1);
|
|
// sciSetBaudrate(scilinREG, BAUDRATE);
|
|
break;
|
|
case 250000:
|
|
delay_os_ms(1);
|
|
break;
|
|
case 500000:
|
|
nSent = WriteReg(0, 16, 0x20F8, 2, FRMWRT_ALL_NR); // set communications baud rate and enable all interfaces
|
|
delay_os_ms(1);
|
|
// sciSetBaudrate(scilinREG, BAUDRATE);
|
|
break;
|
|
case 1000000:
|
|
nSent = WriteReg(0, 16, 0x30F8, 2, FRMWRT_ALL_NR); // set communications baud rate and enable all interfaces
|
|
delay_os_ms(1);
|
|
// sciSetBaudrate(scilinREG, BAUDRATE);
|
|
break;
|
|
}
|
|
|
|
// Clear all faults (section 1.2.7)
|
|
nSent = WriteReg(0, 82, 0xFFC0, 2, FRMWRT_ALL_NR); // clear all fault summary flags
|
|
nSent = WriteReg(0, 81, 0x38, 1, FRMWRT_ALL_NR); // clear fault flags in the system status register
|
|
|
|
delay_os_ms(10);
|
|
|
|
// Configure AFE (section 2.2.1)
|
|
|
|
nDev_ID = 0;
|
|
// nSent = WriteReg(nDev_ID, 60, 0x00, 1, FRMWRT_SGL_NR); // set 0 mux delay
|
|
nSent = WriteReg(nDev_ID, 61, 0x00, 1, FRMWRT_SGL_NR); // set 0 initial sampling delay
|
|
|
|
// Configure voltage and internal sample period (section 2.2.2)
|
|
nDev_ID = 0;
|
|
nSent = WriteReg(nDev_ID, 62, 0xCC, 1, FRMWRT_SGL_NR); // set 99.92us ADC sampling period - Cell and die temperature measurement period
|
|
|
|
// Configure the oversampling rate (section 2.2.3)
|
|
nDev_ID = 0;
|
|
nSent = WriteReg(nDev_ID, 7, 0x00, 1, FRMWRT_SGL_NR); // set no oversampling period
|
|
|
|
// Clear and check faults (section 2.2.4)
|
|
nDev_ID = 0;
|
|
nSent = WriteReg(nDev_ID, 81, 0x38, 1, FRMWRT_SGL_NR); // clear fault flags in the system status register
|
|
nSent = WriteReg(nDev_ID, 82, 0xFFC0, 2, FRMWRT_SGL_NR); // clear all fault summary flags
|
|
nRead = ReadReg(nDev_ID, 81, &wTemp, 1, 0); // 0ms timeout
|
|
nRead = ReadReg(nDev_ID, 82, &wTemp, 2, 0); // 0ms timeout
|
|
|
|
// Select number of cells and channels to sample (section 2.2.5.1)
|
|
nDev_ID = 0;
|
|
nSent = WriteReg(nDev_ID, 13, 0x10, 1, FRMWRT_SGL_NR); // set number of cells to 16
|
|
// 1111 1111 0111 1111
|
|
nSent = WriteReg(nDev_ID, 3, 0xFF7F00C0, 4, FRMWRT_SGL_NR); // select all cell, AUX channels 0 and 1, and internal digital die and internal analog die temperatures
|
|
|
|
// // Select identical number of cells and channels on all modules simultaneously (section 2.2.5.2)
|
|
// nSent = WriteReg(0, 13, 0x10, 1, FRMWRT_ALL_NR); // set number of cells to 16
|
|
// nSent = WriteReg(0, 3, 0xFFFF03C0, 4, FRMWRT_ALL_NR); // select all cell, AUX channels 0 and 1, and internal digital die and internal analog die temperatures
|
|
// nSent = WriteReg(0, 13, 0x08, 1, FRMWRT_ALL_NR); // set number of cells to 8
|
|
// nSent = WriteReg(0, 3, 0x00FF03C0, 4, FRMWRT_ALL_NR); // select all cell channels 1-8, AUX channels 0 and 1, and internal digital die and internal analog die temperatures
|
|
|
|
// Set cell over-voltage and cell under-voltage thresholds on a single board (section 2.2.6.1)
|
|
nDev_ID = 0;
|
|
nSent = WriteReg(nDev_ID, 144, 0xD1EC, 2, FRMWRT_SGL_NR); // set OV threshold = 4.1000V
|
|
nSent = WriteReg(nDev_ID, 142, 0x0000, 2, FRMWRT_SGL_NR); // set UV threshold = 1.9000V
|
|
|
|
// Set CBCONFIG 0x13 (19) Balance Configuration
|
|
nSent = WriteReg(nDev_ID, 19, 0x28, 1, FRMWRT_SGL_NR); // set BAL_TIME = 1 minute and set BAL_CONTINUE = 1
|
|
// Test CBENBL 0x14?15 (20?21) Balancing Enable
|
|
for (int i = 0; i < 16; i++)
|
|
{
|
|
nSent = WriteReg(nDev_ID, 20, (1 << i), 2, FRMWRT_SGL_NR); // set BAL_TIME = 1 minute and set BAL_CONTINUE = 1
|
|
delay_os_ms(200);
|
|
}
|
|
nSent = WriteReg(nDev_ID, 20, 0x0000, 2, FRMWRT_SGL_NR); // set BAL_TIME = 1 minute and set BAL_CONTINUE = 1
|
|
// // Set cell over-voltage and cell under-voltage thresholds on all boards simultaneously (section 2.2.6.2)
|
|
// nSent = WriteReg(0, 144, 0xD1EC, 2, FRMWRT_ALL_NR); // set OV threshold = 4.1000V
|
|
// nSent = WriteReg(0, 142, 0x6148, 2, FRMWRT_ALL_NR); // set UV threshold = 1.9000V
|
|
|
|
// Send broadcast request to all boards to sample and send results (section 3.2)
|
|
// nSent = WriteReg(0, 2, 0x02, 1, FRMWRT_ALL_NR); // send sync sample command
|
|
// nSent = WaitRespFrame(bFrame, 81, 0); // 24 bytes data (x3) + packet header (x3) + CRC (x3), 0ms timeout
|
|
|
|
// Send broadcast request to all boards to sample and store results (section 3.3.1)
|
|
// nSent = WriteReg(0, 2, 0x00, 1, FRMWRT_ALL_NR); // send sync sample command
|
|
|
|
// Read sampled data from boards (section 3.3.2)
|
|
// 24 bytes - still configured for 8 AFE channels plus 2 AUX channels plus internal digital and analog die
|
|
// temperatures (see code for section 2.2.5.2)
|
|
// nDev_ID = 2;
|
|
// nSent = WriteReg(nDev_ID, 2, 0x20, 1, FRMWRT_SGL_R); // send read sampled values command
|
|
// nSent = WaitRespFrame(bFrame, 27, 0); // 24 bytes data + packet header + CRC, 0ms timeout
|
|
// nDev_ID = 1;
|
|
// nSent = WriteReg(nDev_ID, 2, 0x20, 1, FRMWRT_SGL_R); // send read sampled values command
|
|
// nSent = WaitRespFrame(bFrame, 27, 0); // 24 bytes data + packet header + CRC, 0ms timeout
|
|
// nDev_ID = 0;
|
|
// nSent = WriteReg(nDev_ID, 2, 0x20, 1, FRMWRT_SGL_R); // send read sampled values command
|
|
// nSent = WaitRespFrame(bFrame, 27, 0); // 24 bytes data + packet header + CRC, 0ms timeout
|
|
|
|
// // Send sample request to single board to sample and send results (section 4.2)
|
|
// nDev_ID = 1;
|
|
// nSent = WriteReg(nDev_ID, 2, 0x01, 1, FRMWRT_SGL_NR); // send sync sample command
|
|
// nSent = WaitRespFrame(bFrame, 27, 0); // 24 bytes data + packet header + CRC, 0ms timeout
|
|
|
|
// // Send sample request with embedded channel and oversample information (section 4.3.1)
|
|
// nDev_ID = 3;
|
|
// nSent = WriteReg(nDev_ID, 2, 0x0000FF03C000, 6, FRMWRT_SGL_NR); // send sync sample command with channel
|
|
// // selection and oversample selection embedded
|
|
|
|
// Read previously sampled data from single board (section 4.3.2)
|
|
// nDev_ID = 0;
|
|
// nSent = WriteReg(nDev_ID, 2, 0x20, 1, FRMWRT_SGL_R); // send read sampled values command
|
|
// nSent = WaitRespFrame(bFrame, 27, 0); // 24 bytes data + packet header + CRC, 0ms timeout
|
|
|
|
// Configure GPIO pin direction and set new pin values (section 5.2.1)
|
|
// nDev_ID = 0;
|
|
// nSent = WriteReg(nDev_ID, 123, 0x00, 1, FRMWRT_SGL_NR); // turn off all GPIO pull downs
|
|
// nSent = WriteReg(nDev_ID, 122, 0x00, 1, FRMWRT_SGL_NR); // turn off all GPIO pull ups
|
|
// nSent = WriteReg(nDev_ID, 120, 0x07, 1, FRMWRT_SGL_NR); // set GPIO[2:0] to output direction
|
|
// nSent = WriteReg(nDev_ID, 122, 0x07, 1, FRMWRT_SGL_NR); // turn off GPIO[5:4] pull ups and turn on GPIO[2:0] pull ups
|
|
// nSent = WriteReg(nDev_ID, 121, 0x01, 1, FRMWRT_SGL_NR); // set GPIO outputs (pattern b001)
|
|
// nSent = WriteReg(nDev_ID, 121, 0x02, 1, FRMWRT_SGL_NR); // set GPIO outputs (pattern b010)
|
|
// nSent = WriteReg(nDev_ID, 121, 0x04, 1, FRMWRT_SGL_NR); // set GPIO outputs (pattern b100)
|
|
// nSent = WriteReg(nDev_ID, 121, 0x07, 1, FRMWRT_SGL_NR); // set GPIO outputs (pattern b111)
|
|
// nSent = WriteReg(nDev_ID, 121, 0x00, 1, FRMWRT_SGL_NR); // set GPIO outputs (pattern b000)
|
|
|
|
// Configure GPIO inputs with or without pull ups or pull downs (section 5.2.2)
|
|
// nDev_ID = 0;
|
|
// nSent = WriteReg(nDev_ID, 123, 0x04, 1, FRMWRT_SGL_NR); // enable pull down for GPIO2, turn off all other GPIO pull downs
|
|
// nSent = WriteReg(nDev_ID, 122, 0x03, 1, FRMWRT_SGL_NR); // enable pull ups for GPIO[1:0], turn off all other GPIO pull ups
|
|
// nSent = WriteReg(0, 122, 0x03, 1, FRMWRT_ALL_NR); // broadcast to all boards to enable pull ups for GPIO[1:0] and turn off all other GPIO pull ups
|
|
|
|
// Setting a GPIO output value (section 5.2.3.1)
|
|
// nDev_ID = 0;
|
|
// nSent = WriteReg(nDev_ID, 120, 0x17, 1, FRMWRT_SGL_NR); // set GPIO direction for GPIO4 and GPIO[2:0] as outputs, GPIO3 and GPIO5 as inputs
|
|
// nSent = WriteReg(nDev_ID, 121, 0x12, 1, FRMWRT_SGL_NR); // set GPIO4 and GPIO1, clear GPIO2 and GPIO0
|
|
|
|
// Reading a GPIO input value (section 5.2.3.2)
|
|
// nDev_ID = 0;
|
|
// nSent = WriteReg(nDev_ID, 120, 0x30, 1, FRMWRT_SGL_NR); // set GPIO direction for GPIO[5:4] as outputs, GPIO[3:0] as inputs
|
|
// nRead = ReadReg(nDev_ID, 124, &wTemp, 1, 0); // read GPIO inputs, 0ms timeout
|
|
|
|
// Steps for saving register configuration to EEPROM (sections 6.2.1 to 6.2.4)
|
|
// ** the code is commented out below to avoid accidental use - uncomment to use
|
|
// nDev_ID = 0;
|
|
// //nSent = WriteReg(nDev_ID, 130, 0x8C2DB194, 4, FRMWRT_SGL_NR); // write Magic Number 1
|
|
// //nSent = WriteReg(nDev_ID, 252, 0xA375E60F, 4, FRMWRT_SGL_NR); // write Magic Number 2
|
|
// //nSent = WriteReg(nDev_ID, 12, 0x10, 1, FRMWRT_SGL_NR); // send Write RAM to EEPROM command
|
|
// nRead = ReadReg(nDev_ID, 12, &wTemp, 1, 0); // read WRITE_EEPROM status bit, 0ms timeout
|
|
//test WRITE_EEPROM bit to check for completion
|
|
|
|
// Steps for saving register configuration to EEPROM in all devices in stack (sections 6.2.5)
|
|
// ** the code is commented out below to avoid accidental use - uncomment to use
|
|
//nSent = WriteReg(0, 130, 0x8C2DB194, 4, FRMWRT_ALL_NR); // write Magic Number 1
|
|
//nSent = WriteReg(0, 252, 0xA375E60F, 4, FRMWRT_ALL_NR); // write Magic Number 2
|
|
//nSent = WriteReg(0, 12, 0x10, 1, FRMWRT_ALL_NR); // send Write RAM to EEPROM command
|
|
// nDev_ID = 0;
|
|
// nRead = ReadReg(nDev_ID, 12, &wTemp, 1, 0); // read WRITE_EEPROM status bit, 0ms timeout
|
|
// //test WRITE_EEPROM bit to check for completion
|
|
// nDev_ID = 1;
|
|
// nRead = ReadReg(nDev_ID, 12, &wTemp, 1, 0); // read WRITE_EEPROM status bit, 0ms timeout
|
|
// //test WRITE_EEPROM bit to check for completion
|
|
// nDev_ID = 2;
|
|
// nRead = ReadReg(nDev_ID, 12, &wTemp, 1, 0); // read WRITE_EEPROM status bit, 0ms timeout
|
|
//test WRITE_EEPROM bit to check for completion
|
|
|
|
// Assign devices to specific group IDs (section 7)
|
|
// nDev_ID = 1;
|
|
// nSent = WriteReg(nDev_ID, 11, 0x01, 1, FRMWRT_SGL_NR); // assign Dev ID 1 to Group ID 1
|
|
// nDev_ID = 2;
|
|
// nSent = WriteReg(nDev_ID, 11, 0x01, 1, FRMWRT_SGL_NR); // assign Dev ID 1 to Group ID 1
|
|
|
|
// delay_os_ms(1);
|
|
// nRead = ReadReg(1, 11, &wTemp, 1, 0); // read group ID register, 0ms timeout
|
|
// nRead = ReadReg(2, 11, &wTemp, 1, 0); // read group ID register, 0ms timeout
|
|
|
|
// Send group sample request with embedded channel and oversample information (section 7.1)
|
|
// send sync sample command (first data byte = command (b[7:5] = 0) | highest device to respond (0x01)) with
|
|
// channel selection and oversample selection embedded
|
|
// nGrp_ID = 1;
|
|
// nSent = WriteReg(nGrp_ID, 2, 0x02FFFF550000, 6, FRMWRT_GRP_R);
|
|
// nSent = WaitRespFrame(bFrame, 86, 0); // 40 bytes data (x2) + packet header (x2) + CRC (x2), 0ms timeout
|
|
|
|
// Send group sample request - 1 byte method (section 7.2)
|
|
// send sync sample command with channel (data byte = command (b[7:5] = 0) | highest device to respond (0x01))
|
|
// sampling parameters are taken from values already stored in Command Channel Select and Oversampling registers
|
|
// nGrp_ID = 1;
|
|
// nSent = WriteReg(nGrp_ID, 2, 0x02, 1, FRMWRT_GRP_R);
|
|
// nSent = WaitRespFrame(bFrame, 86, 0); // 40 bytes data (x2) + packet header (x2) + CRC (x2), 0ms timeout
|
|
|
|
// Send group register read - 2 byte method (section 7.3)
|
|
// read Command Channel Select register (first data byte = highest device to respond (0x01), second data byte
|
|
// = number of data bytes - 1 (4 bytes = 0x03))
|
|
// sampling parameters are taken from values already stored in Command Channel Select and Oversampling registers
|
|
// nGrp_ID = 1;
|
|
// nSent = WriteReg(nGrp_ID, 3, 0x0203, 2, FRMWRT_GRP_R);
|
|
// nSent = WaitRespFrame(bFrame, 14, 0); // 4 bytes data (x2) + packet header (x2) + CRC (x2), 0ms timeout
|
|
|
|
// Send group register read - 1 byte method (section 7.4)
|
|
// read Command Channel Select register (data byte = number of data bytes - 1 (4 bytes = b011) | highest device
|
|
// to respond (0x01))
|
|
// sampling parameters are taken from values already stored in Command Channel Select and Oversampling registers
|
|
// nGrp_ID = 1;
|
|
// nSent = WriteReg(nGrp_ID, 3, 0x62, 1, FRMWRT_GRP_R);
|
|
// nSent = WaitRespFrame(bFrame, 14, 0); // 4 bytes data (x2) + packet header (x2) + CRC (x2), 0ms timeout
|
|
|
|
// Send general broadcast register read - 2 byte method (section 8.1)
|
|
// read Command Channel Select register (first data byte = highest device to respond (0x01), second data byte
|
|
// = number of data bytes - 1 (0x03))
|
|
// nSent = WriteReg(0, 3, 0x0203, 2, FRMWRT_ALL_R);
|
|
// nSent = WaitRespFrame(bFrame, 14, 0); // 4 bytes data (x2) + packet header (x2) + CRC (x2), 0ms timeout
|
|
|
|
// Send general broadcast register read - 1 byte method (section 8.2)
|
|
// read Command Channel Select register (data byte = number of data bytes - 1 (4 bytes = b011) | highest device
|
|
// to respond (0x01))
|
|
// nSent = WriteReg(0, 3, 0x62, 1, FRMWRT_ALL_R);
|
|
// nSent = WaitRespFrame(bFrame, 14, 0); // 4 bytes data (x2) + packet header (x2) + CRC (x2), 0ms timeout
|
|
}
|
|
|
|
void Pl455DeviceReInit(void)
|
|
{
|
|
int nSent, nRead = 0;
|
|
int nDev_ID;
|
|
uint32_t wTemp = 0;
|
|
|
|
nSent = nSent;
|
|
nRead = nRead;
|
|
|
|
nDev_ID = 0;
|
|
// Wake all devices
|
|
// The wake tone will awaken any device that is already in shutdown and the pwrdown will shutdown any device
|
|
// that is already awake. The least number of times to sequence wake and pwrdown will be half the number of
|
|
// boards to cover the worst case combination of boards already awake or shutdown.
|
|
nSent = WriteReg(nDev_ID, 12, 0x40, 1, FRMWRT_ALL_NR); // send out broadcast pwrdown command
|
|
delay_os_ms(5); //~5ms
|
|
|
|
pl455_wakeup();
|
|
delay_os_ms(5); //~5ms
|
|
|
|
// Mask Customer Checksum Fault bit - [15] USER_CKSUM_MSK
|
|
nSent = WriteReg(0, 107, 0x8000, 2, FRMWRT_ALL_NR); // clear all fault summary flags
|
|
|
|
// Clear all faults
|
|
nSent = WriteReg(0, 82, 0xFFC0, 2, FRMWRT_ALL_NR); // clear all fault summary flags - 7.6.3.27 FAULT_SUM 0x52-53 (82-83) Fault Summary
|
|
nSent = WriteReg(0, 81, 0x38, 1, FRMWRT_ALL_NR); // clear fault flags in the system status register
|
|
|
|
// Auto-address all boards (section 1.2.2)
|
|
nSent = WriteReg(0, 14, 0x19, 1, FRMWRT_ALL_NR); // set auto-address mode on all boards - 7.6.3.9 DEVCONFIG 0x0E (14) Device Configuration
|
|
nSent = WriteReg(0, 12, 0x08, 1, FRMWRT_ALL_NR); // enter auto address mode on all boards, the next write to this ID will be its address
|
|
|
|
// Set addresses for all boards in daisy-chain (section 1.2.3)
|
|
nSent = WriteReg(nDev_ID, 10, nDev_ID, 1, FRMWRT_ALL_NR); // send address to each board
|
|
|
|
// Enable all communication interfaces on all boards in the stack (section 1.2.1)
|
|
// nSent = WriteReg(0, 16, 0x10F8, 2, FRMWRT_ALL_NR); // set communications baud rate and enable all interfaces on all boards in stack
|
|
nSent = WriteReg(0, 16, 0x1080, 2, FRMWRT_ALL_NR); // set communications baud rate and disable all interfaces on all boards in stack - only enable uart
|
|
|
|
/* Change to final baud rate used in the application (set by BAUDRATE define in pl455.h).
|
|
* Up to this point, all communication is at 250Kb, as the COMM_RESET done at the initial
|
|
* startup resets the bq76PL455A-Q1 UART to 250Kb. */
|
|
switch(BAUDRATE)
|
|
{
|
|
case 125000:
|
|
nSent = WriteReg(0, 16, 0x00F8, 2, FRMWRT_ALL_NR); // set communications baud rate and enable all interfaces
|
|
delay_os_ms(1);
|
|
// sciSetBaudrate(scilinREG, BAUDRATE);
|
|
break;
|
|
case 250000:
|
|
delay_os_ms(1);
|
|
break;
|
|
case 500000:
|
|
nSent = WriteReg(0, 16, 0x20F8, 2, FRMWRT_ALL_NR); // set communications baud rate and enable all interfaces
|
|
delay_os_ms(1);
|
|
// sciSetBaudrate(scilinREG, BAUDRATE);
|
|
break;
|
|
case 1000000:
|
|
nSent = WriteReg(0, 16, 0x30F8, 2, FRMWRT_ALL_NR); // set communications baud rate and enable all interfaces
|
|
delay_os_ms(1);
|
|
// sciSetBaudrate(scilinREG, BAUDRATE);
|
|
break;
|
|
}
|
|
|
|
// Clear all faults (section 1.2.7)
|
|
nSent = WriteReg(0, 82, 0xFFC0, 2, FRMWRT_ALL_NR); // clear all fault summary flags
|
|
nSent = WriteReg(0, 81, 0x38, 1, FRMWRT_ALL_NR); // clear fault flags in the system status register
|
|
|
|
delay_os_ms(10);
|
|
|
|
// Configure AFE (section 2.2.1)
|
|
|
|
nDev_ID = 0;
|
|
// nSent = WriteReg(nDev_ID, 60, 0x00, 1, FRMWRT_SGL_NR); // set 0 mux delay
|
|
nSent = WriteReg(nDev_ID, 61, 0x00, 1, FRMWRT_SGL_NR); // set 0 initial sampling delay
|
|
|
|
// Configure voltage and internal sample period (section 2.2.2)
|
|
nDev_ID = 0;
|
|
nSent = WriteReg(nDev_ID, 62, 0xCC, 1, FRMWRT_SGL_NR); // set 99.92us ADC sampling period - Cell and die temperature measurement period
|
|
|
|
// Configure the oversampling rate (section 2.2.3)
|
|
nDev_ID = 0;
|
|
nSent = WriteReg(nDev_ID, 7, 0x00, 1, FRMWRT_SGL_NR); // set no oversampling period
|
|
|
|
// Clear and check faults (section 2.2.4)
|
|
nDev_ID = 0;
|
|
nSent = WriteReg(nDev_ID, 81, 0x38, 1, FRMWRT_SGL_NR); // clear fault flags in the system status register
|
|
nSent = WriteReg(nDev_ID, 82, 0xFFC0, 2, FRMWRT_SGL_NR); // clear all fault summary flags
|
|
nRead = ReadReg(nDev_ID, 81, &wTemp, 1, 0); // 0ms timeout
|
|
nRead = ReadReg(nDev_ID, 82, &wTemp, 2, 0); // 0ms timeout
|
|
|
|
// Select number of cells and channels to sample (section 2.2.5.1)
|
|
nDev_ID = 0;
|
|
nSent = WriteReg(nDev_ID, 13, 0x10, 1, FRMWRT_SGL_NR); // set number of cells to 16
|
|
// 1111 1111 0111 1111
|
|
nSent = WriteReg(nDev_ID, 3, 0xFF7F00C0, 4, FRMWRT_SGL_NR); // select all cell, AUX channels 0 and 1, and internal digital die and internal analog die temperatures
|
|
|
|
// // Select identical number of cells and channels on all modules simultaneously (section 2.2.5.2)
|
|
// nSent = WriteReg(0, 13, 0x10, 1, FRMWRT_ALL_NR); // set number of cells to 16
|
|
// nSent = WriteReg(0, 3, 0xFFFF03C0, 4, FRMWRT_ALL_NR); // select all cell, AUX channels 0 and 1, and internal digital die and internal analog die temperatures
|
|
// nSent = WriteReg(0, 13, 0x08, 1, FRMWRT_ALL_NR); // set number of cells to 8
|
|
// nSent = WriteReg(0, 3, 0x00FF03C0, 4, FRMWRT_ALL_NR); // select all cell channels 1-8, AUX channels 0 and 1, and internal digital die and internal analog die temperatures
|
|
|
|
// Set cell over-voltage and cell under-voltage thresholds on a single board (section 2.2.6.1)
|
|
nDev_ID = 0;
|
|
nSent = WriteReg(nDev_ID, 144, 0xD1EC, 2, FRMWRT_SGL_NR); // set OV threshold = 4.1000V
|
|
nSent = WriteReg(nDev_ID, 142, 0x0000, 2, FRMWRT_SGL_NR); // set UV threshold = 1.9000V
|
|
|
|
nSent = WriteReg(nDev_ID, 20, 0x0000, 2, FRMWRT_SGL_NR); // set BAL_TIME = 1 minute and set BAL_CONTINUE = 1
|
|
}
|
|
|
|
/**
|
|
* @brief Initialize the Ethernet Module communication application
|
|
* @param None
|
|
* @retval None
|
|
*/
|
|
void App_TaskPl455Comm(void)
|
|
{
|
|
Pl455CommInit();
|
|
Pl455DeviceInit();
|
|
|
|
while (DEF_TRUE)
|
|
{
|
|
Pl455CommProcess();
|
|
Pl455UpdateData();
|
|
|
|
delay_os_ms(PL455_COMM_TASK_TIME);
|
|
}
|
|
}
|
|
|
|
void Pl455UpdateData(void)
|
|
{
|
|
device_value.Heartbeat = OptimeStamp;
|
|
device_status.battery_status.bit.AFE = Pl455CommState.Commfail;
|
|
}
|
|
|
|
u8 Pl455BuffFlag = true;
|
|
|
|
void Pl455CommProcess(void)
|
|
{
|
|
int nSent, nRead, nDev_ID = 0;
|
|
uint32_t rTmp = 0;
|
|
|
|
if (Pl455Config.Buffer != NULL)
|
|
{
|
|
nSent = WriteReg(nDev_ID, 81, 0x38, 1, FRMWRT_SGL_NR); // clear fault flags in the system status register
|
|
nSent = WriteReg(nDev_ID, 82, 0xFFC0, 2, FRMWRT_SGL_NR); // clear all fault summary flags
|
|
nRead = ReadReg(nDev_ID, 81, &rTmp, 1, 0); // 0ms timeout
|
|
nRead = ReadReg(nDev_ID, 82, &rTmp, 2, 0); // 0ms timeout
|
|
|
|
delay_os_ms(1);
|
|
|
|
nSent = WriteReg(nDev_ID, 2, 0x00, 1, FRMWRT_SGL_R); // send read sampled values command
|
|
nSent = nSent;
|
|
|
|
delay_os_ms(1);
|
|
|
|
nRead = WaitRespFrame(Pl455Config.Buffer, 27, 0); // 24 bytes data + packet header + CRC, 0ms timeout
|
|
|
|
if (nRead > 0)
|
|
{
|
|
if ((Pl455Config.MsgPrint == true)&&(screenmode == DIAG_MODE))
|
|
UART_DATA_PRINT(1, Pl455Config.Buffer, Pl455Config.Position, RX_PRINT);
|
|
|
|
Pl455_commfail_clear();
|
|
|
|
CellVoltagePutBuf(Pl455Config.Buffer);
|
|
|
|
MakeCellAvgData();
|
|
}
|
|
else
|
|
{
|
|
Pl455_commfail_check();
|
|
}
|
|
|
|
delay_os_ms(1);
|
|
|
|
nRead = ReadReg(nDev_ID, 20, &rTmp, 2, 0); // Cell balancing register
|
|
|
|
if (nRead > 0)
|
|
{
|
|
if (device_status.battery_status.bit.ACB)
|
|
PL455_Cell_AutoBalancing(rTmp);
|
|
else
|
|
PL455_Cell_ManualBalancing(rTmp);
|
|
}
|
|
}
|
|
}
|
|
|
|
// VCELL = [(2 * VREF) / 65535] * READ_ADC_VALUE
|
|
u16 GetCellVoltageConvValue(uint8_t *data)
|
|
{
|
|
uint16_t adcValue = (uint16_t)((data[0] << 8) | data[1]);
|
|
float ftmp;
|
|
|
|
ftmp = ((2 * PL455_VREF) / 65535) * adcValue;
|
|
|
|
return (uint16_t)(ftmp * 1000);;
|
|
}
|
|
|
|
void CellVoltagePutBuf(uint8_t *pdata)
|
|
{
|
|
s32 ch, j, cno, tmp;
|
|
|
|
ch = PackBufCh;
|
|
j = 1;
|
|
cno = 14;
|
|
|
|
// data buffering
|
|
PackBuf[ch].cvolt[cno--] = GetCellVoltageConvValue(&pdata[j]); j += 2; // Cell 15
|
|
PackBuf[ch].cvolt[cno--] = GetCellVoltageConvValue(&pdata[j]); j += 2; // Cell 14
|
|
PackBuf[ch].cvolt[cno--] = GetCellVoltageConvValue(&pdata[j]); j += 2; // Cell 13
|
|
PackBuf[ch].cvolt[cno--] = GetCellVoltageConvValue(&pdata[j]); j += 2; // Cell 12
|
|
PackBuf[ch].cvolt[cno--] = GetCellVoltageConvValue(&pdata[j]); j += 2; // Cell 11
|
|
PackBuf[ch].cvolt[cno--] = GetCellVoltageConvValue(&pdata[j]); j += 2; // Cell 10
|
|
PackBuf[ch].cvolt[cno--] = GetCellVoltageConvValue(&pdata[j]); j += 2; // Cell 9
|
|
PackBuf[ch].cvolt[cno--] = GetCellVoltageConvValue(&pdata[j]); j += 2; // Cell 8
|
|
|
|
PackBuf[ch].cvolt[cno--] = GetCellVoltageConvValue(&pdata[j]); j += 2; // Cell 7
|
|
PackBuf[ch].cvolt[cno--] = GetCellVoltageConvValue(&pdata[j]); j += 2; // Cell 6
|
|
PackBuf[ch].cvolt[cno--] = GetCellVoltageConvValue(&pdata[j]); j += 2; // Cell 5
|
|
PackBuf[ch].cvolt[cno--] = GetCellVoltageConvValue(&pdata[j]); j += 2; // Cell 4
|
|
PackBuf[ch].cvolt[cno--] = GetCellVoltageConvValue(&pdata[j]); j += 2; // Cell 3
|
|
PackBuf[ch].cvolt[cno--] = GetCellVoltageConvValue(&pdata[j]); j += 2; // Cell 2
|
|
PackBuf[ch].cvolt[cno--] = GetCellVoltageConvValue(&pdata[j]); j += 2; // Cell 1
|
|
|
|
if (Pl455BuffFlag == true)
|
|
{
|
|
Pl455BuffFlag = false;
|
|
for (int i = 0; i < DEVICE_MAX_CELL; i++)
|
|
{
|
|
for (int j = 0; j < PACK_BUF_MAX; j++)
|
|
{
|
|
PackBuf[j].cvolt[i] = PackBuf[ch].cvolt[i];
|
|
}
|
|
}
|
|
}
|
|
// Volt Avg
|
|
for (int i = 0; i < DEVICE_MAX_CELL; i++)
|
|
{
|
|
tmp = 0;
|
|
|
|
for (int j = 0; j < PACK_BUF_MAX; j++)
|
|
{
|
|
tmp += PackBuf[j].cvolt[i];
|
|
}
|
|
device_value.Cell.voltage[i] = (uint16_t)(tmp / PACK_BUF_MAX);
|
|
}
|
|
|
|
PackBufCh++;
|
|
PackBufCh %= PACK_BUF_MAX;
|
|
}
|
|
|
|
/*
|
|
Internal Analog Die Temperature deg C = (VADC - 1.8078) * 147.514
|
|
where
|
|
VADC=[(2 * VREF) / 65535] * READ_ADC_VALUE
|
|
VVM = -2 * [(2 * VREF) / 65535] * READ_ADC_VALUE
|
|
Internal Digital Die Temperature deg C = (VADC - 2.287) * 131.944
|
|
VMODULE = ([(2 * VREF) / 65535] * READ_ADC_VALUE) * 25
|
|
VAUX = [(2 * VREF) / 65535] * READ_ADC_VALUE
|
|
*/
|
|
void MakeCellAvgData(void)
|
|
{
|
|
u32 sum;
|
|
TMinMax min, max;
|
|
|
|
sum = 0;
|
|
memset(&min, 0x00, sizeof(TMinMax));
|
|
memset(&max, 0x00, sizeof(TMinMax));
|
|
|
|
for (int i = 0; i < DEVICE_MAX_CELL; i++)
|
|
{
|
|
if (i == 0)
|
|
{
|
|
max.value = device_value.Cell.voltage[i];
|
|
max.num = i;
|
|
min.value = device_value.Cell.voltage[i];
|
|
min.num = i;
|
|
}
|
|
if (max.value < device_value.Cell.voltage[i])
|
|
{
|
|
max.value = device_value.Cell.voltage[i];
|
|
max.num = i;
|
|
}
|
|
if (min.value > device_value.Cell.voltage[i])
|
|
{
|
|
min.value = device_value.Cell.voltage[i];
|
|
min.num = i;
|
|
}
|
|
|
|
sum += device_value.Cell.voltage[i];
|
|
}
|
|
|
|
device_value.BatVoltage = sum / 10;
|
|
|
|
device_value.Cell.avg.Max.value = max.value;
|
|
device_value.Cell.avg.Max.num = max.num;
|
|
device_value.Cell.avg.Min.value = min.value;
|
|
device_value.Cell.avg.Min.num = min.num;
|
|
|
|
device_value.Cell.avg.diff = max.value - min.value;
|
|
device_value.Cell.avg.avg = (u16)(sum / DEVICE_MAX_CELL);
|
|
}
|
|
|
|
void dec_cb_tick(u16 tick)
|
|
{
|
|
if (CB_Tick > tick)
|
|
CB_Tick -= tick;
|
|
else
|
|
CB_Tick = 0;
|
|
}
|
|
|
|
void PL455_Cell_AutoBalancing(uint32_t rBal)
|
|
{
|
|
u16 bal = 0;
|
|
u8 setBal = false;
|
|
PDEVICE_PARAM param = &device_param;
|
|
|
|
for (int i = 0; i < 16; i++)
|
|
{
|
|
if ((rBal >> i) & 0x0001)
|
|
{
|
|
if (i < emptyNo)
|
|
bal |= (uint16_t)(1 << i);
|
|
else if (i == emptyNo)
|
|
;
|
|
else if (i > emptyNo)
|
|
bal |= (uint16_t)(1 << (i - 1));
|
|
}
|
|
}
|
|
device_status.cellbalance.value = bal;
|
|
|
|
if (CB_Rest == true)
|
|
{
|
|
if (CB_Tick == 0)
|
|
{
|
|
CB_Rest = false;
|
|
CB_Tick = param->chg_ctrl.cell_bal_cfg.Cell_Balance_Interval * 1000;
|
|
setBal = true;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (CB_Tick == 0)
|
|
{
|
|
CB_Rest = true;
|
|
CB_Tick = param->chg_ctrl.cell_bal_cfg.Cell_Balance_Interval * 1000;
|
|
setBal = true;
|
|
}
|
|
}
|
|
|
|
if (CellBalancingFlag == true)
|
|
{
|
|
// Before cell balancing status is ON
|
|
if (device_value.Cell.avg.Max.value < param->chg_ctrl.cell_bal_cfg.Cell_Balance_Threshold)
|
|
CellBalancingFlag = false;
|
|
else if (device_value.Cell.avg.diff < (param->chg_ctrl.cell_bal_cfg.Cell_Balance_Min - 5))
|
|
{
|
|
if (device_status.warning.bit.cell_over_voltage == 0)
|
|
CellBalancingFlag = false;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// Before cell balancing status is OFF
|
|
if (device_value.Cell.avg.Max.value > (param->chg_ctrl.cell_bal_cfg.Cell_Balance_Threshold + param->chg_ctrl.cell_bal_cfg.Cell_Balance_Window))
|
|
{
|
|
if (device_value.Cell.avg.diff > param->chg_ctrl.cell_bal_cfg.Cell_Balance_Min)
|
|
CellBalancingFlag = true;
|
|
else if (device_status.warning.bit.cell_over_voltage)
|
|
CellBalancingFlag = true;
|
|
}
|
|
}
|
|
device_status.battery_status.bit.CB = CellBalancingFlag;
|
|
|
|
if (CellBalancingFlag == true)
|
|
{
|
|
if (setBal == true)
|
|
{
|
|
if (CB_Rest == false)
|
|
{
|
|
if (device_value.Cell.avg.Min.value > 3580)
|
|
{
|
|
if ((device_value.Cell.avg.Max.value - device_value.Cell.avg.avg) > 20)
|
|
{
|
|
Balance_Avg = device_value.Cell.avg.avg + 10;
|
|
}
|
|
else
|
|
{
|
|
if ((device_value.Cell.avg.avg - device_value.Cell.avg.Min.value) > 20)
|
|
Balance_Avg = device_value.Cell.avg.avg + 2;
|
|
else
|
|
Balance_Avg = device_value.Cell.avg.avg + 5;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (device_value.Cell.avg.diff > 100)
|
|
{
|
|
if ((device_value.Cell.avg.Max.value - device_value.Cell.avg.avg) > (device_value.Cell.avg.avg - device_value.Cell.avg.Min.value))
|
|
Balance_Avg = device_value.Cell.avg.avg + 20;
|
|
else
|
|
Balance_Avg = device_value.Cell.avg.avg - 20;
|
|
}
|
|
else if (device_value.Cell.avg.diff > 80)
|
|
{
|
|
if ((device_value.Cell.avg.Max.value - device_value.Cell.avg.avg) > (device_value.Cell.avg.avg - device_value.Cell.avg.Min.value))
|
|
Balance_Avg = device_value.Cell.avg.avg + 15;
|
|
else
|
|
Balance_Avg = device_value.Cell.avg.avg - 15;
|
|
}
|
|
else if (device_value.Cell.avg.diff > 60)
|
|
{
|
|
if ((device_value.Cell.avg.Max.value - device_value.Cell.avg.avg) > (device_value.Cell.avg.avg - device_value.Cell.avg.Min.value))
|
|
Balance_Avg = device_value.Cell.avg.avg + 10;
|
|
else
|
|
Balance_Avg = device_value.Cell.avg.avg - 10;
|
|
}
|
|
else if (device_value.Cell.avg.diff > 40)
|
|
{
|
|
if ((device_value.Cell.avg.Max.value - device_value.Cell.avg.avg) > (device_value.Cell.avg.avg - device_value.Cell.avg.Min.value))
|
|
Balance_Avg = device_value.Cell.avg.avg + 5;
|
|
else
|
|
Balance_Avg = device_value.Cell.avg.avg - 5;
|
|
}
|
|
else if (device_value.Cell.avg.diff > 30)
|
|
{
|
|
if ((device_value.Cell.avg.Max.value - device_value.Cell.avg.avg) > (device_value.Cell.avg.avg - device_value.Cell.avg.Min.value))
|
|
Balance_Avg = device_value.Cell.avg.avg + 2;
|
|
else
|
|
Balance_Avg = device_value.Cell.avg.avg - 2;
|
|
}
|
|
else if (device_value.Cell.avg.diff > 20)
|
|
{
|
|
if ((device_value.Cell.avg.Max.value - device_value.Cell.avg.avg) > (device_value.Cell.avg.avg - device_value.Cell.avg.Min.value))
|
|
Balance_Avg = device_value.Cell.avg.avg + 2;
|
|
else
|
|
Balance_Avg = device_value.Cell.avg.avg - 2;
|
|
}
|
|
else if (device_value.Cell.avg.diff > 10)
|
|
{
|
|
if ((device_value.Cell.avg.Max.value - device_value.Cell.avg.avg) > (device_value.Cell.avg.avg - device_value.Cell.avg.Min.value))
|
|
Balance_Avg = device_value.Cell.avg.avg + 1;
|
|
else
|
|
Balance_Avg = device_value.Cell.avg.avg - 1;
|
|
}
|
|
else
|
|
{
|
|
Balance_Avg = device_value.Cell.avg.avg;
|
|
}
|
|
}
|
|
|
|
bal = 0;
|
|
for (int i = 0; i < DEVICE_MAX_CELL; i++)
|
|
{
|
|
if ((device_value.Cell.voltage[i] > Balance_Avg) || ((device_status.cov_warning_cell.uValue >> i) == 1))
|
|
{
|
|
if (i < emptyNo)
|
|
bal = bal | (1 << i);
|
|
else
|
|
bal = bal | (1 << (i + 1));
|
|
}
|
|
}
|
|
WriteReg(0, 20, bal, 2, FRMWRT_SGL_NR); // Cell balancing all off
|
|
}
|
|
else
|
|
{
|
|
// CB Rest time
|
|
bal = 0;
|
|
for (int i = 0; i < DEVICE_MAX_CELL; i++)
|
|
{
|
|
if ((device_status.cov_warning_cell.uValue >> i) == 1)
|
|
{
|
|
if (i < emptyNo)
|
|
bal = bal | (1 << i);
|
|
else
|
|
bal = bal | (1 << (i + 1));
|
|
}
|
|
}
|
|
WriteReg(0, 20, bal, 2, FRMWRT_SGL_NR); // Cell balancing all off
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (device_status.cellbalance.value != 0x0000)
|
|
WriteReg(0, 20, 0x0000, 2, FRMWRT_SGL_NR); // Cell balancing all off
|
|
}
|
|
}
|
|
|
|
void SetManualBalancing(u8 flag, u32 cNo)
|
|
{
|
|
ManualBalFlag = flag;
|
|
|
|
if (ManualBalFlag == true)
|
|
{
|
|
if (cNo >= 1)
|
|
ManualBalValue |= (1 << (cNo - 1));
|
|
}
|
|
else
|
|
{
|
|
ManualBalValue = 0;
|
|
}
|
|
}
|
|
|
|
void PL455_Cell_ManualBalancing(uint32_t rBal)
|
|
{
|
|
u16 bal = 0;
|
|
|
|
for (int i = 0; i < 16; i++)
|
|
{
|
|
if ((rBal >> i) & 0x0001)
|
|
{
|
|
if (i < 8)
|
|
bal |= (uint16_t)(1 << i);
|
|
else if (i == 9)
|
|
;
|
|
else if (i > 9)
|
|
bal |= (uint16_t)(1 << (i - 1));
|
|
}
|
|
}
|
|
device_status.cellbalance.value = bal;
|
|
|
|
if (ManualBalFlag == true)
|
|
{
|
|
if (ManualBalValue != bal)
|
|
WriteReg(0, 20, ManualBalValue, 2, FRMWRT_SGL_NR); // Cell balancing all off
|
|
}
|
|
else
|
|
{
|
|
if (bal != 0)
|
|
WriteReg(0, 20, 0x0000, 2, FRMWRT_SGL_NR); // Cell balancing all off
|
|
}
|
|
}
|
|
|
|
void Pl455_commfail_clear(void)
|
|
{
|
|
Pl455CommState.Timeout = 0;
|
|
Pl455CommState.Commfail = false;
|
|
}
|
|
|
|
void Pl455_commfail_check(void)
|
|
{
|
|
if (Pl455CommState.Commfail == false)
|
|
{
|
|
Pl455CommState.Timeout++;
|
|
|
|
if (Pl455CommState.Timeout >= (PL455_COMM_MAX_TIMEOUT / 2))
|
|
{
|
|
Pl455DeviceReInit();
|
|
delay_os_ms(1000);
|
|
}
|
|
if (Pl455CommState.Timeout >= PL455_COMM_MAX_TIMEOUT)
|
|
{
|
|
Pl455CommState.Commfail = true;
|
|
}
|
|
}
|
|
|
|
if ((Pl455Config.DataPrint == true) && (screenmode == DIAG_MODE))
|
|
{
|
|
printf("\r\nTimeout[%d] PL455 %03d(%d)"
|
|
, Pl455CommState.Timeout
|
|
, Pl455Config.Position
|
|
, Pl455CommState.Commfail
|
|
);
|
|
}
|
|
}
|
|
|
|
void SendDataToPl455(uint8_t *data, u16 len)
|
|
{
|
|
UART2_Flush();
|
|
UART2_PutStr(data, len);
|
|
|
|
if ((Pl455Config.MsgPrint == true)&&(screenmode == DIAG_MODE))
|
|
UART_DATA_PRINT(2, data, len, TX_PRINT);
|
|
}
|
|
|
|
void Pl455PacketInit(void)
|
|
{
|
|
Pl455Config.BufferStart = false;
|
|
Pl455Config.Position = 0;
|
|
}
|
|
|
|
u8 GetPl455CommPacket(uint8_t *rdata, uint16_t len)
|
|
{
|
|
u8 one;
|
|
u16 count;
|
|
|
|
Pl455PacketInit();
|
|
|
|
count = 0;
|
|
while(1)
|
|
{
|
|
if (UART2_GetChar(&one) == SUCCESS)
|
|
{
|
|
count = 0;
|
|
|
|
if ((Pl455Config.DataPrint == true)&&(screenmode == DIAG_MODE))
|
|
{
|
|
if (Pl455Config.BufferStart == false) printf("\r\n[PL455 RECV] : ");
|
|
printf("%02X ", one);
|
|
}
|
|
|
|
if (Pl455Config.Position >= PL455_COMM_MAX_BUFFER_SIZE)
|
|
{
|
|
Pl455PacketInit();
|
|
return false;
|
|
}
|
|
|
|
if (Pl455Config.BufferStart == false)
|
|
{
|
|
rdata[Pl455Config.Position] = one;
|
|
Pl455Config.Position++;
|
|
Pl455Config.BufferStart = true;
|
|
}
|
|
else
|
|
{
|
|
rdata[Pl455Config.Position++] = one;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if ((Pl455Config.BufferStart == true)&&(count > 0)) return true;
|
|
count++;
|
|
if (count >= (PL455_COMM_RX_TIMEOUT / PL455_COMM_RX_DELAY)) return false;
|
|
|
|
delay_os_ms(PL455_COMM_RX_DELAY);
|
|
}
|
|
}
|
|
}
|
|
/* Public Status Function ************************************************************/
|
|
u16 GetBalanceAvg(void)
|
|
{
|
|
return Balance_Avg;
|
|
}
|
|
|
|
u16 GetBalanceFlag(void)
|
|
{
|
|
return CellBalancingFlag;
|
|
}
|
|
|
|
/* Display Function ******************************************************************/
|
|
#ifdef CONSOLE_DEBUG
|
|
|
|
void ODisplayBalancingValue(u8 p)
|
|
{
|
|
float aParam;
|
|
|
|
if (p || (disBalance_Avg != Balance_Avg))
|
|
{
|
|
aParam = (float)Balance_Avg / 1000;
|
|
FloatNormalOutIntXY(71, 10 , aParam, 5, 3);
|
|
disBalance_Avg = Balance_Avg;
|
|
}
|
|
|
|
if (p || (disCellBalancingFlag != CellBalancingFlag))
|
|
{
|
|
if (CellBalancingFlag == true)
|
|
YellowOutXY(68, 11, (u8 *)"O");
|
|
else
|
|
GreenOutXY(68, 11, (u8 *)"X");
|
|
disCellBalancingFlag = CellBalancingFlag;
|
|
}
|
|
|
|
if (p || ((disCB_Tick / 1000) != (CB_Tick / 1000)))
|
|
{
|
|
aParam = (float)(disCB_Tick / 1000);
|
|
FloatNormalOutIntXY(70, 11,aParam, 6, 0);
|
|
disCB_Tick = CB_Tick;
|
|
}
|
|
}
|
|
|
|
void DDisplay_Pl455Comm(u8 p)
|
|
{
|
|
if (p ||(Pl455Config.BakMsgPrint != Pl455Config.MsgPrint))
|
|
{
|
|
if (Pl455Config.MsgPrint) GreenOutXY ( 27, 6, (u8 *)"ENABLE ");
|
|
else NormalOutXY( 27, 6, (u8 *)"DISABLE");
|
|
Pl455Config.BakMsgPrint = Pl455Config.MsgPrint;
|
|
}
|
|
if (p ||(Pl455Config.BakDataPrint != Pl455Config.DataPrint))
|
|
{
|
|
if (Pl455Config.DataPrint)GreenOutXY ( 71, 6, (u8 *)"ENABLE ");
|
|
else NormalOutXY( 71, 6, (u8 *)"DISABLE");
|
|
Pl455Config.BakDataPrint = Pl455Config.DataPrint;
|
|
}
|
|
}
|
|
|
|
u8 DPl455CommCommand(u8 cmd)
|
|
{
|
|
u8 result = false;
|
|
|
|
switch (cmd)
|
|
{
|
|
case '0':
|
|
// PL455 COMM MSG MONITOR
|
|
if (Pl455Config.MsgPrint == true)
|
|
{
|
|
Pl455Config.MsgPrint = false;
|
|
UserMessage("[MESSAGE]: PL455 MSG PRINT DISABLE");
|
|
}
|
|
else
|
|
{
|
|
Pl455Config.MsgPrint = true;
|
|
UserMessage("[MESSAGE]: PL455 MSG PRINT ENABLE");
|
|
}
|
|
break;
|
|
case '1':
|
|
// PL455 COMM DATA MONITOR
|
|
if (Pl455Config.DataPrint == true)
|
|
{
|
|
Pl455Config.DataPrint = false;
|
|
UserMessage("[MESSAGE]: PL455 DATA PRINT DISABLE");
|
|
}
|
|
else
|
|
{
|
|
Pl455Config.DataPrint = true;
|
|
UserMessage("[MESSAGE]: PL455 DATA PRINT ENABLE");
|
|
}
|
|
break;
|
|
default:
|
|
result = 1;
|
|
break;
|
|
}
|
|
|
|
return result;
|
|
}
|
|
#endif // #ifdef CONSOLE_DEBUG
|
|
|
|
/******************* (C) COPYRIGHT 2015 STMicroelectronics *****END OF FILE****/
|