Backup before error handling refactoring

This commit is contained in:
jkwoo
2026-07-13 17:10:02 +09:00
commit 04fc19b485
1132 changed files with 347840 additions and 0 deletions

590
APP/alarm.c Normal file
View File

@@ -0,0 +1,590 @@
/* Copyright (c) 2012-2013 The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
* only version 2 as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
*/
/*
* High Level description:
* http://www.ti.com/lit/ds/symlink/bq28400.pdf
* Thechnical Reference:
* http://www.ti.com/lit/ug/sluu431/sluu431.pdf
*/
#include "includes.h"
#include "dflash_sf1.h"
#include "device_param.h"
#include "asutil.h"
#include "console.h"
#include "temp.h"
#include "led.h"
u8 SleepMode = false;
u32 smode_tick = 60 * 1000;
u32 CV_Diff_Time = 60 * 1000;
void dec_sleepmode_time(u32 tick);
void dec_cv_diff_time(u32 tick);
void ProcessSafety_COV(void);
void ProcessSafety_CUV(void);
void ProcessSafety_OTA(void);
void ProcessSafety_LTA(void);
void ProcessSafety_CellVoltageDiff(void);
void ProcessStatusCheck(void);
void ProcessSafetyControl(void);
#define SLEEP_VOLTAGE 4200
#define WAKEUP_VOLTAGE 4500
#define SLEEP_MODE_TIME 60 * 1000
#define CELL_DEVIATION_CHECK_VOLTAGE 4500
void dec_alarm_tick(u32 tick)
{
dec_cv_diff_time(tick);
dec_sleepmode_time(tick);
}
void dec_sleepmode_time(u32 tick)
{
if (smode_tick > 0)
{
if (smode_tick > tick)
smode_tick -= tick;
else
smode_tick = 0;
}
}
u8 GetSleepMode(void)
{
return SleepMode;
}
void SetSleepMode(u8 mode)
{
SleepMode = mode;
}
void CheckSleepMode(void)
{
if (SleepMode == true)
{
if (device_status.op_status == 1)
{
SleepMode = false;
smode_tick = SLEEP_MODE_TIME;
}
}
else
{
if ((device_status.protection.bit.cell_under_voltage) || (device_status.protection.bit.under_voltage))
{
if (smode_tick == 0)
SleepMode = true;
}
else
{
smode_tick = SLEEP_MODE_TIME;
}
}
}
void ProcessAlarm(void)
{
if (device_status.battery_status.bit.INIT) {
device_status.protection.bit.afe_fail = device_status.battery_status.bit.AFE;
if (device_status.battery_status.bit.AFE == false){
ProcessSafety_COV();
ProcessSafety_CUV();
}
ProcessSafety_OTA();
ProcessSafety_LTA();
ProcessSafety_CellVoltageDiff();
CheckSleepMode();
}
ProcessStatusCheck();
ProcessSafetyControl();
}
void ProcessSafety_COV(void)
{
/* Cell Over Voltage Check */
for (int i = 0; i < CellQty; i++) {
/* Cell Over Voltage Protection */
if (device_status.cov_protection_cell.uValue & BIT32(i)) {
// Release check
if (device_value.Cell.voltage[i] < (device_param.safety.voltage.COV_Recovery * 10))
device_status.cov_protection_cell.uValue &= ~BIT32(i);
} else {
// Alarm check
if (device_value.Cell.voltage[i] > (device_param.safety.voltage.COV_Threshold * 10))
device_status.cov_protection_cell.uValue |= BIT32(i);
}
/* Cell Over Voltage Warning */
if (device_status.cov_warning_cell.uValue & BIT32(i)) {
// Release check
if (device_value.Cell.voltage[i] < (device_param.safety.voltage.COV_Recovery * 10))
device_status.cov_warning_cell.uValue &= ~BIT32(i);
} else {
// Alarm check
if (device_value.Cell.voltage[i] > (device_param.safety.voltage.COV_Warning * 10))
device_status.cov_warning_cell.uValue |= BIT32(i);
}
}
if (device_status.cov_protection_cell.uValue != 0) {
device_status.protection.bit.cell_over_voltage = true;
} else {
device_status.protection.bit.cell_over_voltage = false;
}
if (device_status.cov_warning_cell.uValue != 0) {
device_status.warning.bit.cell_over_voltage = true;
} else {
device_status.warning.bit.cell_over_voltage = false;
}
/* System Over charge protection */
if (device_status.protection.bit.over_voltage)
{
// Release check
if (device_value.BatVoltage < device_param.safety.voltage.SOV_Recovery)
device_status.protection.bit.over_voltage = false;
}
else
{
// Alarm check
if (device_value.BatVoltage > device_param.safety.voltage.SOV_Threshold)
device_status.protection.bit.over_voltage = true;
}
/* System Over Voltage Warning */
if (device_status.warning.bit.over_voltage)
{
// Release check
if (device_value.BatVoltage < device_param.safety.voltage.SOV_Recovery)
device_status.warning.bit.over_voltage = false;
} else {
// Alarm check
if (device_value.BatVoltage > device_param.safety.voltage.SOV_Warning)
device_status.warning.bit.over_voltage = true;
}
}
void ProcessSafety_CUV(void)
{
/* Cell under voltage check */
for (int i = 0; i < CellQty; i++)
{
/* Cell under voltage protection */
if (device_status.cuv_protection_cell.uValue & BIT32(i))
{
// Recovery Check
if (device_value.Cell.voltage[i] > (device_param.safety.voltage.CUV_Recovery * 10))
device_status.cuv_protection_cell.uValue &= ~BIT32(i);
}
else
{
// Protection Check
if (device_value.Cell.voltage[i] < (device_param.safety.voltage.CUV_Threshold * 10))
device_status.cuv_protection_cell.uValue |= BIT32(i);
}
/* Cell under voltage warning */
if (device_status.cuv_warning_cell.uValue & BIT32(i))
{
// Recovery Check
if (device_value.Cell.voltage[i] > (device_param.safety.voltage.CUV_Recovery * 10))
device_status.cuv_warning_cell.uValue &= ~BIT32(i);
}
else
{
// Warning Check
if (device_value.Cell.voltage[i] < (device_param.safety.voltage.CUV_Warning * 10))
device_status.cuv_warning_cell.uValue |= BIT32(i);
}
}
if (device_status.cuv_protection_cell.uValue != 0)
device_status.protection.bit.cell_under_voltage = true;
else
device_status.protection.bit.cell_under_voltage = false;
if (device_status.cuv_warning_cell.uValue != 0)
device_status.warning.bit.cell_under_voltage = true;
else
device_status.warning.bit.cell_under_voltage = false;
if (device_status.protection.bit.cell_under_voltage)
{
if (device_status.op_status == 0x0001)
{
device_status.protection.bit.cell_under_voltage = 0;
device_status.cuv_protection_cell.uValue = 0;
}
}
/* System under voltage protection */
if (device_status.protection.bit.under_voltage)
{
// Release check
if (device_value.BatVoltage > device_param.safety.voltage.SUV_Recovery)
device_status.protection.bit.under_voltage = false;
}
else
{
// Alarm check
if (device_value.BatVoltage < device_param.safety.voltage.SUV_Threshold)
device_status.protection.bit.under_voltage = true;
}
/* System under voltage warning */
if (device_status.warning.bit.under_voltage)
{
// Release check
if (device_value.BatVoltage > device_param.safety.voltage.SUV_Recovery)
device_status.warning.bit.under_voltage = false;
}
else
{
// Alarm check
if (device_value.BatVoltage < device_param.safety.voltage.SUV_Warning)
device_status.warning.bit.under_voltage = true;
}
if (device_status.protection.bit.under_voltage)
{
if (device_status.op_status == 0x0001)
{
device_status.protection.bit.under_voltage = 0;
}
}
}
void ProcessSafety_OTA(void)
{
/* Charge High Temperature */
for (int i = 0; i < TempQty; i++)
{
if (ADState(i) != AD_FAIL)
{
s16 aTemp = device_value.Temp.temperature[i];
/* Over Temperature Charge Protection */
if (device_status.otc_protection_temp.uValue & BIT(i))
{
// Recovery Check
if (aTemp < device_param.safety.temperature.OT_Chg_Recovery)
device_status.otc_protection_temp.uValue &= ~BIT(i);
}
else
{
// Protection Check, when charging
if (device_status.battery_status.bit.MD == 0)
{
if (aTemp > device_param.safety.temperature.OT_Chg_Threshold)
device_status.otc_protection_temp.uValue |= BIT(i);
}
}
/* Over Temperature Charge Warning */
if (device_status.otc_warning_temp.uValue & BIT(i))
{
// Recovery Check
if (aTemp < device_param.safety.temperature.OT_Chg_Recovery)
device_status.otc_warning_temp.uValue &= ~BIT(i);
}
else
{
// Warning Check, when charging
if (device_status.battery_status.bit.MD == 0)
{
if (aTemp > device_param.safety.temperature.OT_Chg_Warning)
device_status.otc_warning_temp.uValue |= BIT(i);
}
}
}
}
/* OTC Protection */
if (device_status.otc_protection_temp.uValue != 0)
device_status.protection.bit.chg_high_temp = true;
else
device_status.protection.bit.chg_high_temp = false;
/* OTC Warning */
if (device_status.otc_warning_temp.uValue != 0)
device_status.warning.bit.chg_high_temp = true;
else
device_status.warning.bit.chg_high_temp = false;
/* High Temperature Discharge */
for (int i = 0; i < TempQty; i++)
{
if (ADState(i) != AD_FAIL)
{
s16 aTemp = device_value.Temp.temperature[i];
/* Over Temperature Discharge Protection */
if (device_status.otd_protection_temp.uValue & BIT(i))
{
// Recovery Check
if (aTemp < device_param.safety.temperature.OT_Dsg_Recovery)
device_status.otd_protection_temp.uValue &= ~BIT(i);
}
else
{
// Protection Check, when charging
if (device_status.battery_status.bit.MD == 1)
{
if (aTemp > device_param.safety.temperature.OT_Dsg_Threshold)
device_status.otd_protection_temp.uValue |= BIT(i);
}
}
/* Over Temperature Charge Warning */
if (device_status.otd_warning_temp.uValue & BIT(i))
{
// Recovery Check
if (aTemp < device_param.safety.temperature.OT_Dsg_Recovery)
device_status.otd_warning_temp.uValue &= ~BIT(i);
}
else
{
// Warning Check, when charging
if (device_status.battery_status.bit.MD == 1)
{
if (aTemp > device_param.safety.temperature.OT_Dsg_Warning)
device_status.otd_warning_temp.uValue |= BIT(i);
}
}
}
}
/* OTD Protection */
if (device_status.otd_protection_temp.uValue != 0)
device_status.protection.bit.dsg_high_temp = true;
else
device_status.protection.bit.dsg_high_temp = false;
/* OTD Warning */
if (device_status.otd_warning_temp.uValue != 0)
device_status.warning.bit.dsg_high_temp = true;
else
device_status.warning.bit.dsg_high_temp = false;
}
void ProcessSafety_LTA(void)
{
/* Charge Low Temperature */
for (int i = 0; i < TempQty; i++)
{
if (ADState(i) != AD_FAIL)
{
s16 aTemp = device_value.Temp.temperature[i];
/* Over Temperature Charge Protection */
if (device_status.ltc_protection_temp.uValue & BIT(i))
{
// Recovery Check
if (aTemp > device_param.safety.temperature.LT_Chg_Recovery)
device_status.ltc_protection_temp.uValue &= ~BIT(i);
}
else
{
// Protection Check, when charging
if (device_status.battery_status.bit.MD == 0)
{
if (aTemp < device_param.safety.temperature.LT_Chg_Threshold)
device_status.ltc_protection_temp.uValue |= BIT(i);
}
}
/* Low Temperature Charge Warning */
if (device_status.ltc_warning_temp.uValue & BIT(i))
{
// Recovery Check
if (aTemp > device_param.safety.temperature.LT_Chg_Recovery)
device_status.ltc_warning_temp.uValue &= ~BIT(i);
}
else
{
// Warning Check, when charging
if (device_status.battery_status.bit.MD == 0)
{
if (aTemp < device_param.safety.temperature.LT_Chg_Warning)
device_status.ltc_warning_temp.uValue |= BIT(i);
}
}
}
}
/* LTC Protection */
if (device_status.ltc_protection_temp.uValue != 0)
device_status.protection.bit.chg_low_temp = true;
else
device_status.protection.bit.chg_low_temp = false;
/* LTC Warning */
if (device_status.ltc_warning_temp.uValue != 0)
device_status.warning.bit.chg_low_temp = true;
else
device_status.warning.bit.chg_low_temp = false;
/* Low Temperature Discharge */
for (int i = 0; i < DEVICE_MAX_TEMP; i++)
{
if (ADState(i) != AD_FAIL)
{
s16 aTemp = device_value.Temp.temperature[i];
/* Low Temperature Discharge Protection */
if (device_status.ltd_protection_temp.uValue & BIT(i))
{
// Recovery Check
if (aTemp > device_param.safety.temperature.LT_Dsg_Recovery)
device_status.ltd_protection_temp.uValue &= ~BIT(i);
}
else
{
// Protection Check, when charging
if (device_status.battery_status.bit.MD == 1)
{
if (aTemp < device_param.safety.temperature.LT_Dsg_Threshold)
device_status.ltd_protection_temp.uValue |= BIT(i);
}
}
/* Over Temperature Charge Warning */
if (device_status.ltd_warning_temp.uValue & BIT(i))
{
// Recovery Check
if (aTemp > device_param.safety.temperature.LT_Dsg_Recovery)
device_status.ltd_warning_temp.uValue &= ~BIT(i);
}
else
{
// Warning Check, when charging
if (device_status.battery_status.bit.MD == 1)
{
if (aTemp < device_param.safety.temperature.LT_Dsg_Warning)
device_status.ltd_warning_temp.uValue |= BIT(i);
}
}
}
}
/* LTD Protection */
if (device_status.ltd_protection_temp.uValue != 0)
device_status.protection.bit.dsg_low_temp = true;
else
device_status.protection.bit.dsg_low_temp = false;
/* LTD Warning */
if (device_status.ltd_warning_temp.uValue != 0)
device_status.warning.bit.dsg_low_temp = true;
else
device_status.warning.bit.dsg_low_temp = false;
}
void dec_cv_diff_time(u32 tick)
{
if (CV_Diff_Time > tick)
CV_Diff_Time -= tick;
else
CV_Diff_Time = 0;
}
void ProcessSafety_CellVoltageDiff(void)
{
if (device_value.BatVoltage >= CELL_DEVIATION_CHECK_VOLTAGE)
{
/* Cell Voltage Diff warning */
if (device_status.warning.bit.cell_voltage_diff)
{
// release check
if (device_value.Cell.avg.diff < (device_param.safety.cv_diff.Cell_Voltage_Diff_Recovery * 10))
device_status.warning.bit.cell_voltage_diff = false;
}
else
{
// alarm check
if (device_value.Cell.avg.diff > (device_param.safety.cv_diff.Cell_Voltage_Diff_Warning * 10))
device_status.warning.bit.cell_voltage_diff = true;
}
/* Cell Voltage Diff protection */
if (device_status.protection.bit.cell_voltage_diff)
{
// release check
if (device_value.Cell.avg.diff < (device_param.safety.cv_diff.Cell_Voltage_Diff_Recovery * 10))
{
device_status.protection.bit.cell_voltage_diff = false;
}
}
else
{
// alarm check
if (device_value.Cell.avg.diff > (device_param.safety.cv_diff.Cell_Voltage_Diff_Threshold * 10))
{
if (CV_Diff_Time == 0)
device_status.protection.bit.cell_voltage_diff = true;
}
else
{
CV_Diff_Time = device_param.safety.cv_diff.Cell_Voltage_Diff_Time * 1000;
}
}
}
else
{
device_status.warning.bit.cell_voltage_diff = 0;
}
}
void ProcessStatusCheck(void)
{
// Alarm Status
if (device_status.battery_status.bit.INIT == false)
device_status.alarm_status = 0x0003; // Warming Up
else if (device_status.protection.value != 0)
device_status.alarm_status = 0x0002; // Protection
else if (device_status.warning.value != 0)
device_status.alarm_status = 0x0001; // Warning
else
device_status.alarm_status = 0x0000; // Normal
}
#define SFC_CELL_VOLTAGE_MAX 39500
#define SFC_CELL_VOLTAGE_MIN 18000
#define SFC_TEMP_MAX 900
void ProcessSafetyControl(void)
{
u8 flag = false;
for (int i = 0; i < CellQty; i++) {
if (device_value.Cell.voltage[i] > SFC_CELL_VOLTAGE_MAX) { flag = true; break; }
if (device_value.Cell.voltage[i] < SFC_CELL_VOLTAGE_MIN) { flag = true; break; }
}
if (flag == false) {
for (int i = 0; i < TempQty; i++) {
if (device_value.Temp.temperature[i] > SFC_TEMP_MAX) { flag = true; break; }
}
}
if (flag) {
SAFETY_SIGNAL = 1;
} else {
SAFETY_SIGNAL = 0;
}
}

26
APP/alarm.h Normal file
View File

@@ -0,0 +1,26 @@
/*****************************************************************************
*
* File : alarm.h
* Compiler : IAR C 6.30
* Revision : $Revision: 1.0 $
* Date : $Date: 2015 / 03 / 13
* Updated by : $Author: Jongkwang Woo
*
* Support mail : spirit0305@naver.com
*
* Description : Header file for alarm.c
*
****************************************************************************/
#ifndef _ALARM_H_
#define _ALARM_H_
#include <stm32f10x.h>
void ProcessAlarm(void);
void dec_alarm_tick(u32 tick);
u8 GetSleepMode(void);
void SetSleepMode(u8 mode);
#endif

114
APP/app_ver.c Normal file
View File

@@ -0,0 +1,114 @@
/**
******************************************************************************
* File Name : app_ver.c
* Description : This file provides code for application version
******************************************************************************
* @attention
*
* <h2><center>&copy; Copyright (c) 2024 Amogreentech Co., Ltd.
* All rights reserved.</center></h2>
*
******************************************************************************
*/
/* Includes ------------------------------------------------------------------*/
#include <includes.h>
#include <string.h>
#include "app_ver.h"
/* Private typedef -----------------------------------------------------------*/
/* Private define ------------------------------------------------------------*/
#define APP_VER_CRITICAL 1
#define APP_VER_MAJOR 0
#define APP_VER_MINOR 0
#define APP_VER_COMPILE 5
/* Private macro -------------------------------------------------------------*/
/* Private variables ---------------------------------------------------------*/
/* Private function prototype -----------------------------------------------*/
/* Private function ----------------------------------------------------------*/
void GetAppVersion(u8 *ver)
{
ver[0] = APP_VER_CRITICAL;
ver[1] = APP_VER_MAJOR;
ver[2] = APP_VER_MINOR;
ver[3] = APP_VER_COMPILE;
}
#ifdef CONSOLE_DEBUG
void APPVerDisplay(void)
{
u8 ver[4];
GetAppVersion(ver);
printf(" %s [OPERATING] VER %d.%d.%d.%d [%s %s]",
BD_MODEL,
ver[0],
ver[1],
ver[2],
ver[3],
__DATE__,
__TIME__
);
}
u16 GetAppVersionStr(u8 *vStr)
{
sprintf((char *)vStr, "%d.%d.%d.%d",
APP_VER_CRITICAL,
APP_VER_MAJOR,
APP_VER_MINOR,
APP_VER_COMPILE
);
return strlen((char *)vStr);
}
void GET_BUILD_DATETIME(u8 *datetime)
{
u8 date_str[12];
u8 time_str[12];
sprintf((char *)date_str, "%s", __DATE__);
sprintf((char *)time_str, "%s", __TIME__);
memcpy(&datetime[0], &date_str[7], 4); //year
if (memcmp(&date_str[0], "Jan", 3) == 0) //month
memcpy(&datetime[4], "01", 2);
else if (memcmp(&date_str[0], "Feb", 3) == 0)
memcpy(&datetime[4], "02", 2);
else if (memcmp(&date_str[0], "Mar", 3) == 0)
memcpy(&datetime[4], "03", 2);
else if (memcmp(&date_str[0], "Apr", 3) == 0)
memcpy(&datetime[4], "04", 2);
else if (memcmp(&date_str[0], "May", 3) == 0)
memcpy(&datetime[4], "05", 2);
else if (memcmp(&date_str[0], "Jun", 3) == 0)
memcpy(&datetime[4], "06", 2);
else if (memcmp(&date_str[0], "Jul", 3) == 0)
memcpy(&datetime[4], "07", 2);
else if (memcmp(&date_str[0], "Aug", 3) == 0)
memcpy(&datetime[4], "08", 2);
else if (memcmp(&date_str[0], "Sep", 3) == 0)
memcpy(&datetime[4], "09", 2);
else if (memcmp(&date_str[0], "Oct", 3) == 0)
memcpy(&datetime[4], "10", 2);
else if (memcmp(&date_str[0], "Nov", 3) == 0)
memcpy(&datetime[4], "11", 2);
else if (memcmp(&date_str[0], "Dec", 3) == 0)
memcpy(&datetime[4], "12", 2);
memcpy(&datetime[6], &date_str[4], 2); //date
if (datetime[6] == ' ')
datetime[6] = '0';
memcpy(&datetime[ 8], &time_str[0], 2); //hour
memcpy(&datetime[10], &time_str[3], 2); //min
memcpy(&datetime[12], &time_str[6], 2); //sec
}
#endif // #ifdef CONSOLE_DEBUG
/*******************(C)COPYRIGHT 2024 Amogreentech *********END OF FILE********/

42
APP/app_ver.h Normal file
View File

@@ -0,0 +1,42 @@
/*
*********************************************************************************************************
* EXAMPLE CODE
*
* (c) Copyright 2003-2007; Micrium, Inc.; Weston, FL
*
* All rights reserved. Protected by international copyright laws.
* Knowledge of the source code may NOT be used to develop a similar product.
* Please help us continue to provide the Embedded community with the finest
* software available. Your honesty is greatly appreciated.
*********************************************************************************************************
*/
/*
*********************************************************************************************************
*
* APPLICATION CONFIGURATION
*
* ST Microelectronics STM32
* with the
* IAR STM32-SK Evaluation Board
*
* Filename : app_cfg.h
* Version : V1.00
* Programmer(s) : FT
*********************************************************************************************************
*/
#ifndef __APP_VER_H__
#define __APP_VER_H__
#include <stm32f10x.h>
#define BD_MODEL "BMU-21S\0"
void GetAppVersion(u8 *ver);
void APPVerDisplay(void);
void GET_BUILD_DATETIME(u8 *datetime);
u16 GetAppVersionStr(u8 *vStr);
#endif

818
APP/asutil.c Normal file
View File

@@ -0,0 +1,818 @@
/*****************************************************************************
*
* MSO Corporation
*
* File : asutil.c
* Compiler : IAR C 5.10C Kickstart
* Revision : $Revision: 1.0 $
* Date : $Date: 2010 / 07 / 16
* Updated by : $Author: Jongkwang Woo
*
* Support mail : spirit0305@naver.com
*
* Target platform : STM32F4 Cortex-M4 support
*
* AppNote : BPCB Application
*
* Description : Utility routines
*
****************************************************************************/
#define _ASUTIL_
#include "includes.h"
#include "asutil.h"
#include "console.h"
#include "usart.h"
#include "app_ver.h"
#include "delay.h"
#include "brtc.h"
u16 reverse16(u16 data)
{
return ((data >> 8) & 0x00FF) + ((data << 8) & 0xFF00);
}
u32 reverse32(u32 data)
{
return ((data >> 24) & 0x000000FF) +
((data >> 8) & 0x0000FF00) +
((data << 8) & 0x00FF0000) +
((data << 24) & 0xFF000000);
}
#ifndef CONSOLE_DEBUG
//void UART_DATA_PRINT(u16 port, u8 * buf, u16 len, u8 mode)
//{
//}
//void CAN_DATA_PRINT(u16 port, CanRxMsg* buf, u8 mode)
//{
//}
//void CAN_TX_DATA_PRINT(u16 port, CanTxMsg* buf)
//{
//}
void UserMessage(char *str)
{
}
#endif // #ifndef CONSOLE_DEBUG
#ifdef CONSOLE_DEBUG
u8 *dump_addr = 0;
void ClearConsol(void)
{
printf("%1c[ ; H [32;40m", 0x1b);
printf("%1c[2J%1c[0;0H%1c[2;37;40m", 0x1b, 0x1b, 0x1b);
}
void UserMessage(char *str)
{
char DisplayStr[81];
s16 i;
printf("%1c[s", 0x1b);
printf("%1c[24;01H%1c[34;47m", 0x1b, 0x1b);
for (i = 0; i < 80; i++)
{
DisplayStr[i] = ' ';
}
i = 0;
while ((str[i] != '\0') && (i < 80))
{
DisplayStr[i] = str[i];
i ++;
}
DisplayStr[80] = 0x00;
printf("%s", DisplayStr);
printf("%1c[37;40m%1c[23;8H", 0x1b, 0x1b);
printf("%1c[u", 0x1b);
}
void NormalOutXY(u16 x, u16 y, u8 *msg)
{
printf("%1c[s%1c[%02d;%02dH%1c[1m", 0x1b, 0x1b, y, x, 0x1b);
printf("%s", msg);
printf("%1c[23;8H%1c[u", 0x1b, 0x1b);
}
void GreenOutXY(u16 x,u16 y, u8 *msg)
{
printf("%1c[s%1c[%02d;%02dH%1c[1;32;40m", 0x1b, 0x1b, y, x, 0x1b);
printf("%s", msg);
printf("%1c[37;40m%1c[23;8H%1c[u", 0x1b, 0x1b, 0x1b);
}
void RedOutXY(u16 x,u16 y, u8 *msg)
{
printf("%1c[s%1c[%02d;%02dH%1c[1;31;40m", 0x1b, 0x1b, y, x, 0x1b);
printf("%s", msg);
printf("%1c[37;40m%1c[23;8H%1c[u", 0x1b, 0x1b, 0x1b);
}
void YellowOutXY(u16 x,u16 y, u8 *msg)
{
printf("%1c[s%1c[%02d;%02dH%1c[1;33;40m", 0x1b, 0x1b, y, x, 0x1b);
printf("%s", msg);
printf("%1c[37;40m%1c[23;8H%1c[u", 0x1b, 0x1b, 0x1b);
}
void ColorOutXY(u8 aColor, u16 x, u16 y, u8 *Text)
{
switch (aColor)
{
case DISPLAY_NORMAL:
NormalOutXY(x, y, Text);
break;
case DISPLAY_RED:
RedOutXY(x, y, Text);
break;
case DISPLAY_GREEN:
GreenOutXY(x, y, Text);
break;
case DISPLAY_YELLOW:
YellowOutXY(x, y, Text);
break;
}
}
void dump_mem(u32 addr)
{
u8 ASC[20];
s16 a,b;
if (addr != 0)
{
dump_addr = (u8 *)(addr);
}
printf("\r\n");
for (a = 0; a < 8; a++)
{
printf("%08lX ", (unsigned long)(dump_addr));
for (b = 0; b < 16; b++)
{
printf("%02X ", dump_addr[0]);
if (dump_addr[0] <' ') ASC[b] = '.';
else if (dump_addr[0] == 0xFF) ASC[b] = '.';
else
{
if ((b == 15)&&(dump_addr[0] > 128))
ASC[b] = '.';
else
ASC[b] = dump_addr[0];
}
dump_addr++;
}
printf(" ");
ASC[16] = 0x00;
printf("%s", ASC);
printf("\r\n");
}
}
u32 TextToAddr(u8 *data)
{
u32 l;
int a, b, c;
a = 0;
while (((data[a] >= '0') && (data[a] <= '9')) ||
((data[a] >= 'A') && (data[a] <= 'F')) ||
((data[a] >= 'a') && (data[a] <= 'f'))
)
{
a++;
}
l = 0;
for (b = 0; b < a; b++)
{
if (data[b] > 'F') { c = data[b] - 'a' + 10; }
else
{
if (data[b] > '9') { c = data[b] - 'A' + 10;}
else { c = data[b] - '0';}
}
l = l * 16 + c;
}
return(l);
}
u8 WaitUserCMD(u8 *cmd)
{
u32 waittime;
u8 ret;
u8 one[2];
u16 i, len;
for (i = 0; i < 20; i++)
{
if (cmd[i] == '\0') break;
}
len = i;
waittime = GetLocalTime() + 5;
ret = 0;
while (waittime > GetLocalTime())
{
if (debug_recv_data(one))
{
for (i = 0; i < len; i++)
{
if (one[0] == cmd[i])
return (i + 1);
}
}
IWDG_ReloadCounter();
delay_os_ms(1);
}
position = 0;
return(ret);
}
void data_print(u8 *data, u16 len)
{
u8 ASC[20];
u16 i, j;
for (i = 0; i < (len/16 + 1); i++)
{
printf("0x%04X ", (u32)(data + (i*16)));
for (j = 0; j < 16; j++)
{
if ((i*16 + j) >= len)
{
printf(" ");
ASC[j] = ' ';
}
else
{
printf("%02X ", data[(i*16)+j]);
if (data[i*16 + j] <' ') ASC[j] = '.';
else
{
if ((j == 15)&&(data[i*16 + j] > 128))
ASC[j] = '.';
else
ASC[j] = data[i*16 + j];
}
}
}
ASC[16] = 0x00;
printf(" %s\r\n", ASC);
}
}
void CAN_RX_DATA_PRINT(u16 port, CanRxMsg* buf)
{
printf("\r\nCAN%d RX: ID(0x%08X): DLC(%d): ", port, buf->ExtId, buf->DLC);
data_print(buf->Data, buf->DLC);
}
void CAN_TX_DATA_PRINT(u16 port, CanTxMsg* buf)
{
printf("\r\nCAN%d TX: ID(0x%08X): DLC(%d): ", port, buf->ExtId, buf->DLC);
data_print(buf->Data, buf->DLC);
}
void DebugMessage(u8 *msg)
{
if (screenmode == DIAG_MODE)
printf("%s", msg);
}
u8 FIND_CHAR(u8 *in, u8 *out, s16 max, u8 fdata)
{
u8 i;
if (max <= 0)
return 0;
for (i = 0; i < max; i++)
{
if (in[i] == fdata) break; // not found
out[i] = in[i];
}
return(i);
}
u8 FIND_DATA(u8 *in, u8 *out, u16 max, u8 fdata, u16 count)
{
u16 i, j, k, ret;
i = 0;
j = 0;
k = 0;
ret = 0;
for (i = 0; i < max; i++)
{
if (in[i] == 0x00) break;
if (in[i] == 0x03) break;
if (in[i] == fdata)
{
j++;
if (j == count)
{
ret = k;
break;
}
k = 0;
}
else
{
out[k++] = in[i];
}
}
return ret;
}
void FloatToStr(float ins, u8 *text, u16 size, u16 point)
{
u32 a = 1;
s32 b, x;
u32 y, k, i;
if (ins < 0) k = true; else k = false;
if (point > 0)
{
for (i = 0; i < point; i++)
a *= 10;
b = (s32)(ins * a);
if (b < 0) b *= -1;
x = (s32)ins;
y = (u32)(b % a);
}
else
{
x = (s32)ins;
y = 0;
}
text[0] = 0x00;
switch (size)
{
case 0:
break;
case 1:
sprintf((char *)text, "%1d", x);
break;
case 2:
sprintf((char *)text, "%2d", x);
break;
case 3:
switch (point)
{
case 0:
sprintf((char *)text, "%3d", x);
break;
case 1:
sprintf((char *)text, "%1d.%01d", x, y);
break;
}
break;
case 4:
switch (point)
{
case 0:
sprintf((char *)text, "%4d", x);
break;
case 1:
sprintf((char *)text, "%2d.%01d", x, y);
break;
case 2:
sprintf((char *)text, "%1d.%02d", x, y);
break;
}
break;
case 5:
switch (point)
{
case 0:
sprintf((char *)text, "%5d", x);
break;
case 1:
sprintf((char *)text, "%3d.%01d", x, y);
break;
case 2:
sprintf((char *)text, "%2d.%02d", x, y);
break;
case 3:
sprintf((char *)text, "%1d.%03d", x, y);
break;
}
break;
case 6:
switch (point)
{
case 0:
sprintf((char *)text, "%6d", x);
break;
case 1:
sprintf((char *)text, "%4d.%01d", x, y);
break;
case 2:
sprintf((char *)text, "%3d.%02d", x, y);
break;
case 3:
sprintf((char *)text, "%2d.%03d", x, y);
break;
case 4:
sprintf((char *)text, "%1d.%04d", x, y);
break;
}
break;
case 7:
switch (point)
{
case 0:
sprintf((char *)text, "%7d", x);
break;
case 1:
sprintf((char *)text, "%5d.%01d", x, y);
break;
case 2:
sprintf((char *)text, "%4d.%02d", x, y);
break;
case 3:
sprintf((char *)text, "%3d.%03d", x, y);
break;
case 4:
sprintf((char *)text, "%2d.%04d", x, y);
break;
case 5:
sprintf((char *)text, "%1d.%05d", x, y);
break;
}
break;
case 8:
switch (point)
{
case 0:
sprintf((char *)text, "%7d", x);
break;
case 1:
sprintf((char *)text, "%5d.%01d", x, y);
break;
case 2:
sprintf((char *)text, "%4d.%02d", x, y);
break;
case 3:
sprintf((char *)text, "%3d.%03d", x, y);
break;
case 4:
sprintf((char *)text, "%2d.%04d", x, y);
break;
case 5:
sprintf((char *)text, "%1d.%05d", x, y);
break;
case 6:
sprintf((char *)text, "%1d.%06d", x, y);
break;
}
break;
}
if ((x == 0)&&(k == true)) text[0] = '-';
}
void FloatColorOutIntXY(u8 Color, u16 x,u16 y, float Value, u16 Length, u16 Point)
{
u8 temp[10];
FloatToStr(Value, temp, Length, Point);
temp[Length] = 0x00;
ColorOutXY(Color, x, y, temp);
}
/* ¼Ò¼öÁ¡ = Point */
void FloatNormalOutIntXY(u16 x,u16 y, float Value, u16 Length, u16 Point)
{
u8 temp[10];
FloatToStr(Value, temp, Length, Point);
temp[Length] = 0x00;
GreenOutXY(x,y,temp);
}
void FloatRedOutIntXY(u16 x,u16 y, float Value, s16 Length, u16 Point)
{
u8 temp[10];
FloatToStr(Value, temp, Length, Point);
temp[Length] = 0x00;
RedOutXY(x, y, temp);
}
char digit2ascii(u8 t)
{
char k;
if (t < 10 ) k = '0' + (char)t;
else if( t == 10) k = 'A';
else if( t == 11) k = 'B';
else if( t == 12) k = 'C';
else if( t == 13) k = 'D';
else if( t == 14) k = 'E';
else if( t == 15) k = 'F';
return(k);
}
s16 ascii2digit(u8 t)
{
s16 k;
k = 0;
switch (t)
{
case '0' : k = 0; break;
case '1' : k = 1; break;
case '2' : k = 2; break;
case '3' : k = 3; break;
case '4' : k = 4; break;
case '5' : k = 5; break;
case '6' : k = 6; break;
case '7' : k = 7; break;
case '8' : k = 8; break;
case '9' : k = 9; break;
case 'a' :
case 'A' : k =10; break;
case 'b' :
case 'B' : k =11; break;
case 'c' :
case 'C' : k =12; break;
case 'd' :
case 'D' : k =13; break;
case 'e' :
case 'E' : k =14; break;
case 'f' :
case 'F' : k =15; break;
}
return(k);
}
void IntToStr(s16 ins, u8 *text, s16 size)
{
s16 i, one, two, a;
a = 1;
if (ins < 0)
{
one = -1* ins;
a = -1;
}
else
{
one = ins;
}
for(i = (size - 1); i >= 0; i--)
{
two = one / 10;
text[i] = one % 10 + '0';
one = two;
}
if (a < 0)
{
text[0] = '-';
}
}
void Int32ToStr(u32 ins, u8 *text, u16 size)
{
s16 i;
u32 one, two;
one = ins;
for(i = (size - 1); i >= 0; i--)
{
two = one / 10;
text[i] = one % 10 + '0';
one = two;
}
}
s16 StrToInt(u8 *text, u16 size)
{
s16 a = 1, i, k = 0;
for (i = (size -1); i >= 0; i--)
{
if (text[i] != '-')
{
k += (text[i] - '0') * a;
a *= 10;
}
else
{
k = -1 * k;
}
}
return(k);
}
u8 Str2ToHex(u8 *text, u16 size)
{
s16 a = 1, i, k = 0;
for (i = (size -1); i >= 0; i--)
{
if ((text[i] >= '0')&&(text[i] <= '9'))
{
k += (text[i] - '0') * a;
a *= 16;
}
else if ((text[i] >= 'A')&&(text[i] <= 'F'))
{
k += (text[i] - 'A' + 10) *a;
a *= 16;
}
else if ((text[i] >= 'a')&&(text[i] <= 'f'))
{
k += (text[i] - 'a' + 10) *a;
a *= 16;
}
}
return(k);
}
u32 strtohex(char *string, int size)
{
int i, sh;
u32 result = 0;
char *ptr = string;
for (i = 0; i < size; i++)
{
sh = (size - i - 1) * 4;
result += ascii2digit(ptr[i]) << sh;
}
return result;
}
u32 StrToInt32(u8 *text, u16 size)
{
s16 i;
u32 a = 1, k = 0;
for (i = (size -1); i >= 0; i--)
{
// if ((text[i] >= '0')&&(text[i] < '9'))
// {
k += (text[i] - '0') * a;
a *= 10;
// }
}
return(k);
}
void Int2Hex(u8 c, u8 *temp)
{
s16 a,b;
a = c / 16;
b = c % 16;
if (a > 9) {temp[0] = a + 'A' - 10;}
else{temp[0] = a + '0';}
if (b > 9) {temp[1] = b + 'A' - 10;}
else{temp[1] = b + '0';}
}
void IntOneHex(u8 c, u8 *temp)
{
if (c > 9) {temp[0] = c + 'A' - 10;}
else{temp[0] = c + '0';}
}
void LongToStr(u16 a, u16 b, u8 *temp)
{
u16 t;
u16 j;
for (j = 8 - b; j < 8; j++)
{
t = (a >> (28 - (4 * j))) & 0x0f;
temp[j] = digit2ascii(t);
}
temp[8] = ' ';
temp[9] = 0x00;
}
u8 str2bcd(u8 *a)
{
u8 i, j;
j = 0;
for (i = 0; i < 2; i++) {
if ((a[i] <= '9') && (a[i] >= '0')) j = j + (a[i] - '0');
if ((a[i] <= 'F') && (a[i] >= 'A')) j = j + (a[i] - 'A') + 10;
if ((a[i] <= 'f') && (a[i] >= 'a')) j = j + (a[i] - 'a') + 10;
if (i == 0) j <<= 4;
}
return j;
}
void bcdstr2(u8 in, u8 *out)
{
u8 i, j;
i = (in >> 4)& 0xF;
j = (in)& 0xF;
out[0] = i + '0';
out[1] = j + '0';
}
void StrToBCD(u8 *in, u8 *out, u16 size)
{
u16 i;
for (i = 0; i < size; i++)
{
out[i] = str2bcd(&in[i * 2]);
}
}
u8 Make_BCC(u8 *data, u16 len)
{
u16 i;
u8 bcc = 0;
for (i = 0; i < (len - 2); i++)
{
bcc ^= data[1 + i];
}
return bcc;
}
u8 MakeCheckSum(u8 *data, u8 size)
{
u8 i, sum;
sum = 0;
for (i = 4; i < (size - 2); i++)
{
sum += data[i];
}
return sum;
}
u16 StrToF2P(u8 *text, u16 size)
{
u16 i, j;
u8 temp[20];
u16 aParam[2];
u16 result;
i = 0;
j = FIND_CHAR((u8 *)&text[i], temp, size - i, '.');
i = i + j + 1;
aParam[0] = StrToInt(temp, j);
temp[j] = 0x00;
j = FIND_CHAR((u8 *)&text[i], temp, size - i, '.');
i = i + j + 1;
aParam[1] = StrToInt(temp, j);
temp[j] = 0x00;
switch (j)
{
case 0:
result = aParam[0] * 100;
break;
case 1:
result = ((aParam[0] * 10) + aParam[1]) * 10;
break;
case 2:
result = (aParam[0] * 100) + aParam[1];
break;
case 3:
result = ((aParam[0] * 1000) + aParam[1]) / 10;
break;
}
return result;
}
#endif // #ifdef CONSOLE_DEBUG
/****************** End of Asutil.c *********************/

