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

View File

@@ -0,0 +1,612 @@
/**
******************************************************************************
* File Name : alarm.c
* Description : This file provides code for process alarm
* of warining and fault.
******************************************************************************
* @attention
*
* <h2><center>&copy; Copyright (c) 2021 Amogreentech Co., Ltd.
* All rights reserved.</center></h2>
*
******************************************************************************
*/
/* Includes ------------------------------------------------------------------*/
#include "includes.h"
#include "dflash_sf1.h"
#include "device_param.h"
#include "asutil.h"
#include "console.h"
#include "temp.h"
#include "led.h"
#include "ltc6813_comm.h"
/* Private define ------------------------------------------------------------*/
#define SLEEP_VOLTAGE 4200
#define WAKEUP_VOLTAGE 4500
#define SLEEP_MODE_TIME 60 * 1000
#define CELL_DEVIATION_CHECK_VOLTAGE 4500
/* Private typedef -----------------------------------------------------------*/
/* Private macro -------------------------------------------------------------*/
/* Private variables ---------------------------------------------------------*/
u8 SleepMode = false;
u32 smode_tick = SLEEP_MODE_TIME;
u32 CV_Diff_Time = 60 * 1000;
/* Private function prototypes -----------------------------------------------*/
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);
/* Private functions ---------------------------------------------------------*/
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) {
if (GetCB_Rest() == true) {
ProcessSafety_COV();
ProcessSafety_CUV();
ProcessSafety_CellVoltageDiff();
}
}
ProcessSafety_OTA();
ProcessSafety_LTA();
// CheckSleepMode();
}
ProcessStatusCheck();
ProcessSafetyControl();
}
void ProcessSafety_COV(void)
{
/* Cell Over Voltage Check */
for (int i = 0; i < DEVICE_MAX_CELL; 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)
device_status.cov_protection_cell.uValue &= ~BIT32(i);
}
else
{
// Alarm check
if (device_value.Cell.voltage[i] > device_param.safety.voltage.COV_Threshold)
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)
device_status.cov_warning_cell.uValue &= ~BIT32(i);
}
else
{
// Alarm check
if (device_value.Cell.voltage[i] > device_param.safety.voltage.COV_Warning)
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 < DEVICE_MAX_CELL; 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)
device_status.cuv_protection_cell.uValue &= ~BIT32(i);
}
else
{
// Protection Check
if (device_value.Cell.voltage[i] < device_param.safety.voltage.CUV_Threshold)
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)
device_status.cuv_warning_cell.uValue &= ~BIT32(i);
}
else
{
// Warning Check
if (device_value.Cell.voltage[i] < device_param.safety.voltage.CUV_Warning)
device_status.cuv_warning_cell.uValue |= BIT32(i);
}
}
if (device_status.cuv_protection_cell.uValue != 0)
{
if (device_status.op_status == 0x0001) // If charging, clear protection
{
device_status.cuv_protection_cell.uValue = 0;
device_status.protection.bit.cell_under_voltage = false;
}
else
{
device_status.protection.bit.cell_under_voltage = true;
}
}
else
{
device_status.protection.bit.cell_under_voltage = false;
}
if (device_status.warning.bit.cell_under_voltage)
{
if (device_status.op_status == 0x0001)
{
device_status.cuv_warning_cell.uValue = 0;
device_status.warning.bit.cell_under_voltage = false;
}
}
/* 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.op_status == 0x0001))
device_status.protection.bit.under_voltage = false;
}
else
{
// Alarm check
if (device_value.BatVoltage < device_param.safety.voltage.SUV_Threshold)
{
if (device_status.op_status != 0x0001)
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;
}
}
void ProcessSafety_OTA(void)
{
/* Charge High Temperature */
for (int i = 0; i < DEVICE_MAX_TEMP; 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 < DEVICE_MAX_TEMP; 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 Discharge 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 < DEVICE_MAX_TEMP; i++)
{
if (ADState(i) != AD_FAIL)
{
s16 aTemp = device_value.Temp.temperature[i];
/* Low 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);
}
}
/* Low Temperature Discharge 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)
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)
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)
{
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)
{
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 3950 // 3.95V
#define SFC_CELL_VOLTAGE_MIN 2000 // 2.00V
#define SFC_PACK_VOLTAGE_MAX 7110 // 3.95V * 18 = 71.1V
#define SFC_TEMP_MAX 900 // 90.0C
void ProcessSafetyControl(void)
{
u8 flag = false;
for (int i = 0; i < DEVICE_MAX_CELL; 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)
{
if (device_value.BatVoltage > SFC_PACK_VOLTAGE_MAX) flag = true;
}
if (flag == false)
{
for (int i = 0; i < DEVICE_MAX_TEMP; i++)
{
if (device_value.Temp.temperature[i] > SFC_TEMP_MAX) { flag = true; break; }
}
}
if (flag)
{
SAFETY_SIGNAL = 1;
}
else
{
SAFETY_SIGNAL = 0;
}
}
/*******************(C)COPYRIGHT 2021 Amogreentech *********END OF FILE********/

View File

@@ -0,0 +1,37 @@
/**
******************************************************************************
* File Name : alarm.h
* Description : This file provides code for process alarm
* of warining and fault.
******************************************************************************
* @attention
*
* <h2><center>&copy; Copyright (c) 2021 Amogreentech Co., Ltd.
* All rights reserved.</center></h2>
*
******************************************************************************
*/
/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef _ALARM_H_
#define _ALARM_H_
/* Includes ------------------------------------------------------------------*/
#include <stm32f10x.h>
/* Exported types ------------------------------------------------------------*/
/* Exported constants --------------------------------------------------------*/
/* Exported macro ------------------------------------------------------------*/
/* Exported define -----------------------------------------------------------*/
/* Exported variables ------------------------------------------------------- */
/* Exported functions ------------------------------------------------------- */
void ProcessAlarm(void);
void dec_alarm_tick(u32 tick);
u8 GetSleepMode(void);
void SetSleepMode(u8 mode);
#endif /* _ALARM_H_ */
/*******************(C)COPYRIGHT 2021 Amogreentech *********END OF 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) 2021 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 6
#define APP_VER_MAJOR 3
#define APP_VER_MINOR 3
#define APP_VER_COMPILE 7
/* 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 2021 Amogreentech *********END OF FILE********/

View File

@@ -0,0 +1,36 @@
/**
******************************************************************************
* File Name : app_ver.h
* Description : This file provides code for application version
******************************************************************************
* @attention
*
* <h2><center>&copy; Copyright (c) 2021 Amogreentech Co., Ltd.
* All rights reserved.</center></h2>
*
******************************************************************************
*/
/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef __APP_VER_H__
#define __APP_VER_H__
/* Includes ------------------------------------------------------------------*/
#include <stm32f10x.h>
/* Exported types ------------------------------------------------------------*/
/* Exported constants --------------------------------------------------------*/
/* Exported macro ------------------------------------------------------------*/
/* Exported define -----------------------------------------------------------*/
#define BD_MODEL "BMU\0"
/* Exported functions ------------------------------------------------------- */
void GetAppVersion(u8 *ver);
void APPVerDisplay(void);
void GET_BUILD_DATETIME(u8 *datetime);
u16 GetAppVersionStr(u8 *vStr);
#endif /* __APP_VER_H__ */
/*******************(C)COPYRIGHT 2021 Amogreentech *********END OF FILE********/

View File

@@ -0,0 +1,788 @@
/**
******************************************************************************
* File Name : asutil.c
* Description : This file provides code for the ascii code utils
******************************************************************************
* @attention
*
* <h2><center>&copy; Copyright (c) 2021 Amogreentech Co., Ltd.
* All rights reserved.</center></h2>
*
******************************************************************************
*/
/* Includes ------------------------------------------------------------------*/
#include "includes.h"
#include "asutil.h"
#include "console.h"
#include "usart.h"
#include "app_ver.h"
#include "delay.h"
#include "brtc.h"
/* Private typedef -----------------------------------------------------------*/
/* Private define ------------------------------------------------------------*/
/* Private macro -------------------------------------------------------------*/
/* Private variables ---------------------------------------------------------*/
#ifdef CONSOLE_DEBUG
u8 *dump_addr = 0;
#endif /* CONSOLE_DEBUG */
/* Private function prototype -----------------------------------------------*/
/* Private function ----------------------------------------------------------*/
#ifdef CONSOLE_DEBUG
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, char *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, char *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, char *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, char *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, char *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, char *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);
}
/* <20>Ҽ<EFBFBD><D2BC><EFBFBD> = 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 *********************/

