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

243 lines
6.1 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_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<act_num;i++)
{
TemperatureAverage += T[i];
}
TemperatureAverage = TemperatureAverage/act_num;
//最高最低温度
TemperatureMax = T[0];
TemperatureMin = T[0];
TemperatureMaxIndex = 0;
TemperatureMinIndex = 0;
for(i=0;i<act_num;i++)
{
if(TemperatureMax < T[i])
{
TemperatureMax = T[i];
TemperatureMaxIndex = i;
}
if(TemperatureMin > 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();
}