397 lines
10 KiB
C
397 lines
10 KiB
C
#include "drv_gpio.h"
|
||
|
||
#include "gpio_manager.h"
|
||
#include "dido_manager.h"
|
||
#include "flash_manager.h"
|
||
#include "signal_manager.h"
|
||
#include "eeprom_manager.h"
|
||
|
||
#include "kit_debug.h"
|
||
|
||
typedef struct
|
||
{
|
||
uint8_t map[kDiType_End];
|
||
uint32_t dly[MAX_DI_NUM];
|
||
uint16_t tick[MAX_DI_NUM];
|
||
DiType type[MAX_DI_NUM];
|
||
DiStatus status[MAX_DI_NUM];
|
||
DiPolarity polarity[MAX_DI_NUM];
|
||
DiFun fun[MAX_DI_NUM];
|
||
}DiItem;
|
||
DiItem di_item __attribute__((section (".CCM_RAM")));
|
||
|
||
typedef struct
|
||
{
|
||
uint8_t relay_start_io;
|
||
uint8_t map[kDoType_End];
|
||
uint16_t tick[APP_CFG_RELAY_NUM];
|
||
DoCtrlStrategy main_ctrl;
|
||
DoType type[APP_CFG_RELAY_NUM];
|
||
DoStatus ctrl_status[APP_CFG_RELAY_NUM];
|
||
DoStatus actual_status[APP_CFG_RELAY_NUM];
|
||
DoErrSrc err_src[APP_CFG_RELAY_NUM]; //DO故障检测源
|
||
DoLogic bmsCircuitCtrl;
|
||
DoLogic doLogicArray[APP_CFG_RELAY_NUM];
|
||
uint32_t off_tick[APP_CFG_RELAY_NUM];
|
||
}DoItem;
|
||
DoItem do_item __attribute__((section (".UNINIT_RAM"), zero_init));
|
||
|
||
|
||
DiStatus bms_get_di_status(DiType type)
|
||
{
|
||
uint8_t idx;
|
||
DiStatus st = kDiStatus_None;
|
||
if(type < kDiType_End)
|
||
{
|
||
idx = di_item.map[type];
|
||
if(idx < MAX_DI_NUM)
|
||
{
|
||
st = di_item.status[idx];
|
||
}
|
||
}
|
||
|
||
return st;
|
||
}
|
||
|
||
|
||
DiType bms_get_di_type(uint8_t idx)
|
||
{
|
||
DiType st = kDiType_Unused;
|
||
|
||
if(idx < MAX_DI_NUM)
|
||
{
|
||
st = di_item.type[idx];
|
||
}
|
||
return st;
|
||
}
|
||
|
||
|
||
DiPolarity bms_get_di_polarity(uint8_t idx)
|
||
{
|
||
DiPolarity st = kDiPolarity_Start;
|
||
|
||
if(idx < MAX_DI_NUM)
|
||
{
|
||
st = di_item.polarity[idx];
|
||
}
|
||
|
||
return st;
|
||
}
|
||
|
||
DoCtrlStrategy bms_get_main_ctrl_strategy(void)
|
||
{
|
||
return do_item.main_ctrl;
|
||
}
|
||
|
||
DoStatus bms_get_do_status_by_idx(uint8_t idx)
|
||
{
|
||
DoStatus res = kDoStatus_Off;
|
||
KIT_ASSERT_PARAM((idx < APP_CFG_RELAY_NUM) || (idx == 0xFF));
|
||
if (idx < APP_CFG_RELAY_NUM)
|
||
{
|
||
res = do_item.actual_status[idx];
|
||
}
|
||
return res;
|
||
}
|
||
|
||
DoStatus bms_get_do_status_by_type(DoType type)
|
||
{
|
||
DoStatus res = kDoStatus_Off;
|
||
KIT_ASSERT_PARAM(type < kDoType_End);
|
||
|
||
if(type < kDoType_End)
|
||
{
|
||
res = bms_get_do_status_by_idx(do_item.map[type]);
|
||
}
|
||
return res;
|
||
}
|
||
|
||
DoType bms_get_do_type(uint8_t idx)
|
||
{
|
||
DoType res = kDoType_Unused;
|
||
KIT_ASSERT_PARAM(idx < APP_CFG_RELAY_NUM);
|
||
if (idx < APP_CFG_RELAY_NUM)
|
||
{
|
||
res = do_item.type[idx];
|
||
}
|
||
return res;
|
||
}
|
||
|
||
bool bms_is_do_config(DoType type)
|
||
{
|
||
bool res = false;
|
||
|
||
if(type < kDoType_End)
|
||
{
|
||
res = (do_item.map[type] != 0xFF);
|
||
}
|
||
|
||
return res;
|
||
}
|
||
|
||
DoErrSrc bms_get_do_err_src(DoType type)
|
||
{
|
||
DoErrSrc res = kDoErrSrc_None;
|
||
KIT_ASSERT_PARAM(type < kDoType_End);
|
||
|
||
if((type < kDoType_End) && (do_item.map[type] < APP_CFG_RELAY_NUM))
|
||
{
|
||
res = do_item.err_src[do_item.map[type]];
|
||
}
|
||
return res;
|
||
}
|
||
|
||
void bms_set_do_fault(DoType type, DoStatus status)
|
||
{
|
||
uint8_t relay_idx = 0;
|
||
KIT_ASSERT_PARAM((type < kDoType_End) && ((status == kDoStatus_Adhesion) || (status == kDoStatus_Open)));
|
||
|
||
if((type < kDoType_End) && ((status == kDoStatus_Adhesion) || (status == kDoStatus_Open)))
|
||
{
|
||
relay_idx = do_item.map[type];
|
||
if(relay_idx < APP_CFG_RELAY_NUM)
|
||
{
|
||
do_item.tick[relay_idx] = 0;
|
||
do_item.actual_status[relay_idx] = status;
|
||
}
|
||
}
|
||
}
|
||
|
||
void bms_crtl_do_status(DoType type, DoCtrlStatus status, uint16_t dly)
|
||
{
|
||
uint8_t relay_idx = 0;
|
||
KIT_ASSERT_PARAM((type < kDoType_End) && ((status == kDoStatus_Off) || (status == kDoStatus_On)));
|
||
|
||
if((type < kDoType_End) && (status < kDoCtrlStatus_None))
|
||
{
|
||
relay_idx = do_item.map[type];
|
||
if((relay_idx < APP_CFG_RELAY_NUM)
|
||
&& (do_item.ctrl_status[relay_idx] < kDoStatus_ForceOff))
|
||
{
|
||
do_item.tick[relay_idx] = dly;
|
||
do_item.ctrl_status[relay_idx] = (DoStatus)status;
|
||
}
|
||
}
|
||
}
|
||
|
||
void bms_crtl_do_status_by_idx(uint8_t idx, DoCtrlStatus status, uint16_t dly)
|
||
{
|
||
KIT_ASSERT_PARAM((idx < APP_CFG_RELAY_NUM) && ((status == kDoStatus_Off) || (status == kDoStatus_On)));
|
||
|
||
if((idx < APP_CFG_RELAY_NUM)
|
||
&& (do_item.ctrl_status[idx] < kDoStatus_ForceOff))
|
||
{
|
||
do_item.tick[idx] = dly;
|
||
do_item.ctrl_status[idx] = (DoStatus)status;
|
||
}
|
||
}
|
||
|
||
void bms_force_crtl_do_status(uint8_t idx, DoCtrlStatus status)
|
||
{
|
||
KIT_ASSERT_PARAM((idx < APP_CFG_RELAY_NUM) && (status < kDoCtrlStatus_End));
|
||
|
||
if((idx < APP_CFG_RELAY_NUM) && (status < kDoCtrlStatus_End))
|
||
{
|
||
if(status < kDoCtrlStatus_None)
|
||
{
|
||
do_item.tick[idx] = RELAY_CTRL_NO_DLY;
|
||
//@wagnk,2-17,这里原本的status加了2,取消了
|
||
do_item.ctrl_status[idx] = (DoStatus)(status);
|
||
}
|
||
else
|
||
{
|
||
//取消强控时判断之前是强控状态,是则复位
|
||
if(do_item.actual_status[idx] > kDoStatus_On)
|
||
{
|
||
do_item.tick[idx] = RELAY_CTRL_NO_DLY;
|
||
do_item.ctrl_status[idx] = kDoStatus_Off;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
void bms_cut_all_relay(void)
|
||
{
|
||
uint32_t i;
|
||
for(i = 0; i < APP_CFG_RELAY_NUM; i++)
|
||
{
|
||
do_item.tick[i] = 0;
|
||
do_item.ctrl_status[i] = kDoStatus_ForceOff;
|
||
do_item.actual_status[i] = kDoStatus_ForceOff;
|
||
drv_gpio_set_pin_status(do_item.relay_start_io + i, kGpioStatus_Low);
|
||
}
|
||
}
|
||
|
||
const GpioStatus relay_status_to_ctrl[kDoStatus_End] ={kGpioStatus_Low, kGpioStatus_High, kGpioStatus_Low, kGpioStatus_High, kGpioStatus_Low, kGpioStatus_Low};
|
||
|
||
void bms_poll_di_do(uint32_t base_time)
|
||
{
|
||
uint32_t i;
|
||
DoStatus rly_st;
|
||
|
||
if(do_item.bmsCircuitCtrl != NULL)
|
||
{
|
||
do_item.bmsCircuitCtrl(base_time, 0);
|
||
}
|
||
|
||
//DO
|
||
for(i = 0; i < APP_CFG_RELAY_NUM; i++)
|
||
{
|
||
if(do_item.doLogicArray[i] != NULL)
|
||
{
|
||
do_item.doLogicArray[i](base_time, i);
|
||
}
|
||
if(do_item.tick[i] > 0)
|
||
{
|
||
if(do_item.tick[i] <= base_time)
|
||
{
|
||
do_item.tick[i] = 0;
|
||
rly_st = do_item.ctrl_status[i];
|
||
do_item.actual_status[i] = rly_st;
|
||
drv_gpio_set_pin_status(do_item.relay_start_io + i, relay_status_to_ctrl[rly_st]);
|
||
}
|
||
else
|
||
{
|
||
do_item.tick[i] -= base_time;
|
||
}
|
||
}
|
||
}
|
||
|
||
for (i = 0; i < MAX_DI_NUM; i++)
|
||
{
|
||
if(bms_get_signal((SignalIdx)(kSignalIdx_Di1 + i)) != di_item.polarity[i])
|
||
{
|
||
di_item.tick[i] += base_time;
|
||
if(di_item.tick[i] >= di_item.dly[i])
|
||
{
|
||
di_item.tick[i] = 0;
|
||
di_item.status[i] = kDiStatus_Trigger;
|
||
}
|
||
}
|
||
else
|
||
{
|
||
di_item.tick[i] = 0;
|
||
di_item.status[i] = kDiStatus_None;
|
||
}
|
||
|
||
if(di_item.fun[i] != NULL)
|
||
{
|
||
di_item.fun[i](base_time, di_item.status[i], di_item.type[i]);
|
||
}
|
||
}
|
||
}
|
||
|
||
/*****************************************************************************
|
||
*函数名称:relay_init
|
||
*函数功能:继电器初始化
|
||
*参 数:无
|
||
*返 回 值:无
|
||
*修订信息:
|
||
******************************************************************************/
|
||
extern const DiFun di_func[kDiType_End];
|
||
void bms_init_di_do(const DoLogic *do_main_poll_array, uint8_t do_main_poll_len, const DoLogic *do_poll_array)
|
||
{
|
||
uint32_t idx;
|
||
DiType di_type;
|
||
DoType do_type;
|
||
EepromDataType data_type;
|
||
DoErrSrc do_err_src_type;
|
||
|
||
// //上电前先断开所有继电器
|
||
//#if defined(BIUxxB) || defined(BSE1B) || defined(BSE2B)
|
||
// drv_gpio_set_pin_status(kGpioType_RlyEn, kGpioStatus_High);
|
||
// drv_gpio_set_pin_status(kGpioType_RlyEn, kGpioStatus_Low);
|
||
//#endif
|
||
bsp_eeprom_set_data(kRelay2_1ForceCtrlStatus, 0x0202, kEepromDataType_Full);
|
||
bsp_eeprom_set_data(kRelay4_3ForceCtrlStatus, 0x0202, kEepromDataType_Full);
|
||
bsp_eeprom_set_data(kRelay6_5ForceCtrlStatus, 0x0202, kEepromDataType_Full);
|
||
bsp_eeprom_set_data(kRelay8_7ForceCtrlStatus, 0x0202, kEepromDataType_Full);
|
||
bsp_eeprom_set_data(kRelay10_9ForceCtrlStatus, 0x0202, kEepromDataType_Full);
|
||
|
||
for(idx = kDoType_Start; idx < kDoType_End; idx++)
|
||
{
|
||
do_item.map[idx] = 0xFF;
|
||
}
|
||
for (idx = 0; idx < APP_CFG_RELAY_NUM; idx++)
|
||
{
|
||
do_item.tick[idx] = 0;
|
||
do_item.off_tick[idx] = 0;
|
||
do_item.relay_start_io = kGpioType_DO1;
|
||
if(get_eeprom_data(kEep_IsSoftReset, kEepromDataType_Low) == 0)
|
||
{
|
||
do_item.ctrl_status[idx] = kDoStatus_Off;
|
||
do_item.actual_status[idx] = kDoStatus_Off;
|
||
}
|
||
else
|
||
{
|
||
if(do_item.ctrl_status[idx] < kDoStatus_End)
|
||
{
|
||
drv_gpio_set_pin_status(do_item.relay_start_io + idx, relay_status_to_ctrl[do_item.ctrl_status[idx]]);
|
||
}
|
||
else
|
||
{
|
||
do_item.ctrl_status[idx] = kDoStatus_Off;
|
||
}
|
||
}
|
||
//sfj 7.23新加 DO9 DO10
|
||
if(idx == 8 || idx == 9)
|
||
{
|
||
do_type = (DoType)(get_eeprom_data(kEep_Relay10_9Type, (EepromDataType)(idx % 2)));
|
||
if (do_type < kDoType_End)
|
||
{
|
||
do_item.map[do_type] = idx;
|
||
do_item.type[idx] = do_type;
|
||
do_item.doLogicArray[idx] = do_poll_array[do_type];
|
||
}
|
||
do_err_src_type = (DoErrSrc)get_eeprom_data(kEep_DO10_DO9_ErrSrc, (EepromDataType)(idx % 2));
|
||
if(do_err_src_type < kDoErrSrc_End)
|
||
{
|
||
do_item.err_src[idx] = do_err_src_type;
|
||
}
|
||
}
|
||
else//do1-do8
|
||
{
|
||
do_type = (DoType)(get_eeprom_data(kEep_Relay2_1Type + (idx >> 1), (EepromDataType)(idx % 2)));
|
||
if (do_type < kDoType_End)
|
||
{
|
||
do_item.map[do_type] = idx;
|
||
do_item.type[idx] = do_type;
|
||
do_item.doLogicArray[idx] = do_poll_array[do_type];
|
||
}
|
||
do_err_src_type = (DoErrSrc)get_eeprom_data(kEep_DO2_DO1_ErrSrc + (idx >> 1), (EepromDataType)(idx % 2));
|
||
if(do_err_src_type < kDoErrSrc_End)
|
||
{
|
||
do_item.err_src[idx] = do_err_src_type;
|
||
}
|
||
}
|
||
}
|
||
|
||
//初始化订单继电器策略=本地和远方
|
||
idx = get_eeprom_data(kEep_ChgDisMode_HighVoltStrategy, kEepromDataType_Low);
|
||
if(idx < do_main_poll_len)
|
||
{
|
||
do_item.main_ctrl = (DoCtrlStrategy)idx;
|
||
do_item.bmsCircuitCtrl = do_main_poll_array[idx];
|
||
}
|
||
|
||
for(idx = kDiType_Start; idx < kDiType_End; idx++)
|
||
{
|
||
di_item.map[idx] = 0xFF;
|
||
}
|
||
|
||
for (idx = 0; idx < MAX_DI_NUM; idx++)
|
||
{
|
||
data_type = (EepromDataType)(idx % 2);
|
||
di_item.dly[idx] = get_eeprom_data(kEep_Di2_1Delay + (idx >> 1), data_type) * 100;
|
||
di_type = (DiType)get_eeprom_data(kEep_Di2_1Type + (idx >> 1), data_type);
|
||
if (di_type < kDiType_End)
|
||
{
|
||
di_item.map[di_type] = idx;
|
||
di_item.type[idx] = di_type;
|
||
di_item.fun[idx] = di_func[di_type];
|
||
}
|
||
di_item.polarity[idx] = (DiPolarity)get_eeprom_data(kEep_Di2_1Polarity + (idx >> 1), data_type);
|
||
}
|
||
}
|
||
|