Files
LFP_48V_mBMS_FW/mBMS_APP_V3117/APP/io.c

848 lines
17 KiB
C

/**
******************************************************************************
* File Name : io.c
* Description : This file provides code for the digital input/output.
******************************************************************************
* @attention
*
* <h2><center>&copy; Copyright (c) 2019 STMicroelectronics.
* All rights reserved.</center></h2>
*
* This software component is licensed by ST under Ultimate Liberty license
* SLA0044, the "License"; You may not use this file except in compliance with
* the License. You may obtain a copy of the License at:
* www.st.com/SLA0044
*
******************************************************************************
*/
/* Includes ------------------------------------------------------------------*/
#include <includes.h>
#include "io.h"
#include "led.h"
#include "relay.h"
#include "dev_addr.h"
#include "asutil.h"
#include "device_param.h"
#include "dflash_sf1.h"
#include "log.h"
#include "delay.h"
#include "modbus.h"
#include "buzzer.h"
#include "alarm.h"
#include "pwm.h"
/* Private typedef -----------------------------------------------------------*/
typedef struct // Input PortNo 0..4 * 8 channels
{
// PORT Information
s16 PortNo;
u8 NormalOpen; // Normal state logic level (0 or 1)
u8 Enabled; // Enable device?
s16 RefPort; // Module disconnection reference Port
u8 State; // Current state of device
u8 OldState; // Previous state of device
// Chattering
u8 UsedChat; // Enable chattering filter
// MultiChat; // If OCCUR Chatt = 100, NORMAL Chatt = ChatTime, ex) Cable Open
u8 ChatState;
u16 AlarmChatTime; // Chattering Time (1 = 1ms)
u16 ReleaseChatTime; // Chattering Time (1 = 1ms)
u16 ChatCount; // Chattering internal counter
// Using Information
u8 Changed;
// Temp Var
u8 BakEnabled; // Flag for screen display
u8 StateFlag; // Flag for state storage
} TDIDeviceRec, *PDIDeviceRec;
/* Private define ------------------------------------------------------------*/
#define IO_TASK_TIME 5 // 50ms TASK
#define IO_ALARM_TIME 500 // 3000ms Alarm Delay
#define LED_ONOFF_TIME 200 // 500ms
#define DIDCount 2
/*********************** Digital Input Define *********************************/
#define DI_DISCHA_RELAY 0
#define DI_CHARGE_RELAY 1
#define RON 1
#define ROFF 0
#define PUSH 1
#define PULL 0
#define High 1 /* USED INVENTORY */
#define Low 0 /* USED INVENTORY */
#define false 0
#define true 1
#define cNormalOpen 0
#define cNormalClose 1
#define cNORMAL 0
#define cINITVALUE 0xff
#define cOCCUR 1
#define cUNKNOWN 2
#define cDISABLE 3
#define cCANCEL 0
#define DSG_RELAY_ID '0'
#define CHG_RELAY_ID '1'
#define PRE_CHG_RELAY_ID '2'
/* Private macro -------------------------------------------------------------*/
/* Private variables ---------------------------------------------------------*/
u8 device_addr = 0;
TDIDeviceRec DID[DIDCount], BakDID[DIDCount];
TDEVICE_STATUS alarm_device_status;
u8 AlarmLed = false;
u8 AlarmLedFlag = false;
u16 AlarmLedTick = 0;
u8 BuzzerWarning = false;
u8 BuzzerProtection = false;
u8 AlarmBuzzerFlag = false;
u16 AlarmBuzzerTick = 0;
u8 RunLedFlag = false;
u16 RunLedTick = 0;
u8 SocLedFlag = false;
u16 SocLedTick = 0;
u8 SocLed[4] = { 0 };
u8 RemoteReset = false;
/* Private function prototypes -----------------------------------------------*/
void IO_Relay_Control(void);
void Buzzer_Process(void);
void Led_Process(void);
void InitDIO(s16 port, s16 ref_port, u8 io_type, u16 alarm_time, u16 release_time, u8 enable);
void Check_DI(void);
void AnalysisDI(PDIDeviceRec aDID);
u8 DIDState(u16 i);
void dec_led_time(u32 tick);
void dec_buzzer_time(u32 tick);
/* Private function ----------------------------------------------------------*/
void InitDIODevice(void)
{
Relay_Init();
DevAddrInit();
for (int i = 0; i < DIDCount; i++)
{
DID[i].Enabled = true;
DID[i].PortNo = -1; // Undefine Port
DID[i].RefPort = -1; // Not used ref Port
DID[i].State = cNORMAL;
DID[i].OldState = cNORMAL;
DID[i].Changed = false;
DID[i].UsedChat = true;
DID[i].AlarmChatTime = 0;
DID[i].ReleaseChatTime = 0;
DID[i].ChatCount = 0;
DID[i].ChatState = cINITVALUE;
DID[i].BakEnabled = cINITVALUE; // Flag for screen display
DID[i].StateFlag = cINITVALUE; // Flag for state storage DID[i].Enabled = true;
}
InitDIO(DI_DISCHA_RELAY , -1, cNormalClose, IO_ALARM_TIME, IO_ALARM_TIME, true);
InitDIO(DI_CHARGE_RELAY , -1, cNormalClose, IO_ALARM_TIME, IO_ALARM_TIME, true);
memset(&alarm_device_status, 0x00, sizeof(TDEVICE_STATUS));
}
void InitDIO(s16 port, s16 ref_port, u8 io_type, u16 alarm_time, u16 release_time, u8 enable)
{
DID[port].Enabled = enable;
DID[port].PortNo = port;
DID[port].RefPort = ref_port;
DID[port].NormalOpen = io_type;
DID[port].AlarmChatTime = alarm_time;
DID[port].ReleaseChatTime = release_time;
}
u8 GetDevAddrIO(void)
{
return device_addr;
// return device_param.sbs.data.System_ID;
}
void SetRemoteReset(void)
{
RemoteReset = true;
}
void App_TaskIO(void)
{
InitDIODevice();
while (DEF_TRUE)
{
device_addr = GetDevAddr();
Check_DI();
ProcessAlarm();
IO_Relay_Control();
Led_Process();
// Buzzer_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);
dec_buzzer_time(tick);
}
void Check_DI(void)
{
s16 i;
for (i = 0; i < DIDCount; i++)
{
DID[i].Changed = false;
AnalysisDI(&DID[i]);
}
device_status.battery_status.bit.DSG_S = (DIDState(DI_DISCHA_RELAY) != cNORMAL) ? 1 : 0;
device_status.battery_status.bit.CHG_S = (DIDState(DI_CHARGE_RELAY) != cNORMAL) ? 1 : 0;
}
u8 GetIOBit(u16 port)
{
u8 result = 0;
switch (port)
{
case DI_DISCHA_RELAY : result = Relay_Status(DI_DISCHA_RELAY); break;
case DI_CHARGE_RELAY : result = Relay_Status(DI_CHARGE_RELAY); break;
default:
break;
}
return result;
}
void AnalysisDI(PDIDeviceRec aDID)
{
u16 ChatTime;
u8 BitState;
if (aDID->PortNo == -1) return; /* Undefined DI PORT */
aDID->OldState = aDID->State;
aDID->Changed = false;
aDID->StateFlag = true;
BitState = GetIOBit(aDID->PortNo);
if (aDID->NormalOpen == cNormalClose) BitState ^= aDID->NormalOpen;
if (aDID->UsedChat == true)
{
if (aDID->State == cNORMAL)
ChatTime = aDID->AlarmChatTime;
else
ChatTime = aDID->ReleaseChatTime;
if (aDID->ChatState == BitState)
{
if (aDID->ChatCount < 10000) aDID->ChatCount += IO_TASK_TIME;
}
else
aDID->ChatCount = 0;
aDID->ChatState = BitState;
if (aDID->ChatCount < ChatTime) BitState = aDID->State;
}
if (aDID->RefPort != -1) /* CABLE OPEN or FAIL reference PORT */
{
if (DID[aDID->RefPort].State == cOCCUR)
{
BitState = cUNKNOWN;
aDID->Changed = DID[aDID->RefPort].Changed;
}
}
if (BitState != aDID->OldState) /* State changed */
{
aDID->Changed = true;
aDID->OldState = BitState;
aDID->State = BitState;
aDID->StateFlag = true; /* Flag for state storage */
}
}
void DIDAlarmHistory(PDIDeviceRec aDID,u8 msg1,u8 msg2,u8 msg3,u8 msg4)
{
if (aDID->Enabled == true){
if (aDID->Changed)
{
// switch (aDID->State) {
// case cNORMAL : ADD_RUN_HISTORY(true,osENVIR,0,0,msg1,msg2);
// break;
// case cOCCUR : ADD_RUN_HISTORY(true,osENVIR,0,0,msg1,msg3);
// break;
// case cUNKNOWN: ADD_RUN_HISTORY(true,osENVIR,0,0,msg1,msg4);
// break;
// }
}
}
}
void DoorAlarmHistory(PDIDeviceRec aDID,u8 msg1,u8 msg2,u8 msg3,u8 msg4)
{
if (aDID->Enabled == true)
{
if (aDID->Changed)
{
switch (aDID->State)
{
case cNORMAL :
// ADD_RUN_HISTORY(true,osENVIR,0,0,msg1,msg2);
break;
case cOCCUR :
// ADD_RUN_HISTORY(true,osENVIR,0,0,msg1,msg3);
break;
case cUNKNOWN:
// ADD_RUN_HISTORY(true,osENVIR,0,0,msg1,msg4);
break;
}
}
}
}
u8 DIDState(u16 i) // return cNORMAL, cDISABLE, cOCCUR, cUNKNOWN
{
u8 Alarmflag;
Alarmflag = cNORMAL;
if (DID[i].Enabled != true) Alarmflag = cDISABLE; // No Alarm
else
{
if (DID[i].State == cOCCUR) Alarmflag = cOCCUR;
if (DID[i].RefPort != -1)
{
if (DID[DID[i].RefPort].State == cOCCUR)
{
Alarmflag = cUNKNOWN; // fail
}
}
}
return(Alarmflag);
}
void IO_Relay_Control(void)
{
if (device_status.battery_status.bit.INIT)
{
if (device_status.battery_status.bit.CHG_C == RON)
// Relay On
Relay_On(CHG_RELAY_ID);
else
// Relay Off
Relay_Off(CHG_RELAY_ID);
if (device_status.battery_status.bit.DSG_C == RON)
// Relay On
Relay_On(DSG_RELAY_ID);
else
// Relay Off
Relay_Off(DSG_RELAY_ID);
if (device_status.battery_status.bit.ZVC_C == RON)
// Relay On
Relay_On(PRE_CHG_RELAY_ID);
else
// Relay Off
Relay_Off(PRE_CHG_RELAY_ID);
}
}
void dec_led_time(u32 tick)
{
if (AlarmLedTick > 0)
{
if (AlarmLedTick > tick)
AlarmLedTick -= tick;
else
AlarmLedTick = 0;
}
if (RunLedTick > 0)
{
if (RunLedTick > tick)
RunLedTick -= tick;
else
RunLedTick = 0;
}
if (SocLedTick > 0)
{
if (SocLedTick > tick)
SocLedTick -= tick;
else
SocLedTick = 0;
}
}
void Alarm_Led_Process(void)
{
switch (device_status.alarm_status)
{
case 0: // Normal
ALM_LED = OFF;
break;
case 1: // Warning
if (AlarmLedFlag == true)
{
if (AlarmLedTick == 0)
{
ALM_LED = ON;
AlarmLedTick = 1000;
AlarmLedFlag = false;
}
}
else
{
if (AlarmLedTick == 0)
{
ALM_LED = OFF;
AlarmLedTick = 1000;
AlarmLedFlag = true;
}
}
break;
case 2: // Protection
ALM_LED = ON;
break;
case 3: // WarmingUp
ALM_LED = OFF;
break;
}
}
void RUN_LED_Process(void)
{
switch (device_status.op_status)
{
case 0: // Standby
RUN_LED = ON;
break;
case 1: // Charging
RUN_LED = ON;
// if (RunLedFlag == true)
// {
// if (RunLedTick == 0)
// {
// BD_RUN_LED = ON;
// RUN_LED = ON;
//
// RunLedTick = 1000;
// RunLedFlag = false;
// }
// }
// else
// {
// if (RunLedTick == 0)
// {
// BD_RUN_LED = OFF;
// RUN_LED = OFF;
//
// RunLedTick = 1000;
// RunLedFlag = true;
// }
// }
break;
case 2: // Discharging
if (RunLedFlag == true)
{
if (RunLedTick == 0)
{
BD_RUN_LED = ON;
RUN_LED = ON;
RunLedTick = 1000;
RunLedFlag = false;
}
}
else
{
if (RunLedTick == 0)
{
BD_RUN_LED = OFF;
RUN_LED = OFF;
RunLedTick = 1000;
RunLedFlag = true;
}
}
break;
case 3: // Floating
RUN_LED = ON;
break;
}
}
void SOC_LED_Buf(u32 soc, u16 mode)
{
switch (mode)
{
case 0: // Standby
for (int i = 0; i < 4; i++)
{
if (SocLed[i] == 2)
SocLed[i] = 1;
else if (SocLed[i] == 3)
SocLed[i] = 0;
}
break;
case 1: // Charging
if (soc > 750)
{
SocLed[0] = 1;
SocLed[1] = 1;
SocLed[2] = 1;
if (SocLed[3] == 1)
SocLed[3] = 2;
else if (SocLed[3] == 0)
SocLed[3] = 3;
}
else if (soc > 500)
{
SocLed[0] = 1;
SocLed[1] = 1;
if (SocLed[2] == 1)
SocLed[2] = 2;
else if (SocLed[2] == 0)
SocLed[2] = 3;
SocLed[3] = 0;
}
else if (soc > 250)
{
SocLed[0] = 1;
if (SocLed[1] == 1)
SocLed[1] = 2;
else if (SocLed[1] == 0)
SocLed[1] = 3;
SocLed[2] = 0;
SocLed[3] = 0;
}
else if (soc > 0)
{
if (SocLed[0] == 1)
SocLed[0] = 2;
else if (SocLed[0] == 0)
SocLed[0] = 3;
SocLed[1] = 0;
SocLed[2] = 0;
SocLed[3] = 0;
}
else
{
SocLed[0] = 0;
SocLed[1] = 0;
SocLed[2] = 0;
SocLed[3] = 0;
}
break;
case 2: // Discharging
if (soc > 750)
{
SocLed[0] = 1;
SocLed[1] = 1;
SocLed[2] = 1;
if (SocLed[3] == 2)
SocLed[3] = 1;
else if (SocLed[3] == 3)
SocLed[3] = 0;
}
else if (soc > 500)
{
SocLed[0] = 1;
SocLed[1] = 1;
if (SocLed[2] == 2)
SocLed[2] = 1;
else if (SocLed[2] == 3)
SocLed[2] = 0;
SocLed[3] = 0;
}
else if (soc > 250)
{
SocLed[0] = 1;
if (SocLed[1] == 2)
SocLed[1] = 1;
else if (SocLed[1] == 3)
SocLed[1] = 0;
SocLed[2] = 0;
SocLed[3] = 0;
}
else if (soc > 0)
{
if (SocLed[0] == 2)
SocLed[0] = 1;
else if (SocLed[0] == 3)
SocLed[0] = 0;
SocLed[1] = 0;
SocLed[2] = 0;
SocLed[3] = 0;
}
else
{
SocLed[0] = 0;
SocLed[1] = 0;
SocLed[2] = 0;
SocLed[3] = 0;
}
break;
case 3: // Floating
if (soc >= 1000)
{
SocLed[0] = 1;
SocLed[1] = 1;
SocLed[2] = 1;
SocLed[3] = 1;
}
else
{
for (int i = 0; i < 4; i++)
{
if (SocLed[i] == 2)
SocLed[i] = 1;
else if (SocLed[i] == 3)
SocLed[i] = 0;
}
}
break;
case 4: // WarmingUp
if (soc > 750)
{
SocLed[0] = 1;
SocLed[1] = 1;
SocLed[2] = 1;
SocLed[3] = 1;
}
else if (soc > 500)
{
SocLed[0] = 1;
SocLed[1] = 1;
SocLed[2] = 1;
SocLed[3] = 0;
}
else if (soc > 250)
{
SocLed[0] = 1;
SocLed[1] = 1;
SocLed[2] = 0;
SocLed[3] = 0;
}
else if (soc > 0)
{
SocLed[0] = 1;
SocLed[1] = 0;
SocLed[2] = 0;
SocLed[3] = 0;
}
else
{
SocLed[0] = 0;
SocLed[1] = 0;
SocLed[2] = 0;
SocLed[3] = 0;
}
break;
}
}
void SOC_LED_Control(u8 no, u8 onoff)
{
switch (no)
{
case 0: SOC_0_LED = onoff; break;
case 1: SOC_1_LED = onoff; break;
case 2: SOC_2_LED = onoff; break;
case 3: SOC_3_LED = onoff; break;
}
}
void SOC_LED_Process(void)
{
SOC_LED_Buf(device_value.RelativeStateOfCharge, device_status.op_status);
for (int i = 0; i < 4; i++)
{
switch (SocLed[i])
{
case 0: // LED Off
SOC_LED_Control(i, 0);
break;
case 1: // LED On
SOC_LED_Control(i, 1);
break;
case 2: // LED Toggle
case 3: // LED Toggle
if (SocLedFlag == true)
{
if (SocLedTick == 0)
{
SOC_LED_Control(i, 1); // On
SocLedTick = 1000;
SocLedFlag = false;
}
}
else
{
if (SocLedTick == 0)
{
SOC_LED_Control(i, 0); // Off
SocLedTick = 1000;
SocLedFlag = true;
}
}
break;
}
}
}
void Led_Process(void)
{
if (GetSleepMode() == false)
{
Alarm_Led_Process();
RUN_LED_Process();
SOC_LED_Process();
}
else
{
SOC_0_LED = OFF;
SOC_1_LED = OFF;
SOC_2_LED = OFF;
SOC_3_LED = OFF;
ALM_LED = OFF;
RUN_LED = OFF;
}
}
void Alarm_Buzzer_Update(void)
{
alarm_device_status.warning.value = device_status.warning.value;
alarm_device_status.protection.value = device_status.protection.value;
}
void Alarm_Buzzer_Process(void)
{
u8 buzzer = false;
if (alarm_device_status.warning.value < device_status.warning.value)
{
buzzer = true;
}
else
{
alarm_device_status.warning.value = device_status.warning.value;
}
BuzzerWarning = buzzer;
buzzer = false;
if (alarm_device_status.protection.value < device_status.protection.value)
{
buzzer = true;
}
else
{
alarm_device_status.protection.value = device_status.protection.value;
}
BuzzerProtection = buzzer;
}
void dec_buzzer_time(u32 tick)
{
if (AlarmBuzzerTick > 0)
{
if (AlarmBuzzerTick > 0)
AlarmBuzzerTick -= tick;
else
AlarmBuzzerTick = 0;
}
}
void Buzzer_Process(void)
{
Alarm_Buzzer_Process();
// Protection
if (BuzzerProtection)
{
if (AlarmBuzzerFlag == true)
{
if (AlarmBuzzerTick == 0)
{
BUZZER = 0;
AlarmBuzzerTick = 500;
AlarmBuzzerFlag = false;
}
}
else
{
if (AlarmBuzzerTick == 0)
{
BUZZER = 1;
AlarmBuzzerTick = 500;
AlarmBuzzerFlag = true;
}
}
}
// Warning
else if (BuzzerWarning)
{
if (AlarmBuzzerFlag == true)
{
if (AlarmBuzzerTick == 0)
{
BUZZER = 0;
AlarmBuzzerTick = 1000;
AlarmBuzzerFlag = false;
}
}
else
{
if (AlarmBuzzerTick == 0)
{
BUZZER = 1;
AlarmBuzzerTick = 1000;
AlarmBuzzerFlag = true;
}
}
}
else
{
BUZZER = 0;
}
}