/** ****************************************************************************** * @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_T1 GPIO_Pin_5 #define PIN_T2 GPIO_Pin_4 #define PIN_T3 GPIO_Pin_1 #define PIN_T4 GPIO_Pin_0 //GPIOC #define PIN_LOAD_VOL GPIO_Pin_4 //【ADC通道】 #define CH_T1 ADC_Channel_5 #define CH_T2 ADC_Channel_4 #define CH_T3 ADC_Channel_1 #define CH_T4 ADC_Channel_0 #define CH_LOAD ADC_Channel_14 int16_t TemperatureAverage; // 平均温度 int16_t TemperatureMax; // 最高温度 int16_t TemperatureMin; // 最低温度 uint16_t TemperatureMaxIndex; // 最高温度序号 uint16_t TemperatureMinIndex; // 最低温度序号 uint32_t loadvol; //负载检测的电压 //ADC单通道单次转换 void uf_ADC_Init(void) { ADC_InitTypeDef ADC_InitStructure; GPIO_InitTypeDef GPIO_InitStructure; //PC4 负载电压检测脚 RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC, ENABLE); GPIO_InitStructure.GPIO_Pin = PIN_LOAD_VOL; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN; GPIO_Init(GPIOC, &GPIO_InitStructure); //PA0.1.4.5 T1~T4输入引脚 RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE); GPIO_InitStructure.GPIO_Pin = PIN_T1 | PIN_T2 | PIN_T3 | PIN_T4; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN; GPIO_Init(GPIOA, &GPIO_InitStructure); RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1, ENABLE ); //使能ADC1通道时钟 RCC_ADCCLKConfig(RCC_PCLK2_Div6); //设置ADC分频因子6,ADC最大时间不能超过14M ADC_DeInit(ADC1); ADC_InitStructure.ADC_Mode = ADC_Mode_Independent; ADC_InitStructure.ADC_ScanConvMode = DISABLE; ADC_InitStructure.ADC_ContinuousConvMode = DISABLE; ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None; //转换由软件而不是外部触发启动 ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right; //ADC数据右对齐 ADC_InitStructure.ADC_NbrOfChannel = 1; //顺序进行规则转换的ADC通道的数目 ADC_Init(ADC1, &ADC_InitStructure); ADC_Cmd(ADC1, ENABLE); //使能指定的ADC1 ADC_ResetCalibration(ADC1); //使能复位校准 while(ADC_GetResetCalibrationStatus(ADC1)); //等待复位校准结束 ADC_StartCalibration(ADC1); //开启AD校准 while(ADC_GetCalibrationStatus(ADC1)); //等待校准结束 } //指定通道ADC值 uint16_t ADC_GetVal(uint8_t ch) { //设置指定ADC的规则组通道,一个序列,采样时间 ADC_RegularChannelConfig(ADC1, ch, 1, ADC_SampleTime_239Cycles5 ); //ADC1,ADC通道,采样时间为239.5周期 ADC_SoftwareStartConvCmd(ADC1, ENABLE); //使能指定的ADC1的软件转换启动功能 while(!ADC_GetFlagStatus(ADC1, ADC_FLAG_EOC ));//等待转换结束 return ADC_GetConversionValue(ADC1); //返回最近一次ADC1规则组的转换结果 } //负载电压检测 void LOAD_VOL(void) { uint16_t adcvol; adcvol = ADC_GetVal(CH_LOAD); loadvol = adcvol * 40 * 3300 / 4095; //将AD值线性变换到0~3.3V的范围,表示电压 } //温度处理 void MCU_TemperaProcess(void) { uint16_t adctmp[4]; //adc read value uint16_t resntc[4]; //res calc value uint16_t mcutmp[4]; uint16_t T[4]; //4路MCU uint8_t i; //获取ADC值 adctmp[0] = ADC_GetVal(CH_T1); adctmp[1] = ADC_GetVal(CH_T2); adctmp[2] = ADC_GetVal(CH_T3); adctmp[3] = ADC_GetVal(CH_T4); resntc[0] = (1000 * adctmp[0]) / (4096-adctmp[0]); resntc[1] = (1000 * adctmp[1]) / (4096-adctmp[1]); resntc[2] = (1000 * adctmp[2]) / (4096-adctmp[2]); resntc[3] = (1000 * adctmp[3]) / (4096-adctmp[3]); mcutmp[0] = TEMP_Cal(resntc[0]); mcutmp[1] = TEMP_Cal(resntc[1]); mcutmp[2] = TEMP_Cal(resntc[2]); mcutmp[3] = TEMP_Cal(resntc[3]); bmsMem.mcu_T1 = mcutmp[0]; bmsMem.mcu_T2 = mcutmp[1]; bmsMem.mcu_T3 = mcutmp[2]; bmsMem.mcu_T4 = mcutmp[3]; //当至少有1个温度可用时 if((paraMem.temp_disable & 0x0F) != 0x0F) { uint8_t act_num = 0; //有效个数 if((paraMem.temp_disable & BIT0) == 0) { T[act_num] = bmsMem.mcu_T1; act_num++; } if((paraMem.temp_disable & BIT1) == 0) { T[act_num] = bmsMem.mcu_T2; act_num++; } if((paraMem.temp_disable & BIT2) == 0) { T[act_num] = bmsMem.mcu_T3; act_num++; } if((paraMem.temp_disable & BIT3) == 0) { T[act_num] = bmsMem.mcu_T4; act_num++; } //平均温度 TemperatureAverage = 0; for(i=0;i T[i]) { TemperatureMin = T[i]; TemperatureMinIndex = i; } } } //当4路温度都不可用时 else { TemperatureAverage = 0; TemperatureMin = 0; TemperatureMax = 0; TemperatureMinIndex = 0; TemperatureMaxIndex = 0; } //sum of all packs bmsMem.can_temp = TemperatureAverage; bmsMem.can_TempMax = TemperatureMax; bmsMem.can_TempMaxIndex = TemperatureMaxIndex; bmsMem.can_TempMin = TemperatureMin; bmsMem.can_TempMinIndex = TemperatureMinIndex; //当至少有1个温度可用时 if((paraMem.temp_disable & 0x0F) != 0x0F) { //电芯温度告警和告警释放 Trigger_mcuTAlarm(); //电芯温度告警 Release_mcuTAlarm(); //电芯温度告警恢复 //电芯温度保护和保护释放 Trigger_mcuTProtect(); //电芯温度保护相关 Release_mcuTProtect(); //电芯温度保护释放 #if DO2_Warm //加热 WARM_Ctrl(); //电芯低温启动加热,温度升高释放 #endif } //当4路温度都不可用时 else { bmsMem.bStatus2 &= ~0xF000; bmsMem.temperaStatus &= ~0x000F; } //电流告警和告警释放 Trigger_CurAlarm(); //电流告警 Release_CurAlarm(); //电流告警恢复 //电流保护和保护释放 Trigger_CurProtect(); //电流保护 Release_CurProtect(); //电流保护释放 /*电流保护连续出现的计算*/ Trigger_CurProtectLock(); }