Files
jiacun-20s-200A/USER/main.c
T
2026-08-25 17:30:40 +08:00

546 lines
12 KiB
C

/**
******************************************************************************
* @file main.c
* @author BMS
* @version V1.0.0
* @date 20-5-2022
* @brief Main program body.
******************************************************************************
* @attention
*
* Copyright (c) 2011 STMicroelectronics.
* All rights reserved.
*
* This software is licensed under terms that can be found in the LICENSE file
* in the root directory of this software component.
* If no LICENSE file comes with this software, it is provided AS-IS.
*
******************************************************************************
*/
/* Includes ------------------------------------------------------------------*/
#include "stm32f10x.h"
#include "global.h"
#include "rtc.h"
#include "soe.h"
/** @addtogroup STM32F10x_StdPeriph_Examples
* @{
*/
/** @addtogroup GPIO_IOToggle
* @{
*/
/* Private typedef -----------------------------------------------------------*/
/* Private define ------------------------------------------------------------*/
/* Private macro -------------------------------------------------------------*/
/* Private variables ---------------------------------------------------------*/
/* Private function prototypes -----------------------------------------------*/
/* Private functions ---------------------------------------------------------*/
/**
* @brief Main program.
* @param None
* @retval None
*/
int main(void)
{
#if Key_PressLong
POWER_Check();
#endif
delay_ms(1000); //上电之后加1S延时,防止WK唤醒误动
//SCB->VTOR = FLASH_BASE | 0x1800;
uf_GPIO_Init();
uf_EXTI_Init();
uf_TIM3_Init(); //10MS
uf_I2C1_Init();
uf_SPI2_Init();
uf_CAN1_Init();
uf_ADC_Init();
uf_IWDG_Init(7,1250); //分频数=7,重载值=1250,溢出时间=((4*2^7)*1250)/40=16000ms=16s
#if Key_PressLong
LED_ALL_ON(); //按钮长按模式,需要先灭再常亮
#endif
uf_FLASH_Init();
uf_GLOBAL_Init();
/*三选一模块*/
#if BLE_Conn
BLE_Init(); //蓝牙初始化
BLE_IO_Init();
BLE_Open();
#endif
#if WIFI_Conn
WIFI_Init(); //WIFI初始化
WIFI_IO_Init();
WIFI_Open();
#endif
#if LTE_Conn
LTE_4G_Init(); //4G初始化
LTE_4G_IO_Init();
LTE_4G_Open();
#endif
// BAL_Off(); //默认关闭外置主动均衡(钰泰)
MODBUS_Init();
MODBUS1_Init();
AFE_VoltageProcess();
InitGasGauge();
MCU_TemperaProcess();
MODBUS_Poll_Init();
Screen_Init(); //[陶晶驰]
if(uf_RTC_Init()==1) //RTC时钟初始化,超时说明晶振有问题
{
LSEErrFlag=1;
sleep_Moni_Count=SLEEP_MON_CNT;
}
else
{
RTC_Get();
}
while (1)
{
//5*10ms
if(TIMER_IsOut(tmrTemp[0],5))
{
tmrTemp[0] = TIMER_Update();
/*三选一模块:蓝牙*/
#if BLE_Conn
BLE_IQ_Update(); //更新数据
BLE_IQ_Transmit(); //发送数据,每0.05s执行一次
#endif
}
//10*10ms
if(TIMER_IsOut(tmrTemp[1],10))
{
tmrTemp[1] = TIMER_Update();
/*三选一模块:WIFI*/
#if WIFI_Conn
WIFI_IQ_Update(); //更新数据
WIFI_IQ_Transmit(); //发送数据,每0.1s执行一次
#endif
}
//25*10ms
if(TIMER_IsOut(tmrTemp[2],25))
{
tmrTemp[2] = TIMER_Update();
AFE_CurrentProcess(); //1s读4次电流后取平均值
#if Key_PressLong
if(OFF_confirm_flg == 1) //若确认关机,此时把所有灯灭掉,提醒松开就会关机
{
LED_ALL_OFF();
}
else if(RST_confirm_flg == 1) //若按键摁下执行复位,灯被接管闪烁
{
LED_RST_Toggle();
}
else if(ON_confirm_flg != 0) //虚地址运行灯快速闪烁
{
if(sleep_flag == 0)
{
if(curLimitFlag == 0)
{
if(bmsMem.E2_485Addr > AddrMax)
{
LED_RUN_Toggle();
}
}
}
}
#endif
/*三选一模块:4G*/
#if LTE_Conn
if((LTE_WarmDelay == 0) && (LTE_ResendDelay == 0) && (LTE_WaitRxDelay == 0) && (LTE_PinRST_Flag == 0) && (LTE_sleep_flag == 0)) //不在等候+不在引脚重启+不在休眠
{
if(MQTT_READY_flag == 0) //未通信MQTT
{
if(LTE_LINK_flag == 1)
{
LTE_4G_IQ_Update(); //更新数据
LTE_4G_IQ_Transmit(); //发送数据,每0.25s执行一次
}
}
else //已通信MQTT
{
if((pre_sleep_flag == 4) || (LTE_status == event_pub) || (LTE_status == srvc_pub) || (LTE_status == setPara_pub) || (LTE_status == getPara_pub))
{
LTE_4G_IQ_Update(); //更新数据
LTE_4G_IQ_Transmit(); //发送数据,每0.25s执行一次
}
else if(LTE_OTA_Flag == 1)
{
LTE_OTA_IQ_Update(); //更新数据
LTE_OTA_IQ_Transmit(); //发送数据,每0.25s执行一次
}
}
}
#endif
}
CALI_CurrentProcess(); //收到校准指令后进行更新,并回复
//50*10ms
if(TIMER_IsOut(tmrTemp[3],50))
{
tmrTemp[3] = TIMER_Update();
//LED 运行灯
#if Key_PressLong
if((ON_confirm_flg != 0) && (RST_confirm_flg != 1) && (OFF_confirm_flg != 1))
#endif
{
if(sleep_flag == 0)
{
if(curLimitFlag == 0)
{
if((bmsMem.E2_485Addr >= 1) && (bmsMem.E2_485Addr <= AddrMax))
{
LED_RUN_Toggle(); //正常地址运行灯正常闪烁
}
}
else
{
LED_RUN_On(); //限流常亮灯
}
}
else
{
LED_RUN_Off(); //休眠不亮灯
}
}
//LED报警灯
#if Key_PressLong
if((ON_confirm_flg != 0) && (RST_confirm_flg != 1) && (OFF_confirm_flg != 1))
#endif
{
if((bAlarmFlag == 0) && (((bmsMem.bStatus2 & 0x00e0) ==0) && ((bmsMem.temperaStatus & 0x0040) ==0))) //无保护
{
if(((bmsMem.bStatus2 & 0xff00) != 0) || ((bmsMem.bStatus3 & 0x3A00) != 0) || ((bmsMem.temperaStatus & 0xf000) != 0)) //有报警(除了单体过压告警和总体过压告警)
{
if(sleep_flag == 0) LED_ALARM_Toggle();
else LED_ALARM_Off();
}
else if((bmsMem.bStatus3 & 0x0500) != 0) //单体过压告警和总体过压告警
{
if(bmsMem.soc<99) //在正常工作时,发生[过压保护],正常显示
{
if(sleep_flag == 0) LED_ALARM_Toggle();
else LED_ALARM_Off();
}
else
{
LED_ALARM_Off();
}
}
}
}
//主机轮询从机
#if Key_PressLong
if(OFF_confirm_flg != 1)
#endif
{
if(sleep_flag == 0) //休眠时,主从通信禁用 //确认关机后,停止通信
{
//主机在3.4口向下通讯
if((bmsMem.E2_485Addr == 1) && (paraMem.PACK_NUM >= 2) && (PollStop_flag == 0))
{
#if Addr_SetAuto
//开机后地址可能从1变2,先等待2s
if((paraMem.addr_FREE_Flg == 0) && (assignAddr_relay > 0))
{
assignAddr_relay--;
}
else if((paraMem.addr_FREE_Flg == 0) && ((assignAddr_State == 0) || (assignAddr_State == 1)))
{
MODBUS_AddrAssign_Tx(); //(主机自动分配从机地址,结束了再进行下一操作)
}
else if((paraMem.addr_FREE_Flg == 0) && ((assignAddr_State == 2) && (assignAddr_WrIndex_Flg == 1)))
{
assignAddr_WrIndex_Flg = 0;
MODBUS_WrIndex_Tx(); //主机广播队列标志数
}
else
#endif
{
if(sdwa_WrAddr_Flg == 1)//(主机屏幕写从机地址,结束了再进行下一操作)
{
MODBUS_Screen_WrSlaveAddr_Tx();
}
else if((ConfigData_Index>=2) && (ConfigData_Index<=paraMem.PACK_NUM))
{
MODBUS_Config_RdSlave_Tx();//(上位机持续读单一从机,上位机比屏幕优先级高)
}
else if((scr_RdData_Index>=2) && (scr_RdData_Index<=paraMem.PACK_NUM))
{
MODBUS_Screen_RdSlave_Tx();//(屏幕持续读单一从机)
}
else
{
MODBUS_MASTER_Polling_Tx();//(轮询,是默认状态)
}
}
}
//主机暂停轮询在收不到之后的30s恢复
else if(PollStop_flag == 1)
{
PollStop_count++;
if(PollStop_count > 30)
{
PollStop_count = 0;
PollStop_flag = 0;
}
}
}
}
}
//100*10ms
if(TIMER_IsOut(tmrTemp[4],100))
{
tmrTemp[4] = TIMER_Update();
AFE_VoltageProcess();
AFE_TemperaProcess();
MCU_TemperaProcess();
AFE_ProtectProcess();
IWDG_Feed(); //程序运行正常,进行喂狗
#if Key_PressLong
POWER_Ctrl();
#endif
#if Key_PressLong
if(OFF_confirm_flg == 1)
{
CTRL_Off(); //关闭充放MOS
delay_ms(2);
CHG_LIMIT_Off(); //关闭限流
curLimitFlag = 0;
delay_ms(2);
PCHG_Off(); //关闭预充
TSC_detectFlag = 0;
PCHG_startFlag = 0;
PCHG_Flag = 0;
delay_ms(2);
// BAL_Off(); //关闭均衡
// balancing = 0;
}
else
#endif
{
// MCU_BalanceProcess();
CHG_LIMIT_Ctrl();
if(TSC_detectFlag == 1)
{
TSC_Detect(); //充接口开路或短路检测,开路检测
}
else if(PCHG_startFlag == 0)
{
PCHG_StartCtrl(); //启动预充(约1s检测开短路)
}
else if(MOS_Close_Flg == 0)
{
AFE_Ctrl(); //正常(开放电MOS前开预充,并检测真短路)
}
}
OCV_CaliSOC();
ParaChange();
GaugeManage();
canMem_refresh();
onlineMem_refresh();
#if Key_PressLong
if(OFF_confirm_flg != 1)
#endif
{
//当屏亮,而上位机在通过主机看从机,屏幕查看地址返回原值
if(ConfigData_Index != 1)
{
scr_RdData_Index = bmsMem.E2_485Addr;
}
//更新屏幕信息(息屏由[陶晶驰]自己做)
if(sleep_flag == 0) Screen_IQ_Transmit(); //每1s更新1次屏幕数据
}
//逆变器协议数据更新
if(bmsMem.E2_485Addr == 1)
{
#if Key_PressLong
if(OFF_confirm_flg != 1)
#endif
{
if(sleep_flag == 0) CAN_UpdateData();
if(sleep_flag == 0) MODBUS1_UpdateData();
}
}
if(LSEErrFlag!=1)
{
uf_RTC_Update(); //写时间或需要等待长时间,可能返回1,所以就不用这里来判断晶振了
RTC_Get(); //时间更新每1s执行1次,若时钟持续10次都不走,可以认为晶振有问题
}
/*三选一模块:4G*/
#if LTE_Conn
Check_eventChange(); //因为要加上时间,所以放在读时间后面
//开机等待or引脚重启等待
if(LTE_WarmDelay > 0)
{
LTE_WarmDelay--;
}
//延迟下次发送等待
else if(LTE_ResendDelay > 0)
{
LTE_ResendDelay--;
}
else if(LTE_WaitRxDelay > 0)
{
LTE_WaitRxDelay--;
}
//引脚重启
else if(LTE_PinRST_Flag != 0)
{
if(LTE_PinRST_Flag == 1)
{
LTE_PinRST_Flag = 2;
LTE_4G_Close();
}
else
{
LTE_PinRST_Flag = 0;
LTE_4G_Init();
LTE_4G_Open();
}
}
//休眠
else if(LTE_sleep_flag != 0)
{
if(LTE_sleep_flag == 1) //1:准备休眠
{
LTE_sleep_flag = 2; //2:正在休眠
LTE_4G_Close(); //关闭4G模块
}
else if(LTE_sleep_flag == 0xAA) //0xAA:退出休眠,执行1次开机4G模块
{
LTE_sleep_flag = 0;
LTE_4G_Init();
LTE_4G_Open(); //启动4G模块
pre_sleep_flag = 0xA0; //上线后,上报退出休眠事件
sleepOff_time=timecount;
}
}
//正常通信or休眠前置步骤
else
{
//休眠前置步骤执行倒计时
if((pre_sleep_flag >=2) && (pre_sleep_flag <= 5))
{
pre_sleep_waitCnt++;
if(pre_sleep_waitCnt > 60)
{
pre_sleep_waitCnt = 0;
pre_sleep_flag = 0;
LTE_sleep_flag = 1; //1min内前置一直卡住,直接执行休眠
}
}
else
{
pre_sleep_waitCnt = 0;
}
if(MQTT_READY_flag == 0) //未通信MQTT
{
if(LTE_LINK_flag == 0)
{
LTE_4G_IQ_Update(); //更新数据
LTE_4G_IQ_Transmit(); //发送数据,每1s执行一次
}
}
else //已通信MQTT
{
if((pre_sleep_flag != 4) && (LTE_OTA_Flag != 1) && (LTE_status != event_pub) && (LTE_status != srvc_pub) && (LTE_status != setPara_pub) && (LTE_status != getPara_pub))
{
LTE_4G_IQ_Update(); //更新数据
LTE_4G_IQ_Transmit(); //发送数据,每1s执行一次
}
}
}
#endif
}
//需要及时响应的动作,直接放入while主循环里
Addr_Set(); //地址写入
RTC_BackUp(); //因各种情况触发的时间备份
//屏幕接收
#if Key_PressLong
if(OFF_confirm_flg != 1)
{
if(Screen_RevHandlerFlg == 1)
{
Screen_RevHandlerFlg = 0;
Screen_IT_Update();
}
}
else
{
SCR_KeepLight0(); //判断关机时收到数据屏幕也不能维持灯0
}
#else
if(Screen_RevHandlerFlg == 1)
{
Screen_RevHandlerFlg = 0;
Screen_IT_Update();
}
#endif
//485发送回复
#if Key_PressLong
if(OFF_confirm_flg != 1) MODBUS_IQ_Transmit();
if(OFF_confirm_flg != 1) MODBUS1_IQ_Transmit();
#else
MODBUS_IQ_Transmit();
MODBUS1_IQ_Transmit();
#endif
}
}