116
APP/asutil.h Normal file
View File

@@ -0,0 +1,116 @@
/*****************************************************************************
*
* MSO Corporation
*
* File : asutil.h
* Compiler : IAR C 5.30C Kickstart
* Revision : $Revision: 1.0 $
* Date : $Date: 2010 / 7 / 16
* Updated by : $Author: Jongkwang Woo
*
* Support mail : spirit0305@naver.com
*
* Target platform : STM32F4 Cortex-M4 support
*
* AppNote : BPCB Application
*
* Description : Header file for asutil.c
*
****************************************************************************/
#ifndef _ASUTIL_H_
#define _ASUTIL_H_
#include <stm32f10x.h>
#pragma pack(1)
#define RX_PRINT 0
#define TX_PRINT 1
#define TCP_RX_PRINT 2
#define TCP_TX_PRINT 3
#define ACT 1
#define WAIT 0
#define High 1
#define Low 0
#define ON 1
#define OFF 0
#define SET 1
#define CLEAR 0
#define DISPLAY_NORMAL 0x00
#define DISPLAY_RED 0x01
#define DISPLAY_GREEN 0x02
#define DISPLAY_YELLOW 0x03
extern u8 *dump_addr;
/* find charater funcion ************************************************/
u8 FIND_CHAR(u8 *in, u8 *out, s16 max, u8 fdata);
u8 FIND_DATA(u8 *in, u8 *out, u16 max, u8 fdata, u16 count);
/************************************************************************/
char digit2ascii(u8 t);
s16 ascii2digit(u8 t);
u8 WaitUserCMD(u8 *cmd);
void UserMessage(char *str);
void ColorOutXY(u8 aColor, u16 x, u16 y, u8 *Text);
void RedOutXY(u16 x,u16 y, u8 *msg);
void GreenOutXY(u16 x,u16 y, u8 *msg);
void YellowOutXY(u16 x,u16 y, u8 *msg);
void NormalOutXY(u16 x,u16 y, u8 *msg);
void OutXY(u8 aRED, u16 x, u16 y, u8 *Text);
void FloatNormalOutIntXY(u16 x,u16 y, float Value, u16 Length, u16 Point);
void FloatRedOutIntXY(u16 x,u16 y, float Value, s16 Length, u16 Point);
void FloatColorOutIntXY(u8 Color, u16 x,u16 y, float Value, u16 Length, u16 Point);
void ClearConsol (void);
void DebugMessage(u8 *msg);
s16 StrToInt(u8 *text, u16 size);
u32 StrToInt32(u8 *text, u16 size);
void IntToStr(s16 ins, u8 *text, s16 size);
void Int32ToStr(u32 ins, u8 *text, u16 size);
void IntToHex(u16 ins, u8 *text, u8 size);
void Int2Hex(u8 c, u8 *temp);
void LongToStr(u16 a, u16 b, u8 *temp);
u8 Str2ToHex(u8 *text, u16 size);
void IntOneHex(u8 c, u8 *temp);
void Int32ToStrD(s32 ins, u8 *text, u16 size);
void FloatToStr(float ins, u8 *text, u16 size, u16 point);
u32 TextToAddr(u8 *data);
void dump_mem(u32 addr);
u8 str2bcd(u8 *a);
void StrToBCD(u8 *in, u8 *out, u16 size);
void StrToBCD2(u8 *in, u8 *out, u16 isize, u16 osize);
void Int32ToBCD(u32 in32, u8 *out, u16 osize);
void BCDToStr(u8 *in, u8 *out, u16 size);
u32 BCDToInt32(u8 *in, u16 size);
void data_print(u8 *data, u16 len);
void CAN_RX_DATA_PRINT(u16 port, CanRxMsg* buf);
void CAN_TX_DATA_PRINT(u16 port, CanTxMsg* buf);
void RTC_MEM_Dump(u16 page);
u8 Make_BCC(u8 *data, u16 len);
u8 MakeCheckSum(u8 *data, u8 size);
u16 reverse16(u16 data);
u32 reverse32(u32 data);
u32 strtohex(char *string, int size);
#pragma pack()
#endif

1665
APP/battery_comm-1.c Normal file

File diff suppressed because it is too large Load Diff

503
APP/battery_comm-1.h Normal file
View File

@@ -0,0 +1,503 @@
#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
} cv;
//! AUX Reg Voltage Data
typedef struct
{
uint16_t a_codes[9]; //!< 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
} 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
} 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;
} register_cfg;
typedef uint8_t bool;
typedef struct
{
ic_register config;
ic_register configb;
cv cells;
ax aux;
st stat;
ic_register com;
ic_register pwm;
ic_register pwmb;
ic_register sctrl;
ic_register sctrlb;
bool isospi_reverse;
pec_counter crc_count;
register_cfg ic_reg;
long system_open_wire;
} 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 total_ic , //!< 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 total_ic, //!< 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);
//! 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 LTC681x_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 LTC681x_pollAdc(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 total_ic, //!<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 current_ic,
uint8_t cell_reg,
uint8_t cell_data[],
uint16_t *cell_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 total_ic, //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 total_ic, //The number of ICs in the system
uint8_t *data //Array of the unparsed stat 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 total_ic, // 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 total_ic,//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 total_ic, //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 total_ic,
uint8_t reg,
cell_asic ic[]);
/*! Helper Function that resets the PEC error counters */
void LTC681x_reset_crc_count(uint8_t total_ic,
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],
bool dcc[12]);
/*! 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[],
bool dcc[]);
////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 total_ic, 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
void App_TaskBatt(void);
#endif

401
APP/battery_comm.c Normal file
View File

@@ -0,0 +1,401 @@
/**
******************************************************************************
* File Name : battery_comm.c
* Description : This file provides code for the configuration
* of CAN communication.
******************************************************************************
* @attention
*
* <h2><center>&copy; 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 "delay.h"
#include "spi.h"
#include "battery_comm.h"
/* Private define ------------------------------------------------------------*/
#define BATT_TASK_TIME 1000 // 10ms TASK
#define COMMAND_PLADC 0x0714
#define COMMAND_ADCV 0x0360 //0x0360
#define COMMAND_RDCVA 0x8004
#define COMMAND_RDCVB 0x8006
#define COMMAND_RDCVC 0x8008
#define COMMAND_RDCVD 0x80A0
#define COMMAND_RDCFG 0x8002
#define BLOCK_SIZE 4
#define LTC6813_MAX_IC_COUNT 2
#define LTC6813_COMM_BUF_SIZE (4 + (8 * LTC6813_MAX_IC_COUNT)) // 20 bytes
static uint8_t g_ltc_comm_buffer[LTC6813_COMM_BUF_SIZE];
#define LTC6813_CS PBout(12) // The chip select signals LTC6813 (LTC6820)
void send_wakeup_signal(void);
/**
* Set up and initialize the interface with the battery bottle.
*/
void init_battery_interface(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE); // GPIOB clock
//SPI_NSS - GPIOB12
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12; // GPIO Line
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; // GPIO Speed
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; // GPIO In/Out
GPIO_Init(GPIOB, &GPIO_InitStructure);
LTC6813_CS = 1; // SPI FLASH is not selected
SPI2_Init(); // Initialize the SPI
SPI2_SetSpeed(SPI_BaudRatePrescaler_2); // Set to 42M clock high-speed mode
send_wakeup_signal();
}
/**
* @brief Initialize the Ethernet Module communication application
* @param None
* @retval None
*/
void App_TaskBatt(void)
{
init_battery_interface();
while (DEF_TRUE)
{
send_wakeup_signal();
delay_os_ms(BATT_TASK_TIME);
}
}
/**
* Obtains the voltage value for battery cells in Cell Group A.
*
* \param[out] cells a pointer to an array of size 6. Destination buffer for
* the battery cell voltage values.
*/
void request_battery_voltage_A(uint16_t *cells)
{
request_battery_voltage(COMMAND_RDCVA, 0x77D6, cells);
}
/**
* Obtains the voltage value for battery cells in Cell Group B.
*
* \param[out] cells a pointer to an array of size 6. Destination buffer for
* the battery cell voltage values.
*/
void request_battery_voltage_B(uint16_t *cells)
{
request_battery_voltage(COMMAND_RDCVB, 0xEA80, cells);
}
/**
* Obtains the voltage value for battery cells in Cell Group C.
*
* \param[out] cells a pointer to an array of size 6. Destination buffer for
* the battery cell voltage values.
*/
void request_battery_voltage_C(uint16_t *cells)
{
request_battery_voltage(COMMAND_RDCVC, 0x2E46, cells);
}
/**
* Obtains the voltage value for battery cells in Cell Group D.
*
* \param[out] cells a pointer to an array of size 6. Destination buffer for
* the battery cell voltage values.
*/
void request_battery_voltage_D(uint16_t *cells)
{
request_battery_voltage(COMMAND_RDCVD, 0xB310, cells);
}
/**
* Obtains the voltage value the battery cells from the specified group.
*
* \param[in] cell_group the SPI command code for the battery cell group
* COMMAND_RDCVA (Cell Group A)
* COMMAND_RDCVB (Cell Group B)
* COMMAND_RDCVC (Cell Group C)
* COMMAND_RDCVD (Cell Group D)
* \param[out] cells a pointer to an array of size 6. Destination buffer for
* the battery cell voltage values.
*/
void request_battery_voltage(uint16_t cell_group, uint16_t pec, uint16_t *cells)
{
uint16_t txBuf[] = {0x03, 0x60, 0xF4, 0x6C};// = {cell_group, pec};
//uint16_t txBuf[] = {0x6C, 0xF4, 0x60, 0x03};
uint16_t txBuf2[] = {0x80, 0x04, 0x77, 0xD6};// = {COMMAND_ADCV, 0xF46C};
uint16_t rxBuf[13];
uint16_t rxBuf2[4];
//memset(txBuf, 0, sizeof(txBuf));
//memset(txBuf2, 0, sizeof(txBuf2));
memset(rxBuf, 0, sizeof(rxBuf));
memset(rxBuf2, 0, sizeof(rxBuf2));
send_wakeup_signal();
//txBuf[0] = COMMAND_ADCV;
//txBuf[1] = 0xF46C;
// spiSendData(spiREG2, &data_config, 4, txBuf);
LTC6813_CS = 0;
SPI2_ReadWriteByte(txBuf[0]);//Send the read ID command
SPI2_ReadWriteByte(txBuf[1]);
SPI2_ReadWriteByte(txBuf[2]);
SPI2_ReadWriteByte(txBuf[3]);
LTC6813_CS = 1;
delay_os_ms(5);
send_wakeup_signal();
// //txBuf2[0] = cell_group;
// //txBuf2[1] = pec;
// spiSendData(spiREG2, &data_config, 4, txBuf2);
// spiGetData(spiREG2, &data_config, 13, rxBuf);
// //spiSendAndGetData(spiREG2, &data_config, 12, txBuf2, rxBuf);
// //spiTransmitAndReceiveData(spiREG2, &data_config, 12, txBuf2, cells);
LTC6813_CS = 0;
SPI2_ReadWriteByte(txBuf2[0]); // Send the read ID command
SPI2_ReadWriteByte(txBuf2[1]);
SPI2_ReadWriteByte(txBuf2[2]);
SPI2_ReadWriteByte(txBuf2[3]);
// Temp|=SPI2_ReadWriteByte(0xFF)<<8;
// Temp|=SPI2_ReadWriteByte(0xFF);
LTC6813_CS = 1;
// printf("RX: ");
// for (i = 0; i < 13; i++) printf("%X ", rxBuf[i]);
// printf("\n");
}
/**
* Sends a dummy byte to the LTC6804 in order to wake up
* the SPI interface.
*/
void send_wakeup_signal(void)
{
uint16_t txBuf[] = {0x00};
LTC6813_CS = 0;
SPI2_ReadWriteByte(txBuf[0]);
LTC6813_CS = 1;
delay_os_ms(5); // 5ms
}
/*************************************** EX Function **********************************************/
void ltc6813_wrcfg(uint8_t total_ic, //The number of ICs being written to
uint8_t w_config[][6] //A two dimensional array of the configuration data that will be written
)
{
const uint8_t BYTES_IN_REG = 6;
const uint8_t CMD_LEN = 4 + (8 * total_ic);
uint8_t *cmd = g_ltc_comm_buffer;
uint16_t cfg_pec;
uint8_t cmd_index; //command counter
if (total_ic > 2) return;
//cmd[0] & cmd[1] for WRCFGA command
cmd[0] = 0x00;
cmd[1] = 0x01;
//cmd[2] & cmd[3] for PEC0 & PEC1 respectively
cmd[2] = 0x3d;
cmd[3] = 0x6e;
cmd_index = 4;
for (uint8_t current_ic = total_ic; current_ic > 0; current_ic--) // executes for each ltc6813 in daisy chain, this loops starts with
{
// the last IC on the stack. The first configuration written is
// received by the last IC in the daisy chain
for (uint8_t current_byte = 0; current_byte < BYTES_IN_REG; current_byte++) // executes for each of the 6 bytes in the CFGR register
{
// current_byte is the byte counter
cmd[cmd_index] = w_config[current_ic - 1][current_byte]; //adding the config data to the array to be sent
cmd_index = cmd_index + 1;
}
cfg_pec = (uint16_t)pec15_calc(BYTES_IN_REG, &w_config[current_ic - 1][0]); // calculating the PEC for each ICs configuration register data
cmd[cmd_index] = (uint8_t)(cfg_pec >> 8);
cmd[cmd_index + 1] = (uint8_t)cfg_pec;
cmd_index = cmd_index + 2;
}
spi_write_array(CMD_LEN, cmd);
}
//Write the ltc6813 configuration 2 register
void ltc6813_wrcfg2(uint8_t total_ic, //The number of ICs being written to
uint8_t w_config[][6] //A two dimensional array of the configuration data that will be written
)
{
const uint8_t BYTES_IN_REG = 6;
const uint8_t CMD_LEN = 4 + (8 * total_ic);
uint8_t *cmd = g_ltc_comm_buffer;
uint16_t cfg_pec;
uint16_t cmd_pec;
uint8_t cmd_index; //command counter
if (total_ic > 2) return;
cmd[0] = 0x00;
cmd[1] = 0x24;
cmd_pec = pec15_calc(2, cmd);
cmd[2] = (uint8_t)(cmd_pec >> 8);
cmd[3] = (uint8_t)(cmd_pec);
cmd_index = 4;
for (uint8_t current_ic = total_ic; current_ic > 0; current_ic--) // executes for each ltc6813 in daisy chain, this loops starts with
{
// the last IC on the stack. The first configuration written is
// received by the last IC in the daisy chain
for (uint8_t current_byte = 0; current_byte < BYTES_IN_REG; current_byte++) // executes for each of the 6 bytes in the CFGR register
{
// current_byte is the byte counter
cmd[cmd_index] = w_config[current_ic-1][current_byte]; //adding the config data to the array to be sent
cmd_index = cmd_index + 1;
}
cfg_pec = (uint16_t)pec15_calc(BYTES_IN_REG, &w_config[current_ic-1][0]); // calculating the PEC for each ICs configuration register data
cmd[cmd_index] = (uint8_t)(cfg_pec >> 8);
cmd[cmd_index + 1] = (uint8_t)cfg_pec;
cmd_index = cmd_index + 2;
}
spi_write_array(CMD_LEN, cmd);
}
//Reads configuration registers of a ltc6813 daisy chain
int8_t ltc6813_rdcfg(uint8_t total_ic, //Number of ICs in the system
uint8_t r_config[][8] //A two dimensional array that the function stores the read configuration data.
)
{
const uint8_t BYTES_IN_REG = 8;
uint8_t cmd[4];
uint8_t *rx_data = g_ltc_comm_buffer;
int8_t pec_error = 0;
uint16_t data_pec;
uint16_t received_pec;
if (total_ic > 2) return -1;
cmd[0] = 0x00;
cmd[1] = 0x02;
cmd[2] = 0x2b;
cmd[3] = 0x0A;
spi_write_read(cmd, 4, rx_data, (BYTES_IN_REG * total_ic)); //Read the configuration data of all ICs on the daisy chain into
//rx_data[] array
for (uint8_t current_ic = 0; current_ic < total_ic; current_ic++) //executes for each ltc6813 in the daisy chain and packs the data
{
//into the r_config array as well as check the received Config data
//for any bit errors
for (uint8_t current_byte = 0; current_byte < BYTES_IN_REG; current_byte++)
{
r_config[current_ic][current_byte] = rx_data[current_byte + (current_ic*BYTES_IN_REG)];
}
received_pec = (r_config[current_ic][6]<<8) + r_config[current_ic][7];
data_pec = pec15_calc(6, &r_config[current_ic][0]);
if (received_pec != data_pec)
{
pec_error = -1;
}
}
return(pec_error);
}
received_pec = (r_config[current_ic][6]<<8) + r_config[current_ic][7];
data_pec = pec15_calc(6, &r_config[current_ic][0]);
if (received_pec != data_pec)
{
pec_error = -1;
}
}
return(pec_error);
}
received_pec = (r_config[current_ic][6]<<8) + r_config[current_ic][7];
data_pec = pec15_calc(6, &r_config[current_ic][0]);
if (received_pec != data_pec)
{
pec_error = -1;
}
}
return(pec_error);
}
//Reads configuration 2 registers of a ltc6813 daisy chain
int8_t ltc6813_rdcfg2(uint8_t total_ic, //Number of ICs in the system
uint8_t r_config[][8] //A two dimensional array that the function stores the read configuration data.
)
{
const uint8_t BYTES_IN_REG = 8;
uint8_t cmd[4];
uint8_t *rx_data = g_ltc_comm_buffer;
int8_t pec_error = 0;
uint16_t data_pec;
uint16_t cmd_pec;
uint16_t received_pec;
if (total_ic > 2) return -1;
cmd[0] = 0x00;
cmd[1] = 0x26;
cmd_pec = pec15_calc(2, cmd);
cmd[2] = (uint8_t)(cmd_pec >> 8);
cmd[3] = (uint8_t)(cmd_pec);
spi_write_read(cmd, 4, rx_data, (BYTES_IN_REG*total_ic)); //Read the configuration data of all ICs on the daisy chain into
for (uint8_t current_ic = 0; current_ic < total_ic; current_ic++) //executes for each ltc6813 in the daisy chain and packs the data
{
//into the r_config array as well as check the received Config data
//for any bit errors
for (uint8_t current_byte = 0; current_byte < BYTES_IN_REG; current_byte++)
{
r_config[current_ic][current_byte] = rx_data[current_byte + (current_ic*BYTES_IN_REG)];
}
received_pec = (r_config[current_ic][6]<<8) + r_config[current_ic][7];
data_pec = pec15_calc(6, &r_config[current_ic][0]);
printf("\n\rreceived PEC = %d data PEC = %d",received_pec,data_pec);
if (received_pec != data_pec)
{
pec_error = -1;
}
}
return(pec_error);
}

39
APP/battery_comm.h Normal file
View File

@@ -0,0 +1,39 @@
/**
******************************************************************************
* @file battery_comm.h
* @author ESS Development Team
* @version V1.0.0
* @date 13/10/2019
* @brief This file contains all the functions prototypes for the battery_comm.c
* file.
******************************************************************************
* @copy
*
* THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS
* WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE
* TIME. AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY
* DIRECT, INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING
* FROM THE CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE
* CODING INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS.
*
* <h2><center>&copy; COPYRIGHT 2019 Amogreentech </center></h2>
*/
/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef BATTERY_COMM_H_
#define BATTERY_COMM_H_
/* Includes ------------------------------------------------------------------*/
#include <stm32f10x.h>
/* Public function prototypes -----------------------------------------------*/
void init_battery_interface(void);
void App_TaskBatt(void);
void request_battery_voltage_A(uint16_t *cells);
void request_battery_voltage_B(uint16_t *cells);
void request_battery_voltage_C(uint16_t *cells);
void request_battery_voltage_D(uint16_t *cells);
void request_battery_voltage(uint16_t cell_group, uint16_t pec, uint16_t *cells);
#endif /* BATTERY_COMM_H_ */

125
APP/brtc.c Normal file
View File

@@ -0,0 +1,125 @@
/**
******************************************************************************
* File Name : brtc.c
* Description : This file provides code for the configuration
* of board real time clock.
******************************************************************************
* @attention
*
* <h2><center>&copy; 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 "brtc.h"
#include "includes.h"
#include "app_ver.h"
#include "asutil.h"
#include "device_param.h"
#include "dflash_sf1.h"
#include "io.h"
#include "alarm.h"
#include "ltc6813_comm.h"
#include "task_manager.h"
/* Private typedef -----------------------------------------------------------*/
/* Private define ------------------------------------------------------------*/
#define RTC_TMR_PERIOD_TIME 10 // 10ms
#define WARMING_UP_TIME 5000 // 5sec
/* Private macro -------------------------------------------------------------*/
/* Private variables ---------------------------------------------------------*/
__IO uint32_t sub_sec = 0;
__IO uint32_t LocalTime = 0; /* this variable is used to create a time reference incremented by 10ms */
uint32_t WarmingUp = WARMING_UP_TIME;
OS_TMR RTC_TMR;
/* Private function prototypes -----------------------------------------------*/
/* Private functions ---------------------------------------------------------*/
void Init_RTC(void)
{
OS_ERR err;
OSTmrCreate (&RTC_TMR,
"RTC Timer",
100,
1,
OS_OPT_TMR_PERIODIC,
(OS_TMR_CALLBACK_PTR)&Time_Update,
NULL,
&err);
OSTmrStart (&RTC_TMR,
&err);
}
uint32_t GetWarmingUp(void)
{
return WarmingUp;
}
void WarmingUp_Process(u16 tick)
{
if (WarmingUp > tick)
{
WarmingUp -= tick;
}
else
{
device_status.battery_status.bit.INIT = true;
}
}
uint32_t GetLocalTime(void)
{
return LocalTime;
}
void SetLocalTime(uint32_t nTime)
{
LocalTime = nTime;
sub_sec = 0;
clear_cb_value();
}
void Time_Update(void *ptmr, void *parg)
{
sub_sec += RTC_TMR_PERIOD_TIME;
if (sub_sec >= 1000)
{
LocalTime++;
sub_sec = 0;
}
WarmingUp_Process(RTC_TMR_PERIOD_TIME);
DecIOTaskTick(RTC_TMR_PERIOD_TIME);
dec_alarm_tick(RTC_TMR_PERIOD_TIME);
dec_cb_tick(RTC_TMR_PERIOD_TIME);
inc_afe_bufftime(RTC_TMR_PERIOD_TIME);
#ifdef CONSOLE_DEBUG
CalOSTaskCtxSwCtrPerSec(RTC_TMR_PERIOD_TIME);
#endif // #ifdef CONSOLE_DEBUG
IWDG_ReloadCounter();
}
/* Display Function *************************************************/
#ifdef CONSOLE_DEBUG
#endif // #ifdef CONSOLE_DEBUG

28
APP/brtc.h Normal file
View File

@@ -0,0 +1,28 @@
/*****************************************************************************
*
* MSO Corporation
*
* File : rtc.h
* Compiler : IAR C 5.30C Kickstart
* Revision : $Revision: 1.0 $
* Date : $Date: 2010 / 7 / 16
* Updated by : $Author: Jongkwang Woo
*
* Support mail : spirit0305@naver.com
*
* Description : Header file for rtc.c
*
****************************************************************************/
#ifndef _BRTC_H_
#define _BRTC_H_
#include <stm32f10x.h>
void Init_RTC(void);
void Time_Update(void *ptmr, void *parg);
uint32_t GetLocalTime(void);
void SetLocalTime(uint32_t nTime);
#endif

289
APP/can_comm.c Normal file
View File

@@ -0,0 +1,289 @@
/**
******************************************************************************
* File Name : can_comm.c
* Description : This file provides code for the configuration
* of CAN communication.
******************************************************************************
* @attention
*
* <h2><center>&copy; 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 "can.h"
#include "can_comm.h"
#include "can_data_process.h"
#include "can_inv_data_process.h"
#include "can_update_process.h"
#include "console.h"
#include "asutil.h"
#include "delay.h"
#include "device_param.h"
#include "brtc.h"
/* Private define ------------------------------------------------------------*/
#define CAN_TASK_TIME 1 // 20ms TASK
#define CAN_RX_TIMEOUT 500 // 500ms TimeOut
#define CAN_RX_DELAY 5
#define CAN_TX_DELAY 50
#define CAN_MAX_TIMEOUT 20
#define CAN_MAX_BUFFER_SIZE 512
/* Private typedef -----------------------------------------------------------*/
typedef struct
{
CanRxMsg Buffer;
u16 Tick;
u8 Current_ID;
u8 Mode;
u8 TxFlag;
u8 TxDetail;
u8 RxFlag;
u8 MsgPrint;
u8 DataPrint;
u8 BakMsgPrint;
u8 BakDataPrint;
} TCanConfig, *PCanConfig;
typedef struct _TCanCommState
{
u32 Tick;
u16 Timeout;
u8 Commfail;
u8 Init;
} TCanCommState, *PCanCommState;
/* Private macro -------------------------------------------------------------*/
/* Private variables ---------------------------------------------------------*/
TCanConfig CanConfig;
TCanCommState CanCommState;
CanRxMsg RxBuffer;
u8 CanBuzzerHold = false;
u8 CanParamSet = false;
u32 OldHeatbeat;
u32 curHsiTrimValue = 0x10;
u32 disHsiTrimValue;
extern uint32_t can_speed;
/* Private function prototypes -----------------------------------------------*/
void CanCommProcess(void);
void CanCommFailCheck(void);
void CanCommFailClear(void);
void CanSendData(void *data, u16 len);
void CanPacketInit(void);
u8 GetCanPacket(void);
void CanRxProcess(void);
void CanTxProcess(void);
void CanTxInitReqModule(void);
void CanTxParamReqModule(void);
void CanTxStatusPolling(u8 *aCmd);
void SendPacket(u32 SendId, u8 *data);
/* Private functions ---------------------------------------------------------*/
extern u8 FwData[];
extern u16 HostBalancingVoltage;
extern u16 HostBalancingVoltageDiff;
void CanCommInit(void)
{
switch (device_param.info.CanSpped) {
case 0: can_speed = 500000; break;
case 1: can_speed = 250000; break;
default: can_speed = 500000; break;
}
can1_init(can_speed);
memset(&CanConfig, 0x00, sizeof(TCanConfig));
memset(&CanCommState, 0x00, sizeof(TCanCommState));
CanCommState.Timeout = 500;
OldHeatbeat = device_value.Heartbeat;
}
/**
* @brief Initialize the Ethernet Module communication application
* @param None
* @retval None
*/
void App_TaskCanComm(void)
{
CanCommInit();
while (DEF_TRUE)
{
CanCommProcess();
delay_os_ms(CAN_TASK_TIME);
}
}
void CanCommProcess(void)
{
if (GetCanPacket() == SUCCESS)
{
CanRxProcess();
}
else
{
u32 aEsr = CAN1->ESR;
if ((aEsr & 0x0000000F) != 0x00)
can1_init(250000);
CanCommFailCheck();
delay_os_ms(5);
}
}
void CanRxProcess(void)
{
#ifdef CONSOLE_DEBUG
if ((CanConfig.MsgPrint == true)&&(screenmode == DIAG_MODE))
CAN_RX_DATA_PRINT(1, &RxBuffer);
#endif
switch (CheckCanPacket(&RxBuffer))
{
case 1: // F/W Update Packet
FwUpdateProcess(&RxBuffer);
break;
case 2: // Normal Comm. Packet
CanCommFailClear();
CanRxDataProcess(&RxBuffer);
break;
case 3: // Inventory Data Packet
CanRxInvDataProcess(&RxBuffer);
break;
}
}
void CanCommFailClear(void)
{
CanCommState.Commfail = false;
CanCommState.Tick = 0;
}
void CanCommFailCheck(void)
{
CanCommState.Tick++;
if (CanCommState.Tick > CanCommState.Timeout)
{
CanCommState.Tick = CanCommState.Timeout;
CanCommState.Commfail = true;
HostBalancingVoltage = 0;
HostBalancingVoltageDiff = 0;
}
}
void SendPacket(u32 SendId, u8 *data)
{
CanTxMsg sendobj;
sendobj.StdId = 0x0;
sendobj.ExtId = SendId;
sendobj.RTR = CAN_RTR_DATA;
sendobj.IDE = CAN_ID_EXT;
sendobj.DLC = 8;// data size
for (int i = 0; i < 8; i++)
{
sendobj.Data[i] = data[i];
}
CAN_SendPacket(&sendobj);
#ifdef CONSOLE_DEBUG
if ((CanConfig.DataPrint == true)&&(screenmode == DIAG_MODE))
CAN_TX_DATA_PRINT(1, &sendobj);
#endif
}
u8 GetCanPacket(void)
{
if (CAN_GetPacket(&RxBuffer) == SUCCESS)
return SUCCESS;
else
return ERROR;
}
#ifdef CONSOLE_DEBUG
void DDisplay_CanComm(u8 p)
{
if (p ||(CanConfig.BakMsgPrint != CanConfig.MsgPrint))
{
if (CanConfig.MsgPrint) GreenOutXY ( 27, 8, (u8 *)"ENABLE ");
else NormalOutXY( 27, 8, (u8 *)"DISABLE");
CanConfig.BakMsgPrint = CanConfig.MsgPrint;
}
if (p ||(CanConfig.BakDataPrint != CanConfig.DataPrint))
{
if (CanConfig.DataPrint)GreenOutXY ( 71, 8, (u8 *)"ENABLE ");
else NormalOutXY( 71, 8, (u8 *)"DISABLE");
CanConfig.BakDataPrint = CanConfig.DataPrint;
}
}
u8 DCanCommCommand(u8 cmd)
{
u8 result = 1;
switch (cmd)
{
case '2':
// CAN COMM MSG MONITOR
if (CanConfig.MsgPrint == true)
{
CanConfig.MsgPrint = false;
UserMessage("[MESSAGE]: CAN MSG PRINT DISABLE");
}
else
{
CanConfig.MsgPrint = true;
UserMessage("[MESSAGE]: CAN MSG PRINT ENABLE");
}
break;
case '3':
// CAN COMM DATA MONITOR
if (CanConfig.DataPrint == true)
{
CanConfig.DataPrint = false;
UserMessage("[MESSAGE]: CAN DATA PRINT DISABLE");
}
else
{
CanConfig.DataPrint = true;
UserMessage("[MESSAGE]: CAN DATA PRINT ENABLE");
}
break;
default:
result = 0;
break;
}
return result;
}
#endif // #ifdef CONSOLE_DEBUG
/******************* (C) COPYRIGHT 2015 STMicroelectronics *****END OF FILE****/

