mtk 电池驱动的电压,电流,温度等数据通过adc通道获取
pmic BATSNS 引脚电压 bat_vol = battery_meter_get_battery_voltage(KAL_TRUE);
// 获得 PMIC 的 BATSNS 引脚电压 通过读adc某个通道可获取
kal_int32 battery_meter_get_battery_voltage(void)
{
int ret=0;
int val=5;
val = 5; //set avg times
// 获得 PMIC 的 BATSNS 引脚电压
ret = battery_meter_ctrl(BATTERY_METER_CMD_GET_ADC_V_BAT_SENSE, &val);
static kal_int32 read_adc_v_bat_sense(void *data)
{
#if defined(CONFIG_POWER_EXT)
*(kal_int32*)(data) = 4201;
#else
*(kal_int32*)(data) = PMIC_IMM_GetOneChannelValue(VBAT_CHANNEL_NUMBER,*(kal_int32*)(data),1);
#endif
return STATUS_OK;
}
g_sw_vbat_temp = val;
return val;
}
PMIC 的 ISENSE 引脚电压 Vsense = battery_meter_get_VSense();
// 获得 PMIC 的 ISENSE 引脚电压 通过读adc某个通道可获取
kal_int32 battery_meter_get_VSense(void)
{
#if defined(CONFIG_POWER_EXT)
return 0;
#else
int ret=0;
int val=0;
val = 1; //set avg times
/* 获得 PMIC 的 ISENSE 引脚电压*/
ret = battery_meter_ctrl(BATTERY_METER_CMD_GET_ADC_V_I_SENSE, &val);
read_adc_v_i_sense(void *data)
*(kal_int32*)(data) = PMIC_IMM_GetOneChannelValue(ISENSE_CHANNEL_NUMBER,*(kal_int32*)(data),1);
return val;
#endif
}
/* 获得充电电流 */
充电电流 //如果isense电压比batsense电压大,计算电流公式,否则电流取0
ICharging = battery_meter_get_charging_current();
kal_int32 battery_meter_get_charging_current(void)
{
kal_int32 ADC_BAT_SENSE_tmp[20]={0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
kal_int32 ADC_BAT_SENSE_sum=0;
kal_int32 ADC_BAT_SENSE=0;
kal_int32 ADC_I_SENSE_tmp[20]={0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
kal_int32 ADC_I_SENSE_sum=0;
kal_int32 ADC_I_SENSE=0;
int repeat=20;
int i=0;
int j=0;
kal_int32 temp=0;
int ICharging=0;
int ret=0;
int val=1;
for(i=0 ; i<repeat ; i++)
{
val = 1; //set avg times
/* 获得 PMIC 的 BATSNS 引脚电压 */
ret = battery_meter_ctrl(BATTERY_METER_CMD_GET_ADC_V_BAT_SENSE, &val);
read_adc_v_bat_sense(void *data)
*(kal_int32*)(data) = PMIC_IMM_GetOneChannelValue(VBAT_CHANNEL_NUMBER,*(kal_int32*)(data),1);
ADC_BAT_SENSE_tmp[i] = val;
val = 1; //set avg times
/* 获得 PMIC 的 ISENSE 引脚电压 */
ret = battery_meter_ctrl(BATTERY_METER_CMD_GET_ADC_V_I_SENSE, &val);
read_adc_v_i_sense(void *data)
*(kal_int32*)(data) = PMIC_IMM_GetOneChannelValue(ISENSE_CHANNEL_NUMBER,*(kal_int32*)(data),1);
ADC_I_SENSE_tmp[i] = val;
ADC_BAT_SENSE_sum += ADC_BAT_SENSE_tmp[i];
ADC_I_SENSE_sum += ADC_I_SENSE_tmp[i];
}
//sorting 排序 BAT_SENSE
for(i=0 ; i<repeat ; i++)
{
for(j=i; j<repeat ; j++)
{
if( ADC_BAT_SENSE_tmp[j] < ADC_BAT_SENSE_tmp[i] )
{
temp = ADC_BAT_SENSE_tmp[j];
ADC_BAT_SENSE_tmp[j] = ADC_BAT_SENSE_tmp[i];
ADC_BAT_SENSE_tmp[i] = temp;
}
}
}
bm_print(BM_LOG_FULL, "[g_Get_I_Charging:BAT_SENSE]\r\n");
for(i=0 ; i<repeat ; i++ )
{
bm_print(BM_LOG_FULL, "%d,", ADC_BAT_SENSE_tmp[i]);
}
bm_print(BM_LOG_FULL, "\r\n");
//sorting I_SENSE
for(i=0 ; i<repeat ; i++)
{
for(j=i ; j<repeat ; j++)
{
if( ADC_I_SENSE_tmp[j] < ADC_I_SENSE_tmp[i] )
{
temp = ADC_I_SENSE_tmp[j];
ADC_I_SENSE_tmp[j] = ADC_I_SENSE_tmp[i];
ADC_I_SENSE_tmp[i] = temp;
}
}
}
bm_print(BM_LOG_FULL, "[g_Get_I_Charging:I_SENSE]\r\n");
for(i=0 ; i<repeat ; i++ )
{
bm_print(BM_LOG_FULL, "%d,", ADC_I_SENSE_tmp[i]);
}
bm_print(BM_LOG_FULL, "\r\n");
ADC_BAT_SENSE_sum -= ADC_BAT_SENSE_tmp[0];
ADC_BAT_SENSE_sum -= ADC_BAT_SENSE_tmp[1];
ADC_BAT_SENSE_sum -= ADC_BAT_SENSE_tmp[18];
ADC_BAT_SENSE_sum -= ADC_BAT_SENSE_tmp[19];
ADC_BAT_SENSE = ADC_BAT_SENSE_sum / (repeat-4);
bm_print(BM_LOG_FULL, "[g_Get_I_Charging] ADC_BAT_SENSE=%d\r\n", ADC_BAT_SENSE);
ADC_I_SENSE_sum -= ADC_I_SENSE_tmp[0];
ADC_I_SENSE_sum -= ADC_I_SENSE_tmp[1];
ADC_I_SENSE_sum -= ADC_I_SENSE_tmp[18];
ADC_I_SENSE_sum -= ADC_I_SENSE_tmp[19];
ADC_I_SENSE = ADC_I_SENSE_sum / (repeat-4);
bm_print(BM_LOG_FULL, "[g_Get_I_Charging] ADC_I_SENSE(Before)=%d\r\n", ADC_I_SENSE);
bm_print(BM_LOG_FULL, "[g_Get_I_Charging] ADC_I_SENSE(After)=%d\r\n", ADC_I_SENSE);
if(ADC_I_SENSE > ADC_BAT_SENSE)
{ //如果isense电压比batsense电压大,计算电流公式,否则电流取0
ICharging = (ADC_I_SENSE - ADC_BAT_SENSE + g_I_SENSE_offset)*1000/CUST_R_SENSE;
}
else
{
ICharging = 0;
}
return ICharging;
}
/* 获得充电器电压 */ // 获得 获取 PMIC 的 VCDT 引脚电压 通过读adc某个通道可获取
charger_vol = battery_meter_get_charger_voltage();
kal_int32 battery_meter_get_charger_voltage(void)
{
int ret=0;
int val=0;
val = 5; // set avg times
ret = battery_meter_ctrl(BATTERY_METER_CMD_GET_ADC_V_CHARGER, &val);
static kal_int32 read_adc_v_charger(void *data)
{
#if defined(CONFIG_POWER_EXT)
*(kal_int32*)(data) = 5001;
#else
kal_int32 val;
/* 获取 PMIC 的 VCDT 引脚电压 */
val = PMIC_IMM_GetOneChannelValue(VCHARGER_CHANNEL_NUMBER,*(kal_int32*)(data),1);
val = (((R_CHARGER_1+R_CHARGER_2)*100*val)/R_CHARGER_2)/100;
*(kal_int32*)(data) = val;
#endif
return STATUS_OK;
}
//val = (((R_CHARGER_1+R_CHARGER_2)*100*val)/R_CHARGER_2)/100;
return val;
}
/* 通过获得当前 NTC 电压,查表并进行线性插值法,得到当前的温度值 */
//得到当前的温度值
temperature = battery_meter_get_battery_temperature();
signed int battery_meter_get_battery_temperature(void)
{
#ifdef MTK_BATTERY_LIFETIME_DATA_SUPPORT
signed int batt_temp = force_get_tbat(KAL_TRUE);
if (batt_temp > gFG_max_temperature)
gFG_max_temperature = batt_temp;
if (batt_temp < gFG_min_temperature)
gFG_min_temperature = batt_temp;
return batt_temp;
#else
return force_get_tbat(KAL_TRUE);
#endif
}
return force_get_tbat();
/* 通过获得当前 NTC 电压,查表并进行线性插值法,得到当前的温度值 */
int force_get_tbat(kal_bool update)
{
#if defined(CONFIG_POWER_EXT) || defined(FIXED_TBAT_25)
bm_print(BM_LOG_CRTI, "[force_get_tbat] fixed TBAT=25 t\n");
return 25;
#else
int bat_temperature_volt = 0;
int bat_temperature_val = 0;
static int pre_bat_temperature_val = -1;
int fg_r_value = 0;
signed int fg_current_temp = 0;
kal_bool fg_current_state = KAL_FALSE;
int bat_temperature_volt_temp = 0;
int ret = 0;
if (batt_meter_cust_data.fixed_tbat_25) {
bm_print(BM_LOG_CRTI, "[force_get_tbat] fixed TBAT=25 t\n");
return 25;
}
if (update == KAL_TRUE || pre_bat_temperature_val == -1) {
/* Get V_BAT_Temperature */
bat_temperature_volt = 2;
/* 对应 PMIC 的硬件接口函数,这个对应的函数是在下面 battery_meter_init 模块中设置的
获得电池 NTC 对应的电压 */
ret =
battery_meter_ctrl(BATTERY_METER_CMD_GET_ADC_V_BAT_TEMP, &bat_temperature_volt);
if (bat_temperature_volt != 0) {
#if defined(SOC_BY_HW_FG)
fg_r_value = get_r_fg_value();
ret =
battery_meter_ctrl(BATTERY_METER_CMD_GET_HW_FG_CURRENT,
&fg_current_temp);
ret =
battery_meter_ctrl(BATTERY_METER_CMD_GET_HW_FG_CURRENT_SIGN,
&fg_current_state);
fg_current_temp = fg_current_temp / 10;
if (fg_current_state == KAL_TRUE) {
bat_temperature_volt_temp = bat_temperature_volt;
bat_temperature_volt =
bat_temperature_volt - ((fg_current_temp * fg_r_value) / 1000);
} else {
bat_temperature_volt_temp = bat_temperature_volt;
bat_temperature_volt =
bat_temperature_volt + ((fg_current_temp * fg_r_value) / 1000);
}
#endif
/* 将 NTC 的电压通过查表获得对应温度值 */
bat_temperature_val = BattVoltToTemp(bat_temperature_volt);
}
#ifdef CONFIG_MTK_BIF_SUPPORT
battery_charging_control(CHARGING_CMD_GET_BIF_TBAT, &bat_temperature_val);
#endif
bm_print(BM_LOG_CRTI, "[force_get_tbat] %d,%d,%d,%d,%d,%d\n",
bat_temperature_volt_temp, bat_temperature_volt, fg_current_state,
fg_current_temp, fg_r_value, bat_temperature_val);
pre_bat_temperature_val = bat_temperature_val;
} else {
bat_temperature_val = pre_bat_temperature_val;
}
return bat_temperature_val;
#endif
}
EXPORT_SYMBOL(force_get_tbat);
/* 这里用来获取电池 NTC 的电压 */
temperatureV = battery_meter_get_tempV();
signed int battery_meter_get_tempV(void)
{
#if defined(CONFIG_POWER_EXT)
return 0;
#else
int ret = 0;
int val = 0;
val = 1; /* set avg times 设置avg时间*/
ret = battery_meter_ctrl(BATTERY_METER_CMD_GET_ADC_V_BAT_TEMP, &val);
return val;
#endif
}
static kal_int32 read_adc_v_bat_temp(void *data)// meter_hal.c文件
{
#if defined(CONFIG_POWER_EXT)
*(kal_int32*)(data) = 0;
#else
#if defined(MTK_PCB_TBAT_FEATURE)
int ret = 0, data[4], i, ret_value = 0, ret_temp = 0;
int Channel=1;
if( IMM_IsAdcInitReady() == 0 )
return g_adc_init_flag;
{
bm_print(BM_LOG_CRTI, "[get_tbat_volt] AUXADC is not ready");
return 0;
}
i = times;
while (i--)
{
ret_value = IMM_GetOneChannelValue(Channel, data, &ret_temp);
ret += ret_temp;
bm_print(BM_LOG_FULL, "[get_tbat_volt] ret_temp=%d\n",ret_temp);
}
ret = ret*1500/4096 ;
ret = ret/times;
bm_print(BM_LOG_CRTI, "[get_tbat_volt] Battery output mV = %d\n",ret);
*(kal_int32*)(data) = ret;
#else
bm_print(BM_LOG_FULL, "[read_adc_v_charger] return PMIC_IMM_GetOneChannelValue(4,times,1);\n");
/* 读取 PMIC 的 BATON1 引脚电压 */
/* 读 PMIC 对应的 ADC 的值,并将其转化为对应的电压值,这里即读取 BATON 引脚电压 */
*(kal_int32*)(data) = PMIC_IMM_GetOneChannelValue(VBATTEMP_CHANNEL_NUMBER,*(kal_int32*)(data),1);
#endif
#endif
return STATUS_OK;
}
/* 获得 下拉电阻与 NTC 并并联的电压 */
temperatureR = battery_meter_get_tempR(temperatureV);
/* 上拉电压/下拉电压 = 上拉电阻/ 下拉电阻 */
TRes = (RBAT_PULL_UP_R*dwVolt) / (RBAT_PULL_UP_VOLT-dwVolt);
signed int battery_meter_get_tempR(signed int dwVolt)
{
#if defined(CONFIG_POWER_EXT)
return 0;
#else
int TRes;
TRes =
(batt_meter_cust_data.rbat_pull_up_r * dwVolt) /
(batt_meter_cust_data.rbat_pull_up_volt - dwVolt);
return TRes;
#endif
}
adc通道层 pmic_auadc.c (提供adc通道直接读通道得到模拟信号可转化成数字信号,如电压,温度等)
int PMIC_IMM_GetOneChannelValue(unsigned int dwChannel, int deCount, int trimd)
{
int ret, adc_rdy, reg_val;
int raw_data, adc_result;
int adc_div = 4096, raw_mask = 0, r_val_temp = 0;
int count = 0;
int raw_data_sum = 0, raw_data_avg = 0;
int u4Sample_times = 0;
unsigned int adc_channel;
adc_channel = dwChannel;
do {
/*defined channel 5 for TYEPC_CC1, channel 6 for TYPEC_CC2*/
/*defined channel 7 for CHG_DP, channel 8 for CHG_DM*/
mutex_lock(&mt6392_adc_mutex);
if ((dwChannel == 5) || (dwChannel == 6)) {
ret = pmic_config_interface(MT6392_TYPE_C_CTRL, 0x0, 0xffff, 0);
if (ret < 0) {
mutex_unlock(&mt6392_adc_mutex);
return ret;
}
ret = pmic_config_interface(MT6392_TYPE_C_CC_SW_FORCE_MODE_ENABLE_0, 0x5B8, 0xffff, 0);
if (ret < 0) {
mutex_unlock(&mt6392_adc_mutex);
return ret;
}
ret = pmic_config_interface(MT6392_TYPE_C_CC_SW_FORCE_MODE_VAL_0, 0x0100, 0xffff, 0);
if (ret < 0) {
mutex_unlock(&mt6392_adc_mutex);
return ret;
}
udelay(1000);
if (dwChannel == 5) {
ret = pmic_config_interface(MT6392_TYPE_C_CC_SW_FORCE_MODE_VAL_0, 0x1f40, 0xffff, 0);
if (ret < 0) {
mutex_unlock(&mt6392_adc_mutex);
return ret;
}
/* AUXADC_RQST0_SET is bit 6*/
adc_channel = 6;
} else {
ret = pmic_config_interface(MT6392_TYPE_C_CC_SW_FORCE_MODE_VAL_0, 0x1fc0, 0xffff, 0);
if (ret < 0) {
mutex_unlock(&mt6392_adc_mutex);
return ret;
}
}
ret = pmic_config_interface(MT6392_TYPE_C_CC_SW_FORCE_MODE_ENABLE_0, 0x05fc, 0xffff, 0);
if (ret < 0) {
mutex_unlock(&mt6392_adc_mutex);
return ret;
}
mdelay(10);
}
if ((dwChannel == 7) || (dwChannel == 8)) {
if (dwChannel == 7) {
/*DP channel*/
ret = pmic_config_interface(MT6392_CHR_CON18, 0x0700, 0x0f00, 0);
if (ret < 0) {
mutex_unlock(&mt6392_adc_mutex);
return ret;
}
/* AUXADC_RQST0_SET is bit 8*/
adc_channel = 8;
} else {
/*DM channel*/
ret = pmic_config_interface(MT6392_CHR_CON18, 0x0b00, 0x0f00, 0);
if (ret < 0) {
mutex_unlock(&mt6392_adc_mutex);
return ret;
}
}
}
/* AUXADC_RQST0 SET */
ret = pmic_config_interface(MT6392_AUXADC_RQST0_SET, 0x1, 0xffff, adc_channel);
if (ret < 0) {
mutex_unlock(&mt6392_adc_mutex);
return ret;
}
if ((adc_channel == 0) || (adc_channel == 1))
udelay(1500);
else
udelay(100);
/* check auxadc is ready */
do {
ret = pmic_read_interface(mt6392_auxadc_regs[adc_channel], ®_val, 0xffff, 0);
if (ret < 0) {
mutex_unlock(&mt6392_adc_mutex);
return ret;
}
udelay(100);
adc_rdy = (reg_val >> 15) & 1;
if (adc_rdy != 0)
break;
count++;
} while (count < count_time_out);
if (adc_rdy != 1) {
mutex_unlock(&mt6392_adc_mutex);
pr_err("PMIC_IMM_GetOneChannelValue adc get ready Fail\n");
return -ETIMEDOUT;
}
count = 0;
/* get the raw data and calculate the adc result of adc */
ret = pmic_read_interface(mt6392_auxadc_regs[adc_channel], ®_val, 0xffff, 0);
if (ret < 0) {
mutex_unlock(&mt6392_adc_mutex);
return ret;
}
mutex_unlock(&mt6392_adc_mutex);
switch (adc_channel) {
case 0:
case 1:
r_val_temp = 3;
raw_mask = 0x7fff;
adc_div = 32768;
break;
case 2:
case 3:
case 4:
r_val_temp = 1;
raw_mask = 0xfff;
adc_div = 4096;
break;
case 5:
case 6:
case 7:
case 8:
r_val_temp = 2;
raw_mask = 0xfff;
adc_div = 4096;
break;
case 9:
case 10:
case 11:
case 12:
case 13:
case 14:
case 15:
r_val_temp = 1;
raw_mask = 0xfff;
adc_div = 4096;
break;
}
/* get auxadc raw data */
raw_data = reg_val & raw_mask;
raw_data_sum += raw_data;
u4Sample_times++;
} while (u4Sample_times < deCount);
raw_data_avg = raw_data_sum / deCount;
/* get auxadc real result*/
adc_result = (raw_data_avg * r_val_temp * VOLTAGE_FULL_RANGE) / adc_div;
return adc_result;
}
hal 层 batter_meter_hal.c (提供一些接口可通过adc通道获取电压值)
/* 读 PMIC 引用 BATSNS 的电压,即电池电压 */
static kal_int32 read_adc_v_bat_sense(void *data)
{
#if defined(CONFIG_POWER_EXT)
*(kal_int32*)(data) = 4201;
#else
*(kal_int32*)(data) = PMIC_IMM_GetOneChannelValue(VBAT_CHANNEL_NUMBER,*(kal_int32*)(data),1);
#endif
return STATUS_OK;
}
core 层 batter_meter.c(调用hal的接口获取电压值)
battery_meter_get_battery_voltage
kal_int32 battery_meter_get_battery_voltage(void)
{
int ret=0;
int val=5;
val = 5; //set avg times
// 获得 PMIC 的 BATSNS 引脚电压
ret = battery_meter_ctrl(BATTERY_METER_CMD_GET_ADC_V_BAT_SENSE, &val);
/* 读 PMIC 引用 BATSNS 的电压,即电池电压 */
static kal_int32 read_adc_v_bat_sense(void *data)
{
#if defined(CONFIG_POWER_EXT)
*(kal_int32*)(data) = 4201;
#else
*(kal_int32*)(data) = PMIC_IMM_GetOneChannelValue(VBAT_CHANNEL_NUMBER,*(kal_int32*)(data),1);
#endif
return STATUS_OK;
}
g_sw_vbat_temp = val;
return val;
}
battery_meter_get_VSense