/** ****************************************************************************** * @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线路挂起位 //}