52
APP/can_comm.h Normal file
View File

@@ -0,0 +1,52 @@
/**
******************************************************************************
* @file can_comm.h
* @author MCD Application Team
* @version V1.0.0
* @date 05/12/2011
* @brief This file contains all the functions prototypes for the bscu_comm.c
* file.
******************************************************************************
* @copy
*
* THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS
* WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE
* TIME. AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY
* DIRECT, INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING
* FROM THE CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE
* CODING INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS.
*
* <h2><center>&copy; COPYRIGHT 2009 STMicroelectronics</center></h2>
*/
/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef _CAN_COMM_H_
#define _CAN_COMM_H_
/* Includes ------------------------------------------------------------------*/
#include <stm32f10x.h>
void App_TaskCanComm(void);
void App_TaskCanTxComm(void);
void SendPacket(u32 SendId, u8 *data);
void ODisplay_HsiCalValue(u8 p);
void DDisplay_CanComm(u8 p);
u8 DCanCommCommand(u8 cmd);
u8 GetCanCommState(void);
void CanBuzzerHoldCmd(void);
void CanParamSetCmd(void);
void CanParamSetReqLCD(void);
void CurrentNetInfoCmd(void);
u8 MakeCanParamSet(s16 id, s16 raddr, s16 rsize, s16 *rdata);
#endif
/******************* (C) COPYRIGHT 2009 STMicroelectronics *****END OF FILE****/

1200
APP/can_data_process.c Normal file

File diff suppressed because it is too large Load Diff

55
APP/can_data_process.h Normal file
View File

@@ -0,0 +1,55 @@
/*****************************************************************************
*
* File : can_data_process.h
* Compiler : IAR C 5.10C Kickstart
* Revision : $Revision: 1.0 $
* Date : $Date: 2019 / 06 / 25
* Updated by : $Author: JK.Woo
*
* Support mail : spirit0305@naver.com
*
* Description : Header file for can_data_process.c
*
****************************************************************************/
#ifndef _CAN_DATA_PROCESS_H_
#define _CAN_DATA_PROCESS_H_
#include <stm32f10x.h>
typedef union
{
uint32_t LV;
struct
{
u32 SA : 8;
u32 PS : 8;
u32 PF : 8;
u32 DP : 1;
u32 R : 1;
u32 Index : 3;
u32 Rsvd : 3;
} BV;
} TCanHeader, *PCanHeader;
typedef union
{
uint32_t LV;
struct
{
uint32_t DID : 7; // Destination ID
uint32_t SID : 7; // Source ID
uint32_t NO : 8; // Number
uint32_t FC : 4; // Function Code
uint32_t PR : 3; // Priority
uint32_t Rsvd : 3;
} BV;
} TCanDLHeader, *PCanDLHeader;
u8 CheckCanAddr(u8 DstAddr);
u32 MakeCanTxExtId(u8 cmd, u8 flag);
s16 CheckCanPacket(CanRxMsg *data);
s16 CanRxDataProcess(CanRxMsg *data);
#endif

166
APP/can_inv_data_process.c Normal file
View File

@@ -0,0 +1,166 @@
/**
******************************************************************************
* File Name : can_inv_data_process.c
* Description : This file provides code for inventory data
* of CAN communication.
******************************************************************************
* @attention
*
* <h2><center>&copy; Copyright (c) 2020 Amogreentech Co., Ltd.
* All rights reserved.</center></h2>
*
******************************************************************************
*/
/* Includes ------------------------------------------------------------------*/
#include <includes.h>
#include "can.h"
#include "can_comm.h"
#include "can_data_process.h"
#include "can_inv_data_process.h"
#include "app_ver.h"
#include "io.h"
#include "console.h"
#include "asutil.h"
#include "delay.h"
#include "device_param.h"
#include "brtc.h"
#include "dflash_cal.h"
#include "ltc6813_comm.h"
/* Define --------------------------------------------------------------------*/
// Function Code Define
// Request Code
#define CAN_REQ_SET_MANUFACTURE_DATE_CODE 1 // Must be get value and status
#define CAN_REQ_SET_SERIAL_NO1_CODE 2
#define CAN_REQ_SET_SERIAL_NO2_CODE 3
// Response Code
#define CAN_RSP_SET_MANUFACTURE_DATE_CODE 11
#define CAN_RSP_SET_SERIAL_NO1_CODE 21
#define CAN_RSP_SET_SERIAL_NO2_CODE 31
/* Private typedef -----------------------------------------------------------*/
/* Private functions prototypes ----------------------------------------------*/
void CanRspManufactureDateCode(CanRxMsg *data); // CAN_REQ_SET_MANUFACTURE_DATE_CODE
void CanRspSerialNoCode(CanRxMsg *data, u8 type); // CAN_REQ_SET_SERIAL_NOx_CODE
/* External variables --------------------------------------------------------*/
/* Private functions ---------------------------------------------------------*/
s16 CanRxInvDataProcess(CanRxMsg *data)
{
u8 dno = 0;
PCanHeader CanHeader;
CanHeader = (PCanHeader)(&data->ExtId);
dno = CheckCanAddr(CanHeader->BV.PS);
if (device_status.battery_status.bit.INIT == false)
return 0;
if (dno != GetDevAddr())
{
printf("\r\n DNO = %d, %d(%d)", dno, GetDevAddr(), CanHeader->BV.PF);
return 0;
}
switch (CanHeader->BV.PF)
{
case CAN_REQ_SET_MANUFACTURE_DATE_CODE: // Manufacuture Date
CanRspManufactureDateCode(data);
break;
case CAN_REQ_SET_SERIAL_NO1_CODE: // Serial No1
CanRspSerialNoCode(data, 0);
break;
case CAN_REQ_SET_SERIAL_NO2_CODE: // Serial No2
CanRspSerialNoCode(data, 1);
break;
}
return (dno);
}
void CanRspManufactureDateCode(CanRxMsg *data) // CAN_REQ_STATUS_CODE
{
u32 RspId, i;
u32 mDate = 0;
u8 RspData[8];
if (data->Data[7] == 0x01)
{
// ManufactureDate
mDate = (u32)((data->Data[0] << 24)
| (data->Data[1] << 16)
| (data->Data[2] << 8)
| (data->Data[3] << 0)
);
device_inv.ManufactureDate = mDate;
Save_Param();
Load_Param();
}
RspId = MakeCanTxExtId(CAN_RSP_SET_MANUFACTURE_DATE_CODE, 2);
memset(RspData, 0x00, sizeof(RspData));
i = 0;
RspData[i] = (u8)(device_inv.ManufactureDate >> 24); i++;
RspData[i] = (u8)(device_inv.ManufactureDate >> 16); i++;
RspData[i] = (u8)(device_inv.ManufactureDate >> 8); i++;
RspData[i] = (u8)(device_inv.ManufactureDate >> 0); i++;
i++;
i++;
i++;
RspData[i] = 1; i++;
SendPacket(RspId, RspData);
}
void CanRspSerialNoCode(CanRxMsg *data, u8 type) // CAN_REQ_SET_SERIAL_NOx_CODE
{
u32 RspId, sField;
u8 RspData[8];
if (data->Data[0] != 0xFF)
{
if (type == 0)
{
// Serial No 1
sField = 0;
for (int i = 0; i < 8; i++)
{
device_inv.SerialNo[sField + i] = data->Data[i];
}
}
else
{
// Serial No 2
sField = 8;
for (int i = 0; i < 8; i++)
{
device_inv.SerialNo[sField + i] = data->Data[i];
}
Save_Param();
}
}
if (type == 0)
RspId = MakeCanTxExtId(CAN_RSP_SET_SERIAL_NO1_CODE, 2);
else
RspId = MakeCanTxExtId(CAN_RSP_SET_SERIAL_NO2_CODE, 2);
memset(RspData, 0x00, sizeof(RspData));
for (int i = 0; i < 8; i++)
{
RspData[i] = device_inv.SerialNo[(type * 8) + i];
}
SendPacket(RspId, RspData);
}
/************************************** Data End **************************************/

View File

@@ -0,0 +1,33 @@
/**
******************************************************************************
* File Name : can_inv_data_process.c
* Description : This file provides code for the inventory data by CAN
******************************************************************************
* @attention
*
* <h2><center>&copy; Copyright (c) 2020 Amogreentech Co., Ltd.
* All rights reserved.</center></h2>
*
******************************************************************************
*/
/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef _CAN_INV_DATA_PROCESS_H_
#define _CAN_INV_DATA_PROCESS_H_
#ifdef __cplusplus
extern "C" {
#endif
/* Includes ------------------------------------------------------------------*/
#include <stm32f10x.h>
/* Public defines */
/* Public Prototypes */
s16 CanRxInvDataProcess(CanRxMsg *data);
#ifdef __cplusplus
}
#endif
#endif /* _CAN_INV_DATA_PROCESS_H_ */

404
APP/can_update_process.c Normal file
View File

@@ -0,0 +1,404 @@
/**
******************************************************************************
* File Name : can_update_process.c
* Description : This file provides code for the configuration
* of Firmware update by CAN communication.
******************************************************************************
* @attention
*
* <h2><center>&copy; 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 "can.h"
#include "can_comm.h"
#include "can_data_process.h"
#include "console.h"
#include "asutil.h"
#include "device_param.h"
#include "flash_if.h"
#include "delay.h"
#include "io.h"
/* Define --------------------------------------------------------------------*/
#define CAN_MASTER_ADDR 0
// Function Code Define
#define DL_START_CODE 0 // Update Start Code
#define DL_SECTOR_ERASE_CODE 1 // Sector Erase Code
#define DL_SET_ADDRESS_CODE 2 // Flash Address Set Code
#define DL_READ_DATA_CODE 3 // Flash Data Read Code
#define DL_WRITE_DATA_CODE 4 // Flash Data Write Code
#define DL_WRITE_DATA_CSUM_CODE 5 // Flash Data Write Check Sum Code
#define DL_IMAGE_CSUM_CODE 6 // Flash Data Write Check Sum Code
#define DL_RESTART_CODE 7 // Restart
/* Private typedef -----------------------------------------------------------*/
typedef struct
{
uint32_t Flag;
uint32_t StratAddr;
uint32_t FileSize;
uint32_t WriteAddr;
uint32_t WriteLength;
uint32_t CurrentAddr;
uint32_t CurrentNumber;
uint32_t CheckSum32;
} TCanDLInfor, *PCanDLInfor;
TCanDLInfor CanDLInfor;
u8 FwData[2048];
/* Private functions ---------------------------------------------------------*/
void RspPacket(PCanDLHeader rhdr, u8 no, u8 *data);
uint32_t FwUpdateStartByCan(CanRxMsg *packet);
uint32_t SectorEraseProcessByCan(CanRxMsg *packet);
uint32_t WriteAddressSetByCan(CanRxMsg *packet);
uint32_t WriteDataByCan(CanRxMsg *packet);
uint32_t WriteDataChkSumByCan(CanRxMsg *packet);
uint32_t FwImageChkSumByCan(CanRxMsg *packet);
uint32_t UpdateRestartByCan(CanRxMsg *packet);
/**
* @brief Firmware Update Process
* @param CAN Message
* @retval Result
*/
s16 FwUpdateProcess(CanRxMsg *data)
{
u16 dno = 0;
s16 result = false;
PCanDLHeader CanHeader;
CanHeader = (PCanDLHeader)(&data->ExtId);
dno = CanHeader->BV.DID;
if (dno != GetDevAddr())
{
return 0;
}
switch (CanHeader->BV.FC)
{
case DL_START_CODE: // Firmware update start
result = FwUpdateStartByCan(data);
break;
case DL_SECTOR_ERASE_CODE: // Sector Erase
result = SectorEraseProcessByCan(data);
break;
case DL_SET_ADDRESS_CODE: // Set Write Address and Length
result = WriteAddressSetByCan(data);
break;
case DL_WRITE_DATA_CODE: // Write data
result = WriteDataByCan(data);
break;
case DL_WRITE_DATA_CSUM_CODE: // Check packet checksum
result = WriteDataChkSumByCan(data);
break;
case DL_IMAGE_CSUM_CODE: // Check firmware image checksum
result = FwImageChkSumByCan(data);
break;
case DL_RESTART_CODE: // Restart option
result = UpdateRestartByCan(data);
break;
}
return result;
}
uint32_t FwUpdateStartByCan(CanRxMsg *packet)
{
uint32_t result = 0;
uint8_t sdata[8];
uint32_t flen;
flen = (uint32_t)((packet->Data[4] << 24)
| (packet->Data[5] << 16)
| (packet->Data[6] << 8)
| (packet->Data[7] << 0)
);
// printf("\r\nStart Fw Update : V%d.%d.%d.%d, %d bytes"
// , packet->Data[0]
// , packet->Data[1]
// , packet->Data[2]
// , packet->Data[3]
// , flen);
if (flen <= mBMS_FW_MAX_SIZE)
{
fwinfo.AppVer[0] = packet->Data[0];
fwinfo.AppVer[1] = packet->Data[1];
fwinfo.AppVer[2] = packet->Data[2];
fwinfo.AppVer[3] = packet->Data[3];
fwinfo.AppFileSize = flen;
fwinfo.AppUpdate = 1;
}
else
result = 2;
for (int i = 0; i < 8; i++)
{
sdata[i] = 0x00;
}
sdata[7] = result;
RspPacket((PCanDLHeader)(&packet->ExtId), 0, sdata);
return result;
}
uint32_t SectorEraseProcessByCan(CanRxMsg *packet)
{
uint32_t result = 0;
uint8_t sdata[8];
uint32_t sector_addr;
if ((fwinfo.AppUpdate == 1) ||(fwinfo.AppUpdate == 2))
{
sector_addr = (uint32_t)((packet->Data[0] << 24)
| (packet->Data[1] << 16)
| (packet->Data[2] << 8)
| (packet->Data[3] << 0));
// printf("\r\nsector_addr = 0x%08X", sector_addr);
if ((sector_addr >= mBMS_FW_ADDRESS) && (sector_addr <= mBMS_FW_END_ADDRESS))
{
if (fwinfo.AppFileSize <= 0xC000)
{
FLASH_If_Erase(sector_addr, fwinfo.AppFileSize);
if (result == 0)
fwinfo.AppUpdate = 2;
}
else
result = 3;
}
else
result = 2;
}
else
result = 9;
for (int i = 0; i < 8; i++)
{
sdata[i] = packet->Data[i];
}
sdata[7] = result;
RspPacket((PCanDLHeader)(&packet->ExtId), 0, sdata);
return result;
}
uint32_t WriteAddressSetByCan(CanRxMsg *packet)
{
uint32_t result = 0;
uint8_t sdata[8];
uint32_t waddr, wlen;
waddr = (uint32_t)((packet->Data[0] << 24)
| (packet->Data[1] << 16)
| (packet->Data[2] << 8)
| (packet->Data[3] << 0));
wlen = (uint32_t)((packet->Data[4] << 24)
| (packet->Data[5] << 16)
| (packet->Data[6] << 8)
| (packet->Data[7] << 0));
if ((waddr >= mBMS_FW_ADDRESS) && (waddr < mBMS_FW_END_ADDRESS))
{
// printf("\r\nwrite_data = 0x%08X (%d bytes)", waddr, wlen);
if ((wlen > 0) && (wlen <= 256))
{
CanDLInfor.WriteAddr = waddr;
CanDLInfor.WriteLength = wlen;
}
else
result = 2;
}
else
result = 1;
for (int i = 0; i < 8; i++)
{
sdata[i] = 0x00;
}
sdata[7] = result;
RspPacket((PCanDLHeader)(&packet->ExtId), 0, sdata);
return result;
}
uint32_t WriteDataByCan(CanRxMsg *packet)
{
uint32_t result = 0;
PCanDLHeader CanHeader;
CanHeader = (PCanDLHeader)(&packet->ExtId);
uint32_t base = CanDLInfor.WriteAddr + (CanHeader->BV.NO * 8);
result = FLASH_If_Write(&base, (uint32_t*)packet->Data, 8 / 4);
return result;
}
uint32_t WriteDataChkSumByCan(CanRxMsg *packet)
{
uint32_t result = 0;
uint8_t sdata[8] = {0};
uint32_t waddr = 0;
uint32_t rsum, csum = 0;
int len = CanDLInfor.WriteLength * 8;
for (int i = 0; i < len; i++)
{
// csum += FwData[i];
csum += *(uint8_t *)(CanDLInfor.WriteAddr + i);
}
waddr = (uint32_t)((packet->Data[0] << 24)
| (packet->Data[1] << 16)
| (packet->Data[2] << 8)
| (packet->Data[3] << 0)
);
rsum = (uint32_t)((packet->Data[4] << 24)
| (packet->Data[5] << 16)
| (packet->Data[6] << 8)
| (packet->Data[7] << 0)
);
// printf("\r\nWriteDataChkSumByCan: 0x%08X, 0x%08X (0x%08X) 0x%08X (%d)", csum, rsum, waddr, CanDLInfor.WriteAddr, len);
if (csum == rsum)
{
if ((waddr >= mBMS_FW_ADDRESS) && (waddr <= (mBMS_FW_END_ADDRESS - 0x800)))
{
if (CanDLInfor.WriteAddr == waddr)
waddr += len;
else
result = 3;
}
else
{
result = 4;
}
}
else
{
result = 5;
}
sdata[0] = (uint8_t)(waddr >> 24);
sdata[1] = (uint8_t)(waddr >> 16);
sdata[2] = (uint8_t)(waddr >> 8);
sdata[3] = (uint8_t)(waddr >> 0);
sdata[7] = result;
RspPacket((PCanDLHeader)(&packet->ExtId), 0, sdata);
return result;
}
uint32_t FwImageChkSumByCan(CanRxMsg *packet)
{
uint32_t result = 0;
uint8_t sdata[8] = {0};
uint32_t rsize = 0;
uint32_t rsum, csum = 0;
uint8_t *base = (uint8_t *)mBMS_FW_ADDRESS;
int len = fwinfo.AppFileSize;
rsize = (uint32_t)((packet->Data[0] << 24)
| (packet->Data[1] << 16)
| (packet->Data[2] << 8)
| (packet->Data[3] << 0)
);
rsum = (uint32_t)((packet->Data[4] << 24)
| (packet->Data[5] << 16)
| (packet->Data[6] << 8)
| (packet->Data[7] << 0)
);
if (rsize == len)
{
for (int i = 0; i < len; i++)
csum += base[i];
if (csum == rsum)
fwinfo.AppUpdate = 3;
else
result = 2;
}
else
result = 1;
sdata[7] = result;
RspPacket((PCanDLHeader)(&packet->ExtId), 0, sdata);
return result;
}
uint32_t UpdateRestartByCan(CanRxMsg *packet)
{
uint32_t result = 0;
uint8_t sdata[8] = {0};
uint32_t reset = 0;
switch (packet->Data[0])
{
case 0:
break;
case 1:
reset = 1;
break;
case 2:
break;
case 3:
fwinfo.AppUpdate = 9;
SaveFwInfo();
reset = 1;
break;
}
sdata[7] = result;
RspPacket((PCanDLHeader)(&packet->ExtId), 0, sdata);
if (reset)
{
delay_os_ms(1000);
Sys_Soft_Reset();
}
return result;
}
void RspPacket(PCanDLHeader rhdr, u8 no, u8 *data)
{
TCanDLHeader shdr;
shdr.BV.PR = 4;
shdr.BV.FC = rhdr->BV.FC;
shdr.BV.NO = no;
shdr.BV.SID = rhdr->BV.DID;
shdr.BV.DID = rhdr->BV.SID;
SendPacket(shdr.LV, data);
}
/************************************** TX Data End **************************************/

22
APP/can_update_process.h Normal file
View File

@@ -0,0 +1,22 @@
/*****************************************************************************
*
* File : can_update_process.h
* Compiler : IAR C 5.10C Kickstart
* Revision : $Revision: 1.0 $
* Date : $Date: 2019 / 06 / 25
* Updated by : $Author: JK.Woo
*
* Support mail : spirit0305@naver.com
*
* Description : Header file for can_update_process.c
*
****************************************************************************/
#ifndef _CAN_UPDATE_PROCESS_H_
#define _CAN_UPDATE_PROCESS_H_
#include <stm32f10x.h>
s16 FwUpdateProcess(CanRxMsg *data);
#endif

539
APP/console.c Normal file
View File

@@ -0,0 +1,539 @@
/**
******************************************************************************
* File Name : console.c
* Description : This file provides code for the configuration
* of debug console.
******************************************************************************
* @attention
*
* <h2><center>&copy; 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 ------------------------------------------------------------------*/
#ifdef CONSOLE_DEBUG
#include "screen.h"
#endif
#include "includes.h"
#include "console.h"
#include "delay.h"
#include "app_ver.h"
#include "usart.h"
#include "asutil.h"
#include "display_status.h"
#include "dflash_sf1.h"
#include "dflash_sbs.h"
#include "can_comm.h"
#include "ltc6813_comm.h"
#include "device_param.h"
#include "io.h"
#include "task_manager.h"
#include "can.h"
#include "brtc.h"
#include "temp.h"
/* Private typedef -----------------------------------------------------------*/
/* Private define ------------------------------------------------------------*/
/* Private macro -------------------------------------------------------------*/
/* Private variables ---------------------------------------------------------*/
s8 screenmode;
u8 position;
u32 BakOSCtxSwCtr; /* Counter of number of context switches */
u32 BakLocalTime; /* this variable is used to create a time reference incremented by 10ms */
u8 console_text[128];
u8 display_text[81];
/* Private prototype functions -----------------------------------------------*/
void DebugConsole(void);
void Console(u8 *one);
void Prompt(void);
s8 Process_Data(u8 *text, u16 size);
s8 Process_DataSet(u8 *text, u16 size);
s8 Process_CurrentDataSet(u8 *text, u16 size);
s8 Process_DataDiagnostic(u8 *text, u16 size);
s8 Process_DataNetSet(u8 *text, u16 size);
s8 Process_OSStatus(u8 *text, u16 size);
s8 Process_Inventory_Data(u8 *text, u16 size);
s8 Process_DataChgCtrlCfgSet(u8 *text, u16 size);
extern void ff_process(void);
void Console_Initial(void)
{
position = 0;
screenmode = OP_MODE;
}
void AppTaskDebug(void)
{
Init_RTC();
Load_Param();
ADC_Param_Load();
#ifdef CONSOLE_DEBUG
Console_Initial();
#endif
while (DEF_TRUE)
{
#ifdef CONSOLE_DEBUG
DebugConsole();
#endif
device_value.Heartbeat = GetLocalTime();
/* Reload IWDG counter */
IWDG_ReloadCounter();
delay_os_ms(1);
}
}
#ifdef CONSOLE_DEBUG
u16 debug_recv_data(u8 *data)
{
u16 len = 0;
if (UART1_GetChar(data) == SUCCESS) len = 1;
return len;
}
void DebugConsole(void)
{
u8 one[20];
u16 i, len;
len = debug_recv_data(one);
for (i = 0; i < len; i++)
Console(&one[i]);
DisplayScreen(false);
}
void Console(u8 *one)
{
u8 i, ok;
ok = 0;
switch (one[0])
{
case 0x0d: /* ENTER(CR)값 */
if (position == 0)
{
ViewScreen();
Prompt(); /* Prompt 출력 */
position = 0;
for (i = 0; i < 80; i++) console_text[i] = 0x00;
break;
}
switch (screenmode)
{
case OP_MODE: /* operating state */
ok = Process_Data(console_text, position);
if (!ok) {UserMessage(" [Invalid Command]");}
break;
case SET_MODE: /* setting state */
ok = Process_DataSet(console_text, position);
if (!ok) {UserMessage(" [Invalid Command]");}
break;
case OS_STATUS_MODE: /* OS Status */
ok = Process_OSStatus(console_text, position);
if (!ok) {UserMessage(" [Invalid Command]");}
break;
case DIAG_MODE: /* diagnostic */
ok = Process_DataDiagnostic(console_text, position);
if (!ok) {UserMessage(" [Invalid Command]");}
break;
case SF1_MODE:
ok = Process_DataSF1Set(console_text, position);
if (!ok) {UserMessage(" [Invalid Command]");}
break;
case SBS_MODE:
ok = Process_DataSBSSet(console_text, position);
if (!ok) {UserMessage(" [Invalid Command]");}
break;
default:
screenmode = OP_MODE;
break;
}
Prompt();
position = 0;
for (i = 0; i < 80; i++) console_text[i] = 0x00;
break;
case 0x08: /* BACKSPACE(BS) 값 */
case 0x7F: /* BACKSPACE(BS) 값 */
if (position > 0)
{
printf("%c %c", 0x08, 0x08);
position--;
}
break;
case 0x0A: /* enter */
break;
default :
if (one[0] >= 0x20)
{
printf("%c", one[0]);
if (position < 80)
{
console_text[position++] = one[0];
console_text[position] = 0x00;
}
else
{
position = 0;
Prompt();
for (i = 0; i < 80; i++) console_text[i] = 0x00;
}
}
break;
}
}
/* OPERATING STATE에서 명령어 처리 */
s8 Process_Data(u8 *text, u16 size) /* console_text[0]=0x00, size =0 (default) */
{
int ret;
if(size > 1)
{
if(text[1] != ' ') return(0); /* 첫칸에 space 포함되어있으면 Invalid command */
}
text[size] = 0x00;
ret = 1;
switch (text[0])
{
case 's':
screenmode = SET_MODE;
ViewScreen();
break;
case 'd':
screenmode = DIAG_MODE;
ViewScreen();
break;
default:
ret = 0;
break;
}
return(ret);
}
/* SETTING STATE 에서 명령어 처리 */
s8 Process_DataSet(u8 *text, u16 size)
{
u16 ret;
/* 첫 칸에 space가 포함되어 있으면 invalid command */
if (size > 1)
if (text[1] != ' ') return(0);
text[size] = 0x00;
ret = 1;
switch (text[0])
{
case 'o': /* operating state로 전환 */
screenmode = OP_MODE;
ViewScreen();
break;
case 'd': /* diagnostic mode로 전환 */
screenmode = DIAG_MODE;
ViewScreen();
break;
case 'z':
screenmode = OS_STATUS_MODE;
ViewScreen();
break;
case '1':
screenmode = SF1_MODE;
ViewScreen();
break;
case '2':
screenmode = SBS_MODE;
ViewScreen();
break;
case '!': /* INIT */
Param_Init(true, false);
Save_Param();
break;
default :
ret = 0;
break;
}
return(ret);
}
// OPERATING STATE에서 명령어 처리
s8 Process_OSStatus(u8 *text, u16 size) // console_text[0]=0x00, size =0 (default)
{
int ret;
if (size > 1)
if (text[1] != ' ') return(0); /* 첫칸에 space 포함되어있으면 Invalid command */
text[size] = 0x00;
ret = 1;
switch (text[0])
{
case 'o':
screenmode = OP_MODE;
ViewScreen();
break;
case 's':
screenmode = SET_MODE;
ViewScreen();
break;
case 'd':
screenmode = DIAG_MODE;
ViewScreen();
break;
default:
ret = 0;
break;
}
return(ret);
}
extern void Vref2Print(void);
/* diagnostic mode 에서 명령어 처리 */
s8 Process_DataDiagnostic(u8 *text, u16 size)
{
s8 ret, i;
text[size] = 0x00;
ret = 1;
switch (text[0])
{
case 'o': /* operating mode로 전환 */
screenmode = OP_MODE;
ViewScreen();
break;
case 's': /* setting status로 전환 */
screenmode = SET_MODE;
ViewScreen();
break;
case 'G' : /* Memory Dump */
if (size > 2)
dump_mem(TextToAddr((u8 *)&text[2]));
break;
case '2':
case '3':
// CAN COMM MONITOR
ret = DCanCommCommand(text[0]);
break;
case '1':
// case '2':
// case '3':
case '4':
case '5':
case '6':
i = SetLtc6813_Param(&text[2],text[0]);
if (i == 0)
UserMessage("COMMAND COMPLETE");
else if (i == 1)
UserMessage("COMMAND FORMAT ERROR"); /* setting format오류 */
else
UserMessage("COMMAND LIMIT ERROR"); /* setting 한계값오류 */
break;
case 'q': /* Exit Application */
UserMessage("Exit Application ? (Y or N)");
switch (WaitUserCMD((u8 *)"YyNn"))
{
case 1:
case 2:
UserMessage("System Reset !!");
Sys_Soft_Reset();
while(1);
case 3:
case 4:
UserMessage("Exit Application Cancel !!");
break;
default:
UserMessage("Command Timeout !!");
break;
}
break;
default :
ret = 0;
break;
}
return(ret);
}
/* Inventor Mode STATE에서 명령어 처리 */
s8 Process_Inventory_Data(u8 *text, u16 size)
{
s8 ret;
if (size > 1)
{
if(text[1] != ' ') return(0); /* 첫칸에 space 포함되어있으면 Invalid command */
}
text[size] = 0x00;
ret = 1;
switch (text[0])
{
case 'o':
screenmode = OP_MODE;
ViewScreen();
break;
case 's':
screenmode = SET_MODE;
ViewScreen();
break;
case 'd':
screenmode = DIAG_MODE;
ViewScreen();
break;
case '1': // H/W Version Set
case '2': // Serial Number Parameter Setting
case '3': // Manufacturer Date Parameter Setting
case '4': // Install Date Parameter Setting
break;
default:
ret = 0;
break;
}
return(ret);
}
void Prompt()
{
u8 ver[4];
switch (screenmode)
{
case 0 :
case 1 :
case 2 :
case 3 :
case 4 :
case 5 :
case 6 :
case 7 :
case 8 :
case 9 :
case 10 :
case 11 :
case 12 :
case 13 :
case 14 :
case 21 :
case 22 :
case 23 :
case 24 :
case 25 :
case 26 :
case 27 :
case 28 :
case 29 :
case 30 :
case 31 :
case 32 :
case 33 :
case 34 :
case 40 :
case 41 :
case 100 :
case 101 :
GetAppVersion(ver);
printf("%1c[%02d;%02dH", 0x1b, 23, 1);
printf("%s %d.%d.%d.%d>"
, BD_MODEL
, ver[0]
, ver[1]
, ver[2]
, ver[3]
);
break;
case GUI_MODE:
break;
default :
GetAppVersion(ver);
printf("%s %d.%d.%d.%d>"
, BD_MODEL
, ver[0]
, ver[1]
, ver[2]
, ver[3]
);
break;
}
}
void DisplayScreen(u8 p)
{
switch(screenmode)
{
case OP_MODE:
ODisplayDevice(p);
ODisplayBalancingValue(p);
ODisplayAdcStatus(p);
break;
case SET_MODE:
break;
case OS_STATUS_MODE:
osDisplayTaskStatus(p);
break;
case DIAG_MODE:
DDisplay_CanComm(p);
break;
case SF1_MODE:
SF1Display(p);
break;
case SBS_MODE:
SBSDisplay(p);
break;
}
}
void ViewScreen() /* Screen Mode에 따른 바탕 화면 출력 */
{
ClearConsol();
switch (screenmode)
{
case OP_MODE : /* View Status */
APPVerDisplay();
OmodeScreen();
break;
case SET_MODE : /* View Setting Status */
SmodeScreen();
break;
case OS_STATUS_MODE: /* View OS Task Status */
OSmodeScreen();
break;
case DIAG_MODE: /* View Diagnostic Status */
DmodeScreen();
break;
case SF1_MODE:
SF1modeScreen();
break;
case SBS_MODE:
SBSmodeScreen();
break;
default :
printf("UNDEFINE SCREEN MODE");
screenmode = 0;
break;
}
DisplayScreen(true);
}
#endif // #ifdef CONSOLE_DEBUG