View File

@@ -0,0 +1,113 @@
/**
******************************************************************************
* File Name : asutil.h
* Description : This file provides code for the ascii code utils
******************************************************************************
* @attention
*
* <h2><center>&copy; Copyright (c) 2021 Amogreentech Co., Ltd.
* All rights reserved.</center></h2>
*
******************************************************************************
*/
/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef _ASUTIL_H_
#define _ASUTIL_H_
/* Includes ------------------------------------------------------------------*/
#include <stm32f10x.h>
/* Exported types ------------------------------------------------------------*/
/* Exported constants --------------------------------------------------------*/
/* Exported macro ------------------------------------------------------------*/
/* Exported define -----------------------------------------------------------*/
#define RX_PRINT 0
#define TX_PRINT 1
#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;
/* Exported functions ------------------------------------------------------- */
/* 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, char *Text);
void RedOutXY(u16 x,u16 y, char *msg);
void GreenOutXY(u16 x,u16 y, char *msg);
void YellowOutXY(u16 x,u16 y, char *msg);
void NormalOutXY(u16 x,u16 y, char *msg);
void OutXY(u8 aRED, u16 x, u16 y, char *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, char *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);
#endif /* _ASUTIL_H_ */
/*******************(C)COPYRIGHT 2021 Amogreentech *********END OF FILE********/

File diff suppressed because it is too large Load Diff

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

View File

@@ -0,0 +1,384 @@
/**
******************************************************************************
* 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_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;
uint16_t cfg_pec;
uint8_t cmd_index; //command counter
cmd = (uint8_t *)malloc(CMD_LEN * sizeof(uint8_t));
//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);
free(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;
uint16_t cfg_pec;
uint16_t cmd_pec;
uint8_t cmd_index; //command counter
cmd = (uint8_t *)malloc(CMD_LEN * sizeof(uint8_t));
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);
free(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;
int8_t pec_error = 0;
uint16_t data_pec;
uint16_t received_pec;
rx_data = (uint8_t *) malloc((8 * total_ic) * sizeof(uint8_t));
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;
}
}
free(rx_data);
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;
int8_t pec_error = 0;
uint16_t data_pec;
uint16_t cmd_pec;
uint16_t received_pec;
rx_data = (uint8_t *) malloc((8*total_ic)*sizeof(uint8_t));
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;
}
}
free(rx_data);
return(pec_error);
}

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_ */

View File

@@ -0,0 +1,156 @@
/**
******************************************************************************
* @file : brtc.c
* @project : BMU-18S-Firmware
* @author : JK.Woo
* @brief : This file provides code for the configuration
* of board real time clock.
******************************************************************************
* @attention
*
* <h2><center>&copy; Copyright (c) 2021 Amogreentech Co., Ltd.
* All rights reserved.</center></h2>
*
******************************************************************************
*/
/* 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 ---------------------------------------------------------*/
/**
* @brief Initialize the Real Time Clock timer.
* @param None
* @retval None
*/
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);
}
/**
* @brief Get the remaining warming up time.
* @param None
* @retval Remaining warming up time in ms.
*/
uint32_t GetWarmingUp(void)
{
return WarmingUp;
}
/**
* @brief Process warming up phase.
* @param tick: Time elapsed in ms.
* @retval None
*/
void WarmingUp_Process(u16 tick)
{
if (WarmingUp > tick)
{
WarmingUp -= tick;
}
else
{
device_status.battery_status.bit.INIT = true;
}
}
/**
* @brief Get the current local system time.
* @param None
* @retval Current local time in seconds.
*/
uint32_t GetLocalTime(void)
{
return LocalTime;
}
/**
* @brief Set the current local system time.
* @param nTime: New local time in seconds.
* @retval None
*/
void SetLocalTime(uint32_t nTime)
{
LocalTime = nTime;
sub_sec = 0;
clear_cb_value();
}
/**
* @brief Timer callback for system time updates and periodic tasks.
* @param ptmr: Pointer to the OS timer.
* @param parg: Pointer to task arguments.
* @retval None
*/
void Time_Update(void *ptmr, void *parg)
{
sub_sec += RTC_TMR_PERIOD_TIME;
if (sub_sec >= 1000)
{
LocalTime++;
sub_sec = 0;
// while(!(USART1->SR & 0x80)); USART1->DR = 'T';
}
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
/*******************(C)COPYRIGHT 2021 Amogreentech *********END OF FILE********/

View File

@@ -0,0 +1,35 @@
/**
******************************************************************************
* File Name : brtc.c
* Description : This file provides code for the configuration
* of board real time clock.
******************************************************************************
* @attention
*
* <h2><center>&copy; Copyright (c) 2021 Amogreentech Co., Ltd.
* All rights reserved.</center></h2>
*
******************************************************************************
*/
/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef _BRTC_H_
#define _BRTC_H_
/* Includes ------------------------------------------------------------------*/
#include <stm32f10x.h>
/* Exported types ------------------------------------------------------------*/
/* Exported constants --------------------------------------------------------*/
/* Exported macro ------------------------------------------------------------*/
/* Exported define -----------------------------------------------------------*/
/* Exported functions ------------------------------------------------------- */
void Init_RTC(void);
void Time_Update(void *ptmr, void *parg);
uint32_t GetLocalTime(void);
void SetLocalTime(uint32_t nTime);
#endif /* _BRTC_H_ */
/*******************(C)COPYRIGHT 2021 Amogreentech *********END OF FILE********/

View File

@@ -0,0 +1,280 @@
/**
******************************************************************************
* File Name : can_comm.c
* Description : This file provides code for the configuration
* of CAN communication.
******************************************************************************
* @attention
*
* <h2><center>&copy; Copyright (c) 2021 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 "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 reserved;
#ifdef CONSOLE_DEBUG
u8 MsgPrint;
u8 DataPrint;
u8 BakMsgPrint;
u8 BakDataPrint;
#endif /* CONSOLE_DEBUG */
} 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 CanParamSet = false;
u32 OldHeatbeat;
extern u8 FwData[];
extern u16 HostBalancingVoltage;
extern u16 HostBalancingVoltageDiff;
/* 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 ---------------------------------------------------------*/
void CanCommInit(void)
{
can1_init(250000);
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
{
// Check for Bus-off (BOFF) or Error Passive (EPVF) state
// Reset early if communication quality degrades significantly
if (CAN1->ESR & (CAN_ESR_BOFF | CAN_ESR_EPVF))
{
can1_init(250000);
}
CanCommFailCheck();
delay_os_ms(1); // Reduced from 5ms to improve responsiveness
}
}
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 /* CONSOLE_DEBUG */
/*******************(C)COPYRIGHT 2021 Amogreentech *********END OF FILE********/

View File

@@ -0,0 +1,44 @@
/**
******************************************************************************
* File Name : can_comm.c
* Description : This file provides code for the configuration
* of CAN communication.
******************************************************************************
* @attention
*
* <h2><center>&copy; Copyright (c) 2021 Amogreentech Co., Ltd.
* All rights reserved.</center></h2>
*
******************************************************************************
*/
/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef _CAN_COMM_H_
#define _CAN_COMM_H_
/* Includes ------------------------------------------------------------------*/
#include <stm32f10x.h>
/* Exported types ------------------------------------------------------------*/
/* Exported constants --------------------------------------------------------*/
/* Exported macro ------------------------------------------------------------*/
/* Exported define -----------------------------------------------------------*/
/* Exported variables ------------------------------------------------------- */
/* Exported functions ------------------------------------------------------- */
void App_TaskCanComm(void);
u8 GetCanCommState(void);
void CanParamSetCmd(void);
void SendPacket(u32 SendId, u8 *data);
#ifdef CONSOLE_DEBUG
void DDisplay_CanComm(u8 p);
u8 DCanCommCommand(u8 cmd);
#endif /* CONSOLE_DEBUG */
#endif /* _CAN_COMM_H_ */
/*******************(C)COPYRIGHT 2021 Amogreentech *********END OF FILE********/

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,66 @@
/**
******************************************************************************
* File Name : can_data_process.h
* Description : This file provides code for the normal data processing
* of CAN communication.
******************************************************************************
* @attention
*
* <h2><center>&copy; Copyright (c) 2021 Amogreentech Co., Ltd.
* All rights reserved.</center></h2>
*
******************************************************************************
*/
/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef _CAN_DATA_PROCESS_H_
#define _CAN_DATA_PROCESS_H_
/* Includes ------------------------------------------------------------------*/
#include <stm32f10x.h>
/* Exported types ------------------------------------------------------------*/
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;
/* Exported constants --------------------------------------------------------*/
/* Exported macro ------------------------------------------------------------*/
/* Exported define -----------------------------------------------------------*/
/* Exported variables ------------------------------------------------------- */
/* Exported functions ------------------------------------------------------- */
u8 CheckCanAddr(u8 DstAddr);
u32 MakeCanTxExtId(u8 cmd, u8 flag);
s16 CheckCanPacket(CanRxMsg *data);
s16 CanRxDataProcess(CanRxMsg *data);
#endif /* _CAN_DATA_PROCESS_H_ */
/*******************(C)COPYRIGHT 2021 Amogreentech *********END OF FILE********/

