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

1054 lines
22 KiB
C

/**
******************************************************************************
* @file gpio.c
* @author Jerry Cai
* @version V2.1
* @date 19-April-2022
* @brief gpio program body.
******************************************************************************
* @attention
*
*
******************************************************************************
*/
/* Includes ------------------------------------------------------------------*/
#include "stm32f10x.h"
#include "global.h"
//GPIOA
//#define PIN_VPRO GPIO_Pin_6 //AFE -EEPROM烧写电源控制
#define PIN_DO GPIO_Pin_6 //DO:输出继电器启动信号,高电平启动
#define PIN_SHIP GPIO_Pin_7 //AFE -仓运模式控制
#define PIN_LED_RUN GPIO_Pin_15 //LED -运行状态指示灯
//GPIOB
#define PIN_LED2 GPIO_Pin_8 //LED2-电量指示
#define PIN_LED3 GPIO_Pin_5 //LED3-电量指示
#define PIN_LED4 GPIO_Pin_4 //LED4-电量指示
#define PIN_LED_ALARM GPIO_Pin_3 //LED -报警和保护指示
#define PIN_CTLC GPIO_Pin_0 //DI/急停
#define PIN_AFE_ALARM GPIO_Pin_1 //AFE -采集模式下,正常输出高电平,在ALARM事件发生时,输出1ms低电平脉冲, 软件这里暂时还没有处理
//GPIOC
#define PIN_LED1 GPIO_Pin_6 //LED1-电量指示
#define PIN_KEY GPIO_Pin_0 //按键 电平检测管脚
//#define PIN_BAL_OUT GPIO_Pin_1 //主动均衡板启动信号,高电平启动
#define PIN_LED_POWER GPIO_Pin_3 //LED电源指示灯
#define PIN_PCHG_CTRL GPIO_Pin_5 //预充控制脚
#define PIN_ADDR_RANK GPIO_Pin_7 //自动分配地址输入脚IO3,当输入低电平时,说明自身是从机
#define PIN_ADDR_IN GPIO_Pin_8 //自动分配地址输入脚IO1
#define PIN_ADDR_OUT GPIO_Pin_9 //自动分配地址输出脚IO2
#define PIN_POWER GPIO_Pin_13 //电源维持控制管脚
uint8_t balancing;
uint16_t balCount;
uint8_t DIMoniCount;
uint8_t DIFlag;
uint8_t PCHG_startFlag; //开机预充标志 0:没执行 1:已完成
uint8_t PCHG_startCnt; //延时计数
uint8_t PCHG_Flag; //放电MOS开启前开启预充的标志 1:执行 2:完成可以打开放电MOS 0:不用预充
uint8_t PCHG_Cnt; //延时计数
uint8_t TSC_Flag; //AFE短路发生后,判断是否是真短路的标志 [=>关闭充放MOS、预充]
uint8_t tscTimeCount; //AFE短路发生后,若第一时间检测的负载电压值<4V,显示“真短路”
uint8_t pchgTimeCount; //AFE短路结束后,单次预充时间,到点后会关闭预充检测负载电压
uint8_t TSC_detectFlag; //不开启预充时,AFE短路发生后,判断是否是真短路的标志 0;不执行 1:要执行 2:执行完成,回到正常 0xAA:检测到真短路
uint16_t ADDR_Moni_Count; //自动分配地址前,因为短接脚而该改变自身的地址 每次10ms
uint8_t ClearArray_Flag; //在定时器函数中,执行清空队列标志的标志
/*6.3.L非自锁按键-长按*/
#define ON_WAIT 100 //100*10ms=1s
#define RST_WAIT 100 //100*10ms=1s
#define OFF_WAIT 300 //300*10ms=3s
uint8_t ON_confirm_flg; //程序运行后,先确认开机 1:按键按下2s确认开机 2:确认开机后按键松开,可以监测下一次按键按下以判断复位和重启
uint8_t RST_confirm_flg; //按钮按下后,通过时长判断执行复位
uint8_t OFF_confirm_flg; //按钮按下后,通过时长判断确认断开电源维持,等按钮松开就关机
uint8_t key_state; //按键状态 0:未按下, 1:按下
uint8_t power_state; //电源脚输出 0:应输出低,1:应输出高
uint8_t led_toggle_step; //执行复位时,LED灯同步闪烁
/*6.3.L非自锁按键*/
void HAL_GPIO_TogglePin(GPIO_TypeDef *GPIOx, uint16_t GPIO_Pin)
{
uint32_t odr;
/* Check the parameters */
assert_param(IS_GPIO_PIN(GPIO_Pin));
/* get current Ouput Data Register value */
odr = GPIOx->ODR;
/* Set selected pins that were at low level, and reset ones that were high */
GPIOx->BSRR = ((odr & GPIO_Pin) << 16u) | (~odr & GPIO_Pin);
}
//LED
//---------------------------------------------
void LED_RUN_On(void)
{
GPIO_SetBits(GPIOA, PIN_LED_RUN);
}
void LED_RUN_Off(void)
{
GPIO_ResetBits(GPIOA, PIN_LED_RUN);
}
void LED_ALARM_On(void)
{
GPIO_SetBits(GPIOB, PIN_LED_ALARM);
}
void LED_ALARM_Off(void)
{
GPIO_ResetBits(GPIOB, PIN_LED_ALARM);
}
void LED1_On(void)
{
GPIO_SetBits(GPIOC, PIN_LED1);
}
void LED1_Off(void)
{
GPIO_ResetBits(GPIOC, PIN_LED1);
}
void LED2_On(void)
{
GPIO_SetBits(GPIOB, PIN_LED2);
}
void LED2_Off(void)
{
GPIO_ResetBits(GPIOB, PIN_LED2);
}
void LED3_On(void)
{
GPIO_SetBits(GPIOB, PIN_LED3);
}
void LED3_Off(void)
{
GPIO_ResetBits(GPIOB, PIN_LED3);
}
void LED4_On(void)
{
GPIO_SetBits(GPIOB, PIN_LED4);
}
void LED4_Off(void)
{
GPIO_ResetBits(GPIOB, PIN_LED4);
}
void LED_RUN_Toggle(void)
{
HAL_GPIO_TogglePin(GPIOA, PIN_LED_RUN);
}
void LED_ALARM_Toggle(void)
{
HAL_GPIO_TogglePin(GPIOB, PIN_LED_ALARM);
}
void LED_ALL_ON(void)
{
LED_RUN_On();
LED_ALARM_On();
LED1_On();
LED2_On();
LED3_On();
LED4_On();
}
void LED_ALL_OFF(void)
{
LED_RUN_Off();
LED_ALARM_Off();
LED1_Off();
LED2_Off();
LED3_Off();
LED4_Off();
}
void LED_ALL_Toggle(void)
{
HAL_GPIO_TogglePin(GPIOA, PIN_LED_RUN);
HAL_GPIO_TogglePin(GPIOB, PIN_LED_ALARM);
HAL_GPIO_TogglePin(GPIOC, PIN_LED1);
HAL_GPIO_TogglePin(GPIOB, PIN_LED2);
HAL_GPIO_TogglePin(GPIOB, PIN_LED3);
HAL_GPIO_TogglePin(GPIOB, PIN_LED4);
}
void LED_RST_Toggle(void)
{
led_toggle_step++;
if(led_toggle_step == 1) //全亮
{
LED_ALL_ON();
}
else if(led_toggle_step <= 9) //闪烁:1亮-2灭-3亮-4灭-5亮-6灭-7亮-8灭-9亮
{
LED_ALL_Toggle();
}
#if Key_PressRST
else if(led_toggle_step == 6) //执行复位,保持常亮
{
uf_I2C1_Init(); //IIC复位
uf_SPI2_Init(); //SPI复位
uf_CAN1_Init(); //CAN复位
MODBUS_Init(); //485通信复位
MODBUS1_Init();
/*三选一模块*/
#if BLE_Conn
BLE_Init(); //蓝牙通信复位
BLE_Reset(); //蓝牙模块复位
#endif
#if WIFI_Conn
WIFI_Init(); //WIFI通信复位
WIFI_Reset(); //WIFI模块复位
#endif
#if LTE_Conn
LTE_4G_Init(); //4G通信复位
LTE_4G_Reset(); //4G模块复位
#endif
bmsMem.bStatus1 = 0; //保护/报警/故障标志复位
bmsMem.bStatus2 = 0;
bmsMem.bStatus3 = 0;
bmsMem.temperaStatus = 0;
bmsMem.balanceStatus = 0;
bmsMem.packStatus = 0;
uf_IWDG_Init(6,1250); //看门狗复位
}
#endif
else if(led_toggle_step >= 13) //结束
{
led_toggle_step = 0;
RST_confirm_flg = 2;
}
}
//--------------------------------------------
//模块已开机,存于Flash
#define POWER_FLAG 0x08020800
uint8_t power_old; //如果是正常工作时重启,保持开机
void POWER_Check(void)
{
uint32_t tmpRd;
//读取标志位
FLASH_RdWord(POWER_FLAG, &tmpRd, 1); //4/4=1
if(tmpRd == 0x20260325)
{
power_old = 1;
}
}
void POWER_On(void)
{
GPIO_SetBits(GPIOC, PIN_POWER);
GPIO_SetBits(GPIOC, PIN_LED_POWER); //电源指示灯亮
}
void POWER_Off(void)
{
GPIO_ResetBits(GPIOC, PIN_POWER);
GPIO_ResetBits(GPIOC, PIN_LED_POWER); //电源指示灯灭
}
void POWER_Ctrl(void)
{
if(power_old == 1) //重启,所以直接维持输出高
{
power_state = 1;
}
else if(power_old == 2) //检测到开机,记录到Flash
{
uint32_t tmpRd = 0x20260325;
//写入标志位
FLASH_WrData(POWER_FLAG, (uint16_t *)&tmpRd, 2); //4/2=2
delay_ms(2);
power_old = 3;
}
else if(power_old == 4) //检测到关机,记录到Flash
{
uint32_t tmpRd = 0xFFFFFFFF;
//写入标志位
FLASH_WrData(POWER_FLAG, (uint16_t *)&tmpRd, 2); //4/2=2
delay_ms(2);
power_old = 5;
}
if(power_state == 1) //正常维持输出高
{
POWER_On();
}
else //判定按钮长按后,输出置低,等按钮松开就断电
{
POWER_Off();
}
}
//输入电平检测
uint8_t KEY_IN(void)
{
uint8_t status;
status = GPIO_ReadInputDataBit(GPIOC,PIN_KEY);
return status;
}
//按键状态监测函数
uint16_t KEY_INH_Count;
uint16_t KEY_INL_Count;
void KEY_TIM_Moni(void)
{
key_state = KEY_IN();
if(power_old == 1)
{
ON_confirm_flg = 2;
}
//开机后,延时2s确认保持开机
if(ON_confirm_flg == 0)
{
if(key_state == 1) //输入高电平
{
KEY_INH_Count++;
if(KEY_INH_Count > ON_WAIT)
{
KEY_INH_Count = 0;
ON_confirm_flg = 1;
power_old = 2; //写入开机
power_state = 1;
}
}
else
{
KEY_INH_Count = 0;
}
}
//确认开机后,要监测到按键松开才能进行对下一次按键摁下监测
else if(ON_confirm_flg == 1)
{
if(key_state == 0) //输入低电平
{
KEY_INL_Count++;
if(KEY_INL_Count > 3) //防抖动
{
KEY_INL_Count = 0;
ON_confirm_flg = 2;
RST_confirm_flg = 0;
OFF_confirm_flg = 0;
}
}
else
{
KEY_INL_Count = 0;
}
}
//确认保持开机后,监测按键下一次按下的时长
else
{
if(OFF_confirm_flg == 0)
{
if(key_state == 1) //输入高电平
{
KEY_INL_Count = 0;
KEY_INH_Count++;
if((KEY_INH_Count > OFF_WAIT) && (OFF_confirm_flg == 0)) //按下3s,执行关机操作
{
KEY_INH_Count = 0;
RST_confirm_flg = 0;
OFF_confirm_flg = 1;
power_old = 4; //写入关机
power_state = 0;
}
else if((KEY_INH_Count > RST_WAIT) && (RST_confirm_flg == 0)) //按下1s,执行复位操作
{
RST_confirm_flg = 1;
led_toggle_step = 0;
}
}
else
{
KEY_INH_Count = 0;
if(RST_confirm_flg == 2) //复位完成后,在按键松开后清零标志
{
KEY_INL_Count++;
if(KEY_INL_Count > 3) //防抖动
{
KEY_INL_Count = 0;
RST_confirm_flg = 0;
}
}
}
}
}
}
////ON: ≥100uS
//void BAL_On(void)
//{
// GPIO_ResetBits(GPIOC, PIN_BAL_OUT);
// delay_us(200);
// GPIO_SetBits(GPIOC, PIN_BAL_OUT);
// delay_us(200);
// GPIO_ResetBits(GPIOC, PIN_BAL_OUT);
// delay_us(200);
//}
////OFF: 20-50uS
//void BAL_Off(void)
//{
// GPIO_ResetBits(GPIOC, PIN_BAL_OUT);
// delay_us(20);
// GPIO_SetBits(GPIOC, PIN_BAL_OUT);
// delay_us(20);
// GPIO_ResetBits(GPIOC, PIN_BAL_OUT);
// delay_us(20);
//}
//1S
void MCU_BalanceProcess(void)
{
//高温关闭均衡
if( ((bmsMem.bStatus2 & 0x0A) !=0) || ((bmsMem.temperaStatus & 0x03) !=0) )
{
if((bmsMem.balanceStatus & 0x01) != 0)
{
// BAL_Off();
bmsMem.balanceStatus &= 0xfffe;
}
balancing = 0;
}
else
{
if( (cellVoltageMax - cellVoltageMin) > paraMem.act_bal_startV)
{
if((bmsMem.balanceStatus & 0x01) == 0)
{
// BAL_On();
// bmsMem.balanceStatus |= 0x01; //BAL status set to 1
}
balancing = 1;
balCount = 0;
}
else if( (cellVoltageMax - cellVoltageMin) < paraMem.act_bal_stopV)
{
balCount++;
if(balCount >= paraMem.act_bal_stopT)
{
if((bmsMem.balanceStatus & 0x01) != 0)
{
// BAL_Off();
bmsMem.balanceStatus &= 0xfffe;
}
balancing = 0;
}
}
}
}
void DO_On(void) //DO控制继电器开启
{
GPIO_SetBits(GPIOA, PIN_DO);
}
void DO_Off(void) //DO控制继电器关闭
{
GPIO_ResetBits(GPIOA, PIN_DO);
}
//void WARM_On(void) //加热开启
//{
// GPIO_SetBits(GPIOC, PIN_WARM);
//}
//void WARM_Off(void) //加热关闭
//{
// GPIO_ResetBits(GPIOC, PIN_WARM);
//}
////加热触发与控制
//uint8_t warm_flag; //加热启动标志
//uint8_t warm_count;
//uint8_t warmr_count;
//void WARM_Ctrl(void)
//{
// uint16_t utc = bmsMem.mcu_utc * 10 + 2731;
// uint16_t utcr = bmsMem.mcu_utcr * 10 + 2731;
//
// //加热触发
// if((bmsMem.bStatus1 & 0x0202) == 0) //触发总体/单体欠压,禁止加热
// {
// if((warm_flag == 0) && (bCHGING == 1))
// {
// if(TemperatureMin < utc)
// {
// warm_count++;
// if(warm_count > 3)
// {
// warm_flag = 1;
// warm_count = 0;
// }
// }
// else
// {
// warm_count = 0;
// }
// }
// }
// else
// {
// warm_flag = 0;
// warm_count = 0;
// warmr_count = 0;
// }
//
// //加热释放
// if(warm_flag == 1)
// {
// if(TemperatureMin > utcr+20) //比释放值高2度
// {
// warmr_count++;
// if(warmr_count > 3)
// {
// warm_flag = 0;
// warmr_count = 0;
// }
// }
// else
// {
// warmr_count = 0;
// }
// }
//
// //加热控制
// if(warm_flag == 1)
// {
// WARM_On();
// }
// else
// {
// WARM_Off();
// }
//}
void PCHG_On(void) //预充开启
{
GPIO_SetBits(GPIOC, PIN_PCHG_CTRL);
}
void PCHG_Off(void) //预充关闭
{
GPIO_ResetBits(GPIOC, PIN_PCHG_CTRL);
}
void PCHG_StartCtrl(void) //开机开启预充
{
//开始节点是1,结束是paraMem.pchg_startTime+1
PCHG_startCnt++;
//通过负载电压判断是否是真短路
if(PCHG_startCnt == 2) //此时已充了1s
{
PCHG_Off();
bmsMem.bStatus3 &= ~0x0004; //预充MOS关闭
delay_ms(2);
LOAD_VOL();
if(loadvol < paraMem.pchg_scVol*1000) //负载电压小于10V说明短路;如果是空载则≈电池电压
{
bmsMem.bStatus2 |= 0x0010; //显示“真短路保护”,不能继续预充
return;
}
}
//预充开启定时
if(PCHG_startCnt <= paraMem.pchg_startTime)
{
PCHG_On();
bmsMem.bStatus3 |= 0x0004; //预充MOS打开
bmsMem.bStatus3 |= 0x0020; //预充状态开启
}
else
{
PCHG_startFlag = 1;
PCHG_startCnt = 0;
PCHG_Off();
bmsMem.bStatus3 &= ~0x0004; //预充MOS关闭
bmsMem.bStatus3 &= ~0x0020; //预充状态关闭
delay_ms(2);
CTRL_On();
}
}
void PCHG_Ctrl(void) //开放电MOS前开启预充
{
//开始节点是1,结束是paraMem.pchg_startTime+1
PCHG_Cnt++;
//通过负载电压判断是否是真短路
if(PCHG_Cnt == 2) //此时已充了1s
{
PCHG_Off();
bmsMem.bStatus3 &= ~0x0004; //预充MOS关闭
delay_ms(2);
LOAD_VOL();
if(loadvol < paraMem.pchg_scVol*1000) //负载电压小于10V说明短路;如果是空载则≈电池电压
{
CTRL_Off();
bmsMem.bStatus2 |= 0x0010; //显示“真短路保护”,不能继续预充
return;
}
}
//预充开启定时
if(PCHG_Cnt <= paraMem.pchg_Time)
{
PCHG_On();
bmsMem.bStatus3 |= 0x0004; //预充MOS打开
bmsMem.bStatus3 |= 0x0020; //预充状态开启
}
else
{
PCHG_Flag = 2;
PCHG_Cnt = 0;
PCHG_Off();
bmsMem.bStatus3 &= ~0x0004; //预充MOS关闭
bmsMem.bStatus3 &= ~0x0020; //预充状态关闭
delay_ms(2);
CTRL_On();
}
}
//在触发浪涌短路时,执行真短路判定
void TSC_Detect(void)
{
/**正常情况下**/
if(TSC_detectFlag == 1)
{
CTRL_Off();
delay_ms(2);
LOAD_VOL();
if(loadvol < paraMem.sp_scVol*1000) //认为是短路情况,显示“真短路保护”
{
TSC_detectFlag = 0xAA;
}
else //检测正常后,回到正常控制
{
CTRL_On();
TSC_detectFlag = 2;
}
}
/**遇到[真短路]的情况,控制充放MOS关闭不变**/
else if(TSC_detectFlag == 0xAA)
{
CTRL_Off();
bmsMem.bStatus2 |= 0x0010; //显示“真短路保护”
}
}
#if Addr_SetAuto
//输入电平检测
uint8_t IO3_IN(void)
{
uint8_t status;
status = GPIO_ReadInputDataBit(GPIOC,PIN_ADDR_RANK);
return status;
}
//输出置高,让下一个从机进入待分配状态
void IO2_OUTSet(void)
{
GPIO_SetBits(GPIOC, PIN_ADDR_OUT);
}
//输出置低,转回正常状态
void IO2_OUTReset(void)
{
GPIO_ResetBits(GPIOC, PIN_ADDR_OUT);
}
//输入电平检测
uint8_t IO1_IN(void)
{
uint8_t status;
status = GPIO_ReadInputDataBit(GPIOC,PIN_ADDR_IN);
return status;
}
//根据IO1的不同电平,进行地址修改操作
uint8_t IO1_INH_Count;
uint8_t IO1_INL_Count;
void ADDR_Assign_Moni(void)
{
if(((bmsMem.E2_485Addr >=2) && (bmsMem.E2_485Addr <= AddrMax+1))) //地址为实地址的从机 and 特定虚地址的从机(避免分配时出现意外)
{
if( IO1_IN() == 1 ) //输入高电平
{
if(IO1_INH_Count < 10)
{
IO1_INH_Count++; //等待100ms
}
else
{
bmsMem.E2_485Addr = 99; //修改为虚地址
}
}
else
{
IO1_INH_Count = 0;
}
}
else if(bmsMem.E2_485Addr > AddrMax+1)//地址本身就为虚地址的从机
{
if( IO1_IN() == 0 ) //输入低电平
{
if(IO1_INL_Count < 10)
{
IO1_INL_Count++; //等待100ms
}
else
{
bmsMem.E2_485Addr = AddrMax+1; //修改为特定的虚地址
}
}
else
{
IO1_INL_Count = 0;
}
}
}
//根据IO3的不同电平,确定自身是主机/从机
void ADDR_Rank_Moni(void)
{
//地址原来是1,过1s后设2
if(bmsMem.E2_485Addr == 1)
{
if(assignAddr_State != 1) //进行分配时不动作
{
if( IO3_IN() == 0 ) //短接
{
ADDR_Moni_Count++;
if(ADDR_Moni_Count > 100)
{
bmsMem.E2_485Addr = 2;
bmsMem.write_Addr = bmsMem.E2_485Addr; //用于之后写入EEPROM
scr_RdData_Index = bmsMem.E2_485Addr;
ADDR_Moni_Count = 0;
MODBUS_Init();
bmsMem.can_ArrayIndex = 0;
ClearArray_Flag = 1; //用于之后写入EEPROM
}
}
else
{
ADDR_Moni_Count = 0;
}
}
}
//地址原不是1,过5s后设1(可能只是调线子要有容错)
else
{
if( IO3_IN() != 0 ) //没有短接
{
ADDR_Moni_Count++;
if(ADDR_Moni_Count > 500)
{
assignAddr_State = 0;
assignAddr_relay = 2;//变1后也有可能变回去
bmsMem.E2_485Addr = 1;
bmsMem.write_Addr = bmsMem.E2_485Addr; //用于之后写入EEPROM
scr_RdData_Index = bmsMem.E2_485Addr;
ADDR_Moni_Count = 0;
MODBUS_Init();
bmsMem.can_ArrayIndex = 0;
ClearArray_Flag = 1; //用于之后写入EEPROM
}
}
else
{
ADDR_Moni_Count = 0;
}
}
}
#endif
//IO初始化
void uf_GPIO_Init(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA , ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB , ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC , ENABLE);
//PB3,PB4,PA15用作普通IO时需要禁用JTAG保留SWD, 并REMAP
RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO , ENABLE);
GPIO_PinRemapConfig(GPIO_Remap_SWJ_JTAGDisable, ENABLE);
//LED
GPIO_InitStructure.GPIO_Pin = PIN_LED2 | PIN_LED3 | PIN_LED4 | PIN_LED_ALARM;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOB, &GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = PIN_LED1;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOC, &GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = PIN_LED_RUN;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure);
#if Key_PressLong
//上电后灯全灭,之后全亮
GPIO_ResetBits(GPIOA, PIN_LED_RUN);
GPIO_ResetBits(GPIOC, PIN_LED1);
GPIO_ResetBits(GPIOB, PIN_LED2);
GPIO_ResetBits(GPIOB, PIN_LED3);
GPIO_ResetBits(GPIOB, PIN_LED4);
GPIO_ResetBits(GPIOB, PIN_LED_ALARM);
#else
//上电后灯全亮
GPIO_SetBits(GPIOA, PIN_LED_RUN);
GPIO_SetBits(GPIOC, PIN_LED1);
GPIO_SetBits(GPIOB, PIN_LED2);
GPIO_SetBits(GPIOB, PIN_LED3);
GPIO_SetBits(GPIOB, PIN_LED4);
GPIO_SetBits(GPIOB, PIN_LED_ALARM);
#endif
//PCHG预充控制
GPIO_InitStructure.GPIO_Pin = PIN_PCHG_CTRL;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOC, &GPIO_InitStructure);
//DO继电器控制
GPIO_InitStructure.GPIO_Pin = PIN_DO;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure);
// //BAL主动均衡器控制
// GPIO_InitStructure.GPIO_Pin = PIN_BAL_OUT;
// GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
// GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
// GPIO_Init(GPIOC, &GPIO_InitStructure);
//控制引脚初始电平
GPIO_ResetBits(GPIOC, PIN_PCHG_CTRL); //预充控制脚,默认关闭状态
GPIO_ResetBits(GPIOA, PIN_DO); //DO继电器控制脚,默认关闭状态
// GPIO_ResetBits(GPIOC, PIN_BAL_OUT); //主动均衡控制脚,默认关闭状态
#if DO2_Warm
//加热控制
GPIO_InitStructure.GPIO_Pin = PIN_WARM;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOC, &GPIO_InitStructure);
GPIO_ResetBits(GPIOC, PIN_WARM); //加热控制脚,默认关闭状态
#endif
#if Key_PressLong
//按键电平检测
GPIO_InitStructure.GPIO_Pin = PIN_KEY;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOC, &GPIO_InitStructure);
//电源维持控制
GPIO_InitStructure.GPIO_Pin = PIN_POWER;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOC, &GPIO_InitStructure);
//电源指示灯
GPIO_InitStructure.GPIO_Pin = PIN_LED_POWER;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOC, &GPIO_InitStructure);
if(power_old == 1)
{
GPIO_SetBits(GPIOC, PIN_POWER); //电源维持控制脚,置高
GPIO_SetBits(GPIOC, PIN_LED_POWER); //电源指示灯亮
}
else
{
GPIO_ResetBits(GPIOC, PIN_POWER); //电源维持控制脚,开机后默认置低
GPIO_ResetBits(GPIOC, PIN_LED_POWER); //电源指示灯先不亮
}
#else
//电源指示灯
GPIO_InitStructure.GPIO_Pin = PIN_LED_POWER;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOC, &GPIO_InitStructure);
GPIO_SetBits(GPIOC, PIN_LED_POWER); //电源指示灯直接亮
#endif
#if Addr_SetAuto
//ADDR_IN IO1
GPIO_InitStructure.GPIO_Pin = PIN_ADDR_IN;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOC, &GPIO_InitStructure);
//ADDR_OUT IO2
GPIO_InitStructure.GPIO_Pin = PIN_ADDR_OUT;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOC, &GPIO_InitStructure);
//ADDR_RANK IO3
GPIO_InitStructure.GPIO_Pin = PIN_ADDR_RANK;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOC, &GPIO_InitStructure);
//地址分配引脚初始电平
GPIO_ResetBits(GPIOC, PIN_ADDR_OUT); //初始化时所有OUT引脚置低
#endif
//AFE-ALARM
GPIO_InitStructure.GPIO_Pin = PIN_AFE_ALARM;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOB, &GPIO_InitStructure);
//AFE- VPRO/SHIP
GPIO_InitStructure.GPIO_Pin = PIN_SHIP;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure);
//AFE-CTL(急停控制)
GPIO_InitStructure.GPIO_Pin = PIN_CTLC;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOB, &GPIO_InitStructure);
//AFE引脚初始电平
GPIO_SetBits(GPIOA, PIN_SHIP); //初始置高,表示退出仓运模式
#if Key_PressLong
if(power_old == 1)
{
GPIO_SetBits(GPIOB, PIN_CTLC);//因为是重启,初始置高,不控制MOS
PCHG_startFlag = 1; //也不执行开机预充
}
else
{
GPIO_ResetBits(GPIOB, PIN_CTLC);//初始置低,控制MOS全关
}
#else
GPIO_ResetBits(GPIOB, PIN_CTLC);//初始置低,控制MOS全关
#endif
CHG_LIMIT_Init();
}
//AFE_ALARM 外部EXTI中断配置
void uf_EXTI_Init(void)
{
// EXTI_InitTypeDef EXTI_InitStructure;
// NVIC_InitTypeDef NVIC_InitStructure;
// //BKP_TamperPinCmd(DISABLE);
// RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE); //外部中断,需要使能AFIO时钟
// GPIO_EXTILineConfig(GPIO_PortSourceGPIOB,GPIO_PinSource9);
// EXTI_InitStructure.EXTI_Line=EXTI_Line9;
// EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;
// EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling; // 下降沿 触发
// EXTI_InitStructure.EXTI_LineCmd = ENABLE;
// EXTI_Init(&EXTI_InitStructure);
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
// NVIC_InitStructure.NVIC_IRQChannel = EXTI9_5_IRQn;
// NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
// NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
// NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
// NVIC_Init(&NVIC_InitStructure);
}
////用定时器还是用外部中断去读数据,纠结中...
////用外部中断考虑外部硬件连接有问题会导致读取不到数据
//void EXTI9_5_IRQHandler(void)
//{
// bAlarmFlag = 1;
// EXTI_ClearITPendingBit(EXTI_Line9); //清除EXTI0线路挂起位
//}