53
APP/console.h Normal file
View File

@@ -0,0 +1,53 @@
/**
******************************************************************************
* File Name : console.h
* Description : This file provides code for the configuration
* of debug console.
******************************************************************************
* @attention
*
* <h2><center>&copy; 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
*
******************************************************************************
*/
#ifndef _CONSOLE_H_
#define _CONSOLE_H_
#include <stm32f10x.h>
#define OP_MODE 0
#define SET_MODE 1
#define DIAG_MODE 2
#define OS_STATUS_MODE 9
#define SF1_MODE 21
#define SBS_MODE 22
#define TEST_MODE 100
#define GUI_MODE -1
#define RX_PRINT 0
#define TX_PRINT 1
extern s8 screenmode;
extern u8 position;
extern u32 BakOSCtxSwCtr; /* Counter of number of context switches */
extern u32 BakLocalTime; /* this variable is used to create a time reference incremented by 10ms */
void AppTaskDebug(void);
u16 debug_recv_data(u8 *data);
void ViewScreen(void);
void DisplayScreen(u8 p);
void Console_Initial(void);
void Console(u8 *one);
#endif

156
APP/device_param.c Normal file
View File

@@ -0,0 +1,156 @@
/* Copyright (c) 2012-2013 The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
* only version 2 as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
*/
/*
* High Level description:
* http://www.ti.com/lit/ds/symlink/device.pdf
* Thechnical Reference:
* http://www.ti.com/lit/ug/sluu431/sluu431.pdf
*/
#include "includes.h"
#include "device_param.h"
#include "flash_if.h"
#include "dflash_sf1.h"
#include "dflash_cal.h"
#include "dflash_sbs.h"
#include "asutil.h"
#define PARAM_INIT_DATA 0xAAAA32F6
TDEVICE_VALUE device_value, dis_device_value;
TDEVICE_STATUS device_status, dis_device_status;
TDEVICE_PARAM device_param, dis_device_param;
TDEVICE_INV device_inv, dis_device_inv;
int CellQty = 21;
int TempQty = 8;
void SetCellQuantity(u8 cQuantity)
{
if ((cQuantity > 0) && (cQuantity <= 21))
{
device_param.info.CellQuantity = cQuantity;
Save_Param();
}
}
void SetCanSpeed(uint8_t Speed)
{
device_param.info.CanSpped = Speed;
Save_Param();
}
void Param_Init(u8 flag, u8 factory)
{
SF1_InitData();
if (factory == true)
{
SBS_InitData();
}
}
void Load_Param(void)
{
uint32_t len = sizeof(TDEVICE_PARAM);
if ((len % 4) > 0) len = len / 4 + 1;
else len = len / 4;
memcpy(&device_param, (uint8_t *)mBMS_PARAM_BASE_ADDR, (len * 4));
memcpy(&device_inv, (uint8_t *)(mBMS_PARAM_BASE_ADDR + (len * 4)), sizeof(TDEVICE_INV));
if (device_param.initdata != PARAM_INIT_DATA)
{
device_param.initdata = PARAM_INIT_DATA;
// Parameter init
Param_Init(true, true);
Save_Param();
}
else if ((device_param.info.DevAddr == 0) || (device_param.info.DevAddr > DEVICE_MAX_ADDR))
{
SBS_InitData();
Save_Param();
}
}
void Save_Param(void)
{
uint32_t result = 0;
uint32_t sector_addr = mBMS_PARAM_BASE_ADDR;
result = FLASH_If_Erase(sector_addr, PAGE_SIZE);
if (result == 0)
{
uint32_t base = (uint32_t)&device_param;
uint32_t len = sizeof(TDEVICE_PARAM);
if ((len % 4) > 0) len = len / 4 + 1;
else len = len / 4;
result = FLASH_If_Write(&sector_addr, (uint32_t *)base, len);
#ifdef CONSOLE_DEBUG
if (result != 0)
printf("\r\n Param save fail (%d)", result);
#endif
sector_addr = mBMS_PARAM_BASE_ADDR + (len * 4);
base = (uint32_t)&device_inv;
len = sizeof(TDEVICE_INV);
if ((len % 4) > 0) len = len / 4 + 1;
else len = len / 4;
result = FLASH_If_Write(&sector_addr, (uint32_t *)base, len);
#ifdef CONSOLE_DEBUG
if (result != 0)
printf("\r\n Inventory data save fail (%d)", result);
#endif
}
}
void LoadFwInfo(void)
{
memcpy(&fwinfo, (uint8_t *)mBMS_FW_INFO_BASE_ADDR, sizeof(FW_INFO));
}
void SaveFwInfo(void)
{
uint32_t result = 0;
uint32_t sector_addr = mBMS_FW_INFO_BASE_ADDR;
result = FLASH_If_Erase(sector_addr, PAGE_SIZE);
if (result == 0)
{
uint32_t base = (uint32_t)&fwinfo;
uint32_t len = sizeof(FW_INFO);
if ((len % 4) > 0)
len = len / 4 + 1;
else
len = len / 4;
result = FLASH_If_Write(&sector_addr, (uint32_t *)base, len);
if (result != 0)
printf("\r\n Fw information save fail (%d)", result);
}
}

443
APP/device_param.h Normal file
View File

@@ -0,0 +1,443 @@
/*****************************************************************************
*
* File : device.h
* Compiler : IAR C 6.30
* Revision : $Revision: 1.0 $
* Date : $Date: 2015 / 03 / 13
* Updated by : $Author: Jongkwang Woo
*
* Support mail : spirit0305@naver.com
*
* Description : Header file for device.c
*
****************************************************************************/
#ifndef _DEVICE_PARAM_H_
#define _DEVICE_PARAM_H_
#include <stm32f10x.h>
#include <stdint.h>
#define DEVICE_NAME "PR-67150S"
#define DEVICE_TYPE 64150
#define DEVICE_REV "1.2"
#define DEVICE_MAX_ADDR 22
#define DEVICE_MAX_CELL 24
#define DEVICE_MAX_TEMP 8
#define CELL_DIV_UNIT 10000
#define BIT(x) (unsigned short)(0x0001 << x)
#define BIT32(x) (unsigned long)(0x00000001 << x)
typedef union {
u16 value;
struct {
u16 DSG_S : 1; // LSB 0 // Dischage Fet Control
u16 CHG_S : 1; // LSB 1 // Charge Fet Control
u16 DCP : 1; // LSB 2 // Pre-charge Fet Control
u16 RXM : 1; // LSB 3
u16 FD : 1; // LSB 4
u16 FC : 1; // LSB 5
u16 MD : 1; // LSB 6
u16 INIT : 1; // LSB 7
u16 DSG_C : 1; // MSB 8 // Dischage Fet Status
u16 CHG_C : 1; // MSB 9 // Charge Fet Status
u16 ZVC_C : 1; // MSB 10 // Pre-charge Fet Status
u16 CB : 1; // MSB 11 // Cell Balancing Flag
u16 AFE : 1; // MSB 12 // AFE PL455 Comm Status
u16 TDA : 1; // MSB 13
u16 TCA : 1; // MSB 14
u16 ACB : 1; // MSB 15
} bit;
} TBATTERY_STATUS, *pBATTERY_STATUS;
typedef struct {
u16 voltage[DEVICE_MAX_CELL]; // Offset 0 ; 2bytes * (24) = 48bytes
struct {
struct {
u16 value; // Offset 0 ; 2bytes
u16 num; // Offset 2 ; 2bytes
} Max, Min; // Offset 0 ; 4bytes + 4bytes = 8bytes
u16 avg; // Offset 8 ; 2bytes
u16 diff; // Offset 10 ; 2bytes
} avg; // Offset 48 ; 12bytes
} TCELL_STATUS, *PCELL_STATUS; // 60bytes
typedef struct
{
s16 temperature[DEVICE_MAX_TEMP]; // Offset 0 ; 2bytes * (8) = 16bytes
struct
{
struct
{
s16 value; // Offset 0 ; 2bytes
u16 num; // Offset 2 ; 2bytes
} Max, Min; // Offset 0 ; 4bytes + 4bytes = 8bytes
s16 avg; // Offset 8 ; 2bytes
s16 diff; // Offset 10 ; 2bytes
} avg; // Offset 36 ; 12bytes
} TTEMP_STATUS, *PTEMP_STATUS; // 28bytes
typedef struct
{
struct
{
u16 value;
u16 num;
} Max, Min;
u16 avg;
u16 diff;
} TAVG_VALUE, *PAVG_VALUE;
typedef struct
{
u16 value;
u16 num;
} TVoltMinMax, *PVoltMinMax;
typedef struct
{
s16 value;
u16 num;
} TTempMinMax, *PTempMinMax;
typedef struct
{
u32 Heartbeat; // Offset 0
u32 ManufactureDate; // Offset 4
u32 FwVersion; // Offset 8
u32 RemainingCapacity; // Offset 12
u32 CycleCount; // Offset 16
u32 BatVoltage; // Offset 20
u32 BatSumVoltage; // Offset 24
s16 Current; // Offset 28
u16 RelativeStateOfCharge; // Offset 30
u16 StateOfHealth; // Offset 32
TCELL_STATUS Cell;
TTEMP_STATUS Temp;
} TDEVICE_VALUE, *PDEVICE_VALUE;
typedef union
{
u16 value;
struct
{
u16 over_voltage : 1; // 0x0001
u16 cell_over_voltage : 1; // 0x0002
u16 under_voltage : 1; // 0x0004
u16 cell_under_voltage : 1; // 0x0008
u16 chg_over_current : 1; // 0x0010
u16 dsg_over_current : 1; // 0x0020
u16 reserved1 : 2; //
u16 chg_high_temp : 1; // 0x0100
u16 dsg_high_temp : 1; // 0x0200
u16 chg_low_temp : 1; // 0x0400
u16 dsg_low_temp : 1; // 0x0800
u16 low_capacity : 1; // 0x1000
u16 reserved2 : 1; //
u16 cell_voltage_diff : 1; //
u16 reserved3 : 1; //
} bit;
} TWarning;
typedef union
{
u16 value;
struct
{
u16 over_voltage : 1; // 0x0001
u16 cell_over_voltage : 1; // 0x0002
u16 under_voltage : 1; // 0x0004
u16 cell_under_voltage : 1; // 0x0008
u16 chg_over_current : 1; // 0x0010
u16 dsg_over_current : 1; // 0x0020
u16 reserved1 : 2; //
u16 chg_high_temp : 1; // 0x0100
u16 dsg_high_temp : 1; // 0x0200
u16 chg_low_temp : 1; // 0x0400
u16 dsg_low_temp : 1; // 0x0800
u16 reserved2 : 1; // 0x1000
u16 short_circuit : 1; // 0x2000
u16 cell_voltage_diff : 1; // 0x4000
u16 afe_fail : 1; // 0x8000
} bit;
} TProtection;
typedef union {
u32 value;
struct {
u32 cell_00 : 1;
u32 cell_01 : 1;
u32 cell_02 : 1;
u32 cell_03 : 1;
u32 cell_04 : 1;
u32 cell_05 : 1;
u32 cell_06 : 1;
u32 cell_07 : 1;
u32 cell_08 : 1;
u32 cell_09 : 1;
u32 cell_10 : 1;
u32 cell_11 : 1;
u32 cell_12 : 1;
u32 cell_13 : 1;
u32 cell_14 : 1;
u32 cell_15 : 1;
u32 cell_16 : 1;
u32 cell_17 : 1;
u32 cell_18 : 1;
u32 cell_19 : 1;
u32 cell_20 : 1;
u32 cell_21 : 1;
u32 cell_22 : 1;
u32 cell_23 : 1;
u32 cell_24 : 1;
u32 cell_25 : 1;
u32 cell_26 : 1;
u32 cell_27 : 1;
u32 cell_28 : 1;
u32 cell_29 : 1;
u32 cell_flag : 1;
u32 reserved : 1;
} bit;
} TCellBalanceData, *PCellBalanceData;
typedef union {
u32 value;
struct {
u32 ch_00 : 1;
u32 ch_01 : 1;
u32 ch_02 : 1;
u32 ch_03 : 1;
u32 ch_04 : 1;
u32 ch_05 : 1;
u32 ch_06 : 1;
u32 ch_07 : 1;
u32 ch_08 : 1;
u32 ch_09 : 1;
u32 ch_10 : 1;
u32 ch_11 : 1;
u32 ch_12 : 1;
u32 ch_13 : 1;
u32 ch_14 : 1;
u32 ch_15 : 1;
u32 ch_16 : 1;
u32 ch_17 : 1;
u32 ch_18 : 1;
u32 ch_19 : 1;
u32 ch_flag : 1;
u32 reserved : 11;
} bit;
} TBalanceEnable, *PBalanceEnable;
typedef union
{
u32 uValue;
struct
{
u32 cell0 : 1;
u32 cell1 : 1;
u32 cell2 : 1;
u32 cell3 : 1;
u32 cell4 : 1;
u32 cell5 : 1;
u32 cell6 : 1;
u32 cell7 : 1;
u32 cell8 : 1;
u32 cell9 : 1;
u32 cell10 : 1;
u32 cell11 : 1;
u32 cell12 : 1;
u32 cell13 : 1;
u32 cell14 : 1;
u32 cell15 : 1;
u32 cell16 : 1;
u32 cell17 : 1;
u32 cell18 : 1;
u32 cell19 : 1;
u32 cell20 : 1;
u32 reserved : 11;
} Bit;
} TCELL_BIT, *PCELL_BIT;
typedef union
{
u16 uValue;
struct {
u16 temp0 : 1;
u16 temp1 : 1;
u16 temp2 : 1;
u16 temp3 : 1;
u16 temp4 : 1;
u16 temp5 : 1;
u16 temp6 : 1;
u16 temp7 : 1;
u16 reserved : 8;
} Bit;
} TTEMP_BIT, *PTEMP_BIT;
typedef struct
{
TBATTERY_STATUS battery_status; // 2 16 bit
u16 op_status; // 4 16 bit
u16 alarm_status; // 6 16 bit
TWarning warning; // 8 16 bit
TProtection protection; // 10 16 bit
u16 auto_balancing; // 12 16 bit
TCellBalanceData cellbalance; // 16 32 bit
TBalanceEnable balance_enable; // 20 32 bit
TCELL_BIT cov_warning_cell; // 24 32 bit
TCELL_BIT cov_protection_cell; // 24 32 bit
TCELL_BIT cuv_warning_cell; // 28 32 bit
TCELL_BIT cuv_protection_cell; // 32 32 bit
TTEMP_BIT otd_warning_temp; // 34 16 bit
TTEMP_BIT otd_protection_temp; // 36 16 bit
TTEMP_BIT otc_warning_temp; // 38 16 bit
TTEMP_BIT otc_protection_temp; // 40 16 bit
TTEMP_BIT ltd_warning_temp; // 42 16 bit
TTEMP_BIT ltd_protection_temp; // 44 16 bit
TTEMP_BIT ltc_warning_temp; // 46 16 bit
TTEMP_BIT ltc_protection_temp; // 48 16 bit
} TDEVICE_STATUS, *PDEVICE_STATUS;
typedef struct
{
u16 Reserved[7];
u16 CanSpped;
s16 CvOffset[2];
u16 DevAddr;
u16 CellQuantity;
} TDEVICE_INFO, *PDEVICE_INFO;
#pragma pack(2)
typedef struct
{
u16 COV_Threshold; // ST COV Threshold (Offset 0)
u16 COV_Warning; // ST COV Warning (Offset 2)
u16 COV_Recovery; // ST COV Recovery (Offset 4)
u16 CUV_Threshold; // CUV Threshold (Offset 6)
u16 CUV_Warning; // CUV Warning (Offset 8)
u16 CUV_Recovery; // CUV Recovery (Offset 10)
u16 SOV_Threshold; // ST COV Threshold (Offset 0)
u16 SOV_Warning; // ST COV Warning (Offset 2)
u16 SOV_Recovery; // ST COV Recovery (Offset 4)
u16 SUV_Threshold; // CUV Threshold (Offset 6)
u16 SUV_Warning; // CUV Warning (Offset 8)
u16 SUV_Recovery; // CUV Recovery (Offset 10)
} TDEVICE_PARAM_VOLTAGE_VALUE, *PDEVICE_PARAM_VOLTAGE_VALUE;
// C.2.3 Temperature (Subclass 690)
typedef struct
{
s16 OT_Chg_Threshold; // (Offset 0) 0.1C
s16 OT_Chg_Warning; // (Offset 2) 0.1C
s16 OT_Chg_Recovery; // (Offset 6) 0.1C
s16 OT_Dsg_Threshold; // (Offset 8) 0.1C
s16 OT_Dsg_Warning; // (Offset 10) 0.1C
s16 OT_Dsg_Recovery; // (Offset 14) 0.1C
s16 LT_Chg_Threshold; // (Offset 16) 0.1C
s16 LT_Chg_Warning; // (Offset 18) 0.1C
s16 LT_Chg_Recovery; // (Offset 22) 0.1C
s16 LT_Dsg_Threshold; // (Offset 16) 0.1C
s16 LT_Dsg_Warning; // (Offset 18) 0.1C
s16 LT_Dsg_Recovery; // (Offset 22) 0.1C
s16 Open_Thermistor; // Open Thermistor (Offset 24)
s16 Recovery_Thermistor; // Recovery Thermistor (Offset 26)
} TDEVICE_PARAM_TEMPERATURE_VALUE, *PDEVICE_PARAM_TEMPERATURE_VALUE;
typedef struct
{
u16 Cell_Voltage_Diff_Threshold; // (Offset 0) mV
u16 Cell_Voltage_Diff_Warning; // (Offset 2) mV
u16 Cell_Voltage_Diff_Recovery; // (Offset 4) mV
u16 Cell_Voltage_Diff_Time; // (Offset 6) Sec
} TDEVICE_PARAM_CELL_VOLTAGE_DIFF_VALUE, *PDEVICE_PARAM_CELL_VOLTAGE_DIFF_VALUE;
typedef struct
{
TDEVICE_PARAM_VOLTAGE_VALUE voltage;
TDEVICE_PARAM_TEMPERATURE_VALUE temperature;
TDEVICE_PARAM_CELL_VOLTAGE_DIFF_VALUE cv_diff;
} TDEVICE_PARAM_SAFETY_VALUE, *PDEVICE_PARAM_SAFETY_VALUE;
typedef struct
{
s16 Cell_Balance_Threshold; // (Offset 0) mV
s16 Cell_Balance_Window; // (Offset 2) mV
s16 Cell_Balance_Min; // (Offset 4) mV
s16 Cell_Balance_Interval; // (offset 6) S
} TDEVICE_CHG_CTRL_CFG_CELL_BAL_CFG_VALUE, *PDEVICE_CHG_CTRL_CFG_CELL_BAL_CFG_VALUE;
typedef struct _TDEVICE_CHG_CTRL_VALUE
{
TDEVICE_CHG_CTRL_CFG_CELL_BAL_CFG_VALUE cell_bal_cfg;
} TDEVICE_CHG_CTRL_VALUE, *PDEVICE_CHG_CTRL_VALUE;
typedef struct
{
uint32_t initdata;
TDEVICE_INFO info;
TDEVICE_PARAM_SAFETY_VALUE safety;
TDEVICE_CHG_CTRL_VALUE chg_ctrl;
} TDEVICE_PARAM, *PDEVICE_PARAM;
typedef struct
{
/* Time of testing and calibration data, NOT the factory out day. Local time in seconds since 2000.
Ex:
Epoch time offset (1 January 2000 00:00:00) = 946684800
Current epoch time (1 October 2019 12:00:00) = 1569931200
Timestamp = 1569931200 - 946684800 = 623246400
(Used 'https://www.epochconverter.com/' for conversion)
*/
u32 ManufactureDate;
u8 SerialNo[16]; // BMU18SAYYMMNNNN
u8 ModuleNo[16]; //
} TDEVICE_INV, *PDEVICE_INV;
// Setting value
typedef struct _TDEVICE_SET_VALUE
{
u8 Flag;
u8 Busy;
u16 SubClass;
u16 Offset;
u16 Size;
u16 Value;
} TDEVICE_SET_VALUE, *PDEVICE_SET_VALUE;
extern TDEVICE_VALUE device_value, dis_device_value;
extern TDEVICE_STATUS device_status, dis_device_status;
extern TDEVICE_PARAM device_param, dis_device_param;
extern TDEVICE_INV device_inv;
extern int CellQty;
extern int TempQty;
void Load_Param(void);
void Save_Param(void);
void LoadFwInfo(void);
void SaveFwInfo(void);
void SetCanSpeed(uint8_t Speed);
void Param_Init(u8 flag, u8 factory);
#pragma pack()
#endif

487
APP/dflash_cal.c Normal file
View File

@@ -0,0 +1,487 @@
/* Copyright (c) 2012-2013 The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
* only version 2 as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
*/
/*
* High Level description:
* http://www.ti.com/lit/ds/symlink/bq28400.pdf
* Thechnical Reference:
* http://www.ti.com/lit/ug/sluu431/sluu431.pdf
*/
#include "includes.h"
#include "dflash_cal.h"
#include "console.h"
#include "asutil.h"
#include "device_param.h"
u8 SetCal_Param(u8 *text, u8 aDevice);
u8 SetCal_Param1(u8 *text, u8 aDevice);
s32 CalibrationVoltage(u16 voltage, u8 item)
{
s32 sum = 0;
float a, b, result;
// switch (item)
// {
// case DSG_CURR_ID:
// sum = GetRealCurrentAdc(item) + device_param.cal.current.DC_Offset;
// break;
// case CHG_CURR_ID:
// sum = GetRealCurrentAdc(item) + device_param.cal.current.CC1_Offset;
// break;
// }
a = (float)voltage / 100;
b = (float)sum / 10000;
result = a / b;
return (s32)(result * 1000);
}
s32 CalibrationCurrentA(u16 current, u8 item)
{
s32 sum;
float a, b, result;
switch (item)
{
// case DSG_CURR_ID:
// sum = GetRealCurrentSum() - device_param.cal.current.DC_Offset;
// break;
// case CHG_CURR_ID:
// sum = GetRealCurrentSum() - device_param.cal.current.CC1_Offset;
// break;
}
if (sum < 0) sum *= -1;
a = (float)current / 100;
b = (float)(sum) / 10000;
result = a / b;
return (s32)(result * 1000);
}
#ifdef CONSOLE_DEBUG
/* SETTING STATE 에서 명령어 처리 */
s8 Process_DataCalSet(u8 *text, u16 size)
{
u16 i, ret;
/* 첫 칸에 space가 포함되어 있으면 invalid command */
if (size > 1) {if (text[1] != ' ') return(0);}
text[size] = 0x00;
ret = 1;
switch (text[0])
{
case 'o': /* operating state로 전환 */
screenmode = OP_MODE;
ViewScreen();
break;
case 's': /* diagnostic mode로 전환 */
screenmode = SET_MODE;
ViewScreen();
break;
case 'd': /* diagnostic mode로 전환 */
screenmode = DIAG_MODE;
ViewScreen();
break;
case '1': // OCV Alarm Parameter Setting
case '2': // OCV Shutdown Parameter Setting
case '3': // OCV Alarm Parameter Setting
case '4': // OCV Shutdown Parameter Setting
case '5': // OCV Shutdown Parameter Setting
case '6': // OCV Shutdown Parameter Setting
i = SetCal_Param(&text[2],text[0]);
if (i == 0)
UserMessage("COMMAND COMPLETE");
else if (i == 1)
UserMessage("COMMAND FORMAT ERROR"); /* setting format오류 */
else
UserMessage("COMMAND LIMIT ERROR"); /* setting 한계값오류 */
break;
case '7':
case '8':
case '9':
case 'A':
case 'B':
case 'C':
case 'K' : // Charge Current Calibration
i = SetCal_Param1(&text[2], text[0]);
if (i == 0)
UserMessage("COMMAND COMPLETE");
else if (i == 1)
UserMessage("COMMAND FORMAT ERROR"); /* setting format오류 */
else
UserMessage("COMMAND LIMIT ERROR"); /* setting 한계값오류 */
break;
case 'I':
Cal_InitData();
Save_Param();
break;
default :
ret = 1;
break;
}
return(ret);
}
u8 SetCal_Param(u8 *text, u8 aDevice)
{
u16 size, i, j;
s16 aParam[4];
s32 bParam[4];
u8 temp[10];
u8 ret;
u8 cmd;
ret = 0;
size = 0;
while (text[size] != 0x00) size++; /* text의 전체 문자열 size 측정 */
switch (aDevice)
{
case '1': // Cal_Voltage_Subclass
i = 0;
if (size < 2 ) return(1);
j = FIND_CHAR((u8 *)&text[i], temp, size - i, ' ');
i = i + j + 1;
temp[j] = 0x00;
cmd = temp[0];
j = FIND_CHAR((u8 *)&text[i], temp, size - i, ' ');
i = i + j + 1;
temp[j] = 0x00;
aParam[0] = StrToInt(temp, j); /* Value */
switch (cmd)
{
case '1': device_param.cal.voltage.Cell_Scale_0 = aParam[0]; break;
case '2': device_param.cal.voltage.Cell_Scale_1 = aParam[0]; break;
case '3': device_param.cal.voltage.BAT_Gain = aParam[0]; break;
case '4': device_param.cal.voltage.BAT_Offset = aParam[0]; break;
default : return (1);
}
Save_Param();
break;
case '2': // Cal_Discharge_Current_Subclass
i = 0;
if (size < 2 ) return(1);
j = FIND_CHAR((u8 *)&text[i], temp, size - i, ' ');
i = i + j + 1;
temp[j] = 0x00;
cmd = temp[0];
j = FIND_CHAR((u8 *)&text[i], temp, size - i, ' ');
i = i + j + 1;
temp[j] = 0x00;
bParam[0] = StrToInt32(temp, j); /* Value */
switch (cmd)
{
case '1': device_param.cal.current.DC_Gain = bParam[0]; break;
case '2': device_param.cal.current.DC_Offset = bParam[0]; break;
default: return(1);
}
Save_Param();
break;
case '3': // Cal_Charge_Current_Subclass
i = 0;
if (size < 2 ) return(1);
j = FIND_CHAR((u8 *)&text[i], temp, size - i, ' ');
i = i + j + 1;
temp[j] = 0x00;
cmd = temp[0];
j = FIND_CHAR((u8 *)&text[i], temp, size - i, ' ');
i = i + j + 1;
temp[j] = 0x00;
bParam[0] = StrToInt32(temp, j); /* Value */
switch (cmd)
{
case '1': device_param.cal.current.CC1_Gain = bParam[0]; break;
case '2': device_param.cal.current.CC1_Offset = bParam[0]; break;
case '3': device_param.cal.current.CC2_Gain = bParam[0]; break;
case '4': device_param.cal.current.CC2_Offset = bParam[0]; break;
default: return(1);
}
Save_Param();
break;
case '6': // Current Offset (Subclass 20)
i = 0;
if (size < 2 ) return(1);
j = FIND_CHAR((u8 *)&text[i], temp, size - i, ' ');
i = i + j + 1;
temp[j] = 0x00;
cmd = temp[0];
j = FIND_CHAR((u8 *)&text[i], temp, size - i, ' ');
i = i + j + 1;
temp[j] = 0x00;
aParam[0] = StrToInt(temp, j); /* Value */
switch (cmd)
{
case '1': device_param.cal.current_offset.Int_Power = aParam[0]; break;
case '2': device_param.cal.current_offset.Relay_Power = aParam[0]; break;
default: return(1);
}
Save_Param();
break;
default:
ret = 1;
break;
}
return(ret); /* setting value 정상 */
}
u8 SetCal_Param1(u8 *text, u8 aDevice)
{
u8 temp[20];
float fParam[2];
u16 i, j, size;
u8 ret;
ret = 0;
size = 0;
while (text[size] != 0x00) size++; /* text의 전체 문자열 size 측정 */
switch (aDevice)
{
case '8' : // Discharge Current Calibration
i = 0;
if (size < 2 ) return(1);
j = FIND_CHAR((u8 *)&text[i], temp, size - i, ' ');
temp[j] = 0x00;
i = i + j + 1;
fParam[0] = atof((char *)temp); /* IP a */
device_param.cal.current.DC_Gain = CalibrationVoltage((u16)(fParam[0] * 100), DSG_CURR_ID);
Save_Param();
break;
case '9' : // Charge Current Calibration
i = 0;
if (size < 2 ) return(1);
j = FIND_CHAR((u8 *)&text[i], temp, size - i, ' ');
temp[j] = 0x00;
i = i + j + 1;
fParam[0] = atof((char *)temp); /* IP a */
if ((device_param.sbs.data.Spec_Info & 0x8000) != 0)
device_param.cal.current.CC1_Gain = CalibrationVoltage((u16)(fParam[0] * 100), CHG_CURR_ID);
else
device_param.cal.current.CC2_Gain = CalibrationVoltage((u16)(fParam[0] * 100), CHG_CURR_ID);
Save_Param();
break;
case 'K' : // Charge Current Calibration
device_param.cal.current.DC_Offset = -GetRealCurrentAdc(DSG_CURR_ID);
device_param.cal.current.CC1_Offset = -GetRealCurrentAdc(CHG_CURR_ID);
device_param.cal.current.CC2_Offset = -GetRealCurrentAdc(CHG_CURR_ID);
Save_Param();
break;
case 'B' : // Discharge Current Calibration
i = 0;
if (size < 2 ) return(1);
j = FIND_CHAR((u8 *)&text[i], temp, size - i, ' ');
temp[j] = 0x00;
i = i + j + 1;
fParam[0] = atof((char *)temp); /* IP a */
device_param.cal.current.DC_Gain = CalibrationCurrentA((u16)(fParam[0] * 100), DSG_CURR_ID);
Save_Param();
break;
case 'C' : // Charge Current Calibration
i = 0;
if (size < 2 ) return(1);
j = FIND_CHAR((u8 *)&text[i], temp, size - i, ' ');
temp[j] = 0x00;
i = i + j + 1;
fParam[0] = atof((char *)temp); /* IP a */
if ((device_param.sbs.data.Spec_Info & 0x8000) != 0)
device_param.cal.current.CC1_Gain = CalibrationCurrentA((u16)(fParam[0] * 100), CHG_CURR_ID);
else
device_param.cal.current.CC2_Gain = CalibrationCurrentA((u16)(fParam[0] * 100), CHG_CURR_ID);
Save_Param();
break;
default:
ret = 1;
break;
}
return(ret); /* setting value 정상 */
}
void CalDisplayVoltage(u8 p)
{
u8 text[20];
// Cell_Scale_0 (Offset 0)
if (p || (dis_device_param.cal.voltage.Cell_Scale_0 != device_param.cal.voltage.Cell_Scale_0))
{
sprintf((char *)text, "%5d", device_param.cal.voltage.Cell_Scale_0);
GreenOutXY(19, 3, text);
dis_device_param.cal.voltage.Cell_Scale_0 = device_param.cal.voltage.Cell_Scale_0;
}
// Cell_Scale_1 (Offset 2)
if (p || (dis_device_param.cal.voltage.Cell_Scale_1 != device_param.cal.voltage.Cell_Scale_1))
{
sprintf((char *)text, "%5d", device_param.cal.voltage.Cell_Scale_1);
GreenOutXY(19, 4, text);
dis_device_param.cal.voltage.Cell_Scale_1 = device_param.cal.voltage.Cell_Scale_1;
}
// Pack_Offset (Offset 8)
if (p || (dis_device_param.cal.voltage.BAT_Gain != device_param.cal.voltage.BAT_Gain))
{
sprintf((char *)text, "%5d", device_param.cal.voltage.BAT_Gain);
GreenOutXY(19, 5, text);
dis_device_param.cal.voltage.BAT_Gain = device_param.cal.voltage.BAT_Gain;
}
// BAT_Offset (Offset 10)
if (p || (dis_device_param.cal.voltage.BAT_Offset != device_param.cal.voltage.BAT_Offset))
{
sprintf((char *)text, "%5d", device_param.cal.voltage.BAT_Offset);
GreenOutXY(19, 6, text);
dis_device_param.cal.voltage.BAT_Offset = device_param.cal.voltage.BAT_Offset;
}
}
void CalDisplayDischargeCurrent(u8 p)
{
u8 text[20];
u16 x;
x = 18;
// DC_Gain (Offset 0)
if (p || (dis_device_param.cal.current.DC_Gain != device_param.cal.current.DC_Gain))
{
sprintf((char *)text, "%8d", device_param.cal.current.DC_Gain);
GreenOutXY(x, 8, text);
dis_device_param.cal.current.DC_Gain = device_param.cal.current.DC_Gain;
}
// DC_Offset (Offset 4)
if (p || (dis_device_param.cal.current.DC_Offset != device_param.cal.current.DC_Offset))
{
sprintf((char *)text, "%8d", device_param.cal.current.DC_Offset);
GreenOutXY(x, 9, text);
dis_device_param.cal.current.DC_Offset = device_param.cal.current.DC_Offset;
}
}
void CalDisplayChargeCurrent(u8 p)
{
u8 text[20];
u16 x;
x = 18;
// CC1_Gain (Offset 0)
if (p || (dis_device_param.cal.current.CC1_Gain != device_param.cal.current.CC1_Gain))
{
sprintf((char *)text, "%8d", device_param.cal.current.CC1_Gain);
GreenOutXY(x, 11, text);
dis_device_param.cal.current.CC1_Gain = device_param.cal.current.CC1_Gain;
}
// CC1_Offset (Offset 4)
if (p || (dis_device_param.cal.current.CC1_Offset != device_param.cal.current.CC1_Offset))
{
sprintf((char *)text, "%8d", device_param.cal.current.CC1_Offset);
GreenOutXY(x, 12, text);
dis_device_param.cal.current.CC1_Offset = device_param.cal.current.CC1_Offset;
}
x = 18;
// CC2_Gain (Offset 0)
if (p || (dis_device_param.cal.current.CC2_Gain != device_param.cal.current.CC2_Gain))
{
sprintf((char *)text, "%8d", device_param.cal.current.CC2_Gain);
GreenOutXY(x, 14, text);
dis_device_param.cal.current.CC2_Gain = device_param.cal.current.CC2_Gain;
}
// CC2_Offset (Offset 4)
if (p || (dis_device_param.cal.current.CC2_Offset != device_param.cal.current.CC2_Offset))
{
sprintf((char *)text, "%8d", device_param.cal.current.CC2_Offset);
GreenOutXY(x, 15, text);
dis_device_param.cal.current.CC2_Offset = device_param.cal.current.CC2_Offset;
}
}
void CalDisplayPwrConsumpt(u8 p)
{
u8 text[20];
u16 x;
x = 46;
// Internal Power Consumption (Offset 0)
if (p || (dis_device_param.cal.current_offset.Int_Power != device_param.cal.current_offset.Int_Power))
{
sprintf((char *)text, "%5d", device_param.cal.current_offset.Int_Power);
GreenOutXY(x, 3, text);
dis_device_param.cal.current_offset.Int_Power = device_param.cal.current_offset.Int_Power;
}
// Relay Power Consumption (Offset 0)
if (p || (dis_device_param.cal.current_offset.Relay_Power != device_param.cal.current_offset.Relay_Power))
{
sprintf((char *)text, "%5d", device_param.cal.current_offset.Relay_Power);
GreenOutXY(x, 4, text);
dis_device_param.cal.current_offset.Relay_Power = device_param.cal.current_offset.Relay_Power;
}
}
void CalDisplay(u8 p)
{
CalDisplayVoltage(p);
CalDisplayChargeCurrent(p);
CalDisplayDischargeCurrent(p);
CalDisplayPwrConsumpt(p);
}
#endif // #ifdef CONSOLE_DEBUG
void Cal_InitData(void)
{
device_param.cal.voltage.Cell_Scale_0 = 0;
device_param.cal.voltage.Cell_Scale_1 = 0;
device_param.cal.voltage.BAT_Gain = 0; // (1/1000)
device_param.cal.voltage.BAT_Offset = 0; // (1/10000)
device_param.cal.current.CC1_Gain = 0;
device_param.cal.current.CC1_Offset = 0;
device_param.cal.current.CC2_Gain = 0;
device_param.cal.current.CC2_Offset = 0;
device_param.cal.current.DC_Gain = 0;
device_param.cal.current.DC_Offset = 0;
device_param.cal.current_offset.Int_Power = 100;
device_param.cal.current_offset.Relay_Power = 0;
}