View File

@@ -0,0 +1,168 @@
/**
******************************************************************************
* File Name : can_inv_data_process.c
* Description : This file provides code for the inventory data processing
* of CAN communication.
******************************************************************************
* @attention
*
* <h2><center>&copy; Copyright (c) 2021 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())
{
#ifdef CONSOLE_DEBUG
printf("\r\n DNO = %d, %d(%d)", dno, GetDevAddr(), CanHeader->BV.PF);
#endif /* CONSOLE_DEBUG */
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);
}
/*******************(C)COPYRIGHT 2021 Amogreentech *********END OF FILE********/

View File

@@ -0,0 +1,32 @@
/**
******************************************************************************
* File Name : can_inv_data_process.h
* Description : This file provides code for the inventory data processing
* of CAN communication.
******************************************************************************
* @attention
*
* <h2><center>&copy; Copyright (c) 2021 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_
/* Includes ------------------------------------------------------------------*/
#include <stm32f10x.h>
/* Exported types ------------------------------------------------------------*/
/* Exported constants --------------------------------------------------------*/
/* Exported macro ------------------------------------------------------------*/
/* Exported define -----------------------------------------------------------*/
/* Exported variables ------------------------------------------------------- */
/* Exported functions ------------------------------------------------------- */
s16 CanRxInvDataProcess(CanRxMsg *data);
#endif /* _CAN_INV_DATA_PROCESS_H_ */
/*******************(C)COPYRIGHT 2021 Amogreentech *********END OF FILE********/

View File

@@ -0,0 +1,436 @@
/**
******************************************************************************
* @file : can_update_process.c
* @project : BMU-18S-Firmware
* @author : JK.Woo
* @brief : This file provides code for the configuration
* of Firmware update by CAN communication.
******************************************************************************
* @attention
*
* <h2><center>&copy; Copyright (c) 2021 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 "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;
/* Private macro -------------------------------------------------------------*/
/* Private variables ---------------------------------------------------------*/
u8 FwData[256];
/* Private function prototypes -----------------------------------------------*/
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);
/* Private functions ---------------------------------------------------------*/
/**
* @brief Firmware Update Process handler.
* @param data: Pointer to received CAN message.
* @retval result of the process.
*/
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;
}
/**
* @brief Start firmware update via CAN.
* @param packet: Pointer to CAN RX message.
* @retval 0 on success, error code otherwise.
*/
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)
);
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;
}
/**
* @brief Handle flash sector erase via CAN.
* @param packet: Pointer to CAN RX message.
* @retval 0 on success, error code otherwise.
*/
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));
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;
}
/**
* @brief Set flash write address and length via CAN.
* @param packet: Pointer to CAN RX message.
* @retval 0 on success, error code otherwise.
*/
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))
{
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;
}
/**
* @brief Write firmware data to flash via CAN.
* @param packet: Pointer to CAN RX message.
* @retval 0 on success, error code otherwise.
*/
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;
}
/**
* @brief Verify written data checksum via CAN.
* @param packet: Pointer to CAN RX message.
* @retval 0 on success, error code otherwise.
*/
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 += *(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)
);
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;
}
/**
* @brief Verify complete firmware image checksum via CAN.
* @param packet: Pointer to CAN RX message.
* @retval 0 on success, error code otherwise.
*/
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;
}
/**
* @brief Handle system restart request after update.
* @param packet: Pointer to CAN RX message.
* @retval 0 on success, error code otherwise.
*/
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;
}
/**
* @brief Send response CAN packet.
* @param rhdr: Pointer to received CAN header.
* @param no: Packet sequence number.
* @param data: Pointer to data to send.
* @retval None
*/
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);
}
/*******************(C)COPYRIGHT 2021 Amogreentech *********END OF FILE********/

View File

@@ -0,0 +1,33 @@
/**
******************************************************************************
* File Name : can_update_process.h
* Description : This file provides code for the configuration
* of Firmware update by CAN communication.
******************************************************************************
* @attention
*
* <h2><center>&copy; Copyright (c) 2021 Amogreentech Co., Ltd.
* All rights reserved.</center></h2>
*
******************************************************************************
*/
/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef _CAN_UPDATE_PROCESS_H_
#define _CAN_UPDATE_PROCESS_H_
/* Includes ------------------------------------------------------------------*/
#include <stm32f10x.h>
/* Exported types ------------------------------------------------------------*/
/* Exported constants --------------------------------------------------------*/
/* Exported macro ------------------------------------------------------------*/
/* Exported define -----------------------------------------------------------*/
/* Exported variables ------------------------------------------------------- */
/* Exported functions ------------------------------------------------------- */
s16 FwUpdateProcess(CanRxMsg *data);
#endif /* _CAN_UPDATE_PROCESS_H_ */
/*******************(C)COPYRIGHT 2021 Amogreentech *********END OF FILE********/

View File

