mtk 電池驅動的電壓,電流,溫度等資料通過adc通道獲取
阿新 • • 發佈:2018-12-24
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