27
APP/dflash_cal.h Normal file
View File

@@ -0,0 +1,27 @@
/*****************************************************************************
*
* File : dflash_cfg.h
* Compiler : IAR C 6.30
* Revision : $Revision: 1.0 $
* Date : $Date: 2015 / 03 / 13
* Updated by : $Author: Jongkwang Woo
*
* Support mail : spirit0305@naver.com
*
* Description : Header file for dflash_cfg.c
*
****************************************************************************/
#ifndef _DFLASH_CAL_H_
#define _DFLASH_CAL_H_
#include <stm32f10x.h>
s8 Process_DataCalSet(u8 *text, u16 size);
void CalDisplay(u8 p);
void Cal_InitData(void);
s32 CalibrationVoltage(u16 voltage, u8 item);
s32 CalibrationCurrentA(u16 current, u8 item);
#endif

191
APP/dflash_sbs.c Normal file
View File

@@ -0,0 +1,191 @@
/* Copyright (c) 2012-2013 The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
* only version 2 as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
*/
/*
* High Level description:
* http://www.ti.com/lit/ds/symlink/bq28400.pdf
* Thechnical Reference:
* http://www.ti.com/lit/ug/sluu431/sluu431.pdf
*/
#include "includes.h"
#include "dflash_sbs.h"
#include "console.h"
#include "asutil.h"
#include "device_param.h"
#ifdef CONSOLE_DEBUG
u8 SSet_SbsCfg(u8 *text, u8 aDevice);
/* SETTING STATE 에서 명령어 처리 */
s8 Process_DataSBSSet(u8 *text, u16 size)
{
u16 i, ret;
/* 첫 칸에 space가 포함되어 있으면 invalid command */
if (size > 1) {if (text[1] != ' ') return(0);}
text[size] = 0x00;
ret = 1;
switch (text[0])
{
case 'o': /* operating state로 전환 */
screenmode = OP_MODE;
ViewScreen();
break;
case 's': /* diagnostic mode로 전환 */
screenmode = SET_MODE;
ViewScreen();
break;
case 'd': /* diagnostic mode로 전환 */
screenmode = DIAG_MODE;
ViewScreen();
break;
case '1': // SBS Data Parameter Setting
case '2': // SBS Data Parameter Setting
i = SSet_SbsCfg(&text[2],text[0]);
if (i == 0)
UserMessage("COMMAND COMPLETE");
else if (i == 1)
UserMessage("COMMAND FORMAT ERROR"); /* setting format오류 */
else
UserMessage("COMMAND LIMIT ERROR"); /* setting 한계값오류 */
break;
case 'I':
SBS_InitData();
Save_Param();
break;
default :
ret = 0;
break;
}
return(ret);
}
u8 SSet_SbsCfg(u8 *text, u8 aDevice)
{
u16 size, i, j;
s16 aParam[4];
u8 temp[10];
u8 ret;
u8 cmd;
ret = 0;
size = 0;
while (text[size] != 0x00) size++; /* text의 전체 문자열 size 측정 */
switch (aDevice)
{
case '1': // Data
i = 0;
if (size < 2 ) return(1);
j = FIND_CHAR((u8 *)&text[i], temp, size - i, ' ');
i = i + j + 1;
temp[j] = 0x00;
cmd = temp[0];
j = FIND_CHAR((u8 *)&text[i], temp, size - i, ' ');
i = i + j + 1;
temp[j] = 0x00;
switch (cmd)
{
case '1': aParam[0] = StrToInt(temp, j); break; /* Int Value */
}
switch (cmd)
{
case '1': device_param.info.DevAddr = aParam[0]; break;
default : return (1);
}
Save_Param();
break;
case '2': // Data
i = 0;
if (size < 2 ) return(1);
j = FIND_CHAR((u8 *)&text[i], temp, size - i, ' ');
i = i + j + 1;
temp[j] = 0x00;
cmd = temp[0];
j = FIND_CHAR((u8 *)&text[i], temp, size - i, ' ');
i = i + j + 1;
temp[j] = 0x00;
switch (cmd)
{
case '1': aParam[0] = StrToInt(temp, j); break; /* Int Value */
case '2': aParam[0] = StrToInt(temp, j); break; /* Int Value */
}
switch (cmd)
{
case '1': device_param.info.CvOffset[0] = aParam[0]; break;
case '2': device_param.info.CvOffset[1] = aParam[0]; break;
default : return (1);
}
Save_Param();
break;
default:
ret = 1;
break;
}
return(ret); /* setting value 정상 */
}
void SBSDisplayData(u8 p)
{
u8 text[20];
// Initial_Battery_Mode (Offset 0)
if (p || (dis_device_param.info.DevAddr != device_param.info.DevAddr))
{
sprintf((char *)text, "%4d", device_param.info.DevAddr);
GreenOutXY(20, 3, text);
dis_device_param.info.DevAddr = device_param.info.DevAddr;
}
// Cell Voltage Offset - LSB
if (p || (dis_device_param.info.CvOffset[0] != device_param.info.CvOffset[0]))
{
sprintf((char *)text, "%4d", device_param.info.CvOffset[0]);
GreenOutXY(20, 5, text);
dis_device_param.info.CvOffset[0] = device_param.info.CvOffset[0];
}
// Cell Voltage Offset - MSB
if (p || (dis_device_param.info.CvOffset[1] != device_param.info.CvOffset[1]))
{
sprintf((char *)text, "%4d", device_param.info.CvOffset[1]);
GreenOutXY(20, 6, text);
dis_device_param.info.CvOffset[1] = device_param.info.CvOffset[1];
}
}
void SBSDisplay(u8 p)
{
SBSDisplayData(p);
}
#endif // #ifdef CONSOLE_DEBUG
void SBS_InitData(void)
{
device_param.info.DevAddr = 1;
device_param.info.CvOffset[0] = 0;
device_param.info.CvOffset[1] = 0;
}

25
APP/dflash_sbs.h Normal file
View File

@@ -0,0 +1,25 @@
/*****************************************************************************
*
* File : dflash_cfg.h
* Compiler : IAR C 6.30
* Revision : $Revision: 1.0 $
* Date : $Date: 2015 / 03 / 13
* Updated by : $Author: Jongkwang Woo
*
* Support mail : spirit0305@naver.com
*
* Description : Header file for dflash_sbs.c
*
****************************************************************************/
#ifndef _DFLASH_SBS_H_
#define _DFLASH_SBS_H_
#include <stm32f10x.h>
s8 Process_DataSBSSet(u8 *text, u16 size);
void SBSDisplay(u8 p);
void SBS_InitData(void);
#endif

597
APP/dflash_sf1.c Normal file
View File

@@ -0,0 +1,597 @@
/* Copyright (c) 2012-2013 The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
* only version 2 as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
*/
/*
* High Level description:
* http://www.ti.com/lit/ds/symlink/bq28400.pdf
* Thechnical Reference:
* http://www.ti.com/lit/ug/sluu431/sluu431.pdf
*/
#include "includes.h"
#include "dflash_sf1.h"
#include "device_param.h"
#include "asutil.h"
#include "console.h"
#ifdef CONSOLE_DEBUG
u8 SetSF1_Param(u8 *text, u8 aDevice);
/* SETTING STATE 에서 명령어 처리 */
s8 Process_DataSF1Set(u8 *text, u16 size)
{
u16 i, ret;
/* 첫 칸에 space가 포함되어 있으면 invalid command */
if (size > 1) {if (text[1] != ' ') return(0);}
text[size] = 0x00;
ret = 1;
switch (text[0])
{
case 'o': /* operating state로 전환 */
screenmode = OP_MODE;
ViewScreen();
break;
case 's': /* diagnostic mode로 전환 */
screenmode = SET_MODE;
ViewScreen();
break;
case 'd': /* diagnostic mode로 전환 */
screenmode = DIAG_MODE;
ViewScreen();
break;
case 'z':
screenmode = OS_STATUS_MODE;
ViewScreen();
break;
case '1': // Cell Voltage Parameter Setting
case '2': // Current Parameter Setting
case '3': // Temperature Parameter Setting
case '4': // System Voltage Parameter Setting
case '5': // SOC Parameter Setting
case '6': // Open Thermistor Parameter Setting
i = SetSF1_Param(&text[2],text[0]);
if (i == 0)
UserMessage("COMMAND COMPLETE");
else if (i == 1)
UserMessage("COMMAND FORMAT ERROR"); /* setting format오류 */
else
UserMessage("COMMAND LIMIT ERROR"); /* setting 한계값오류 */
break;
case 'I':
SF1_InitData();
Save_Param();
break;
default :
ret = 0;
break;
}
return(ret);
}
void SF1DisplayCellVoltage(u8 p)
{
u8 text[20];
PDEVICE_PARAM param = &device_param;
PDEVICE_PARAM dis_param = &dis_device_param;
int x;
x = 20;
// COV Threshold (Offset 0)
if (p || (dis_param->safety.voltage.COV_Threshold != param->safety.voltage.COV_Threshold))
{
sprintf((char *)text, "%4d", param->safety.voltage.COV_Threshold);
GreenOutXY(x, 4, text);
dis_param->safety.voltage.COV_Threshold = param->safety.voltage.COV_Threshold;
}
// COV Warning (Offset 2)
if (p || (dis_param->safety.voltage.COV_Warning != param->safety.voltage.COV_Warning))
{
sprintf((char *)text, "%4d", param->safety.voltage.COV_Warning);
GreenOutXY(x, 5, text);
dis_param->safety.voltage.COV_Warning = param->safety.voltage.COV_Warning;
}
// COV Recovery (Offset 4)
if (p || (dis_param->safety.voltage.COV_Recovery != param->safety.voltage.COV_Recovery))
{
sprintf((char *)text, "%4d", param->safety.voltage.COV_Recovery);
GreenOutXY(x, 6, text);
dis_param->safety.voltage.COV_Recovery = param->safety.voltage.COV_Recovery;
}
// CUV Threshold (Offset 6)
if (p || (dis_param->safety.voltage.CUV_Threshold != param->safety.voltage.CUV_Threshold))
{
sprintf((char *)text, "%4d", param->safety.voltage.CUV_Threshold);
GreenOutXY(x, 8, text);
dis_param->safety.voltage.CUV_Threshold = param->safety.voltage.CUV_Threshold;
}
// CUV Warning (Offset 8)
if (p || (dis_param->safety.voltage.CUV_Warning != param->safety.voltage.CUV_Warning))
{
sprintf((char *)text, "%4d", param->safety.voltage.CUV_Warning);
GreenOutXY(x, 9, text);
dis_param->safety.voltage.CUV_Warning = param->safety.voltage.CUV_Warning;
}
// CUV Recovery (Offset 10)
if (p || (dis_param->safety.voltage.CUV_Recovery != param->safety.voltage.CUV_Recovery))
{
sprintf((char *)text, "%4d", param->safety.voltage.CUV_Recovery);
GreenOutXY(x, 10, text);
dis_param->safety.voltage.CUV_Recovery = param->safety.voltage.CUV_Recovery;
}
}
void SF1DisplayTemperature(u8 p)
{
PDEVICE_PARAM param = &device_param;
PDEVICE_PARAM dis_param = &dis_device_param;
int x;
x = 46;
// Over Temp Chg Threshold (Offset 0)
if (p || (dis_param->safety.temperature.OT_Chg_Threshold != param->safety.temperature.OT_Chg_Threshold))
{
FloatNormalOutIntXY(x, 4, (float)param->safety.temperature.OT_Chg_Threshold / 10, 5, 1);
dis_param->safety.temperature.OT_Chg_Threshold = param->safety.temperature.OT_Chg_Threshold;
}
// Over Temp Chg Warning (Offset 2)
if (p || (dis_param->safety.temperature.OT_Chg_Warning != param->safety.temperature.OT_Chg_Warning))
{
FloatNormalOutIntXY(x, 5, (float)param->safety.temperature.OT_Chg_Warning / 10, 5, 1);
dis_param->safety.temperature.OT_Chg_Warning = param->safety.temperature.OT_Chg_Warning;
}
// OT Chg Recovery (Offset 3)
if (p || (dis_param->safety.temperature.OT_Chg_Recovery != param->safety.temperature.OT_Chg_Recovery))
{
FloatNormalOutIntXY(x, 6, (float)param->safety.temperature.OT_Chg_Recovery / 10, 5, 1);
dis_param->safety.temperature.OT_Chg_Recovery = param->safety.temperature.OT_Chg_Recovery;
}
// Over Temp Dsg Threshold (Offset 5)
if (p || (dis_param->safety.temperature.OT_Dsg_Threshold != param->safety.temperature.OT_Dsg_Threshold))
{
FloatNormalOutIntXY(x, 8, (float)param->safety.temperature.OT_Dsg_Threshold / 10, 5, 1);
dis_param->safety.temperature.OT_Dsg_Threshold = param->safety.temperature.OT_Dsg_Threshold;
}
// Over Temp Dsg Warning (Offset 5)
if (p || (dis_param->safety.temperature.OT_Dsg_Warning != param->safety.temperature.OT_Dsg_Warning))
{
FloatNormalOutIntXY(x, 9, (float)param->safety.temperature.OT_Dsg_Warning / 10, 5, 1);
dis_param->safety.temperature.OT_Dsg_Warning = param->safety.temperature.OT_Dsg_Warning;
}
// OT Dsg Recovery (Offset 8)
if (p || (dis_param->safety.temperature.OT_Dsg_Recovery != param->safety.temperature.OT_Dsg_Recovery))
{
FloatNormalOutIntXY(x, 10, (float)param->safety.temperature.OT_Dsg_Recovery / 10, 5, 1);
dis_param->safety.temperature.OT_Dsg_Recovery = param->safety.temperature.OT_Dsg_Recovery;
}
// Low temperature
// LT Chg Threshold (Offset 0)
if (p || (dis_param->safety.temperature.LT_Chg_Threshold != param->safety.temperature.LT_Chg_Threshold))
{
FloatNormalOutIntXY(x, 12, (float)param->safety.temperature.LT_Chg_Threshold / 10, 5, 1);
dis_param->safety.temperature.LT_Chg_Threshold = param->safety.temperature.LT_Chg_Threshold;
}
// LT Chg Warning (Offset 2)
if (p || (dis_param->safety.temperature.LT_Chg_Warning != param->safety.temperature.LT_Chg_Warning))
{
FloatNormalOutIntXY(x, 13, (float)param->safety.temperature.LT_Chg_Warning / 10, 5, 1);
dis_param->safety.temperature.LT_Chg_Warning = param->safety.temperature.LT_Chg_Warning;
}
// LT Chg Recovery (Offset 3)
if (p || (dis_param->safety.temperature.LT_Chg_Recovery != param->safety.temperature.LT_Chg_Recovery))
{
FloatNormalOutIntXY(x, 14, (float)param->safety.temperature.LT_Chg_Recovery / 10, 5, 1);
dis_param->safety.temperature.LT_Chg_Recovery = param->safety.temperature.LT_Chg_Recovery;
}
// LT Dsg Threshold (Offset 5)
if (p || (dis_param->safety.temperature.LT_Dsg_Threshold != param->safety.temperature.LT_Dsg_Threshold))
{
FloatNormalOutIntXY(x, 16, (float)param->safety.temperature.LT_Dsg_Threshold / 10, 5, 1);
dis_param->safety.temperature.LT_Dsg_Threshold = param->safety.temperature.LT_Dsg_Threshold;
}
// LT Dsg Warning (Offset 5)
if (p || (dis_param->safety.temperature.LT_Dsg_Warning != param->safety.temperature.LT_Dsg_Warning))
{
FloatNormalOutIntXY(x, 17, (float)param->safety.temperature.LT_Dsg_Warning / 10, 5, 1);
dis_param->safety.temperature.LT_Dsg_Warning = param->safety.temperature.LT_Dsg_Warning;
}
// LT Dsg Recovery (Offset 8)
if (p || (dis_param->safety.temperature.LT_Dsg_Recovery != param->safety.temperature.LT_Dsg_Recovery))
{
FloatNormalOutIntXY(x, 18, (float)param->safety.temperature.LT_Dsg_Recovery / 10, 5, 1);
dis_param->safety.temperature.LT_Dsg_Recovery = param->safety.temperature.LT_Dsg_Recovery;
}
}
void SF1DisplaySVoltage(u8 p)
{
u8 text[20];
PDEVICE_PARAM param = &device_param;
PDEVICE_PARAM dis_param = &dis_device_param;
int x;
x = 73;
// SOV Threshold (Offset 0)
if (p || (dis_param->safety.voltage.SOV_Threshold != param->safety.voltage.SOV_Threshold))
{
sprintf((char *)text, "%4d", param->safety.voltage.SOV_Threshold);
GreenOutXY(x, 4, text);
dis_param->safety.voltage.SOV_Threshold = param->safety.voltage.SOV_Threshold;
}
// SOV Warning (Offset 2)
if (p || (dis_param->safety.voltage.SOV_Warning != param->safety.voltage.SOV_Warning))
{
sprintf((char *)text, "%4d", param->safety.voltage.SOV_Warning);
GreenOutXY(x, 5, text);
dis_param->safety.voltage.SOV_Warning = param->safety.voltage.SOV_Warning;
}
// SOV Recovery (Offset 4)
if (p || (dis_param->safety.voltage.SOV_Recovery != param->safety.voltage.SOV_Recovery))
{
sprintf((char *)text, "%4d", param->safety.voltage.SOV_Recovery);
GreenOutXY(x, 6, text);
dis_param->safety.voltage.SOV_Recovery = param->safety.voltage.SOV_Recovery;
}
// SUV Threshold (Offset 6)
if (p || (dis_param->safety.voltage.SUV_Threshold != param->safety.voltage.SUV_Threshold))
{
sprintf((char *)text, "%4d", param->safety.voltage.SUV_Threshold);
GreenOutXY(x, 8, text);
dis_param->safety.voltage.SUV_Threshold = param->safety.voltage.SUV_Threshold;
}
// SUV Warning (Offset 8)
if (p || (dis_param->safety.voltage.SUV_Warning != param->safety.voltage.SUV_Warning))
{
sprintf((char *)text, "%4d", param->safety.voltage.SUV_Warning);
GreenOutXY(x, 9, text);
dis_param->safety.voltage.SUV_Warning = param->safety.voltage.SUV_Warning;
}
// SUV Recovery (Offset 10)
if (p || (dis_param->safety.voltage.SUV_Recovery != param->safety.voltage.SUV_Recovery))
{
sprintf((char *)text, "%4d", param->safety.voltage.SUV_Recovery);
GreenOutXY(x, 10, text);
dis_param->safety.voltage.SUV_Recovery = param->safety.voltage.SUV_Recovery;
}
}
void SF1DisplayCellVoltageDiff(u8 p)
{
u8 text[20];
PDEVICE_PARAM param = &device_param;
PDEVICE_PARAM dis_param = &dis_device_param;
int x;
x = 73;
// Cell Voltage Diff Threshold (Offset 0)
if (p || (dis_param->safety.cv_diff.Cell_Voltage_Diff_Threshold != param->safety.cv_diff.Cell_Voltage_Diff_Threshold))
{
sprintf((char *)text, "%4d", param->safety.cv_diff.Cell_Voltage_Diff_Threshold);
GreenOutXY(x, 15, text);
dis_param->safety.cv_diff.Cell_Voltage_Diff_Threshold = param->safety.cv_diff.Cell_Voltage_Diff_Threshold;
}
// Cell Voltage Diff Warning (Offset 2)
if (p || (dis_param->safety.cv_diff.Cell_Voltage_Diff_Warning != param->safety.cv_diff.Cell_Voltage_Diff_Warning))
{
sprintf((char *)text, "%4d", param->safety.cv_diff.Cell_Voltage_Diff_Warning);
GreenOutXY(x, 16, text);
dis_param->safety.cv_diff.Cell_Voltage_Diff_Warning = param->safety.cv_diff.Cell_Voltage_Diff_Warning;
}
// Cell Voltage Diff Recovery (Offset 4)
if (p || (dis_param->safety.cv_diff.Cell_Voltage_Diff_Recovery != param->safety.cv_diff.Cell_Voltage_Diff_Recovery))
{
sprintf((char *)text, "%4d", param->safety.cv_diff.Cell_Voltage_Diff_Recovery);
GreenOutXY(x, 17, text);
dis_param->safety.cv_diff.Cell_Voltage_Diff_Recovery = param->safety.cv_diff.Cell_Voltage_Diff_Recovery;
}
}
void SF1DisplayThermistorOpen(u8 p)
{
PDEVICE_PARAM param = &device_param;
PDEVICE_PARAM dis_param = &dis_device_param;
int x;
x = 72;
// Open Thermistor (Offset 0)
if (p || (dis_param->safety.temperature.Open_Thermistor != param->safety.temperature.Open_Thermistor))
{
FloatNormalOutIntXY(x, 19, (float)param->safety.temperature.Open_Thermistor / 10, 5, 1);
dis_param->safety.temperature.Open_Thermistor = param->safety.temperature.Open_Thermistor;
}
// Recovery Thermistor (Offset 2)
if (p || (dis_param->safety.temperature.Recovery_Thermistor != param->safety.temperature.Recovery_Thermistor))
{
FloatNormalOutIntXY(x, 20, (float)param->safety.temperature.Recovery_Thermistor / 10, 5, 1);
dis_param->safety.temperature.Recovery_Thermistor = param->safety.temperature.Recovery_Thermistor;
}
}
void ChgDisplayCellBalCfg(u8 p)
{
u8 text[20];
int x;
x = 19;
// Cell Balance Threshold (Offset 0)
if (p || (dis_device_param.chg_ctrl.cell_bal_cfg.Cell_Balance_Threshold != device_param.chg_ctrl.cell_bal_cfg.Cell_Balance_Threshold))
{
sprintf((char *)text, "%5d", device_param.chg_ctrl.cell_bal_cfg.Cell_Balance_Threshold);
GreenOutXY(x, 17, text);
dis_device_param.chg_ctrl.cell_bal_cfg.Cell_Balance_Threshold = device_param.chg_ctrl.cell_bal_cfg.Cell_Balance_Threshold;
}
// Cell Balance Window (Offset 2)
if (p || (dis_device_param.chg_ctrl.cell_bal_cfg.Cell_Balance_Window != device_param.chg_ctrl.cell_bal_cfg.Cell_Balance_Window))
{
sprintf((char *)text, "%5d", device_param.chg_ctrl.cell_bal_cfg.Cell_Balance_Window);
GreenOutXY(x, 18, text);
dis_device_param.chg_ctrl.cell_bal_cfg.Cell_Balance_Window = device_param.chg_ctrl.cell_bal_cfg.Cell_Balance_Window;
}
// Cell Balance Min (Offset 4)
if (p || (dis_device_param.chg_ctrl.cell_bal_cfg.Cell_Balance_Min != device_param.chg_ctrl.cell_bal_cfg.Cell_Balance_Min))
{
sprintf((char *)text, "%5d", device_param.chg_ctrl.cell_bal_cfg.Cell_Balance_Min);
GreenOutXY(x, 19, text);
dis_device_param.chg_ctrl.cell_bal_cfg.Cell_Balance_Min = device_param.chg_ctrl.cell_bal_cfg.Cell_Balance_Min;
}
x = 21;
// Cell Balance Interval (Offset 6)
if (p || (dis_device_param.chg_ctrl.cell_bal_cfg.Cell_Balance_Interval != device_param.chg_ctrl.cell_bal_cfg.Cell_Balance_Interval))
{
sprintf((char *)text, "%3d", device_param.chg_ctrl.cell_bal_cfg.Cell_Balance_Interval);
GreenOutXY(x, 20, text);
dis_device_param.chg_ctrl.cell_bal_cfg.Cell_Balance_Interval = device_param.chg_ctrl.cell_bal_cfg.Cell_Balance_Interval;
}
}
void SF1Display(u8 p)
{
SF1DisplayCellVoltage(p);
SF1DisplayTemperature(p);
SF1DisplaySVoltage(p);
SF1DisplayCellVoltageDiff(p);
SF1DisplayThermistorOpen(p);
ChgDisplayCellBalCfg(p);
}
u8 SetSF1_Param(u8 *text, u8 aDevice)
{
u16 size, i, j;
s16 aParam[4];
u8 temp[10];
u8 ret;
u8 cmd;
ret = 0;
size = 0;
while (text[size] != 0x00) size++; /* text의 전체 문자열 size 측정 */
switch (aDevice)
{
case '1': // SF1_VoltageSubClass
i = 0;
if (size < 2 ) return(1);
j = FIND_CHAR((u8 *)&text[i], temp, size - i, ' ');
i = i + j + 1;
temp[j] = 0x00;
cmd = temp[0];
j = FIND_CHAR((u8 *)&text[i], temp, size - i, ' ');
i = i + j + 1;
temp[j] = 0x00;
aParam[0] = StrToInt(temp, j); /* Value */
switch (cmd)
{
case '1': device_param.safety.voltage.COV_Threshold = aParam[0]; break;
case '2': device_param.safety.voltage.COV_Warning = aParam[0]; break;
case '3': device_param.safety.voltage.COV_Recovery = aParam[0]; break;
case '4': device_param.safety.voltage.CUV_Threshold = aParam[0]; break;
case '5': device_param.safety.voltage.CUV_Warning = aParam[0]; break;
case '6': device_param.safety.voltage.CUV_Recovery = aParam[0]; break;
default : return (1);
}
Save_Param();
break;
case '2': // SF1_VoltageSubClass
i = 0;
if (size < 2 ) return(1);
j = FIND_CHAR((u8 *)&text[i], temp, size - i, ' ');
i = i + j + 1;
temp[j] = 0x00;
cmd = temp[0];
j = FIND_CHAR((u8 *)&text[i], temp, size - i, ' ');
i = i + j + 1;
temp[j] = 0x00;
aParam[0] = StrToInt(temp, j); /* Value */
switch (cmd)
{
case '1': device_param.chg_ctrl.cell_bal_cfg.Cell_Balance_Threshold = aParam[0]; break;
case '2': device_param.chg_ctrl.cell_bal_cfg.Cell_Balance_Window = aParam[0]; break;
case '3': device_param.chg_ctrl.cell_bal_cfg.Cell_Balance_Min = aParam[0]; break;
case '4': device_param.chg_ctrl.cell_bal_cfg.Cell_Balance_Interval = aParam[0]; break;
default : return (1);
}
Save_Param();
break;
case '3': // SF1_TemperatureSubClass
i = 0;
if (size < 2 ) return(1);
j = FIND_CHAR((u8 *)&text[i], temp, size - i, ' ');
i = i + j + 1;
temp[j] = 0x00;
cmd = temp[0];
j = FIND_CHAR((u8 *)&text[i], temp, size - i, ' ');
i = i + j + 1;
temp[j] = 0x00;
aParam[0] = StrToInt(temp, j); /* Value */
switch (cmd)
{
case '1': device_param.safety.temperature.OT_Chg_Threshold = aParam[0]; break;
case '2': device_param.safety.temperature.OT_Chg_Warning = aParam[0]; break;
case '3': device_param.safety.temperature.OT_Chg_Recovery = aParam[0]; break;
case '4': device_param.safety.temperature.OT_Dsg_Threshold = aParam[0]; break;
case '5': device_param.safety.temperature.OT_Dsg_Warning = aParam[0]; break;
case '6': device_param.safety.temperature.OT_Dsg_Recovery = aParam[0]; break;
case '7': device_param.safety.temperature.LT_Chg_Threshold = aParam[0]; break;
case '8': device_param.safety.temperature.LT_Chg_Warning = aParam[0]; break;
case '9': device_param.safety.temperature.LT_Chg_Recovery = aParam[0]; break;
case 'a': device_param.safety.temperature.LT_Dsg_Threshold = aParam[0]; break;
case 'b': device_param.safety.temperature.LT_Dsg_Warning = aParam[0]; break;
case 'c': device_param.safety.temperature.LT_Dsg_Recovery = aParam[0]; break;
default : return (1);
}
Save_Param();
break;
case '4': // SF1_SVoltageSubClass
i = 0;
if (size < 2 ) return(1);
j = FIND_CHAR((u8 *)&text[i], temp, size - i, ' ');
i = i + j + 1;
temp[j] = 0x00;
cmd = temp[0];
j = FIND_CHAR((u8 *)&text[i], temp, size - i, ' ');
i = i + j + 1;
temp[j] = 0x00;
aParam[0] = StrToInt(temp, j); /* Value */
switch (cmd)
{
case '1': device_param.safety.voltage.SOV_Threshold = aParam[0]; break;
case '2': device_param.safety.voltage.SOV_Warning = aParam[0]; break;
case '3': device_param.safety.voltage.SOV_Recovery = aParam[0]; break;
case '4': device_param.safety.voltage.SUV_Threshold = aParam[0]; break;
case '5': device_param.safety.voltage.SUV_Warning = aParam[0]; break;
case '6': device_param.safety.voltage.SUV_Recovery = aParam[0]; break;
default : return (1);
}
Save_Param();
break;
case '6': // SF1_SocSubClass
i = 0;
if (size < 2 ) return(1);
j = FIND_CHAR((u8 *)&text[i], temp, size - i, ' ');
i = i + j + 1;
temp[j] = 0x00;
cmd = temp[0];
j = FIND_CHAR((u8 *)&text[i], temp, size - i, ' ');
i = i + j + 1;
temp[j] = 0x00;
aParam[0] = StrToInt(temp, j); /* Value */
switch (cmd)
{
case '1': device_param.safety.cv_diff.Cell_Voltage_Diff_Threshold = aParam[0]; break;
case '2': device_param.safety.cv_diff.Cell_Voltage_Diff_Warning = aParam[0]; break;
case '3': device_param.safety.cv_diff.Cell_Voltage_Diff_Recovery = aParam[0]; break;
case '4': device_param.safety.cv_diff.Cell_Voltage_Diff_Time = aParam[0]; break;
default : return (1);
}
Save_Param();
break;
case '7': // SF1_OpenThermistorSubClass
i = 0;
if (size < 2 ) return(1);
j = FIND_CHAR((u8 *)&text[i], temp, size - i, ' ');
i = i + j + 1;
temp[j] = 0x00;
cmd = temp[0];
j = FIND_CHAR((u8 *)&text[i], temp, size - i, ' ');
i = i + j + 1;
temp[j] = 0x00;
aParam[0] = StrToInt(temp, j); /* Value */
switch (cmd)
{
case '1': device_param.safety.temperature.Open_Thermistor = aParam[0]; break;
case '2': device_param.safety.temperature.Recovery_Thermistor = aParam[0]; break;
default : return (1);
}
Save_Param();
break;
default:
ret = 1;
break;
}
return(ret); /* setting value 정상 */
}
#endif //#ifdef CONSOLE_DEBUG
void SF1_InitData(void)
{
device_param.safety.voltage.COV_Threshold = 3850; // mV
device_param.safety.voltage.COV_Warning = 3750; // mV
device_param.safety.voltage.COV_Recovery = 3580; // mV
device_param.safety.voltage.CUV_Threshold = 2500; // mV
device_param.safety.voltage.CUV_Warning = 2800; // mV
device_param.safety.voltage.CUV_Recovery = 3000; // mV
device_param.safety.voltage.SOV_Threshold = (u16)(3.8 * CellQty * 100); // 10mV 3.8 * 20 = 68.4
device_param.safety.voltage.SOV_Warning = (u16)(3.7 * CellQty * 100); // 10mV 3.7 * 20 = 66.6
device_param.safety.voltage.SOV_Recovery = (u16)(3.6 * CellQty * 100); // 10mV 3.6 * 20 = 64.8
device_param.safety.voltage.SUV_Threshold = (u16)(2.6 * CellQty * 100); // 10mV 2.6 * 20 = 46.8
device_param.safety.voltage.SUV_Warning = (u16)(2.8 * CellQty * 100); // 10mV 2.8 * 20 = 50.4
device_param.safety.voltage.SUV_Recovery = (u16)(3.0 * CellQty * 100); // 10mV 3.0 * 20 = 54.0
device_param.safety.temperature.OT_Chg_Threshold = 600; // 0.1C
device_param.safety.temperature.OT_Chg_Warning = 580; // 0.1C
device_param.safety.temperature.OT_Chg_Recovery = 500; // 0.1C
device_param.safety.temperature.OT_Dsg_Threshold = 700; // 0.1C
device_param.safety.temperature.OT_Dsg_Warning = 680; // 0.1C
device_param.safety.temperature.OT_Dsg_Recovery = 500; // 0.1C
device_param.safety.temperature.LT_Chg_Threshold = -50; // 0.1C
device_param.safety.temperature.LT_Chg_Warning = -30; // 0.1C
device_param.safety.temperature.LT_Chg_Recovery = 0; // 0.1C
device_param.safety.temperature.LT_Dsg_Threshold = -200; // 0.1C
device_param.safety.temperature.LT_Dsg_Warning = -150; // 0.1C
device_param.safety.temperature.LT_Dsg_Recovery = -100; // 0.1C
device_param.safety.temperature.Open_Thermistor = -420; // 0.1C
device_param.safety.temperature.Recovery_Thermistor = -380; // 0.1C
device_param.safety.cv_diff.Cell_Voltage_Diff_Threshold = 1000; // mV
device_param.safety.cv_diff.Cell_Voltage_Diff_Warning = 300; // mV
device_param.safety.cv_diff.Cell_Voltage_Diff_Recovery = 100; // mV
device_param.safety.cv_diff.Cell_Voltage_Diff_Time = 60; // mV
device_param.chg_ctrl.cell_bal_cfg.Cell_Balance_Threshold = 3300; // mV
device_param.chg_ctrl.cell_bal_cfg.Cell_Balance_Window = 60; // mV
device_param.chg_ctrl.cell_bal_cfg.Cell_Balance_Min = 5; // mV
device_param.chg_ctrl.cell_bal_cfg.Cell_Balance_Interval = 5; // Sec
}