@@ -0,0 +1,541 @@
/**
******************************************************************************
* File Name : console.c
* Description : This file provides code for the configuration
* of debug console.
******************************************************************************
* @attention
*
* <h2><center>&copy; Copyright (c) 2021 Amogreentech Co., Ltd.
* All rights reserved.</center></h2>
*
******************************************************************************
*/
/* 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 ---------------------------------------------------------*/
#ifdef CONSOLE_DEBUG
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];
#endif
/* 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)
{
#ifdef CONSOLE_DEBUG
position = 0;
screenmode = OP_MODE;
#endif
}
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;
}
extern void Led_Process(void);
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<54><45><EFBFBD><EFBFBD> <20><><EFBFBD>ɾ<EFBFBD> ó<><C3B3> */
s8 Process_Data(u8 *text, u16 size) /* console_text[0]=0x00, size =0 (default) */
{
int ret;
if(size > 1)
{
if(text[1] != ' ') return(0); /* ùĭ<C3B9><C4AD> space <20><><EFBFBD>ԵǾ<D4B5><C7BE><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> 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 <20><><EFBFBD><EFBFBD> <20><><EFBFBD>ɾ<EFBFBD> ó<><C3B3> */
s8 Process_DataSet(u8 *text, u16 size)
{
u16 ret;
/* ù ĭ<><C4AD> space<63><65> <20><><EFBFBD>ԵǾ<D4B5> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> invalid command */
if (size > 1)
if (text[1] != ' ') return(0);
text[size] = 0x00;
ret = 1;
switch (text[0])
{
case 'o': /* operating state<74><65> <20><>ȯ */
screenmode = OP_MODE;
ViewScreen();
break;
case 'd': /* diagnostic mode<64><65> <20><>ȯ */
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<54><45><EFBFBD><EFBFBD> <20><><EFBFBD>ɾ<EFBFBD> ó<><C3B3>
s8 Process_OSStatus(u8 *text, u16 size) // console_text[0]=0x00, size =0 (default)
{
int ret;
if (size > 1)
if (text[1] != ' ') return(0); /* ùĭ<C3B9><C4AD> space <20><><EFBFBD>ԵǾ<D4B5><C7BE><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> 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);
}
/* diagnostic mode <20><><EFBFBD><EFBFBD> <20><><EFBFBD>ɾ<EFBFBD> ó<><C3B3> */
s8 Process_DataDiagnostic(u8 *text, u16 size)
{
s8 ret, i;
text[size] = 0x00;
ret = 1;
switch (text[0])
{
case 'o': /* operating mode<64><65> <20><>ȯ */
screenmode = OP_MODE;
ViewScreen();
break;
case 's': /* setting status<75><73> <20><>ȯ */
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<61><74><EFBFBD><EFBFBD> */
else
UserMessage("COMMAND LIMIT ERROR"); /* setting <20>Ѱ谪<D1B0><E8B0AA><EFBFBD><EFBFBD> */
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<54><45><EFBFBD><EFBFBD> <20><><EFBFBD>ɾ<EFBFBD> ó<><C3B3> */
s8 Process_Inventory_Data(u8 *text, u16 size)
{
s8 ret;
if (size > 1)
{
if(text[1] != ' ') return(0); /* ùĭ<C3B9><C4AD> space <20><><EFBFBD>ԵǾ<D4B5><C7BE><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> 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<64><65> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> ȭ<><C8AD> <20><><EFBFBD> */
{
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
/*******************(C)COPYRIGHT 2021 Amogreentech *********END OF FILE********/

View File

@@ -0,0 +1,52 @@
/**
******************************************************************************
* File Name : console.h
* Description : This file provides code for the configuration
* of debug console.
******************************************************************************
* @attention
*
* <h2><center>&copy; Copyright (c) 2021 Amogreentech Co., Ltd.
* All rights reserved.</center></h2>
*
******************************************************************************
*/
#ifndef _CONSOLE_H_
#define _CONSOLE_H_
#include <stm32f10x.h>
#ifdef CONSOLE_DEBUG
#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
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 */
u16 debug_recv_data(u8 *data);
void ViewScreen(void);
void DisplayScreen(u8 p);
void Console_Initial(void);
void Console(u8 *one);
#endif /* #ifdef CONSOLE_DEBUG */
void AppTaskDebug(void);
#endif /* _CONSOLE_H_ */
/*******************(C)COPYRIGHT 2021 Amogreentech *********END OF FILE********/

View File

@@ -0,0 +1,151 @@
/**
******************************************************************************
* File Name : device_param.c
* Description : This file provides code for device parameter
******************************************************************************
* @attention
*
* <h2><center>&copy; Copyright (c) 2021 Amogreentech Co., Ltd.
* All rights reserved.</center></h2>
*
******************************************************************************
*/
/* Includes ------------------------------------------------------------------*/
#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"
/* Private typedef -----------------------------------------------------------*/
/* Private define ------------------------------------------------------------*/
#define PARAM_INIT_DATA 0xAAAA32F5
/* Private macro -------------------------------------------------------------*/
/* Private variables ---------------------------------------------------------*/
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;
/* Private function prototype -----------------------------------------------*/
/* Private function ----------------------------------------------------------*/
void SetCellQuantity(u8 cQuantity)
{
if ((cQuantity > 0) && (cQuantity <= 16))
{
device_param.info.CellQuantity = cQuantity;
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);
#ifdef CONSOLE_DEBUG
if (result != 0)
printf("\r\n Fw information save fail (%d)", result);
#endif
}
}
/*******************(C)COPYRIGHT 2021 Amogreentech *********END OF FILE********/

View File

@@ -0,0 +1,420 @@
/**
******************************************************************************
* File Name : device_param.h
* Description : This file provides code for device parameter
******************************************************************************
* @attention
*
* <h2><center>&copy; Copyright (c) 2021 Amogreentech Co., Ltd.
* All rights reserved.</center></h2>
*
******************************************************************************
*/
/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef _DEVICE_PARAM_H_
#define _DEVICE_PARAM_H_
/* Includes ------------------------------------------------------------------*/
#include <stm32f10x.h>
/* Exported types ------------------------------------------------------------*/
/* Exported constants --------------------------------------------------------*/
/* Exported macro ------------------------------------------------------------*/
/* Exported define -----------------------------------------------------------*/
#define DEVICE_NAME "PR-57150S"
#define DEVICE_TYPE 57150
#define DEVICE_REV "1.1"
#define DEVICE_MAX_ADDR 24
#define DEVICE_MAX_CELL 18
#define DEVICE_MAX_TEMP 8
#define BIT(x) (unsigned short)(0x0001 << x)
#define BIT32(x) (unsigned long)(0x00000001 << x)
typedef union
{
uint16_t value;
struct {
uint16_t DSG_S : 1; // LSB 0 // Dischage Fet Control
uint16_t CHG_S : 1; // LSB 1 // Charge Fet Control
uint16_t DCP : 1; // LSB 2 // Pre-charge Fet Control
uint16_t RXM : 1; // LSB 3
uint16_t FD : 1; // LSB 4
uint16_t FC : 1; // LSB 5
uint16_t MD : 1; // LSB 6
uint16_t INIT : 1; // LSB 7
uint16_t DSG_C : 1; // MSB 8 // Dischage Fet Status
uint16_t CHG_C : 1; // MSB 9 // Charge Fet Status
uint16_t ZVC_C : 1; // MSB 10 // Pre-charge Fet Status
uint16_t CB : 1; // MSB 11 // Cell Balancing Flag
uint16_t AFE : 1; // MSB 12 // AFE PL455 Comm Status
uint16_t AFE_COMM_FAULT : 1; // MSB 13 // [DARK] LTC6813 Comm Fault
uint16_t ACB : 1; // MSB 14
uint16_t TCA : 1; // MSB 15
} bit;
} TBATTERY_STATUS, *pBATTERY_STATUS;
typedef struct
{
uint16_t voltage[DEVICE_MAX_CELL]; // Offset 0 ; 2bytes * (18) = 36bytes
struct
{
struct
{
uint16_t value; // Offset 0 ; 2bytes
uint16_t num; // Offset 2 ; 2bytes
} Max, Min; // Offset 0 ; 4bytes + 4bytes = 8bytes
uint16_t avg; // Offset 8 ; 2bytes
uint16_t diff; // Offset 10 ; 2bytes
} avg; // Offset 36 ; 12bytes
} TCELL_STATUS, *PCELL_STATUS; // 48bytes
typedef struct
{
s16 temperature[DEVICE_MAX_TEMP]; // Offset 0 ; 2bytes * (8) = 16bytes
struct
{
struct
{
s16 value; // Offset 0 ; 2bytes
uint16_t 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
{
uint16_t value;
uint16_t num;
} Max, Min;
uint16_t avg;
uint16_t diff;
} TAVG_VALUE, *PAVG_VALUE;
typedef struct
{
s16 value;
uint16_t num;
} TMinMax, *PMinMax;
typedef struct
{
u32 Heartbeat; // Offset 0
u32 ManufactureDate; // Offset 4
u32 FwVersion; // Offset 8
u32 RemainingCapacity; // Offset 12
u32 CycleCount; // Offset 16
uint16_t BatVoltage; // Offset 20
s16 Current; // Offset 22
uint16_t RelativeStateOfCharge; // Offset 24
uint16_t StateOfHealth; // Offset 26
TCELL_STATUS Cell;
TTEMP_STATUS Temp;
} TDEVICE_VALUE, *PDEVICE_VALUE;
typedef union
{
uint16_t value;
struct
{
uint16_t over_voltage : 1; // 0x0001
uint16_t cell_over_voltage : 1; // 0x0002
uint16_t under_voltage : 1; // 0x0004
uint16_t cell_under_voltage : 1; // 0x0008
uint16_t chg_over_current : 1; // 0x0010
uint16_t dsg_over_current : 1; // 0x0020
uint16_t reserved1 : 2; //
uint16_t chg_high_temp : 1; // 0x0100
uint16_t dsg_high_temp : 1; // 0x0200
uint16_t chg_low_temp : 1; // 0x0400
uint16_t dsg_low_temp : 1; // 0x0800
uint16_t low_capacity : 1; // 0x1000
uint16_t reserved2 : 1; //
uint16_t cell_voltage_diff : 1; //
uint16_t reserved3 : 1; //
} bit;
} TWarning;
typedef union
{
uint16_t value;
struct
{
uint16_t over_voltage : 1; // 0x0001
uint16_t cell_over_voltage : 1; // 0x0002
uint16_t under_voltage : 1; // 0x0004
uint16_t cell_under_voltage : 1; // 0x0008
uint16_t chg_over_current : 1; // 0x0010
uint16_t dsg_over_current : 1; // 0x0020
uint16_t reserved1 : 2; //
uint16_t chg_high_temp : 1; // 0x0100
uint16_t dsg_high_temp : 1; // 0x0200
uint16_t chg_low_temp : 1; // 0x0400
uint16_t dsg_low_temp : 1; // 0x0800
uint16_t reserved2 : 1; // 0x1000
uint16_t short_circuit : 1; // 0x2000
uint16_t cell_voltage_diff : 1; // 0x4000
uint16_t 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_flag : 1;
u32 reserved : 13;
} 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_flag : 1;
u32 reserved : 13;
} 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 reserved : 14;
} Bit;
} TCELL_BIT, *PCELL_BIT;
typedef union
{
uint16_t uValue;
struct {
uint16_t temp0 : 1;
uint16_t temp1 : 1;
uint16_t temp2 : 1;
uint16_t temp3 : 1;
uint16_t temp4 : 1;
uint16_t temp5 : 1;
uint16_t temp6 : 1;
uint16_t temp7 : 1;
uint16_t reserved : 8;
} Bit;
} TTEMP_BIT, *PTEMP_BIT;
typedef struct
{
TBATTERY_STATUS battery_status; // 2 16 bit
uint16_t op_status; // 4 16 bit
uint16_t alarm_status; // 6 16 bit
TWarning warning; // 8 16 bit
TProtection protection; // 10 16 bit
uint16_t auto_balancing; // 12 16 bit
TCellBalanceData cellbalance; // 16 32 bit
TBalanceEnable balance_enable; // 20 32 bit
TCELL_BIT cov_warning_cell; // 20 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
{
uint16_t Reserved[10];
uint16_t DevAddr;
uint16_t CellQuantity;
} TDEVICE_INFO, *PDEVICE_INFO;
#pragma pack(2)
typedef struct
{
uint16_t COV_Threshold; // ST COV Threshold (Offset 0)
uint16_t COV_Warning; // ST COV Warning (Offset 2)
uint16_t COV_Recovery; // ST COV Recovery (Offset 4)
uint16_t CUV_Threshold; // CUV Threshold (Offset 6)
uint16_t CUV_Warning; // CUV Warning (Offset 8)
uint16_t CUV_Recovery; // CUV Recovery (Offset 10)
uint16_t SOV_Threshold; // ST COV Threshold (Offset 0)
uint16_t SOV_Warning; // ST COV Warning (Offset 2)
uint16_t SOV_Recovery; // ST COV Recovery (Offset 4)
uint16_t SUV_Threshold; // CUV Threshold (Offset 6)
uint16_t SUV_Warning; // CUV Warning (Offset 8)
uint16_t 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
{
uint16_t Cell_Voltage_Diff_Threshold; // (Offset 0) mV
uint16_t Cell_Voltage_Diff_Warning; // (Offset 2) mV
uint16_t Cell_Voltage_Diff_Recovery; // (Offset 4) mV
uint16_t 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;
uint16_t SubClass;
uint16_t Offset;
uint16_t Size;
uint16_t Value;
} TDEVICE_SET_VALUE, *PDEVICE_SET_VALUE;
/* Exported variables ------------------------------------------------------- */
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;
/* Exported functions ------------------------------------------------------- */
void Load_Param(void);
void Save_Param(void);
void LoadFwInfo(void);
void SaveFwInfo(void);
void Param_Init(u8 flag, u8 factory);
#endif /* _DEVICE_PARAM_H_ */
/*******************(C)COPYRIGHT 2021 Amogreentech *********END OF 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))
{
snprintf((char *)text, sizeof(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))
{
snprintf((char *)text, sizeof(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))
{
snprintf((char *)text, sizeof(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))
{
snprintf((char *)text, sizeof(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))
{
snprintf((char *)text, sizeof(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))
{
snprintf((char *)text, sizeof(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))
{
snprintf((char *)text, sizeof(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))
{
snprintf((char *)text, sizeof(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))
{
snprintf((char *)text, sizeof(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))
{
snprintf((char *)text, sizeof(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))
{
snprintf((char *)text, sizeof(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))
{
snprintf((char *)text, sizeof(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;
}

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

View File

@@ -0,0 +1,159 @@
/**
******************************************************************************
* File Name : dflash_sbs.c
* Description : This file provides code for system base status parameter
******************************************************************************
* @attention
*
* <h2><center>&copy; Copyright (c) 2021 Amogreentech Co., Ltd.
* All rights reserved.</center></h2>
*
******************************************************************************
*/
/* Includes ------------------------------------------------------------------*/
#include "includes.h"
#include "dflash_sbs.h"
#include "console.h"
#include "asutil.h"
#include "device_param.h"
/* Private typedef -----------------------------------------------------------*/
/* Private define ------------------------------------------------------------*/
/* Private macro -------------------------------------------------------------*/
/* Private variables ---------------------------------------------------------*/
/* Private function prototype -----------------------------------------------*/
#ifdef CONSOLE_DEBUG
u8 SSet_SbsCfg(u8 *text, u8 aDevice);
#endif /* CONSOLE_DEBUG */
/* Private function ----------------------------------------------------------*/
void SBS_InitData(void)
{
device_param.info.DevAddr = 1;
}
#ifdef CONSOLE_DEBUG
/* 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
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] = strtohex((char *)temp, j); break; /* Hex Value */
case '2': aParam[0] = StrToInt(temp, j); break; /* Int Value */
case '3': aParam[0] = strtohex((char *)temp, j); break; /* Hex Value */
case '4': aParam[0] = strtohex((char *)temp, j); break; /* Hex Value */
case '5': aParam[0] = strtohex((char *)temp, j); break; /* Hex Value */
case '6': aParam[0] = StrToInt(temp, j); break; /* Int Value */
case '7': aParam[0] = StrToInt(temp, j); break; /* Int Value */
case '8': aParam[0] = StrToInt(temp, j); break; /* Int Value */
case '9': aParam[0] = StrToInt(temp, j); break; /* Int Value */
case 'a': 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;
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))
{
snprintf((char *)text, sizeof(text), "%04X", device_param.info.DevAddr);
GreenOutXY(20, 3, text);
dis_device_param.info.DevAddr = device_param.info.DevAddr;
}
}
void SBSDisplay(u8 p)
{
SBSDisplayData(p);
}
#endif /* CONSOLE_DEBUG */
/*******************(C)COPYRIGHT 2021 Amogreentech *********END OF FILE********/

View File

@@ -0,0 +1,37 @@
/**
******************************************************************************
* File Name : dflash_sbs.h
* Description : This file provides code for system base status parameter
******************************************************************************
* @attention
*
* <h2><center>&copy; Copyright (c) 2021 Amogreentech Co., Ltd.
* All rights reserved.</center></h2>
*
******************************************************************************
*/
/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef _DFLASH_SBS_H_
#define _DFLASH_SBS_H_
/* Includes ------------------------------------------------------------------*/
#include <stm32f10x.h>
/* Exported types ------------------------------------------------------------*/
/* Exported constants --------------------------------------------------------*/
/* Exported macro ------------------------------------------------------------*/
/* Exported define -----------------------------------------------------------*/
/* Exported variables ------------------------------------------------------- */
/* Exported functions ------------------------------------------------------- */
void SBS_InitData(void);
#ifdef CONSOLE_DEBUG
s8 Process_DataSBSSet(u8 *text, u16 size);
void SBSDisplay(u8 p);
#endif /* CONSOLE_DEBUG */
#endif /* _DFLASH_SBS_H_ */
/*******************(C)COPYRIGHT 2021 Amogreentech *********END OF FILE********/

View File

@@ -0,0 +1,602 @@
/**
******************************************************************************
* File Name : dflash_sf1.c
* Description : This file provides code for safety parameter
******************************************************************************
* @attention
*
* <h2><center>&copy; Copyright (c) 2021 Amogreentech Co., Ltd.
* All rights reserved.</center></h2>
*
******************************************************************************
*/
/* Includes ------------------------------------------------------------------*/
#include "includes.h"
#include "dflash_sf1.h"
#include "device_param.h"
#include "asutil.h"
#include "console.h"
/* Private typedef -----------------------------------------------------------*/
/* Private define ------------------------------------------------------------*/
/* Private macro -------------------------------------------------------------*/
/* Private variables ---------------------------------------------------------*/
/* Private function prototype -----------------------------------------------*/
#ifdef CONSOLE_DEBUG
u8 SetSF1_Param(u8 *text, u8 aDevice);
#endif
/* Private function ----------------------------------------------------------*/
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 = 6840; // 10mV 3.8 * 18 = 68.4
device_param.safety.voltage.SOV_Warning = 6660; // 10mV 3.7 * 18 = 66.6
device_param.safety.voltage.SOV_Recovery = 6480; // 10mV 3.6 * 18 = 64.8
device_param.safety.voltage.SUV_Threshold = 4680; // 10mV 2.6 * 18 = 46.8
device_param.safety.voltage.SUV_Warning = 5040; // 10mV 2.8 * 18 = 50.4
device_param.safety.voltage.SUV_Recovery = 5400; // 10mV 3.0 * 18 = 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 = 500; // 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 = 3450; // mV
device_param.chg_ctrl.cell_bal_cfg.Cell_Balance_Window = 60; // mV
device_param.chg_ctrl.cell_bal_cfg.Cell_Balance_Min = 10; // mV
device_param.chg_ctrl.cell_bal_cfg.Cell_Balance_Interval = 5; // Sec
}
#ifdef CONSOLE_DEBUG
/* SETTING STATE <20><><EFBFBD><EFBFBD> <20><><EFBFBD>ɾ<EFBFBD> ó<><C3B3> */
s8 Process_DataSF1Set(u8 *text, u16 size)
{
u16 i, ret;
/* ù ĭ<><C4AD> space<63><65> <20><><EFBFBD>ԵǾ<D4B5> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> invalid command */
if (size > 1) {if (text[1] != ' ') return(0);}
text[size] = 0x00;
ret = 1;
switch (text[0])
{
case 'o': /* operating state<74><65> <20><>ȯ */
screenmode = OP_MODE;
ViewScreen();
break;
case 's': /* diagnostic mode<64><65> <20><>ȯ */
screenmode = SET_MODE;
ViewScreen();
break;
case 'd': /* diagnostic mode<64><65> <20><>ȯ */
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<61><74><EFBFBD><EFBFBD> */
else
UserMessage("COMMAND LIMIT ERROR"); /* setting <20>Ѱ谪<D1B0><E8B0AA><EFBFBD><EFBFBD> */
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))
{
snprintf((char *)text, sizeof(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))
{
snprintf((char *)text, sizeof(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))
{
snprintf((char *)text, sizeof(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))
{
snprintf((char *)text, sizeof(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))
{
snprintf((char *)text, sizeof(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))
{
snprintf((char *)text, sizeof(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))
{
snprintf((char *)text, sizeof(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))
{
snprintf((char *)text, sizeof(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))
{
snprintf((char *)text, sizeof(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))
{
snprintf((char *)text, sizeof(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))
{
snprintf((char *)text, sizeof(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))
{
snprintf((char *)text, sizeof(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))
{
snprintf((char *)text, sizeof(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))
{
snprintf((char *)text, sizeof(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))
{
snprintf((char *)text, sizeof(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))
{
snprintf((char *)text, sizeof(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))
{
snprintf((char *)text, sizeof(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))
{
snprintf((char *)text, sizeof(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))
{
snprintf((char *)text, sizeof(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<78><74> <20><>ü <20><><EFBFBD>ڿ<EFBFBD> size <20><><EFBFBD><EFBFBD> */
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 <20><><EFBFBD><EFBFBD> */
}
#endif /* CONSOLE_DEBUG */
/*******************(C)COPYRIGHT 2021 Amogreentech *********END OF FILE********/

View File

@@ -0,0 +1,37 @@
/**
******************************************************************************
* File Name : dflash_sf1.h
* Description : This file provides code for safety parameter
******************************************************************************
* @attention
*
* <h2><center>&copy; Copyright (c) 2021 Amogreentech Co., Ltd.
* All rights reserved.</center></h2>
*
******************************************************************************
*/
/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef _DFLASH_SF1_H_
#define _DFLASH_SF1_H_
/* Includes ------------------------------------------------------------------*/
#include <stm32f10x.h>
/* Exported types ------------------------------------------------------------*/
/* Exported constants --------------------------------------------------------*/
/* Exported macro ------------------------------------------------------------*/
/* Exported define -----------------------------------------------------------*/
/* Exported variables ------------------------------------------------------- */
/* Exported functions ------------------------------------------------------- */
void SF1_InitData(void);
#ifdef CONSOLE_DEBUG
void SF1Display(u8 p);
s8 Process_DataSF1Set(u8 *text, u16 size);
#endif /* CONSOLE_DEBUG */
#endif /* _DFLASH_SF1_H_ */
/*******************(C)COPYRIGHT 2021 Amogreentech *********END OF FILE********/

View File

@@ -0,0 +1,392 @@
/**
******************************************************************************
* File Name : display_status.c
* Description : This file provides code for status display in debug
******************************************************************************
* @attention
*
* <h2><center>&copy; Copyright (c) 2021 Amogreentech Co., Ltd.
* All rights reserved.</center></h2>
*
******************************************************************************
*/
#ifdef CONSOLE_DEBUG
/* Includes ------------------------------------------------------------------*/
#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"
/* Private typedef -----------------------------------------------------------*/
/* Private define ------------------------------------------------------------*/
/* Private macro -------------------------------------------------------------*/
/* Private variables ---------------------------------------------------------*/
/* Private function prototype -----------------------------------------------*/
/* Private function ----------------------------------------------------------*/
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, 13, (u8 *)"STAND BY ");
break;
case 1: // Charging
GreenOutXY(11, 13, (u8 *)"CHARGING ");
break;
case 2: // Discharging
GreenOutXY(11, 13, (u8 *)"DISCHARGING");
break;
case 3: // Float
GreenOutXY(11, 13, (u8 *)"FLOAT ");
break;
case 4: // Float
GreenOutXY(11, 13, (u8 *)"WARMING UP ");
break;
default:
snprintf((char *)text, sizeof(text), "UNKNOWN(%d)", device_status.op_status);
GreenOutXY(11, 13, 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, 14, (u8 *)"NORMAL ");
break;
case 1: // Warning
YellowOutXY(11, 14, (u8 *)"WARNING ");
break;
case 2: // Protection
RedOutXY (11, 14, (u8 *)"PROTECTION");
break;
case 3: // WarmingUp
GreenOutXY (11, 14, (u8 *)"WARMING UP");
break;
}
dis_device_status.alarm_status = device_status.alarm_status;
}
}
void ODisplayDeviceLiveStatus(u8 p)
{
char text[20];
// Device ID
if (p)
{
snprintf(text, sizeof(text), "%3d", GetDevAddr());
GreenOutXY(15, 2, text);
}
// Heartbeat
if (p || (dis_device_value.Heartbeat != device_value.Heartbeat))
{
snprintf(text, sizeof(text), "%7d", device_value.Heartbeat);
GreenOutXY(11, 4, text);
// printf("%7d\r\n", device_value.Heartbeat);
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, 6, 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, 7, 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, 8, aParam, 5, 1);
dis_device_value.RelativeStateOfCharge = device_value.RelativeStateOfCharge;
}
mcount = 20;
}
mcount--;
}
void ODisplayDeviceStatus(u8 p)
{
u8 text[20];
// OP Status
ODisplayAlarmStatus(p);
ODisplayBatteryStatus(p);
ODisplayOperatingStatus(p);
// Warning Status
if (p || (dis_device_status.warning.value != device_status.warning.value))
{
ODisplayWarningStatus(true);
snprintf((char *)text, sizeof(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);
snprintf((char *)text, sizeof(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 < DEVICE_MAX_CELL; i++)
{
x = 3 + ((i / 6)* 7);
y = 16 + (i % 6);
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] / 1000;
if ((device_status.cellbalance.value >> i)& 0x00000001)
FloatColorOutIntXY(DISPLAY_YELLOW, x, y, aParam, 5, 3);
else
FloatColorOutIntXY(DISPLAY_GREEN, x, y, aParam, 5, 3);
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 / 1000;
FloatNormalOutIntXY(71, 6 , aParam, 5, 3);
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 / 1000;
FloatNormalOutIntXY(71, 7 , aParam, 5, 3);
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 / 1000;
FloatNormalOutIntXY(71, 8 , aParam, 5, 3);
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 / 1000;
FloatNormalOutIntXY(71, 9 , aParam, 5, 3);
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
/*******************(C)COPYRIGHT 2021 Amogreentech *********END OF FILE********/

View File

@@ -0,0 +1,32 @@
/**
******************************************************************************
* File Name : display_status.h
* Description : This file provides code for status display in debug
******************************************************************************
* @attention
*
* <h2><center>&copy; Copyright (c) 2021 Amogreentech Co., Ltd.
* All rights reserved.</center></h2>
*
******************************************************************************
*/
/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef _DISPLAY_STATUS_H_
#define _DISPLAY_STATUS_H_
/* Includes ------------------------------------------------------------------*/
#include <stm32f10x.h>
/* Exported types ------------------------------------------------------------*/
/* Exported constants --------------------------------------------------------*/
/* Exported macro ------------------------------------------------------------*/
/* Exported define -----------------------------------------------------------*/
/* Exported functions ------------------------------------------------------- */
#ifdef CONSOLE_DEBUG
void ODisplayDevice(u8 p);
#endif /* CONSOLE_DEBUG */
#endif /* _DISPLAY_STATUS_H_ */
/*******************(C)COPYRIGHT 2021 Amogreentech *********END OF FILE********/

View File

@@ -0,0 +1,205 @@
/**
******************************************************************************
* @file : flash_if.c
* @project : BMU-18S-Firmware
* @author : JK.Woo
* @brief : This file provides all the memory related operation functions.
******************************************************************************
* @attention
*
* <h2><center>&copy; Copyright (c) 2021 Amogreentech Co., Ltd.
* All rights reserved.</center></h2>
*
******************************************************************************
*/
/* 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 and clears pending flags.
* @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 flash pages required for a given size.
* @param Size: The image size in bytes.
* @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 Erases a specified range of flash memory.
* @param EraseStartAddr: Start address for erasure.
* @param uSize: Size of the memory area to erase.
* @retval 0 on success.
*/
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 Writes a data buffer to flash memory.
* @param FlashAddress: Pointer to the start address for writing.
* @param Data: Pointer to the data buffer.
* @param DataLength: Length of the data buffer in 32-bit words.
* @retval 0 on success, 1 on error, 2 on verify fail.
*/
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 <= (BMU_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 Disables the write protection of specified 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)
{
#ifdef CONSOLE_DEBUG
printf("Write Protection disabled...\r\n");
printf("...and a System Reset will be generated to re-load the new option bytes\r\n");
#endif
/* Generate System Reset to load the new option byte values */
NVIC_SystemReset();
}
else
{
#ifdef CONSOLE_DEBUG
printf("Error: Flash write unprotection failed...\r\n");
#endif
}
}
else
{
#ifdef CONSOLE_DEBUG
printf("Flash memory not write protected\r\n");
#endif
}
}
/**
* @}
*/
/*******************(C)COPYRIGHT 2021 Amogreentech *********END OF FILE********/

View File

@@ -0,0 +1,74 @@
/**
******************************************************************************
* File Name : flash_if.h
* Description : This file provides all the memory related
* operation functions.
******************************************************************************
* @attention
*
* <h2><center>&copy; Copyright (c) 2021 Amogreentech Co., Ltd.
* All rights reserved.</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 BMU_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 2021 Amogreentech *********END OF FILE********/

View File

@@ -0,0 +1,217 @@
/**
******************************************************************************
* File Name : io.c
* Description : This file provides code for the digital input/output.
******************************************************************************
* @attention
*
* <h2><center>&copy; Copyright (c) 2021 Amogreentech Co., Ltd.
* All rights reserved.</center></h2>
*
******************************************************************************
*/
/* 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 ---------------------------------------------------------*/
uint8_t device_addr = 0;
TDEVICE_STATUS alarm_device_status;
uint8_t RunLedFlag = false;
u16 RunLedTick = 0;
uint8_t 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));
}
uint8_t GetDevAddrMem(void)
{
return device_param.info.DevAddr;
}
uint8_t GetDevAddr(void)
{
return device_addr;
}
void SetRemoteReset(void)
{
RemoteReset = true;
}
void App_TaskIO(void)
{
InitDIODevice();
AdcInit();
while (DEF_TRUE) {
device_addr = GetDevAddrMem();
ProcessAlarm();
Led_Process();
ADC_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 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();
} else {
BD_RUN_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;
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;
}
void MD_BAL_Enable_Ctrl(uint8_t enable)
{
if (enable) MD_BALANCE = false;
else MD_BALANCE = true;
}
/*******************(C)COPYRIGHT 2021 Amogreentech *********END OF FILE********/

View File

@@ -0,0 +1,42 @@
/**
******************************************************************************
* File Name : io.c
* Description : This file provides code for the digital input/output.
******************************************************************************
* @attention
*
* <h2><center>&copy; Copyright (c) 2021 Amogreentech Co., Ltd.
* All rights reserved.</center></h2>
*
******************************************************************************
*/
/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef _IO_H_
#define _IO_H_
/* Includes ------------------------------------------------------------------*/
#include <stm32f10x.h>
/* Exported types ------------------------------------------------------------*/
/* Exported constants --------------------------------------------------------*/
/* Exported macro ------------------------------------------------------------*/
/* Exported define -----------------------------------------------------------*/
/* Exported functions ------------------------------------------------------- */
void App_TaskIO(void);
void DecIOTaskTick(uint32_t tick);
uint8_t GetDevAddr(void);
void SetRemoteReset(void);
void MP2642_Enable_Ctrl(uint8_t ch, uint8_t enable);
void MP2642_EnaDis_All(uint8_t enable);
void MD_BAL_Enable_Ctrl(uint8_t enable);
#endif /* _IO_H_ */
/*******************(C)COPYRIGHT 2021 Amogreentech *********END OF FILE********/

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,58 @@
/**
******************************************************************************
* File Name : ltc6813_comm.h
* Description : This file provides code for the configuration
* of LTC-6813.
******************************************************************************
* @attention
*
* <h2><center>&copy; Copyright (c) 2021 Amogreentech Co., Ltd.
* All rights reserved.</center></h2>
*
******************************************************************************
*/
/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef _LTC6813_COMM_H_
#define _LTC6813_COMM_H_
/* Includes ------------------------------------------------------------------*/
#include <stm32f10x.h>
/* Exported types ------------------------------------------------------------*/
/* Exported constants --------------------------------------------------------*/
/* Exported macro ------------------------------------------------------------*/
/* Exported define -----------------------------------------------------------*/
/* Exported variables ------------------------------------------------------- */
/* Exported functions ------------------------------------------------------- */
void App_TaskBatt(void);
uint16_t GetTempRawValue(uint8_t tNo);
uint16_t GetTempRawValueNewBd(uint8_t tNo);
void dec_cb_tick(u16 tick);
void clear_cb_value(void);
void ForceBalancingRest(uint32_t delay_ms);
uint8_t GetCB_Rest(void);
//void SetManualBalancing(uint8_t flag, uint32_t ch, uint8_t mode, uint8_t enable);
void SetManualBalancing(uint8_t flag, uint8_t *data);
void SetManualBalancingMd(uint8_t *data);
void inc_afe_bufftime(uint32_t tick);
uint32_t GetOneBuffTime(void);
uint32_t GetAllBuffTime(void);
uint32_t GetBalancingAvgVoltage(void);
#ifdef CONSOLE_DEBUG
u8 SetLtc6813_Param(u8 *text, u8 aDevice);
void ODisplayBalancingValue(u8 p);
#endif /* CONSOLE_DEBUG */
#endif /* _LTC6813_COMM_H_ */
/*******************(C)COPYRIGHT 2021 Amogreentech *********END OF FILE********/

View File

@@ -0,0 +1,248 @@
/**
******************************************************************************
* File Name : screen.c
* Description : This file provides code for the string
* of debug console.
******************************************************************************
* @attention
*
* <h2><center>&copy; Copyright (c) 2021 Amogreentech Co., Ltd.
* All rights reserved.</center></h2>
*
******************************************************************************
*/
#ifdef CONSOLE_DEBUG
/* Includes ------------------------------------------------------------------*/
#include <includes.h>
#include "delay.h"
#define SCREEN_LINE_DELAY 2 // line delay 2ms
const char * const OPMODE_STR[] =
{
// 1 2 3 4 5 6 7 8
// 123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
"\r\n+--[Battery : ]---+---+---+---+---+---+---+---+---+---+--------------------+", // 2
"\r\n| | B |OCA|TCA|TDA|AFE|RSV|ZVC|F-C|F-D| Warning ( )HEX|", // 3
"\r\n| HeartB ( ) | S |INI|MD |FC |FD |RXM|ZVC|F-C|F-D| Protection( )HEX|", // 4
"\r\n+---------------------+---+---+---+---+---+---+---+---+---+-[CELL AVG ]--------+", // 5
"\r\n| B-Volt ( . )V | W |RSV|RSV|RSV|L-C|LTD|LTC|HTD|HTC| C-MAX ( . )V |", // 6
"\r\n| Current ( . )A | N |RSV|RSV|OCD|OCC|CUV|SUV|COV|SOV| C-AVG ( . )V |", // 7
"\r\n| SOC ( . )% +---+---+---+---+---+---+---+---+---+ C-MIN ( . )V |", // 8
"\r\n| | P |AFE|RSV|SC |RSV|LTD|LTC|HTD|HTC| C-DIFF ( . )V |", // 9
"\r\n+---------------------+ T |RSV|RSV|OCD|OCC|CUV|SUV|COV|SOV| CB AVG ( . )V |", // 0
"\r\n| F-Capa ( . )AH +---+---+---+---+---+---+---+---+---+ [ ] |", // 1
"\r\n+---------------------+ M-FLAG( ) +-[TEMP AVG ]--------+", // 2
"\r\n| Operate( )| M-BAL ( ) | T-MAX ( . )C |", // 3
"\r\n| Status ( )| | T-AVG ( . )C |", // 4
"\r\n+--[Cell Volt]--------+ | T-MIN ( . )C |", // 5
"\r\n|( . )( . )( . )| MODE ( ) | T-DIFF ( . )C |", // 6
"\r\n|( . )( . )( . )+---------+---------+---------+-----+--------------------+", // 7
"\r\n|( . )( . )( . )|T1( . )|T3( . )|T5( . )| |", // 8
"\r\n|( . )( . )( . )| | | | |", // 9
"\r\n|( . )( . )( . )|T2( . )|T4( . )|T6( . )| |", // 0
"\r\n|( . )( . )( . )| | | | |", // 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 * const SETMODE_STR[] =
{
// 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 * const DIAGMODE_STR[] = {
// 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 * const TASK_STS_MODE_STR[] =
{
// 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 * const SF1_SET_STR[] =
{
// 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 * const SBS_SET_STR[] =
{
// 1 2 3 4 5 6 7 8
// 123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
" mBMS [SBS Configuration] MODE",
"\r\n+-[Data : '1']-------------+---------------------------------------------------+",
"\r\n| '1': Dev Addr ( ) | |",
"\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+------------------------------------------------------------------------------+",
"\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
/*******************(C)COPYRIGHT 2021 Amogreentech *********END OF FILE********/

View File

@@ -0,0 +1,37 @@
/**
******************************************************************************
* File Name : screen.h
* Description : This file provides code for the string
* of debug console.
******************************************************************************
* @attention
*
* <h2><center>&copy; Copyright (c) 2021 Amogreentech Co., Ltd.
* All rights reserved.</center></h2>
*
******************************************************************************
*/
#ifdef CONSOLE_DEBUG
/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef _SCREEN_H_
#define _SCREEN_H_
/* Exported types ------------------------------------------------------------*/
/* Exported constants --------------------------------------------------------*/
/* Exported macro ------------------------------------------------------------*/
/* Exported define -----------------------------------------------------------*/
/* Exported functions ------------------------------------------------------- */
void OmodeScreen(void);
void SmodeScreen(void);
void DmodeScreen(void);
void OSmodeScreen(void);
void SF1modeScreen(void);
void SBSmodeScreen(void);
#endif /* _SCREEN_H_ */
#endif /* CONSOLE_DEBUG */
/*******************(C)COPYRIGHT 2021 Amogreentech *********END OF FILE********/

View File

@@ -0,0 +1,158 @@
/**
******************************************************************************
* File Name : task_manager.c
* Description : This file provides code for management of application
* task.
******************************************************************************
* @attention
*
* <h2><center>&copy; Copyright (c) 2021 Amogreentech Co., Ltd.
* All rights reserved.</center></h2>
*
******************************************************************************
*/
/* Includes ------------------------------------------------------------------*/
#include "includes.h"
#include "asutil.h"
#include "console.h"
/* Private typedef -----------------------------------------------------------*/
/* Private define ------------------------------------------------------------*/
#define OS_MAX_TASK_PRIO 8
/* 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 2021 Amogreentech *********END OF FILE********/

View File

@@ -0,0 +1,38 @@
/**
******************************************************************************
* File Name : task_manager.h
* Description : This file provides code for management of application
* task.
******************************************************************************
* @attention
*
* <h2><center>&copy; Copyright (c) 2021 Amogreentech Co., Ltd.
* All rights reserved.</center></h2>
*
******************************************************************************
*/
/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef _TASK_MANAGER_H_
#define _TASK_MANAGER_H_
/* Includes ------------------------------------------------------------------*/
#include <stm32f10x.h>
/* Exported types ------------------------------------------------------------*/
/* Exported constants --------------------------------------------------------*/
/* Exported macro ------------------------------------------------------------*/
/* Exported define -----------------------------------------------------------*/
/* Exported variables ------------------------------------------------------- */
/* 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 2021 Amogreentech *********END OF FILE********/

View File

@@ -0,0 +1,615 @@
/**
******************************************************************************
* File Name : temp.c
* Description : This file provides code for the measument of temperature
******************************************************************************
* @attention
*
* <h2><center>&copy; Copyright (c) 2021 Amogreentech Co., Ltd.
* All rights reserved.</center></h2>
*
******************************************************************************
*/
/* 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 6
#define TEMP_CH_MAX 6
#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 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;
/* Private function prototype -----------------------------------------------*/
void InitAD(u8 ch);
void ADC_Data_Process(void);
s16 GetTemperature(u8 ch);
s16 CalcTemperatureST32(u16 volt);
/* Private function ----------------------------------------------------------*/
/*
*********************************************************************************************************
* 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);
ADC_Param_Load();
TempUnit = cCent;
for (int i = 0; i < TEMP_CH_MAX; i++)
InitAD(i);
}
/*
*********************************************************************************************************
* Function for App_TaskAdc
*
* Description : ADC TASK
*
*********************************************************************************************************
*/
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++)
{
if (memcmp(device_inv.SerialNo, "BMU18SA", 7) == 0)
AdData[i][AdCh] = GetTempRawValueNewBd(i) / 10;
else
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]);
}
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:
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 :
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 :
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:
TEMPERATURE_Process(ch);
break;
}
}
void CalcAvgTemperature(void)
{
u32 sum;
TMinMax 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
/*******************(C)COPYRIGHT 2021 Amogreentech *********END OF FILE********/

View File

@@ -0,0 +1,49 @@
/**
******************************************************************************
* File Name : temp.h
* Description : This file provides code for the measument of temperature
******************************************************************************
* @attention
*
* <h2><center>&copy; Copyright (c) 2021 Amogreentech Co., Ltd.
* All rights reserved.</center></h2>
*
******************************************************************************
*/
/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef _TEMP_H_
#define _TEMP_H_
/* Includes ------------------------------------------------------------------*/
#include <stm32f10x.h>
/* Exported types ------------------------------------------------------------*/
/* Exported constants --------------------------------------------------------*/
/* Exported macro ------------------------------------------------------------*/
/* Exported define -----------------------------------------------------------*/
#define AD_NORMAL 0x0000
#define AD_DISABLE 0x0000
#define AD_FAIL 0x0001
#define AD_HIGH 0x0002
#define AD_LOW 0x0003
/* Exported functions ------------------------------------------------------- */
u16 ReadAdc(u8 adc_input);
void SetAdc(u8 adc_input);
u16 GetAdc(void);
void AdcInit(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 /* _TEMP_H_ */
/*******************(C)COPYRIGHT 2021 Amogreentech *********END OF FILE********/