27
APP/dflash_sf1.h Normal file
View File

@@ -0,0 +1,27 @@
/*****************************************************************************
*
* File : dflash_cfg.h
* Compiler : IAR C 6.30
* Revision : $Revision: 1.0 $
* Date : $Date: 2015 / 03 / 13
* Updated by : $Author: Jongkwang Woo
*
* Support mail : spirit0305@naver.com
*
* Description : Header file for dflash_cfg.c
*
****************************************************************************/
#ifndef _DFLASH_SF1_H_
#define _DFLASH_SF1_H_
#include <stm32f10x.h>
#pragma pack(1)
void SF1_InitData(void);
void SF1Display(u8 p);
s8 Process_DataSF1Set(u8 *text, u16 size);
#endif

389
APP/display_status.c Normal file
View File

@@ -0,0 +1,389 @@
/* Copyright (c) 2012-2013 The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
* only version 2 as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
*/
/*
* High Level description:
* http://www.ti.com/lit/ds/symlink/bq28400.pdf
* Thechnical Reference:
* http://www.ti.com/lit/ug/sluu431/sluu431.pdf
*/
#ifdef CONSOLE_DEBUG
#include "includes.h"
#include "display_status.h"
#include "device_param.h"
#include "asutil.h"
#include "can_comm.h"
#include "delay.h"
#include "io.h"
#include "alarm.h"
void DisplayMsg(u16 x, u16 y, u16 data, u8 bit, u8 *msg)
{
if ((data & BIT(bit)))
RedOutXY(x, y, msg);
else
GreenOutXY(x, y, msg);
}
void DisplayMsg1(u16 x, u16 y, u16 data, u8 bit, u8 *msg)
{
if ((data & BIT(bit)))
YellowOutXY(x, y, msg);
else
GreenOutXY(x, y, msg);
}
void ODisplayBatteryStatus(u8 p)
{
u16 x;
if (p ||(dis_device_status.battery_status.value != device_status.battery_status.value))
{
x = 28;
DisplayMsg(x, 3, device_status.battery_status.value, 15, (u8 *)"ACB"); x += 4;
DisplayMsg(x, 3, device_status.battery_status.value, 14, (u8 *)"TCA"); x += 4;
DisplayMsg(x, 3, device_status.battery_status.value, 13, (u8 *)"TDA"); x += 4;
DisplayMsg(x, 3, device_status.battery_status.value, 12, (u8 *)"AFE"); x += 4;
x += 4;
DisplayMsg(x, 3, device_status.battery_status.value, 10, (u8 *)"ZVC"); x += 4;
DisplayMsg(x, 3, device_status.battery_status.value, 9, (u8 *)"F-C"); x += 4;
DisplayMsg(x, 3, device_status.battery_status.value, 8, (u8 *)"F-D"); x += 4;
x = 28;
DisplayMsg(x, 4, device_status.battery_status.value, 7, (u8 *)"INI"); x += 4;
DisplayMsg(x, 4, device_status.battery_status.value, 6, (u8 *)"MD "); x += 4;
DisplayMsg(x, 4, device_status.battery_status.value, 5, (u8 *)"FC "); x += 4;
DisplayMsg(x, 4, device_status.battery_status.value, 4, (u8 *)"FD "); x += 4;
DisplayMsg(x, 4, device_status.battery_status.value, 3, (u8 *)"RXM"); x += 4;
DisplayMsg(x, 4, device_status.battery_status.value, 2, (u8 *)"ZVC"); x += 4;
DisplayMsg(x, 4, device_status.battery_status.value, 1, (u8 *)"F-C"); x += 4;
DisplayMsg(x, 4, device_status.battery_status.value, 0, (u8 *)"F-D"); x += 4;
dis_device_status.battery_status.value = device_status.battery_status.value;
}
}
void ODisplayWarningStatus(u8 p)
{
u16 x;
if (p ||(dis_device_status.warning.value != device_status.warning.value))
{
x = 28;
x += 4;
x += 4;
x += 4;
DisplayMsg1(x, 6, device_status.warning.value, 12, (u8 *)"L-C"); x += 4;
DisplayMsg1(x, 6, device_status.warning.value, 11, (u8 *)"LTD"); x += 4;
DisplayMsg1(x, 6, device_status.warning.value, 10, (u8 *)"LTC"); x += 4;
DisplayMsg1(x, 6, device_status.warning.value, 9, (u8 *)"HTD"); x += 4;
DisplayMsg1(x, 6, device_status.warning.value, 8, (u8 *)"HTC"); x += 4;
x = 28;
x += 4;
x += 4;
DisplayMsg1(x, 7, device_status.warning.value, 5, (u8 *)"OCD"); x += 4;
DisplayMsg1(x, 7, device_status.warning.value, 4, (u8 *)"OCC"); x += 4;
DisplayMsg1(x, 7, device_status.warning.value, 3, (u8 *)"CUV"); x += 4;
DisplayMsg1(x, 7, device_status.warning.value, 2, (u8 *)"SUV"); x += 4;
DisplayMsg1(x, 7, device_status.warning.value, 1, (u8 *)"COV"); x += 4;
DisplayMsg1(x, 7, device_status.warning.value, 0, (u8 *)"SOV"); x += 4;
dis_device_status.warning.value = device_status.warning.value;
}
}
void ODisplayProtectStatus(u8 p)
{
u16 x;
if (p ||(dis_device_status.protection.value != device_status.protection.value))
{
x = 28;
DisplayMsg(x, 9, device_status.protection.value, 15, (u8 *)"AFE"); x += 4;
x += 4;
DisplayMsg(x, 9, device_status.protection.value, 13, (u8 *)"SC "); x += 4;
x += 4;
DisplayMsg(x, 9, device_status.protection.value, 11, (u8 *)"LTD"); x += 4;
DisplayMsg(x, 9, device_status.protection.value, 10, (u8 *)"LTC"); x += 4;
DisplayMsg(x, 9, device_status.protection.value, 9, (u8 *)"HTD"); x += 4;
DisplayMsg(x, 9, device_status.protection.value, 8, (u8 *)"HTC"); x += 4;
x = 28;
x += 4;
x += 4;
DisplayMsg(x, 10, device_status.protection.value, 5, (u8 *)"OCD"); x += 4;
DisplayMsg(x, 10, device_status.protection.value, 4, (u8 *)"OCC"); x += 4;
DisplayMsg(x, 10, device_status.protection.value, 3, (u8 *)"CUV"); x += 4;
DisplayMsg(x, 10, device_status.protection.value, 2, (u8 *)"SUV"); x += 4;
DisplayMsg(x, 10, device_status.protection.value, 1, (u8 *)"COV"); x += 4;
DisplayMsg(x, 10, device_status.protection.value, 0, (u8 *)"SOV"); x += 4;
dis_device_status.protection.value = device_status.protection.value;
}
}
void ODisplayOperatingStatus(u8 p)
{
u8 text[20];
if (p ||(dis_device_status.op_status != device_status.op_status))
{
switch (device_status.op_status)
{
case 0: // Stand by
GreenOutXY(11, 9, (u8 *)"STAND BY ");
break;
case 1: // Charging
GreenOutXY(11, 9, (u8 *)"CHARGING ");
break;
case 2: // Discharging
GreenOutXY(11, 9, (u8 *)"DISCHARGING");
break;
case 3: // Float
GreenOutXY(11, 9, (u8 *)"FLOAT ");
break;
case 4: // Float
GreenOutXY(11, 9, (u8 *)"WARMING UP ");
break;
default:
sprintf((char *)text, "UNKNOWN(%d)", device_status.op_status);
GreenOutXY(11, 9, text);
break;
}
dis_device_status.op_status = device_status.op_status;
}
}
void ODisplayAlarmStatus(u8 p)
{
if (p ||(dis_device_status.alarm_status != device_status.alarm_status))
{
switch (device_status.alarm_status)
{
case 0: // Normal
GreenOutXY (11, 10, (u8 *)"NORMAL ");
break;
case 1: // Warning
YellowOutXY(11, 10, (u8 *)"WARNING ");
break;
case 2: // Protection
RedOutXY (11, 10, (u8 *)"PROTECTION");
break;
case 3: // WarmingUp
GreenOutXY (11, 10, (u8 *)"WARMING UP");
break;
}
dis_device_status.alarm_status = device_status.alarm_status;
}
}
void ODisplayDeviceLiveStatus(u8 p)
{
uint8_t text[20];
// Device ID
if (p)
{
sprintf((char *)text, "%3d", GetDevAddr());
GreenOutXY(15, 2, text);
}
// Heartbeat
if (p || (dis_device_value.Heartbeat != device_value.Heartbeat))
{
sprintf((char *)text, "%7d", device_value.Heartbeat);
GreenOutXY(11, 3, text);
dis_device_value.Heartbeat = device_value.Heartbeat;
}
}
void ODisplayDeviceValue(u8 p)
{
float aParam;
static int mcount = 0;
if (p|| (mcount == 0))
{
// Battery Voltage
if (p || (dis_device_value.BatVoltage != device_value.BatVoltage))
{
aParam = (float)device_value.BatVoltage / 100;
FloatNormalOutIntXY(12, 5, aParam, 6, 1);
dis_device_value.BatVoltage = device_value.BatVoltage;
}
// Current
if (p || (dis_device_value.Current != device_value.Current))
{
aParam = (float)device_value.Current / 10;
FloatNormalOutIntXY(12, 6, aParam, 6, 1);
dis_device_value.Current = device_value.Current;
}
// RelativeStateOfCharge
if (p || (dis_device_value.RelativeStateOfCharge != device_value.RelativeStateOfCharge))
{
aParam = (float)device_value.RelativeStateOfCharge / 10;
FloatNormalOutIntXY(13, 7, aParam, 5, 1);
dis_device_value.RelativeStateOfCharge = device_value.RelativeStateOfCharge;
}
mcount = 20;
}
mcount--;
}
void ODisplayDeviceStatus(u8 p)
{
u8 text[20];
// OP Status
ODisplayOperatingStatus(p);
ODisplayAlarmStatus(p);
ODisplayBatteryStatus(p);
// Warning Status
if (p || (dis_device_status.warning.value != device_status.warning.value))
{
ODisplayWarningStatus(true);
sprintf((char *)text, "%04X", *(u16 *)&device_status.warning.value);
GreenOutXY(72, 3, text);
dis_device_status.warning.value = device_status.warning.value;
}
// Protection Status
if (p || (dis_device_status.protection.value != device_status.protection.value))
{
ODisplayProtectStatus(true);
sprintf((char *)text, "%04X", *(u16 *)&device_status.protection.value);
GreenOutXY(72, 4, text);
dis_device_status.protection.value = device_status.protection.value;
}
static u8 disSleepMode = 0;
if (p || (disSleepMode != GetSleepMode()))
{
switch (GetSleepMode())
{
case 0: // Normal
GreenOutXY (32, 16, (u8 *)"NORM ");
break;
case 1: // Sleep
RedOutXY (32, 16, (u8 *)"SLEEP");
break;
}
disSleepMode = GetSleepMode();
}
}
void ODisplayCellStatus(u8 p)
{
u16 i, x, y;
float aParam;
static int vcount = 10;
if (p || (vcount == 0))
{
for (i = 0; i < CellQty; i++)
{
x = 5 + ((i / 10) * 11);
y = 12 + (i % 10);
if (p ||(dis_device_value.Cell.voltage[i] != device_value.Cell.voltage[i])
||((dis_device_status.cellbalance.value >> i) & 0x00000001) != ((device_status.cellbalance.value >> i) & 0x00000001))
{
aParam = (float)device_value.Cell.voltage[i] / CELL_DIV_UNIT;
if ((device_status.cellbalance.value >> i) & 0x00000001)
FloatColorOutIntXY(DISPLAY_YELLOW, x, y, aParam, 6, 4);
else
FloatColorOutIntXY(DISPLAY_GREEN, x, y, aParam, 6, 4);
dis_device_value.Cell.voltage[i] = device_value.Cell.voltage[i];
}
}
dis_device_status.cellbalance.value = device_status.cellbalance.value;
vcount = 10;
}
vcount--;
}
void ODisplayAvgValue(u8 p)
{
float aParam;
// Cell Voltage Max, Min, Avg
if (p || (dis_device_value.Cell.avg.Max.value != device_value.Cell.avg.Max.value)) {
aParam = (float)device_value.Cell.avg.Max.value / CELL_DIV_UNIT;
FloatNormalOutIntXY(70, 6 , aParam, 6, 4);
dis_device_value.Cell.avg.Max.value = device_value.Cell.avg.Max.value;
}
if (p || (dis_device_value.Cell.avg.avg != device_value.Cell.avg.avg)) {
aParam = (float)device_value.Cell.avg.avg / CELL_DIV_UNIT;
FloatNormalOutIntXY(70, 7 , aParam, 6, 4);
dis_device_value.Cell.avg.avg = device_value.Cell.avg.avg;
}
if (p || (dis_device_value.Cell.avg.Min.value != device_value.Cell.avg.Min.value)) {
aParam = (float)device_value.Cell.avg.Min.value / CELL_DIV_UNIT;
FloatNormalOutIntXY(70, 8 , aParam, 6, 4);
dis_device_value.Cell.avg.Min.value = device_value.Cell.avg.Min.value;
}
if (p || (dis_device_value.Cell.avg.diff != device_value.Cell.avg.diff)) {
aParam = (float)device_value.Cell.avg.diff / CELL_DIV_UNIT;
FloatNormalOutIntXY(70, 9 , aParam, 6, 4);
dis_device_value.Cell.avg.diff = device_value.Cell.avg.diff;
}
// Temp Max, Min, Avg
if (p || (dis_device_value.Temp.avg.Max.value != device_value.Temp.avg.Max.value))
{
aParam = (float)device_value.Temp.avg.Max.value / 10;
FloatNormalOutIntXY(71, 13, aParam, 5, 1);
dis_device_value.Temp.avg.Max.value = device_value.Temp.avg.Max.value;
}
if (p || (dis_device_value.Temp.avg.avg != device_value.Temp.avg.avg))
{
aParam = (float)device_value.Temp.avg.avg / 10;
FloatNormalOutIntXY(71, 14, aParam, 5, 1);
dis_device_value.Temp.avg.avg = device_value.Temp.avg.avg;
}
if (p || (dis_device_value.Temp.avg.Min.value != device_value.Temp.avg.Min.value))
{
aParam = (float)device_value.Temp.avg.Min.value / 10;
FloatNormalOutIntXY(71, 15, aParam, 5, 1);
dis_device_value.Temp.avg.Min.value = device_value.Temp.avg.Min.value;
}
if (p || (dis_device_value.Temp.avg.diff != device_value.Temp.avg.diff))
{
aParam = (float)device_value.Temp.avg.diff / 10;
FloatNormalOutIntXY(71, 16, aParam, 5, 1);
dis_device_value.Temp.avg.diff = device_value.Temp.avg.diff;
}
}
void ODisplayDevice(u8 p)
{
ODisplayDeviceLiveStatus(p);
ODisplayDeviceStatus(p);
ODisplayDeviceValue(p);
ODisplayCellStatus(p);
ODisplayAvgValue(p);
}
#endif // #ifdef CONSOLE_DEBUG

22
APP/display_status.h Normal file
View File

@@ -0,0 +1,22 @@
/*****************************************************************************
*
* File : device_status.h
* Compiler : IAR C 6.30
* Revision : $Revision: 1.0 $
* Date : $Date: 2015 / 03 / 13
* Updated by : $Author: Jongkwang Woo
*
* Support mail : spirit0305@naver.com
*
* Description : Header file for device_status.c
*
****************************************************************************/
#ifndef _DISPLAY_STATUS_H_
#define _DISPLAY_STATUS_H_
#include <stm32f10x.h>
void ODisplayDevice(u8 p);
#endif

214
APP/flash_if.c Normal file
View File

@@ -0,0 +1,214 @@
/**
******************************************************************************
* @file STM32F4xx_IAP/src/flash_if.c
* @author MCD Application Team
* @version V1.0.0
* @date 10-October-2011
* @brief This file provides all the memory related operation functions.
******************************************************************************
* @attention
*
* THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS
* WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE
* TIME. AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY
* DIRECT, INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING
* FROM THE CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE
* CODING INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS.
*
* <h2><center>&copy; COPYRIGHT 2011 STMicroelectronics</center></h2>
******************************************************************************
*/
/** @addtogroup STM32F4xx_IAP
* @{
*/
/* Includes ------------------------------------------------------------------*/
#include <stdio.h>
#include <string.h>
#include "flash_if.h"
/* Private typedef -----------------------------------------------------------*/
/* Private define ------------------------------------------------------------*/
/* Private macro -------------------------------------------------------------*/
/* Private variables ---------------------------------------------------------*/
FW_INFO fwinfo;
/* Private function prototypes -----------------------------------------------*/
/* Private functions ---------------------------------------------------------*/
/**
* @brief Unlocks Flash for write access
* @param None
* @retval None
*/
void FLASH_If_Init(void)
{
FLASH_Unlock();
/* Clear pending flags (if any) */
FLASH_ClearFlag(FLASH_FLAG_EOP | FLASH_FLAG_OPTERR | FLASH_FLAG_WRPRTERR |
FLASH_FLAG_PGERR | FLASH_FLAG_BANK1_EOP | FLASH_FLAG_BANK1_PGERR | FLASH_FLAG_BANK1_WRPRTERR);
}
/**
* @brief Calculate the number of pages
* @param Size: The image size
* @retval The number of pages
*/
uint32_t FLASH_PagesMask(__IO uint32_t Size)
{
uint32_t pagenumber = 0x0;
uint32_t size = Size;
if ((size % PAGE_SIZE) != 0)
{
pagenumber = (size / PAGE_SIZE) + 1;
}
else
{
pagenumber = size / PAGE_SIZE;
}
return pagenumber;
}
/**
* @brief This function does an erase of all user flash area
* @param StartSector: start of user flash area
* @retval 0: user flash area successfully erased
* 1: error occurred
*/
uint32_t FLASH_If_Erase(uint32_t EraseStartAddr, uint32_t uSize)
{
FLASH_Status FLASHStatus = FLASH_COMPLETE;
uint32_t NbrOfPage = 0;
/* init flash */
FLASH_If_Init();
/* Erase the needed pages where the user application will be loaded */
/* Define the number of page to be erased */
NbrOfPage = FLASH_PagesMask(uSize);
/* Erase the FLASH pages */
for (int EraseCounter = 0; (EraseCounter < NbrOfPage) && (FLASHStatus == FLASH_COMPLETE); EraseCounter++)
{
FLASHStatus = FLASH_ErasePage(EraseStartAddr + (PAGE_SIZE * EraseCounter));
}
return (0);
}
/**
* @brief This function writes a data buffer in flash (data are 32-bit aligned).
* @note After writing data buffer, the flash content is checked.
* @param FlashAddress: start address for writing data buffer
* @param Data: pointer on data buffer
* @param DataLength: length of data buffer (unit is 32-bit word)
* @retval 0: Data successfully written to Flash memory
* 1: Error occurred while writing data in Flash memory
* 2: Written Data in flash memory is different from expected one
*/
uint32_t FLASH_If_Write(__IO uint32_t* FlashAddress, uint32_t* Data ,uint32_t DataLength)
{
uint32_t i = 0;
for (i = 0; (i < DataLength) && (*FlashAddress <= (mBMS_FLASH_END_ADDR - 4)); i++)
{
/* Device voltage range supposed to be [2.7V to 3.6V], the operation will
be done by word */
if (FLASH_ProgramWord(*FlashAddress, *(uint32_t*)(Data + i)) == FLASH_COMPLETE)
{
/* Check the written value */
if (*(uint32_t*)*FlashAddress != *(uint32_t*)(Data + i))
{
/* Flash content doesn't match SRAM content */
return (2);
}
/* Increment FLASH destination address */
*FlashAddress += 4;
}
else
{
/* Error occurred while writing data in Flash memory */
return (1);
}
}
return (0);
}
/**
* @brief Disable the write protection of desired pages
* @param None
* @retval None
*/
void FLASH_DisableWriteProtectionPages(void)
{
uint32_t UserMemoryMask = 0;
uint32_t useroptionbyte = 0, WRPR = 0;
uint16_t var1 = OB_IWDG_SW, var2 = OB_STOP_NoRST, var3 = OB_STDBY_NoRST;
FLASH_Status status = FLASH_BUSY;
WRPR = FLASH_GetWriteProtectionOptionByte();
/* Test if user memory is write protected */
if ((WRPR & UserMemoryMask) != UserMemoryMask)
{
useroptionbyte = FLASH_GetUserOptionByte();
UserMemoryMask |= WRPR;
status = FLASH_EraseOptionBytes();
if (UserMemoryMask != 0xFFFFFFFF)
{
status = FLASH_EnableWriteProtection((uint32_t)~UserMemoryMask);
}
/* Test if user Option Bytes are programmed */
if ((useroptionbyte & 0x07) != 0x07)
{
/* Restore user Option Bytes */
if ((useroptionbyte & 0x01) == 0x0)
{
var1 = OB_IWDG_HW;
}
if ((useroptionbyte & 0x02) == 0x0)
{
var2 = OB_STOP_RST;
}
if ((useroptionbyte & 0x04) == 0x0)
{
var3 = OB_STDBY_RST;
}
FLASH_UserOptionByteConfig(var1, var2, var3);
}
if (status == FLASH_COMPLETE)
{
printf("Write Protection disabled...\r\n");
printf("...and a System Reset will be generated to re-load the new option bytes\r\n");
/* Generate System Reset to load the new option byte values */
NVIC_SystemReset();
}
else
{
printf("Error: Flash write unprotection failed...\r\n");
}
}
else
{
printf("Flash memory not write protected\r\n");
}
}
/**
* @}
*/
/******************* (C) COPYRIGHT 2011 STMicroelectronics *****END OF FILE****/

82
APP/flash_if.h Normal file
View File

@@ -0,0 +1,82 @@
/**
******************************************************************************
* @file STM32F4xx_IAP/inc/flash_if.h
* @author MCD Application Team
* @version V1.0.0
* @date 10-October-2011
* @brief This file provides all the headers of the flash_if functions.
******************************************************************************
* @attention
*
* THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS
* WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE
* TIME. AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY
* DIRECT, INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING
* FROM THE CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE
* CODING INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS.
*
* <h2><center>&copy; COPYRIGHT 2011 STMicroelectronics</center></h2>
******************************************************************************
*/
/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef __FLASH_IF_H
#define __FLASH_IF_H
/* Includes ------------------------------------------------------------------*/
#include "stm32f10x.h"
/* Exported types ------------------------------------------------------------*/
typedef struct
{
u32 AppFileSize;
u8 BootVer[4];
u8 AppVer[4];
u8 FileName[30];
u8 BootUpdate;
u8 AppUpdate;
} FW_INFO;
/* Exported constants --------------------------------------------------------*/
/* Base address of the Flash sectors */
#define FLASH_BASE_ADDRESS 0x8000000
#if defined (STM32F10X_MD) || defined (STM32F10X_MD_VL)
#define PAGE_SIZE (0x400) /* 1 Kbyte */
#define FLASH_SIZE (0x20000) /* 128 KBytes */
#elif defined STM32F10X_CL
#define PAGE_SIZE (0x800) /* 2 Kbytes */
#define FLASH_SIZE (0x40000) /* 256 KBytes */
#elif defined STM32F10X_HD || defined (STM32F10X_HD_VL)
#define PAGE_SIZE (0x800) /* 2 Kbytes */
#define FLASH_SIZE (0x80000) /* 512 KBytes */
#elif defined STM32F10X_XL
#define PAGE_SIZE (0x800) /* 2 Kbytes */
#define FLASH_SIZE (0x100000) /* 1 MByte */
#else
#error "Please select first the STM32 device to be used (in stm32f10x.h)"
#endif
/* Define the address from where user application will be loaded. */
#define mBMS_FLASH_END_ADDR 0x8020000
#define APPLICATION_ADDRESS 0x8003000
#define mBMS_PARAM_BASE_ADDR 0x8002800
#define mBMS_FW_INFO_BASE_ADDR 0x8002C00
#define mBMS_FW_ADDRESS 0x8012000
#define mBMS_FW_END_ADDRESS 0x8020000
#define mBMS_FW_MAX_SIZE mBMS_FW_END_ADDRESS - mBMS_FW_ADDRESS
/* Exported macro ------------------------------------------------------------*/
/* Exported functions ------------------------------------------------------- */
void FLASH_If_Init(void);
uint32_t FLASH_If_Erase(uint32_t EraseStartAddr, uint32_t uSize);
uint32_t FLASH_If_Write(__IO uint32_t* FlashAddress, uint32_t* Data, uint32_t DataLength);
void FLASH_DisableWriteProtectionPages(void);
extern FW_INFO fwinfo;
#endif /* __FLASH_IF_H */
/*******************(C)COPYRIGHT 2011 STMicroelectronics *****END OF FILE******/

215
APP/io.c Normal file
View File

@@ -0,0 +1,215 @@
/**
******************************************************************************
* File Name : io.c
* Description : This file provides code for the digital input/output.
******************************************************************************
* @attention
*
* <h2><center>&copy; 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 "delay.h"
#include "led.h"
#include "device_param.h"
#include "asutil.h"
#include "dflash_sf1.h"
#include "alarm.h"
#include "io.h"
#include "temp.h"
/* Private typedef -----------------------------------------------------------*/
/* Private define ------------------------------------------------------------*/
#define IO_TASK_TIME 10 // 50ms TASK
#define RUN_LED_ONOFF_TIME 500 // 500ms
#define DIDCount 2
/*********************** Digital Input Define *********************************/
/* Private macro -------------------------------------------------------------*/
/* Private variables ---------------------------------------------------------*/
u8 device_addr = 0;
TDEVICE_STATUS alarm_device_status;
u8 RunLedFlag = false;
u16 RunLedTick = 0;
u8 RemoteReset = false;
/* Private function prototypes -----------------------------------------------*/
void Led_Process(void);
void dec_led_time(u32 tick);
/* Private function ----------------------------------------------------------*/
void InitDIODevice(void)
{
memset(&alarm_device_status, 0x00, sizeof(TDEVICE_STATUS));
}
u8 GetDevAddrMem(void)
{
return device_param.info.DevAddr;
}
u8 GetDevAddr(void)
{
return device_addr;
}
void SetRemoteReset(void)
{
RemoteReset = true;
}
void App_TaskIO(void)
{
InitDIODevice();
while (DEF_TRUE)
{
device_addr = GetDevAddrMem();
ProcessAlarm();
Led_Process();
if (RemoteReset == true) {
delay_os_ms(100);
Sys_Soft_Reset();
}
delay_os_ms(IO_TASK_TIME);
}
}
void DecIOTaskTick(u32 tick)
{
dec_led_time(tick);
}
void dec_led_time(u32 tick)
{
if (RunLedTick > 0)
{
if (RunLedTick > tick)
RunLedTick -= tick;
else
RunLedTick = 0;
}
}
void Alarm_Led_Process(void)
{
switch (device_status.alarm_status) {
case 0: // Normal
GREEN_LED = ON;
RED_LED = OFF;
break;
case 1: // Warning
GREEN_LED = ON;
RED_LED = ON;
break;
case 2: // Protection
GREEN_LED = OFF;
RED_LED = ON;
break;
case 3: // WarmingUp
GREEN_LED = ON;
RED_LED = OFF;
break;
}
}
void RUN_LED_Process(void)
{
if (RunLedFlag == true) {
if (RunLedTick == 0) {
BD_RUN_LED = ON;
RunLedTick = RUN_LED_ONOFF_TIME;
RunLedFlag = false;
}
} else {
if (RunLedTick == 0) {
BD_RUN_LED = OFF;
RunLedTick = RUN_LED_ONOFF_TIME;
RunLedFlag = true;
}
}
}
void Led_Process(void)
{
if (GetSleepMode() == false) {
RUN_LED_Process();
Alarm_Led_Process();
} else {
BD_RUN_LED = OFF;
GREEN_LED = OFF;
RED_LED = OFF;
}
}
void MP2642_Enable_Ctrl(uint8_t ch, uint8_t enable)
{
switch (ch) {
case 0: MP2642_ENABLE_01 = enable; break;
case 1: MP2642_ENABLE_02 = enable; break;
case 2: MP2642_ENABLE_03 = enable; break;
case 3: MP2642_ENABLE_04 = enable; break;
case 4: MP2642_ENABLE_05 = enable; break;
case 5: MP2642_ENABLE_06 = enable; break;
case 6: MP2642_ENABLE_07 = enable; break;
case 7: MP2642_ENABLE_08 = enable; break;
case 8: MP2642_ENABLE_09 = enable; break;
case 9: MP2642_ENABLE_10 = enable; break;
case 10: MP2642_ENABLE_11 = enable; break;
case 11: MP2642_ENABLE_12 = enable; break;
case 12: MP2642_ENABLE_13 = enable; break;
case 13: MP2642_ENABLE_14 = enable; break;
case 14: MP2642_ENABLE_15 = enable; break;
case 15: MP2642_ENABLE_16 = enable; break;
case 16: MP2642_ENABLE_17 = enable; break;
case 17: MP2642_ENABLE_18 = enable; break;
case 18: MP2642_ENABLE_19 = enable; break;
case 19: MP2642_ENABLE_20 = enable; break;
default: break;
}
}
void MP2642_EnaDis_All(uint8_t enable)
{
MP2642_ENABLE_01 = enable;
MP2642_ENABLE_02 = enable;
MP2642_ENABLE_03 = enable;
MP2642_ENABLE_04 = enable;
MP2642_ENABLE_05 = enable;
MP2642_ENABLE_06 = enable;
MP2642_ENABLE_07 = enable;
MP2642_ENABLE_08 = enable;
MP2642_ENABLE_09 = enable;
MP2642_ENABLE_10 = enable;
MP2642_ENABLE_11 = enable;
MP2642_ENABLE_12 = enable;
MP2642_ENABLE_13 = enable;
MP2642_ENABLE_14 = enable;
MP2642_ENABLE_15 = enable;
MP2642_ENABLE_16 = enable;
MP2642_ENABLE_17 = enable;
MP2642_ENABLE_18 = enable;
MP2642_ENABLE_19 = enable;
MP2642_ENABLE_20 = enable;
}

33
APP/io.h Normal file
View File

@@ -0,0 +1,33 @@
/*****************************************************************************
*
* MSO Corporation
*
* File : io.h
* Compiler : IAR C 5.30C Kickstart
* Revision : $Revision: 1.0 $
* Date : $Date: 2012 / 4 / 30
* Updated by : $Author: Jongkwang Woo
*
* Support mail : spirit0305@naver.com
*
* Description : Header file for io.c
*
****************************************************************************/
#ifndef _IO_H_
#define _IO_H_
#include <stm32f10x.h>
void App_TaskIO(void);
void DecIOTaskTick(u32 tick);
u8 GetDevAddr(void);
void SetRemoteReset(void);
void MP2642_Enable_Ctrl(uint8_t ch, uint8_t enable);
void MP2642_EnaDis_All(uint8_t enable);
#endif

1532
APP/ltc6811_comm.c Normal file

File diff suppressed because it is too large Load Diff

1532
APP/ltc6811_daisy.c Normal file

File diff suppressed because it is too large Load Diff

837
APP/ltc6811_daisy.h Normal file
View File

@@ -0,0 +1,837 @@
/************************************
REVISION HISTORY
$Revision: 1200 $
$Date: 2016-3-9
Copyright (c) 2015, Linear Technology Corp.(LTC)
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
2. 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.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, 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.
The views and conclusions contained in the software and documentation are those
of the authors and should not be interpreted as representing official policies,
either expressed or implied, of Linear Technology Corp.
The Linear Technology Linduino is not affiliated with the official Arduino team.
However, the Linduino is only possible because of the Arduino team's commitment
to the open-source community. Please, visit http://www.arduino.cc and
http://store.arduino.cc , and consider a purchase that will help fund their
ongoing work.
Copyright 2015 Linear Technology Corp. (LTC)
***********************************************************/
/*! @file
@ingroup ltc68111
Header for ltc6811-1 Multicell Battery Monitor
*/
#ifndef LTC68111_H
#define LTC68111_H
#ifndef LTC6811_CS
#define LTC6811_CS QUIKEVAL_CS
#endif
#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 CELL_CHANNELS 12
#define AUX_CHANNELS 6
#define STAT_CHANNELS 4
#define CELL 1
#define AUX 2
#define STAT 3
/*! 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 ltc6811_diagn();
//! 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 ltc6811_pladc();
//! 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();
/*! 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:
|Variable|Function |
|--------|----------------------------------------------|
| MD | Determines the filter corner of the ADC |
| CH | Determines which cell channels are converted |
| DCP | Determines if Discharge is Permitted |
| ST | Determines which Self Test is executed |
Command Code:
-------------
|CMD[0:1] | 15 | 14 | 13 | 12 | 11 | 10 | 9 | 8 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
|-----------|-------|-------|-------|-------|-------|-------|-------|-------|-------|-------|-------|-------|-------|-------|-------|-------|
|ADCV: | 0 | 0 | 0 | 0 | 0 | 0 | 1 | MD[1] | MD[2] | 1 | 1 | DCP | 0 | CH[2] | CH[1] | CH[0] |
*/
void ltc6811_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
Command Code:
-------------
|CMD[0:1] | 15 | 14 | 13 | 12 | 11 | 10 | 9 | 8 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
|-----------|-------|-------|-------|-------|-------|-------|-------|-------|-------|-------|-------|-------|-------|-------|-------|-------|
|ADCVAX: | 0 | 0 | 0 | 0 | 0 | 1 | 0 | MD[1] | MD[2] | 1 | 1 | DCP | 1 | 1 | 1 | 1 |
*/
void ltc6811_adcvax(
uint8_t MD, //!< ADC Conversion Mode
uint8_t DCP //!< Controls if Discharge is permitted during conversion
);
/*! Starts cell voltage self test conversion
Command Code:
-------------
|CMD[0:1] | 15 | 14 | 13 | 12 | 11 | 10 | 9 | 8 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
|-----------|-------|-------|-------|-------|-------|-------|-------|-------|-------|-------|-------|-------|-------|-------|-------|-------|
|CVST: | 0 | 0 | 0 | 0 | 0 | 0 | 1 | MD[1] | MD[2] | ST[1] | ST[0] | 0 | 0 | 1 | 1 | 1 |
*/
void ltc6811_cvst(
uint8_t MD, //!< ADC Conversion Mode
uint8_t ST //!< Self Test Mode
);
/*! Starts cell voltage and SOC conversion
Command Code:
-------------
|CMD[0:1] | 15 | 14 | 13 | 12 | 11 | 10 | 9 | 8 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
|-----------|-------|-------|-------|-------|-------|-------|-------|-------|-------|-------|-------|-------|-------|-------|-------|-------|
|ADCVSC: | 0 | 0 | 0 | 0 | 0 | 1 | 0 | MD[1] | MD[2] | 1 | 1 | DCP | 0 | 1 | 1 | 1 |
*/
void ltc6811_adcvsc(
uint8_t MD, //!< ADC Conversion Mode
uint8_t DCP //!< Controls if Discharge is permitted during conversion
);
/*! Starts cell voltage overlap conversion
Command Code:
-------------
|CMD[0:1] | 15 | 14 | 13 | 12 | 11 | 10 | 9 | 8 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
|-----------|-------|-------|-------|-------|-------|-------|-------|-------|-------|-------|-------|-------|-------|-------|-------|-------|
|ADCV: | 0 | 0 | 0 | 0 | 0 | 0 | 1 | MD[1] | MD[2] | 0 | 0 | DCP | 0 | 0 | 0 | 1 |
*/
void ltc6811_adol(
uint8_t MD, //!< ADC Conversion Mode
uint8_t DCP //!< Discharge permitted during conversion
);
/*! Start an open wire Conversion
Command Code:
-------------
|CMD[0:1] | 15 | 14 | 13 | 12 | 11 | 10 | 9 | 8 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
|-----------|-------|-------|-------|-------|-------|-------|-------|-------|-------|-------|-------|-------|-------|-------|-------|-------|
|ADOW: | 0 | 0 | 0 | 0 | 0 | 0 | 1 | MD[1] | MD[2] | PUP | 1 | DCP | 1 | CH[2] | CH[1] | CH[0] |
*/
void ltc6811_adow(
uint8_t MD, //!< ADC Conversion Mode
uint8_t PUP //!< Controls if Discharge is permitted during conversion
);
/*! Start GPIO and Vref2 Conversion
The type of ADC conversion executed can be changed by passing the following variables to the conversion functions:
|Variable|Function |
|--------|----------------------------------------------|
| MD | Determines the filter corner of the ADC |
| CHG | Determines which GPIO channels are converted |
| ST | Determines which Self Test is executed |
Starts an ADC conversions of the ltc6811 GPIO inputs.
Command Code:
-------------
|CMD[0:1] | 15 | 14 | 13 | 12 | 11 | 10 | 9 | 8 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
|-----------|-------|-------|-------|-------|-------|-------|-------|-------|-------|-------|-------|-------|-------|-------|-------|-------|
|ADAX: | 0 | 0 | 0 | 0 | 0 | 1 | 0 | MD[1] | MD[2] | 1 | 1 | 0 | 0 | CHG[2]| CHG[1]| CHG[0]|
*/
void ltc6811_adax(
uint8_t MD, //!< ADC Conversion Mode
uint8_t CHG //!< Sets which GPIO channels are converted
);
/*! Start an GPIO Redundancy self test
Command Code:
-------------
|CMD[0:1] | 15 | 14 | 13 | 12 | 11 | 10 | 9 | 8 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
|-----------|-------|-------|-------|-------|-------|-------|-------|-------|-------|-------|-------|-------|-------|-------|-------|-------|
|ADAXD: | 0 | 0 | 0 | 0 | 0 | 1 | 0 | MD[1] | MD[2] | 0 | 0 | 0 | 0 | CHG[2]| CHG[1]| CHG[0]|
*/
void ltc6811_adaxd(
uint8_t MD, //!< ADC Conversion Mode
uint8_t CHG //!< Sets which GPIO channels are converted
);
/*! Start an Auxiliary Register Self Test Conversion
Starts an ADC conversions for testing the Auxiliary register memory.
Command Code:
-------------
|CMD[0:1] | 15 | 14 | 13 | 12 | 11 | 10 | 9 | 8 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
|-----------|-------|-------|-------|-------|-------|-------|-------|-------|-------|-------|-------|-------|-------|-------|-------|-------|
|AXST: | 0 | 0 | 0 | 0 | 0 | 1 | 0 | MD[1] | MD[2] | ST[1] | ST[0] | 0 | 0 | 1 | 1 | 1 |
*/
void ltc6811_axst(
uint8_t MD, //!< ADC Conversion Mode
uint8_t ST //!< Sets if self test 1 or 2 is run
);
/*! Start a Status ADC Conversion
Starts an ADC conversions of the ltc6811 status inputs.
The type of ADC conversion executed can be changed by passing the following variables to the conversion functions:
|Variable|Function |
|--------|-----------------------------------------------|
| MD | Determines the filter corner of the ADC |
| CHST | Determines which status channels are converted|
| ST | Determines which Self Test is executed |
Command Code:
-------------
|CMD[0:1] | 15 | 14 | 13 | 12 | 11 | 10 | 9 | 8 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
|-----------|-------|-------|-------|-------|-------|-------|-------|-------|-------|-------|-------|-------|-------|--------|--------|--------|
|ADSTAT: | 0 | 0 | 0 | 0 | 0 | 1 | 0 | MD[1] | MD[2] | 1 | 1 | 0 | 1 | CHST[2]| CHST[1]| CHST[0]|
*/
void ltc6811_adstat(
uint8_t MD, //!< ADC Conversion Mode
uint8_t CHST //!< Sets which Stat channels are converted
);
/*! Start a Status register redundancy test Conversion
Command Code:
-------------
|CMD[0:1] | 15 | 14 | 13 | 12 | 11 | 10 | 9 | 8 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
|-----------|-------|-------|-------|-------|-------|-------|-------|-------|-------|-------|-------|-------|-------|--------|--------|--------|
|ASTATD: | 0 | 0 | 0 | 0 | 0 | 1 | 0 | MD[1] | MD[2] | 0 | 0 | 0 | 1 | CHST[2]| CHST[1]| CHST[0]|
*/
void ltc6811_adstatd(
uint8_t MD, //!< ADC Mode
uint8_t CHST //!< Sets which Status channels are converted
);
/*! Start a Status Register Self Test Conversion
Command Code:
-------------
|CMD[0:1] | 15 | 14 | 13 | 12 | 11 | 10 | 9 | 8 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
|-----------|-------|-------|-------|-------|-------|-------|-------|-------|-------|-------|-------|-------|-------|--------|--------|--------|
|STATST: | 0 | 0 | 0 | 0 | 0 | 1 | 0 | MD[1] | MD[2] | ST[1] | ST[0] | 0 | 1 | 1 | 1 | 1 |
*/
void ltc6811_statst(
uint8_t MD, //!< ADC Conversion Mode
uint8_t ST //!< Sets if self test 1 or 2 is run
);
/*! Reads and parses the ltc6811 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 cell_codes variable.
uint8_t reg; This controls which cell voltage register is read back.
0: Read back all Cell registers
1: Read back cell group A
2: Read back cell group B
3: Read back cell group C
4: Read back cell group D
uint8_t total_ic; This is the number of ICs in the daisy chain(-1 only)
uint16_t cell_codes[]; An array of the parsed cell codes from lowest to highest. The cell codes will
be stored in the cell_codes[] array in the following format:
| cell_codes[0][0]| cell_codes[0][1] | cell_codes[0][2]| ..... | cell_codes[0][11]| cell_codes[1][0] | cell_codes[1][1]| ..... |
|------------------|------------------|------------------|--------------|-------------------|-------------------|-----------------|----------|
|IC1 Cell 1 |IC1 Cell 2 |IC1 Cell 3 | ..... | IC1 Cell 12 |IC2 Cell 1 |IC2 Cell 2 | ..... |
@return int8_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 total_ic, //!< the number of ICs in the daisy chain(-1 only)
uint16_t cell_codes[][CELL_CHANNELS] //!< array of the parsed cell codes from lowest to highest.
);
/*! Read the raw data from the ltc6811 cell voltage register
The function reads a single cell voltage register and stores the read data
in the *data point as a byte array. This function is rarely used outside of
the ltc6811_rdcv() command.
@param[in] uint8_t reg; This controls which cell voltage register is read back.
1: Read back cell group A
2: Read back cell group B
3: Read back cell group C
4: Read back cell group D
Command Code:
-------------
|CMD[0:1] | 15 | 14 | 13 | 12 | 11 | 10 | 9 | 8 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
|-----------|-------|-------|-------|-------|-------|-------|-------|-------|-------|-------|-------|-------|-------|-------|-------|-------|
|RDCVA: | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 0 | 0 |
|RDCVB: | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 1 | 0 |
|RDCVC: | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 0 | 0 | 0 |
|RDCVD: | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 0 | 1 | 0 |
*/
void ltc6811_rdcv_reg(uint8_t reg, //!< Controls which cell voltage register is read back.
uint8_t nIC, //!< The number of ICs in the daisy chain
uint8_t *data //!< An array of the unparsed cell codes
);
/*! Reads and parses the ltc6811 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 aux_codes variable
uint16_t aux_codes[][6]; A two dimensional array of the gpio voltage codes. The GPIO codes will
be stored in the aux_codes[][6] array in the following format:
| aux_codes[0][0]| aux_codes[0][1] | aux_codes[0][2]| aux_codes[0][3]| aux_codes[0][4]| aux_codes[0][5]| aux_codes[1][0] |aux_codes[1][1]| ..... |
|-----------------|-----------------|-----------------|-----------------|-----------------|-----------------|-----------------|---------------|-----------|
|IC1 GPIO1 |IC1 GPIO2 |IC1 GPIO3 |IC1 GPIO4 |IC1 GPIO5 |IC1 Vref2 |IC2 GPIO1 |IC2 GPIO2 | ..... |
@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 nIC, //!< the number of ICs in the daisy chain
uint16_t aux_codes[][AUX_CHANNELS] //!< A two dimensional array of the parsed gpio voltage codes
);
/*! Read the raw data from the ltc6811 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 ltc6811_rdaux() command.
Command Code:
-------------
|CMD[0:1] | 15 | 14 | 13 | 12 | 11 | 10 | 9 | 8 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
|---------------|-------|-------|-------|-------|-------|-------|-------|-------|-------|-------|-------|-------|-------|-------|-------|-------|
|RDAUXA: | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 1 | 0 | 0 |
|RDAUXB: | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 1 | 1 | 0 |
*/
void ltc6811_rdaux_reg(uint8_t reg, //!< controls which GPIO voltage register is read back
uint8_t nIC, //!< the number of ICs in the daisy chain
uint8_t *data //!< An array of the unparsed aux codes
);
/*! Read the raw data from the ltc6811 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 ltc6811_rdstat() command.
@param[in] uint8_t reg; This controls which GPIO voltage register is read back.
1: Read back stat group A
2: Read back stat group B
Command Code:
-------------
|CMD[0:1] | 15 | 14 | 13 | 12 | 11 | 10 | 9 | 8 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
|---------------|-------|-------|-------|-------|-------|-------|-------|-------|-------|-------|-------|-------|-------|-------|-------|-------|
|RDstatA: | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 0 | 0 | 0 | 0 |
|RDstatB: | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 0 | 0 | 1 | 0 |
*/
void ltc6811_rdstat_reg(uint8_t reg, //!< Determines which GPIO voltage register is read back
uint8_t total_ic, //!< the number of ICs in the daisy chain
uint8_t *data //!< Array of the unparsed statiliary codes
);
/*! Reads and parses the ltc6811 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 stat_codes variable
@param[in] uint8_t reg; This controls which GPIO voltage register is read back.
0: Read back all stat registers
1: Read back stat group A
2: Read back stat group B
uint16_t stat_codes[][6]; A two dimensional array of the gpio voltage codes. The GPIO codes will
be stored in the stat_codes[][6] array in the following format:
| stat_codes[0][0]| stat_codes[0][1] | stat_codes[0][2]| stat_codes[0][3]| stat_codes[1][0] |stat_codes[1][1]| ..... |
|------------------|------------------|------------------|------------------|------------------|----------------|-----------|
|IC1 SOC |IC1 ITMP |IC1 VregA |IC1 VregD |IC2 SOC |IC2 ITMP | ..... |
@return int8_t, PEC Status
0: No PEC error detected
-1: PEC error detected, retry read
*/
int8_t ltc6811_rdstat(uint8_t reg, //!< Determines which GPIO voltage register is read back.
uint8_t total_ic,//!< the number of ICs in the system
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
);
/*! Clears the ltc6811 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.
Command Code:
-------------
|CMD[0:1] | 15 | 14 | 13 | 12 | 11 | 10 | 9 | 8 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
|---------------|-------|-------|-------|-------|-------|-------|-------|-------|-------|-------|-------|-------|-------|-------|-------|-------|
|CLRCELL: | 0 | 0 | 0 | 0 | 0 | 1 | 1 | 1 | 0 | 0 | 0 | 1 | 0 | 0 | 0 | 1 |
*/
void ltc6811_clrcell();
/*! Clears the ltc6811 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.
Command Code:
-------------
|CMD[0:1] | 15 | 14 | 13 | 12 | 11 | 10 | 9 | 8 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
|---------------|-------|-------|-------|-------|-------|-------|-------|-------|-------|-------|-------|-------|-------|-------|-------|-------|
|CLRAUX: | 0 | 0 | 0 | 0 | 0 | 1 | 1 | 1 | 0 | 0 | 0 | 1 | 0 | 0 | 1 | 0 |
*/
void ltc6811_clraux();
/*! Clears the ltc6811 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.
Command Code:
-------------
|CMD[0:1] | 15 | 14 | 13 | 12 | 11 | 10 | 9 | 8 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
|---------------|-------|-------|-------|-------|-------|-------|-------|-------|-------|-------|-------|-------|-------|-------|-------|-------|
|CLRSTAT: | 0 | 0 | 0 | 0 | 0 | 1 | 1 | 1 | 0 | 0 | 0 | 1 | 0 | 0 | 1 | 1 |
*/
void ltc6811_clrstat();
/*! Clears the ltc6811 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.
Command Code:
-------------
|CMD[0:1] | 15 | 14 | 13 | 12 | 11 | 10 | 9 | 8 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
|---------------|-------|-------|-------|-------|-------|-------|-------|-------|-------|-------|-------|-------|-------|-------|-------|-------|
|CLRSCTRL: | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 1 | 0 | 0 | 0 |
*/
void ltc6811_clrsctrl();
/*! Write the ltc6811 configuration register
This command will write the configuration registers of the ltc6811-1s
connected in a daisy chain stack. The configuration is written in descending
order so the last device's configuration is written first.
uint8_t config[][6] is a two dimensional array of the configuration data that will be written, the array should contain the 6 bytes for each
IC in the daisy chain. The lowest IC in the daisy chain should be the first 6 byte block in the array. The array should
have the following format:
| config[0][0]| config[0][1] | config[0][2]| config[0][3]| config[0][4]| config[0][5]| config[1][0] | config[1][1]| config[1][2]| ..... |
|--------------|--------------|--------------|--------------|--------------|--------------|--------------|--------------|--------------|-----------|
|IC1 CFGR0 |IC1 CFGR1 |IC1 CFGR2 |IC1 CFGR3 |IC1 CFGR4 |IC1 CFGR5 |IC2 CFGR0 |IC2 CFGR1 | IC2 CFGR2 | ..... |
The function will calculate the needed PEC codes for the write data
and then transmit data to the ICs on a daisy chain.
Command Code:
-------------
| | CMD[0] | CMD[1] |
|---------------|---------------------------------------------------------------|---------------------------------------------------------------|
|CMD[0:1] | 15 | 14 | 13 | 12 | 11 | 10 | 9 | 8 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
|---------------|-------|-------|-------|-------|-------|-------|-------|-------|-------|-------|-------|-------|-------|-------|-------|-------|
|WRCFG: | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 |
*/
void ltc6811_wrcfg(uint8_t nIC, //!< The number of ICs being written
uint8_t config[][6] //!< a two dimensional array of the configuration data that will be written
);
/*! Reads configuration registers of a ltc6811 daisy chain
uint8_t r_config[][8] is a two dimensional array that the function stores the read configuration data. The configuration data for each IC
is stored in blocks of 8 bytes with the configuration data of the lowest IC on the stack in the first 8 bytes
block of the array, the second IC in the second 8 byte etc. Below is an table illustrating the array organization:
|r_config[0][0]|r_config[0][1]|r_config[0][2]|r_config[0][3]|r_config[0][4]|r_config[0][5]|r_config[0][6] |r_config[0][7] |r_config[1][0]|r_config[1][1]| ..... |
|--------------|--------------|--------------|--------------|--------------|--------------|----------------|---------------|--------------|--------------|-----------|
|IC1 CFGR0 |IC1 CFGR1 |IC1 CFGR2 |IC1 CFGR3 |IC1 CFGR4 |IC1 CFGR5 |IC1 PEC High |IC1 PEC Low |IC2 CFGR0 |IC2 CFGR1 | ..... |
@return int8_t, PEC Status.
0: Data read back has matching PEC
-1: Data read back has incorrect PEC
Command Code:
-------------
|CMD[0:1] | 15 | 14 | 13 | 12 | 11 | 10 | 9 | 8 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
|---------------|-------|-------|-------|-------|-------|-------|-------|-------|-------|-------|-------|-------|-------|-------|-------|-------|
|RDCFG: | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 0 |
*/
int8_t ltc6811_rdcfg(uint8_t nIC, //!< number of ICs in the daisy chain
uint8_t r_config[][8] //!< a two dimensional array that the function stores the read configuration data
);
/*! Write the ltc6811 PWM register
This command will write the pwm registers of the ltc6811-1s
connected in a daisy chain stack. The pwm is written in descending
order so the last device's pwm is written first.
uint8_t pwm[][6] is a two dimensional array of the pwm data that will be written, the array should contain the 6 bytes for each
IC in the daisy chain. The lowest IC in the daisy chain should be the first 6 byte block in the array. The array should
have the following format:
| pwm[0][0]| pwm[0][1] | pwm[0][2]| pwm[0][3]| pwm[0][4]| pwm[0][5]| pwm[1][0] | pwm[1][1]| pwm[1][2]| ..... |
|-----------|-----------|-----------|-----------|-----------|-----------|-----------|-----------|-----------|-----------|
|IC1 pwm0 |IC1 pwm1 |IC1 pwm2 |IC1 pwm3 |IC1 pwm4 |IC1 pwm5 |IC2 pwm0 |IC2 pwm1 | IC2 pwm2 | ..... |
The function will calculate the needed PEC codes for the write data
and then transmit data to the ICs on a daisy chain.
Command Code:
-------------
| | CMD[0] | CMD[1] |
|---------------|---------------------------------------------------------------|---------------------------------------------------------------|
|CMD[0:1] | 15 | 14 | 13 | 12 | 11 | 10 | 9 | 8 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
|---------------|-------|-------|-------|-------|-------|-------|-------|-------|-------|-------|-------|-------|-------|-------|-------|-------|
|WRPWM: | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 |
*/
void ltc6811_wrpwm(uint8_t nIC, //!< number of ICs in the daisy chain
uint8_t pwmReg,
uint8_t pwm[][6]
);
/*! Reads pwm registers of a ltc6811 daisy chain
uint8_t r_pwm[][8] is a two dimensional array that the function stores the read pwm data. The pwm data for each IC
is stored in blocks of 8 bytes with the pwm data of the lowest IC on the stack in the first 8 bytes
block of the array, the second IC in the second 8 byte etc. Below is an table illustrating the array organization:
|r_pwm[0][0]|r_pwm[0][1]|r_pwm[0][2]|r_pwm[0][3]|r_pwm[0][4]|r_pwm[0][5]|r_pwm[0][6] |r_pwm[0][7] |r_pwm[1][0]|r_pwm[1][1]| ..... |
|-----------|-----------|-----------|-----------|-----------|-----------|-------------|------------|-----------|-----------|-----------|
|IC1 pwm0 |IC1 pwm1 |IC1 pwm2 |IC1 pwm3 |IC1 pwm4 |IC1 pwm5 |IC1 PEC High |IC1 PEC Low |IC2 CFGR0 |IC2 CFGR1 | ..... |
@return int8_t, PEC Status.
0: Data read back has matching PEC
-1: Data read back has incorrect PEC
Command Code:
-------------
|CMD[0:1] | 15 | 14 | 13 | 12 | 11 | 10 | 9 | 8 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
|---------------|-------|-------|-------|-------|-------|-------|-------|-------|-------|-------|-------|-------|-------|-------|-------|-------|
|RDPWM: | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 0 | 0 | 0 | 1 | 0 |
*/
int8_t ltc6811_rdpwm(uint8_t nIC, //!< number of ICs in the daisy chain
uint8_t pwmReg,
uint8_t r_pwm[][8] //!< a two dimensional array that the function stores the read pwm data
);
/*! Write the ltc6811 Sctrl register
This command will write the pwm registers of the ltc6811-1s
connected in a daisy chain stack. The pwm is written in descending
order so the last device's pwm is written first.
The function will calculate the needed PEC codes for the write data
and then transmit data to the ICs on a daisy chain.
Command Code:
-------------
| | CMD[0] | CMD[1] |
|---------------|---------------------------------------------------------------|---------------------------------------------------------------|
|CMD[0:1] | 15 | 14 | 13 | 12 | 11 | 10 | 9 | 8 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
|---------------|-------|-------|-------|-------|-------|-------|-------|-------|-------|-------|-------|-------|-------|-------|-------|-------|
|WRSCTRL: | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 0 | 1 | 0 | 0 |
*/
void ltc6811_wrsctrl(uint8_t nIC, //!< number of ICs in the daisy chain
uint8_t sctrl_reg,
uint8_t sctrl[][6]
);
/*! Reads sctrl registers of a ltc6811 daisy chain
uint8_t r_sctrl[][8] is a two dimensional array that the function stores the read pwm data. The sctrl data for each IC
is stored in blocks of 8 bytes with the pwm data of the lowest IC on the stack in the first 8 bytes
block of the array, the second IC in the second 8 byte etc. Below is an table illustrating the array organization:
@return int8_t, PEC Status.
0: Data read back has matching PEC
-1: Data read back has incorrect PEC
Command Code:
-------------
|CMD[0:1] | 15 | 14 | 13 | 12 | 11 | 10 | 9 | 8 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
|---------------|-------|-------|-------|-------|-------|-------|-------|-------|-------|-------|-------|-------|-------|-------|-------|-------|
|rdsctrl: | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 0 | 1 | 1 | 0 |
*/
int8_t ltc6811_rdsctrl(uint8_t nIC, //!< number of ICs in the daisy chain
uint8_t sctrl_reg,
uint8_t r_sctrl[][8] //!< a two dimensional array that the function stores the read pwm data
);
/*! Start Sctrl data communication
This command will start the sctrl pulse communication over the spins
Command Code:
-------------
| | CMD[0] | CMD[1] |
|---------------|---------------------------------------------------------------|---------------------------------------------------------------|
|CMD[0:1] | 15 | 14 | 13 | 12 | 11 | 10 | 9 | 8 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
|---------------|-------|-------|-------|-------|-------|-------|-------|-------|-------|-------|-------|-------|-------|-------|-------|-------|
|stsctrl: | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 0 | 1 | 0 | 0 |
*/
void ltc6811_stsctrl();
/*! Write the ltc6811 COMM register
This command will write the comm registers of the ltc6811-1s
connected in a daisy chain stack. The comm is written in descending
order so the last device's configuration is written first.
uint8_t comm[][6] is a two dimensional array of the configuration data that will be written, the array should contain the 6 bytes for each
IC in the daisy chain. The lowest IC in the daisy chain should be the first 6 byte block in the array. The array should
have the following format:
| COMM[0][0]| COMM[0][1] | COMM[0][2]| COMM[0][3]| COMM[0][4]| COMM[0][5]| COMM[1][0] | COMM[1][1]| COMM[1][2]| ..... |
|------------|------------|------------|------------|------------|------------|------------|------------|------------|-----------|
|IC1 COMM0 |IC1 COMM1 |IC1 COMM2 |IC1 COMM3 |IC1 COMM4 |IC1 COMM5 |IC2 COMM0 |IC2 COMM1 | IC2 COMM2 | ..... |
The function will calculate the needed PEC codes for the write data
and then transmit data to the ICs on a daisy chain.
Command Code:
-------------
| | CMD[0] | CMD[1] |
|---------------|---------------------------------------------------------------|---------------------------------------------------------------|
|CMD[0:1] | 15 | 14 | 13 | 12 | 11 | 10 | 9 | 8 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
|---------------|-------|-------|-------|-------|-------|-------|-------|-------|-------|-------|-------|-------|-------|-------|-------|-------|
|WRCOMM: | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 |
*/
void ltc6811_wrcomm(uint8_t total_ic, //!< Number of ICs in the daisy chain
uint8_t comm[][6] //!< A two dimensional array of the comm data that will be written
);
/*! Reads comm registers of a ltc6811 daisy chain
uint8_t r_comm[][8] is a two dimensional array that the function stores the read comm data. The comm data for each IC
is stored in blocks of 8 bytes with the comm data of the lowest IC on the stack in the first 8 bytes
block of the array, the second IC in the second 8 byte etc. Below is an table illustrating the array organization:
|r_comm[0][0]|r_comm[0][1]|r_comm[0][2]|r_comm[0][3]|r_comm[0][4]|r_comm[0][5]|r_comm[0][6] |r_comm[0][7] |r_comm[1][0]|r_comm[1][1]| ..... |
|------------|------------|------------|------------|------------|------------|-------------|-------------|------------|------------|-----------|
|IC1 comm0 |IC1 comm1 |IC1 comm2 |IC1 comm3 |IC1 comm4 |IC1 comm5 |IC1 PEC High |IC1 PEC Low |IC2 CFGR0 |IC2 CFGR1 | ..... |
@return int8_t, PEC Status.
0: Data read back has matching PEC
-1: Data read back has incorrect PEC
Command Code:
-------------
|CMD[0:1] | 15 | 14 | 13 | 12 | 11 | 10 | 9 | 8 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
|---------------|-------|-------|-------|-------|-------|-------|-------|-------|-------|-------|-------|-------|-------|-------|-------|-------|
|RDCCOMM: | 0 | 0 | 0 | 0 | 0 | 1 | 1 | 1 | 0 | 0 | 1 | 0 | 0 | 0 | 1 | 0 |
*/
int8_t ltc6811_rdcomm(uint8_t total_ic, //!< number of ICs in the daisy chain
uint8_t r_comm[][8] //!< Two dimensional array that the function stores the read comm data.
);
/*! issues a stcomm command and clocks data out of the COMM register */
void ltc6811_stcomm();
/*! Wake isoSPI up from idle state */
void wakeup_idle();
/*! Wake the ltc6811 from the sleep state */
void wakeup_sleep();
/*! 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
);
/*! @returns returns the register data pattern for a given ADC MD and Self test */
uint16_t ltc6811_st_lookup(
uint8_t MD, //!< ADC Conversion Mode
uint8_t ST //!< Self test number
);
/*! Writes an array of bytes out of the SPI port*/
void spi_write_array(uint8_t length, //!< length of the data array being written on the SPI port
uint8_t *data); //!< the data array 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 *TxData, //!< array of data to be written on the SPI port
uint8_t TXlen, //!< tx_len length of the tx_data array
uint8_t *rx_data, //!< rx_data array that read data will be written too.
uint8_t RXlen); //!< number of bytes to be read from the SPI port.
const uint16_t crc15Table[256] PROGMEM = {0x0,0xc599, 0xceab, 0xb32, 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, 0x2be, 0xc727, 0xcc15, 0x98c, 0xda71, 0x1fe8, 0x14da, 0xd143, 0xf3c5, 0x365c,
0x3d6e, 0xf8f7,0x2b0a, 0xee93, 0xe5a1, 0x2038, 0x7c2, 0xc25b, 0xc969, 0xcf0, 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, 0x57c, 0xc0e5, 0xcbd7, 0xe4e, 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, 0xf84, 0xca1d, 0xc12f, 0x4b6, 0xd74b, 0x12d2, 0x19e0, 0xdc79, 0xfb83, 0x3e1a, 0x3528,
0xf0b1, 0x234c, 0xe6d5, 0xede7, 0x287e, 0xf93d, 0x3ca4, 0x3796, 0xf20f, 0x21f2, 0xe46b, 0xef59,
0x2ac0, 0xd3a, 0xc8a3, 0xc391, 0x608, 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, 0x846, 0xcddf, 0xc6ed, 0x374, 0xd089, 0x1510, 0x1e22, 0xdbbb, 0xaf8, 0xcf61, 0xc453,
0x1ca, 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
};
#endif

2337
APP/ltc6813_comm.c Normal file

File diff suppressed because it is too large Load Diff

58
APP/ltc6813_comm.h Normal file
View File

@@ -0,0 +1,58 @@
/**
******************************************************************************
* @file ltc6813_comm.h
* @author MCD Application Team
* @version V1.0.0
* @date 05/12/2011
* @brief This file contains all the functions prototypes for the ltc6813_comm.c
* file.
******************************************************************************
* @copy
*
* THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS
* WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE
* TIME. AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY
* DIRECT, INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING
* FROM THE CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE
* CODING INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS.
*
* <h2><center>&copy; COPYRIGHT 2009 STMicroelectronics</center></h2>
*/
/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef LTC6813_COMM_H_
#define LTC6813_COMM_H_
/* Includes ------------------------------------------------------------------*/
#include <stm32f10x.h>
void App_TaskBatt(void);
uint16_t GetTempRawValue(uint8_t tNo);
void dec_cb_tick(u16 tick);
void clear_cb_value(void);
uint8_t GetCB_Rest(void);
void SetManualBalancing(uint8_t flag, uint8_t *data);
void inc_afe_bufftime(uint32_t tick);
uint32_t GetOneBuffTime(void);
uint32_t GetAllBuffTime(void);
uint8_t SetLtc6813_Param(uint8_t *text, uint8_t aDevice);
void ODisplayBalancingValue(uint8_t p);
uint32_t GetBalancingAvgVoltage(void);
extern uint8_t ManualBalFlag;
extern uint32_t ManualBalEnable;
extern uint32_t ManualBalMode;
extern uint32_t BalMode;
#endif
/******************* (C) COPYRIGHT 2009 STMicroelectronics *****END OF FILE****/

251
APP/screen.c Normal file
View File

@@ -0,0 +1,251 @@
/**
******************************************************************************
* File Name : screen.c
* Description : This file provides code for the string
* of debug console.
******************************************************************************
* @attention
*
* <h2><center>&copy; 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
*
******************************************************************************
*/
#ifdef CONSOLE_DEBUG
/* Includes ------------------------------------------------------------------*/
#include <includes.h>
#include "delay.h"
#define SCREEN_LINE_DELAY 2 // line delay 2ms
const char OPMODE_STR[][84] =
{
// 1 2 3 4 5 6 7 8
// 123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
"\r\n+--[Battery : ]---+---+---+---+---+---+---+---+---+---+--------------------+", // 2
"\r\n| HeartB ( ) | B |OCA|TCA|TDA|AFE|RSV|ZVC|F-C|F-D| Warning ( )HEX|", // 3
"\r\n+---------------------+ S |INI|MD |FC |FD |RXM|ZVC|F-C|F-D| Protection( )HEX|", // 4
"\r\n| B-Volt ( . )V |---+---+---+---+---+---+---+---+---+-[CELL AVG ]--------+", // 5
"\r\n| Current ( . )A | W |RSV|RSV|RSV|L-C|LTD|LTC|HTD|HTC| C-MAX ( . )V |", // 6
"\r\n| SOC ( . )% + N |RSV|RSV|OCD|OCC|CUV|SUV|COV|SOV| C-AVG ( . )V |", // 7
"\r\n+---------------------+---+---+---+---+---+---+---+---+---+ C-MIN ( . )V |", // 8
"\r\n| Operate( )| P |AFE|RSV|SC |RSV|LTD|LTC|HTD|HTC| C-DIFF ( . )V |", // 9
"\r\n| Status ( )| T |RSV|RSV|OCD|OCC|CUV|SUV|COV|SOV| CB AVG ( . )V |", // 0
"\r\n+--[Cell Volt]--------+---+---+---+---+---+---+---+---+---+ [ ] |", // 1
"\r\n|01( . ) 11( . )| M-FLAG( ) +-[TEMP AVG ]--------+", // 2
"\r\n|02( . ) 12( . )| M-BAL ( ) | T-MAX ( . )C |", // 3
"\r\n|03( . ) 13( . )| BAL-ST( ) | T-AVG ( . )C |", // 4
"\r\n|04( . ) 14( . )| | T-MIN ( . )C |", // 5
"\r\n|05( . ) 15( . )| MODE ( ) | T-DIFF ( . )C |", // 6
"\r\n|06( . ) 16( . )+---------+---------+---------+-----+---+-[CONFIG]-------+", // 7
"\r\n|07( . ) 17( . )|T1( . )|T3( . )|T5( . )|T7( . )| 0 ( ) ( ) |", // 8
"\r\n|08( . ) 18( . )| | | | | 1 ( ) ( ) |", // 9
"\r\n|09( . ) 19( . )|T2( . )|T4( . )|T6( . )|T8( . )| 2 ( ) ( ) |", // 0
"\r\n|10( . ) 20( . )| | | | | 3 ( ) ( ) |", // 1
"\r\n+---------------------+---------+---------+---------+---------+----------------+", // 2
"\r\n s : SETTING d : DIAGNOSTIC " // 3
};
void OmodeScreen(void)
{
for (int i = 0; i < 22; i++)
{
printf("%s", OPMODE_STR[i]);
delay_os_ms(SCREEN_LINE_DELAY);
}
}
const char SETMODE_STR[22][84] =
{
// 1 2 3 4 5 6 7 8
// 123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
" mBMS [SETTING] MODE",
"\r\n+--[PARMAMETER]---------+------------------------------------------------------+",
"\r\n| '1': Safety Config | |",
"\r\n| '2': SBS Config | |",
"\r\n+-----------------------+ |",
"\r\n| |",
"\r\n| |",
"\r\n| |",
"\r\n| |",
"\r\n| |",
"\r\n| |",
"\r\n| |",
"\r\n| |",
"\r\n| |",
"\r\n| |",
"\r\n| |",
"\r\n| |",
"\r\n| |",
"\r\n| |",
"\r\n| |",
"\r\n+------------------------------------------------------------------------------+",
"\r\n 'o' : OPERATING 'd' : DIAGNOSTIC "
};
void SmodeScreen(void)
{
for (int i = 0; i < 22; i++)
{
printf("%s", SETMODE_STR[i]);
delay_os_ms(SCREEN_LINE_DELAY);
}
}
const char DIAGMODE_STR[22][84] = {
// 1 2 3 4 5 6 7 8
// 123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
" mBMS [DIAGNOSTIC] MODE",
"\r\n+------------------------------------------------------------------------------+",
"\r\n| |",
"\r\n| |",
"\r\n| |",
"\r\n| |",
"\r\n|----------------------------< CAN COMM MONITOR >----------------------------|",
"\r\n| '2' : CAN MSG MONITOR ( ) '3' : CAN DATA MONITOR ( ) |",
"\r\n|------------------------------------------------------------------------------|",
"\r\n| |",
"\r\n| |",
"\r\n| |",
"\r\n| |",
"\r\n| |",
"\r\n|---------------------------------------------------+--[SYSTEM CONTROL]--------+",
"\r\n| | 'q': S/W Reset |",
"\r\n| | |",
"\r\n| | |",
"\r\n| | |",
"\r\n| | |",
"\r\n+---------------------------------------------------+--------------------------+",
"\r\n o : OPERATING s: SETTING "
};
void DmodeScreen(void)
{
u16 i;
for (i = 0; i < 22; i++)
{
printf("%s", DIAGMODE_STR[i]);
delay_os_ms(SCREEN_LINE_DELAY);
}
}
const char TASK_STS_MODE_STR[22][84] =
{
// 1 2 3 4 5 6 7 8
// 123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
" mBMS [OS TASK STATUS] MODE",
"\r\n+------------------------------------------------------------------------------+",
"\r\n| uC/OS-III, The Real-Time Kernel |",
"\r\n| Modify by JKWoo In Amogreentech |",
"\r\n|------------------------------------------------------------------------------|",
"\r\n| Task TStack FStack UStack CPU Us Peak ExecTime (mS) |",
"\r\n|-------------- ------ ------ ------ ------ ------ ------------- |",
"\r\n| |",
"\r\n| |",
"\r\n| |",
"\r\n| |",
"\r\n| |",
"\r\n| |",
"\r\n| |",
"\r\n| |",
"\r\n| |",
"\r\n| |",
"\r\n| |",
"\r\n|------------------------------------------------------------------------------|",
"\r\n| #Tasks : #CPU Usage: % #Task switch/sec: |",
"\r\n+------------------------------------------------------------------------------+",
"\r\n o : OPERATING s: SETTING "
};
void OSmodeScreen(void)
{
for (int i = 0; i < 22; i++)
{
printf("%s", TASK_STS_MODE_STR[i]);
delay_os_ms(SCREEN_LINE_DELAY);
}
}
const char SF1_SET_STR[22][84] =
{
// 1 2 3 4 5 6 7 8
// 123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
" mBMS [SAFETY] MODE",
"\r\n+--[1ST LEVEL SAFETY ]---------------------------------------------------------+",
"\r\n+-[VOLTAGE : '1' ]---------+-[TEMP : '3']------------+-[S VOLTAGE : '4']------+",
"\r\n| '1': COV Protect( )mV | '1': OT Chg Pro( . )C | '1': SOV Protect( )V |",
"\r\n| '2': COV Warning( )mV | '2': OT Chg War( . )C | '2': SOV Warning( )V |",
"\r\n| '3': COV Recover( )mV | '3': OT Chg Rec( . )C | '3': SOV Recover( )V |",
"\r\n|--------------------------|-------------------------|-------------------------|",
"\r\n| '4': CUV Protect( )mV | '4': OT Dsg Pro( . )C | '4': SUV Protect( )V |",
"\r\n| '5': CUV Warning( )mV | '5': OT Dsg War( . )C | '5': SUV Warning( )V |",
"\r\n| '6': CUV Recover( )mV | '6': OT Dsg Rec( . )C | '6': SUV Recover( )V |",
"\r\n+--------------------------+-------------------------+-------------------------+",
"\r\n| | '7': LT Chg Pro( . )C | |",
"\r\n| | '8': LT Chg War( . )C | |",
"\r\n| | '9': LT Chg Rec( . )C +-[CELL DIFF : '6']------+",
"\r\n| |-------------------------| '1': CVD Protect( )mV|",
"\r\n+-[Balance Cfg : '2']-----+ 'a': LT Dsg Pro( . )C | '2': CVD Warning( )mV|",
"\r\n| '1': C-Bal Thr ( )mV | 'b': LT Dsg War( . )C | '3': CVD Recover( )mV|",
"\r\n| '2': C-Bal Win ( )mV | 'c': LT Dsg Rec( . )C +-[Thermistor : '7']------+",
"\r\n| '3': C-Bal Min ( )mV +-------------------------+ '1': Therm Open( . )C |",
"\r\n| '4': C-Bal Int ( )S | | '2': Therm Reco( . )C |",
"\r\n+--------------------------+-------------------------+-------------------------+",
"\r\n 'o' : OPERATING 'd' : DIAGNOSTIC "
};
void SF1modeScreen(void)
{
for (int i = 0; i < 22; i++)
{
printf("%s", SF1_SET_STR[i]);
delay_os_ms(SCREEN_LINE_DELAY);
}
}
const char SBS_SET_STR[22][84] =
{
// 1 2 3 4 5 6 7 8
// 123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
" mBMS [SBS Configuration] MODE",
"\r\n+-[Data : '1']------------+---------------------------------------------------+",
"\r\n| '1': Dev Addr ( ) | |",
"\r\n+-[Offset: '2']------------+ |",
"\r\n| '1': CV-LOW ( ) | |",
"\r\n| '2': CV-HIGH ( ) | |",
"\r\n+--------------------------+ |",
"\r\n| |",
"\r\n| |",
"\r\n| |",
"\r\n| |",
"\r\n| |",
"\r\n| |",
"\r\n| |",
"\r\n| |",
"\r\n| |",
"\r\n| |",
"\r\n| |",
"\r\n| |",
"\r\n| |",
"\r\n+------------------------------------------------------------------------------+",
"\r\n 'o' : OPERATING 'd' : DIAGNOSTIC "
};
void SBSmodeScreen(void)
{
for (int i = 0; i < 22; i++)
{
printf("%s", SBS_SET_STR[i]);
delay_os_ms(SCREEN_LINE_DELAY);
}
}
#endif //CONSOLE_DEBUG

34
APP/screen.h Normal file
View File

@@ -0,0 +1,34 @@
/**
******************************************************************************
* File Name : screen.h
* Description : This file provides code for the string
* of debug console.
******************************************************************************
* @attention
*
* <h2><center>&copy; 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
*
******************************************************************************
*/
#ifdef CONSOLE_DEBUG
#ifndef _SCREEN_H_
#define _SCREEN_H_
void OmodeScreen(void);
void SmodeScreen(void);
void DmodeScreen(void);
void OSmodeScreen(void);
void SF1modeScreen(void);
void SBSmodeScreen(void);
#endif
#endif

168
APP/task_manager.c Normal file
View File

@@ -0,0 +1,168 @@
/**
******************************************************************************
* @file task_manager.c
* @author MSO Application Team
* @version V1.0.0
* @date 10-October-2011
* @brief This file provides all the memory related operation functions.
******************************************************************************
* @attention
*
* THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS
* WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE
* TIME. AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY
* DIRECT, INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING
* FROM THE CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE
* CODING INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS.
*
* <h2><center>&copy; COPYRIGHT 2015 MSO</center></h2>
******************************************************************************
*/
/** @addtogroup BMCU(EMCB)
* @{
*/
/* Includes ------------------------------------------------------------------*/
#include "includes.h"
#include "asutil.h"
#include "console.h"
/* Private typedef -----------------------------------------------------------*/
/* Private define ------------------------------------------------------------*/
#define OS_MAX_TASK_PRIO 9
/* Private macro -------------------------------------------------------------*/
/* Private variables ---------------------------------------------------------*/
OS_TCB AppTaskTCB[OS_MAX_TASK_PRIO - 3]; // 0 ~ 2 Task -> uC/OS
u16 disCPU_Usage[OS_MAX_TASK_PRIO - 3];
/* Private function prototypes -----------------------------------------------*/
/* Private functions ---------------------------------------------------------*/
void TaksTCBInit(void)
{
memset(AppTaskTCB, 0x00, sizeof(OS_TCB) * (OS_MAX_TASK_PRIO - 3));
}
void *GetAppTaskTCB(u16 prio)
{
return &AppTaskTCB[prio - 3];
}
#ifdef CONSOLE_DEBUG
/* Task Status Mode STATE에서 명령어 처리 */
s8 Process_TaskStatus_Data(u8 *text, u16 size)
{
s8 ret;
if (size > 1) {
if(text[1] != ' ') return(0); /* 첫칸에 space 포함되어있으면 Invalid command */
}
text[size] = 0x00;
ret = 1;
switch (text[0]) {
case 'o':
screenmode = OP_MODE;
ViewScreen();
break;
case 's':
screenmode = SET_MODE;
ViewScreen();
break;
case 'd':
screenmode = DIAG_MODE;
ViewScreen();
break;
default:
ret = 0;
break;
}
return(ret);
}
u32 disCPUSum;
u32 bakOSTaskCtxSwCtr;
u32 PerSecOSTaskCtxSwCrt;
u32 disOSTaskCtxSwCtr;
u32 cswTick = 0;
void CalOSTaskCtxSwCtrPerSec(u32 tick)
{
cswTick += tick;
if (cswTick >= 1000)
{
PerSecOSTaskCtxSwCrt = OSTaskCtxSwCtr - bakOSTaskCtxSwCtr;
bakOSTaskCtxSwCtr = OSTaskCtxSwCtr;
cswTick = 0;
}
}
void osDisplayTaskStatus(u8 p)
{
u32 CPUSum = 0;
uint8_t text[100];
static u32 tsCount = 0;
if (p || (tsCount <= 0))
{
for (int i = 0; i < OS_MAX_TASK_PRIO - 3; i++)
{
if (AppTaskTCB[i].StkPtr == NULL) continue;
if (p)
{
sprintf((char *)text, "%s", AppTaskTCB[i].NamePtr);
NormalOutXY( 2, 8 + i, text);
}
if (p)
{
sprintf((char *)text, "%6d %6d %6d",
AppTaskTCB[i].StkSize,
AppTaskTCB[i].StkFree,
AppTaskTCB[i].StkUsed
);
NormalOutXY( 18, 8 + i, text);
}
if (p ||(disCPU_Usage[i] != AppTaskTCB[i].CPUUsage))
{
uint8_t a[12];
uint8_t b[12];
FloatToStr((float)AppTaskTCB[i].CPUUsage / 100, a, 6, 2);
FloatToStr((float)AppTaskTCB[i].CPUUsageMax / 100, b, 6, 2);
sprintf((char *)text, "%s(%s)", a, b);
NormalOutXY( 18 + 24, 8 + i, text);
disCPU_Usage[i] = AppTaskTCB[i].CPUUsage;
}
if (p)
{
sprintf((char *)text, "%6d", AppTaskTCB[i].TickRemain);
NormalOutXY( 64, 8 + i, text);
}
CPUSum += AppTaskTCB[i].CPUUsage;
}
if (p ||(disCPUSum != CPUSum))
{
FloatToStr((float)CPUSum / 100, text, 5, 1);
GreenOutXY( 42, 20, text);
disCPUSum = CPUSum;
}
if (p || (disOSTaskCtxSwCtr != PerSecOSTaskCtxSwCrt))
{
sprintf((char *)text, "%6d", PerSecOSTaskCtxSwCrt);
GreenOutXY( 70, 20, text);
disOSTaskCtxSwCtr = PerSecOSTaskCtxSwCrt;
}
tsCount = 200;
}
tsCount--;
}
#endif // #ifdef CONSOLE_DEBUG
/*******************(C)COPYRIGHT 2015 MSO ********************END OF FILE******/

43
APP/task_manager.h Normal file
View File

@@ -0,0 +1,43 @@
/**
******************************************************************************
* @file task_manager.h
* @author MSO Application Team
* @version V1.0.0
* @date 10-October-2011
* @brief This file provides all the headers of the flash_if functions.
******************************************************************************
* @attention
*
* THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS
* WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE
* TIME. AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY
* DIRECT, INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING
* FROM THE CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE
* CODING INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS.
*
* <h2><center>&copy; COPYRIGHT 2015 MSO</center></h2>
******************************************************************************
*/
/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef __TASK_MANAGER_H
#define __TASK_MANAGER_H
/* Includes ------------------------------------------------------------------*/
#include "sys.h"
/* Exported types ------------------------------------------------------------*/
/* Exported constants --------------------------------------------------------*/
/* Exported macro ------------------------------------------------------------*/
/* Exported functions ------------------------------------------------------- */
void TaksTCBInit(void);
void *GetAppTaskTCB(u16 prio);
s8 Process_TaskStatus_Data(u8 *text, u16 size);
void osDisplayTaskStatus(u8 p);
void CalOSTaskCtxSwCtrPerSec(u32 tick);
#endif /* __TASK_MANAGER_H */
/*******************(C)COPYRIGHT 2015 MSO ********************END OF FILE******/

639
APP/temp.c Normal file
View File

@@ -0,0 +1,639 @@
/**
******************************************************************************
* File Name : temp.c
* Description : This file provides code for the measument of voltage
and current.
******************************************************************************
* @attention
*
* <h2><center>&copy; 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 "delay.h"
#include "device_param.h"
#include "asutil.h"
#include "temp.h"
#include "ltc6813_comm.h"
/* Private typedef -----------------------------------------------------------*/
typedef struct
{
s16 Value;
s16 AdValue;
// PARAMETER Information
s16 HighParam; // 온도Parameter는 AD[4](Unify-Temp)에서만 참조된다
s16 HighCParam;
s16 LowParam;
s16 LowCParam;
s16 FailParam;
s16 FailCParam;
u8 Enabled; // Enabled/Disabled
u8 Failed; // Fail/Noraml
u8 State; // 정상,고온(습),저온,NotUsed (0/1/2/3)
u8 Changed; // notchanged,적온->고온,고온->적온,적온->저온,저온->적온,NotUsed->Used,Used->NotUsed,Normal->Failed,Failed->Normal
} TAnalogrec, *PAnalogrec;
typedef struct
{
s16 temp;
u16 vref;
u16 vbat;
u16 reserved;
} TCPUStatus, *PCPUStatus;
/* Private define ------------------------------------------------------------*/
#define TEMP_TASK_TIME 50 // 100ms TASK
#define AD_TEMP_CH_MAX 8
#define TEMP_CH_MAX 8
#define T1_TEMP_ID 0
#define T2_TEMP_ID 1
#define T3_TEMP_ID 2
#define T4_TEMP_ID 3
#define T5_TEMP_ID 4
#define T6_TEMP_ID 5
#define T7_TEMP_ID 6
#define T8_TEMP_ID 7
#define TEMP_BUF_MAX 10
// Temperature alarm flag define
#define cFahr 0x00
#define cCent 0x01
#define cHighOccur 0x01 // 정상->고온(습)
#define cLowOccur 0x02 // 정상->저온
#define cNotUsed 0x03 // Disabled
#define cNotChanged 0x00 // 변화없음
#define cNormToHigh 0x11 // 정상->고온(습)
#define cHighToNorm 0x12 // 고온(습)->정상
#define cNormToLow 0x13 // 정상->저온
#define cLowToNorm 0x14 // 저온->정상
#define cNotToUsed 0x15 // NotUsed->Used
#define cUsedToNot 0x16 // Used->NotUsed
#define cFailToNorm 0x17 // Fail->Normal
#define cNormToFail 0x18 // Normal->Fail
#define cNormalOpen 0
#define cNormalClose 1
#define cNORMAL 0
#define cINITVALUE 0xff
#define cOCCUR 1
#define cUNKNOWN 2
#define cDISABLE 3
#define cCANCEL 0
/* Private macro -------------------------------------------------------------*/
/* Private variables ---------------------------------------------------------*/
// ADC Buffer
u16 AdData[AD_TEMP_CH_MAX][TEMP_BUF_MAX];
u16 AdCh = 0;
// Temperature Buffer
TAnalogrec TD[TEMP_CH_MAX];
TAnalogrec DisTD[TEMP_CH_MAX];
u8 TempUnit, BakTempUnit;
void AdcInit(void);
void InitAD(u8 ch);
void ADC_Data_Process(void);
s16 GetTemperature(u8 ch);
s16 CalcTemperatureST32(u16 volt);
/*
*********************************************************************************************************
* App_TaskAdc Init
*
* Description : ADC TASK INIT
*
*********************************************************************************************************
*/
void AdcInit(void)
{
// ADC initialization
// ADC Clock frequency: 115.200 kHz
// ADC Voltage Reference: Vref Pin
// ADC High Speed Mode: On
memset(AdData, 0x00, sizeof(AdData));
memset(TD , 0x00, sizeof(TAnalogrec) * TEMP_CH_MAX);
TempUnit = cCent;
for (int i = 0; i < TEMP_CH_MAX; i++)
InitAD(i);
}
/*
*********************************************************************************************************
* Function for App_TaskAdc
*
* Description : ADC TASK
*
*********************************************************************************************************
*/
void App_TaskTemp(void)
{
AdcInit();
while (DEF_TRUE)
{
ADC_Process();
delay_os_ms(TEMP_TASK_TIME);
}
}
void InitAD(u8 ch)
{
for (int i = 0; i < 20; i++)
{
TD[ch].Value = GetTemperature(ch);
}
TD[ch].Enabled = true;
TD[ch].Failed = false;
TD[ch].State = cNORMAL;
TD[ch].Changed = cNotChanged;
}
void ADC_Data_Process(void)
{
for (int i = 0; i < AD_TEMP_CH_MAX; i++)
{
AdData[i][AdCh] = GetTempRawValue(i) / 10;
}
AdCh++;
AdCh %= TEMP_BUF_MAX;
}
s16 CalcTemperatureNTC(u16 volt, u16 beta)
{
// double beta1 = 3380;
// double beta2 = 3950;
double Rnom = 10000;
double Koffset = 273.16;
double Tnom = 25 + Koffset;
double R1 = 10 * 1000;
double Vref = 3.0;
// R2 = V * R1 / (Vref - V) # Calculate resistance value of NTC
// V = R1 / (R1 + R2) * Vref --> V * R1 + V * R2 = Vref * R1 --> V * R2 = (Vref * R1) - (V * R1) --> R2 = (Vref * R1) / V - R1
// V = R2 / (R1 + R2) * Vref --> (V * R1) + (V * R2) = (Vref * R2) --> (Vref * R2) - (V * R2) = (V * R1) --> R2 = (V * R1)/(Vref - V) * NTC Bottom side
// V = RL / (R1 + RL) * Vref --> V * (R1 + RL) = Vref * RL --> VR1 + VRL = VrefRL --> VrefRL - VRL = VR1 --> (Vref - V)RL = VR1 --> RL = (V * R1)/(Vref - V)
// RL = (V * R1)/(Vref - V)
double V = (double)volt / 1000;
double RL = (V * R1) / (Vref - V);
double T = (beta * Tnom / (Tnom * log(RL / Rnom) + beta)) - Koffset; // # Calculate corresponding temperature (above shortened)
return (s16)(T * 10);
}
// y = -8.1415x5 + 65.574x4 - 207.39x3 + 323.01x2 - 286.28x + 157.85 ; R² = 0.9998
s16 CalcTemperatureST32(u16 volt)
{
// s16 cvolt;
double imsi;
double xx[6];
double flt;
// cvolt = volt;
imsi = (double)volt / 1000;
xx[5] = imsi * imsi * imsi * imsi * imsi;
xx[4] = imsi * imsi * imsi * imsi;
xx[3] = imsi * imsi * imsi;
xx[2] = imsi * imsi;
xx[1] = imsi;
flt = ( -8.1415 * xx[5]) +
( 65.5740 * xx[4]) +
(-207.3900 * xx[3]) +
( 323.0100 * xx[2]) +
(-286.2800 * xx[1]) +
157.8500;
return(s16)(flt * 10);
}
s16 GetTemperature(u8 ch)
{
s32 tsum = 0;
for (int i = 0; i < TEMP_BUF_MAX; i++)
{
tsum += CalcTemperatureST32(AdData[ch][i]);
// tsum += CalcTemperatureNTC(AdData[ch][i], 3435);
}
return (s16)(tsum / TEMP_BUF_MAX);
}
void ADC_Param_Load(void)
{
for (int i = 0; i < TEMP_CH_MAX; i++)
{
TD[i].HighParam = device_param.safety.temperature.OT_Chg_Warning;
TD[i].HighCParam = device_param.safety.temperature.OT_Chg_Recovery;
TD[i].LowParam = device_param.safety.temperature.LT_Chg_Warning;
TD[i].LowCParam = device_param.safety.temperature.LT_Chg_Recovery;
TD[i].FailParam = device_param.safety.temperature.Open_Thermistor;
TD[i].FailCParam = device_param.safety.temperature.Recovery_Thermistor;
}
}
u8 Check_Analog(u8 ch)
{
s16 aValue, ret, aHighOccur, aHighCancel, aLowOccur, aLowCancel;
switch (ch)
{
case T1_TEMP_ID:
case T2_TEMP_ID:
case T3_TEMP_ID:
case T4_TEMP_ID:
case T5_TEMP_ID:
case T6_TEMP_ID:
case T7_TEMP_ID:
case T8_TEMP_ID:
aValue = TD[ch].Value;
aHighOccur = TD[ch].HighParam;
aHighCancel = TD[ch].HighCParam;
aLowOccur = TD[ch].LowParam;
aLowCancel = TD[ch].LowCParam;
break;
default:
return 0;
}
ret = cNotChanged; // Nothing
switch(TD[ch].State) // 과거 상태
{
case cHighOccur: // 과거:고온(습)
if (aValue < aHighCancel) ret = cHighToNorm; // HIGH CANCEL
break;
case cLowOccur: // 과거:저온
if (aValue > aLowCancel) ret = cLowToNorm; // LOW CANCEL
break;
default:
if (aValue >= aHighOccur) ret = cHighOccur; // HIGH OCCUR
else if (aValue <= aLowOccur) ret = cLowOccur; // LOW OCCUR
break;
}
return(ret);
}
void Analog_Process(u8 ch) // 현재의 온,습도값을 가져와 경보를 분석한다.
{
TD[ch].Value = GetTemperature(ch);
if(TD[ch].Enabled == true)
{
// Check sensor fail on low temperature range
if (TD[ch].Failed != true)
{
if ((TD[ch].Value < TD[ch].FailParam) || (TD[ch].Value > 1250))
{
TD[ch].State = cNORMAL;
TD[ch].Changed = cNormToFail;
TD[ch].Failed = true;
}
}
else
{
if ((TD[ch].Value > TD[ch].FailCParam) && (TD[ch].Value < 1200))
{
TD[ch].State = cNORMAL;
TD[ch].Changed = cFailToNorm;
TD[ch].Failed = false;
}
}
// Check temperature alarm
if (TD[ch].Failed == false)
{
switch (Check_Analog(ch))
{
case cHighOccur: // HIGH OCCUR
TD[ch].State = cHighOccur;
TD[ch].Changed = cNormToHigh;
break;
case cHighToNorm: // HIGH CANCEL
TD[ch].State = cNORMAL;
TD[ch].Changed = cHighToNorm;
break;
case cLowOccur: // LOW OCCUR
TD[ch].State = cLowOccur;
TD[ch].Changed = cNormToLow;
break;
case cLowToNorm: // LOW CANCEL
TD[ch].State = cNORMAL;
TD[ch].Changed = cLowToNorm;
break;
}
}
}
else
TD[ch].State = cNotUsed;
}
u16 ADState(u8 ch)
{
u16 ret = AD_DISABLE;
if (TD[ch].Enabled == true)
{
if (TD[ch].Failed == true)
{
ret = AD_FAIL;
}
else
{
switch (TD[ch].State)
{
case cHighOccur:
ret = AD_HIGH;
break;
case cLowOccur:
ret = AD_LOW;
break;
case cNORMAL :
ret = AD_NORMAL;
break;
default :
ret = AD_NORMAL;
break;
}
}
}
return ret;
}
s16 TEMP_GRADE_CONVERTOR(s16 aTempValue, u8 aGrade)
{
s16 Tf, Tc;
if (aGrade == 'F')
{
Tc = aTempValue;
Tf = (18 * Tc)/10 + 320; // 섭씨를 화씨로
return(Tf);
}
else
{
Tf = aTempValue;
Tc = (Tf - 320)/18;
return(Tc);
}
/*
섭씨를 화씨로 바꾸는 공식: Tf = 9/5 * Tc +32
화씨를 섭씨로 바꾸는 공식: Tc = (Tf - 32) * 5/9
*/
}
s16 ADValue(u8 ch)
{
s16 result = 0;
switch (ch)
{
case T1_TEMP_ID :
case T2_TEMP_ID :
case T3_TEMP_ID :
case T4_TEMP_ID :
case T5_TEMP_ID :
case T6_TEMP_ID :
case T7_TEMP_ID:
case T8_TEMP_ID:
if (TempUnit == cCent) result = TD[ch].Value;
else result = TEMP_GRADE_CONVERTOR(TD[ch].Value,'F');
break;
}
return result;
}
float ADValueF(u8 ch)
{
float result = 0.0;
switch (ch)
{
case T1_TEMP_ID :
case T2_TEMP_ID :
case T3_TEMP_ID :
case T4_TEMP_ID :
case T5_TEMP_ID :
case T6_TEMP_ID :
case T7_TEMP_ID:
case T8_TEMP_ID:
result = (float)TD[ch].Value / 10;
break;
}
return result;
}
void TEMPERATURE_Process(u8 ch)
{
u8 aAlarm;
aAlarm = TD[ch].State;
switch (TD[ch].Changed)
{
case cHighToNorm :
aAlarm = cNORMAL;
break;
case cLowToNorm :
aAlarm = cNORMAL;
break;
case cNormToHigh :
aAlarm = cHighOccur;
break;
case cNormToLow :
aAlarm = cLowOccur;
break;
case cNormToFail :
aAlarm = cNORMAL;
break;
case cFailToNorm :
aAlarm = cNORMAL;
break;
}
if (TD[ch].Enabled != true)
aAlarm = cNORMAL;
TD[ch].State = aAlarm;
}
void Analog_Event_Process(u8 ch)
{
switch (ch)
{
case T1_TEMP_ID:
case T2_TEMP_ID:
case T3_TEMP_ID:
case T4_TEMP_ID:
case T5_TEMP_ID:
case T6_TEMP_ID:
case T7_TEMP_ID:
case T8_TEMP_ID:
TEMPERATURE_Process(ch);
break;
}
}
void CalcAvgTemperature(void)
{
u32 sum;
TTempMinMax min, max;
sum = 0;
max.value = 0;
max.num = 0;
min.value = 0;
min.num = 0;
int j = 0;
for (int i = 0; i < (TEMP_CH_MAX - 2); i++)
{
if (TD[i].Failed == false)
{
if (j == 0)
{
max.value = ADValue(i);
max.num = i;
min.value = ADValue(i);
min.num = i;
}
if (max.value < ADValue(i))
{
max.value = ADValue(i);
max.num = i;
}
if (min.value > ADValue(i))
{
min.value = ADValue(i);
min.num = i;
}
sum += ADValue(i);
j++;
}
}
if (j == 0)
device_value.Temp.avg.avg = 0;
else
device_value.Temp.avg.avg = sum / j;
device_value.Temp.avg.Max.value = max.value;
device_value.Temp.avg.Max.num = max.num;
device_value.Temp.avg.Min.value = min.value;
device_value.Temp.avg.Min.num = min.value;
device_value.Temp.avg.diff = max.value - min.value;
}
void ADC_Get_Process(u8 ch)
{
TD[ch].Changed = cNotChanged; // Changed_Member 초기화
Analog_Process(ch);
Analog_Event_Process(ch);
}
void ADC_Process(void)
{
ADC_Data_Process();
for (int i = 0; i < (TEMP_CH_MAX - 0); i++)
{
ADC_Get_Process(i);
device_value.Temp.temperature[i] = ADValue(i);
delay_os_ms(1);
}
CalcAvgTemperature();
}
#ifdef CONSOLE_DEBUG
void ODisplayAdcStatus(u8 p)
{
u16 i, x, y;
float aParam;
u8 aRedFont;
static int tcount = 0;
// TEMP DISPLAY
if (p || (tcount == 0))
{
tcount = 10;
for (i = 0; i < (TEMP_CH_MAX); i++)
{
if (p || (memcmp(&TD[i], &DisTD[i], sizeof(TAnalogrec)) != 0))
{
x = 27 + ((i / 2)* 10);
y = 18 + ((i % 2)* 2);
if ((TD[i].Enabled == true) & ((TD[i].State != cNORMAL) | (TD[i].Failed == true)))
aRedFont = DISPLAY_RED;
else
aRedFont = DISPLAY_GREEN;
if (TD[i].Failed == true)
{
aParam = (float)ADValue(i) / 10;
FloatColorOutIntXY(aRedFont, x, y, aParam, 5, 1);
if (p || (TD[i].Failed != DisTD[i].Failed))
ColorOutXY(aRedFont, x + 1, y + 1, (u8 *)"FAIL");
}
else
{
aParam = (float)ADValue(i) / 10;
FloatColorOutIntXY(aRedFont, x, y, aParam, 5, 1);
if (p || (TD[i].State != DisTD[i].State)||(TD[i].Failed != DisTD[i].Failed))
{
switch (TD[i].State)
{
case cHighOccur: ColorOutXY(aRedFont, x + 1, y + 1, (u8 *)"HIGH");
break;
case cLowOccur: ColorOutXY(aRedFont, x + 1, y + 1, (u8 *)"LOW ");
break;
case cNORMAL : ColorOutXY(aRedFont, x + 1, y + 1, (u8 *)"NORM");
break;
default : ColorOutXY(aRedFont, x + 1, y + 1, (u8 *)"????");
break;
}
}
}
memcpy(&DisTD[i], &TD[i], sizeof(TAnalogrec));
}
}
}
tcount--;
}
#endif // #ifdef CONSOLE_DEBUG

39
APP/temp.h Normal file
View File

@@ -0,0 +1,39 @@
/*
*********************************************************************************************************
*
* APPLICATION CONFIGURATION
*
* ST Microelectronics STM32
* with the
* BMCU for AMO LFP 380-100
*
* Filename : adc.h
* Version : V1.00
* Programmer(s) : JK.Woo
*********************************************************************************************************
*/
#ifndef _TEMP_H_
#define _TEMP_H_
#include <stm32f10x.h>
#define AD_NORMAL 0x0000
#define AD_DISABLE 0x0000
#define AD_FAIL 0x0001
#define AD_HIGH 0x0002
#define AD_LOW 0x0003
void App_TaskTemp(void);
void ADC_Process(void);
void ADC_Param_Load(void);
float ADValueF(u8 ch);
s16 ADValue(u8 ch);
u16 ADState(u8 ch);
void ODisplayAdcStatus(u8 p);
#endif