#include "include.h" #include "app_variable.h" #if VBAT_DETECT_EN #define VBG_VOLTAGE sys_trim.vbg_volt #define VBAT2_COEF sys_trim.vbat_coef #define TRACE_EN 0 #if TRACE_EN #define TRACE(...) printf(__VA_ARGS__) #else #define TRACE(...) #endif static vbat_cb_t vbat_cb; AT(.com_rodata.bat) const char bat_str[] = "VBAT: %d.%03dV\n"; AT(.com_text.port.vbat) u16 bsp_vbat_get_voltage(u32 rst_flag) { u32 vbat; u32 vbat2 = saradc_get_value10(VBAT2_ADCCH); vbat = saradc_vbat_get_calc_value(vbat2, adc_cb.bg, adc_cb.vrtc_val, adc_cb.vrtc_first); if (rst_flag) { adc_cb.vbat_bak = 0; adc_cb.vbat_val = vbat; adc_cb.vbat_total = adc_cb.vbat_val << 5; } //不同方案可能采用不同 vbat 滤波算法, 在方案对应的plugin.c中处理 plugin_vbat_filter(&vbat); //默认的取平均值算法. adc_cb.vbat_total = adc_cb.vbat_total - adc_cb.vbat_val + vbat; adc_cb.vbat_val = adc_cb.vbat_total >> 5; //平均值 if (adc_cb.vbat_val > adc_cb.vbat_bak) { vbat = adc_cb.vbat_val - adc_cb.vbat_bak; } else { vbat = adc_cb.vbat_bak - adc_cb.vbat_val; } if (vbat >= 2) { //偏差大于一定值则更新 adc_cb.vbat_bak = adc_cb.vbat_val; } // printf(bat_str, adc_cb.vbat_val/1000, adc_cb.vbat_val%1000); return adc_cb.vbat_bak; } void bsp_vbat_voltage_init(void) { sys_cb.vbat = bsp_vbat_get_voltage(1); // printf("!!!bsp_vbat_voltage_init sys_cb.vbat=%d\n", sys_cb.vbat); } int bsp_vbat_get_lpwr_status(void) { if(CHARGE_DC_IN()){ return 0; } if(sys_cb.charge_sta > 0) { return 0; } if ((sys_cb.vbat <= LPWR_OFF_VBAT)&&(bsp_vbat_percent_get() <= 3 )) { if (LPWR_OFF_VBAT) { if (!sys_cb.lpwr_cnt) { sys_cb.lpwr_cnt = 1; // printf("!!!sys_cb.vbat=%d\n", sys_cb.vbat); } else if (sys_cb.lpwr_cnt >= 10) { return 2; //VBAT低电关机 } } return 0; //VBAT低电不关机 } else { sys_cb.lpwr_cnt = 0; if ((sys_cb.vbat < LPWR_WARNING_VBAT)&&(bsp_vbat_percent_get() <= 24 )) { return 1; //VBAT低电提醒状态 } else { } return 0; } sys_cb.lpwr_cnt = 0; return 0; } // static int printf_sec = 0; void bsp_vbat_lpwr_process(void) { int vbat_sta = bsp_vbat_get_lpwr_status(); if (vbat_sta == 2) { //达到低电关机状态 if (func_cb.sta != FUN_POWER_OFF_LOGO) { printf("now is a vaba_sta low power enter to power off !!!\n"); if (sys_cb.gui_sleep_sta) { sys_cb.wkp_flag = true; } func_switch_to_assign_screen(FUN_POWER_OFF_LOGO, true); // 低电,进入关机或省电模式 } return; } else if (vbat_sta == 1) { //低电提醒状态 //低电提示音播放 sys_cb.vbat_nor_cnt = 0; if (sys_cb.lpwr_warning_cnt > LPWR_WARNING_PERIOD) { sys_cb.lpwr_warning_cnt = 0; if(func_cb.sta != FUNC_CHARGE) { if (sys_cb.gui_sleep_sta) { sys_cb.wkp_flag = true; } sys_cb.motor_flag = 1; set_func_motor(80, 10, 0, 1); func_popup_new(POPUP_ID_LOW_POWER_REMIND); } if (sys_cb.lpwr_warning_times) { //低电语音提示次数 sys_cb.lowbat_flag = 1; plugin_lowbat_vol_reduce(); //低电降低音乐音量 if (sys_cb.lpwr_warning_times != 0xff) { sys_cb.lpwr_warning_times--; } } } } else { if ((sys_cb.lowbat_flag) && (sys_cb.vbat > 3800)) { sys_cb.vbat_nor_cnt++; if (sys_cb.vbat_nor_cnt > 40) { sys_cb.lowbat_flag = 0; sys_cb.lpwr_warning_times = LPWR_WARING_TIMES; plugin_lowbat_vol_recover(); //离开低电, 恢复音乐音量 } } } } /* 中性32M方屏的电流曲线 */ #if (GUI_SCREEN_WIDTH == 240 && GUI_SCREEN_HEIGHT == 296 && FLASH_SIZE == FSIZE_4M) /** * 电池电量对应百分百表 不同电池修改这张表格,表格默认的是4.2v的电池 */ static const u16 vbat_percent_table[11] = { // 0% 10% 20% 30% 40% 50% 60% 70% 80% 90% 100% 3480, 3580, 3640, 3690, 3760, 3790, 3820, 3860, 3950, 4050, 4180 };//优化了100%~70%之间的电压值,使这段区间更加耐用;拉宽40%~60%之间的电压值,避免40%的电量很快掉到30%以下,不能OTA #else /** * 电池电量对应百分百表 不同电池修改这张表格,表格默认的是4.2v的电池 */ static const u16 vbat_percent_table[11] = { // 0% 10% 20% 30% 40% 50% 60% 70% 80% 90% 100% 3480, 3580, 3640, 3690, 3720, 3750, 3780, 3820, 3900, 3980, 4100 }; #endif /** * 电池电量标定回到,充电和放电都在这里处理了,10s一次回调 */ static u16 vbat_percent_convert(u16 adc_value) { u16 pervent = 0; u8 i = 0; if(adc_value >= vbat_percent_table[10]){ return 100; } if(adc_value <= vbat_percent_table[0]){ return 0; } for(i=0; i<=10; i++){ if(adc_value < vbat_percent_table[i]){ break; } } pervent = (adc_value - vbat_percent_table[i-1]) * 10 / (vbat_percent_table[i] - vbat_percent_table[i-1]) + (i-1)*10; //pervent = (i-1) * 10; return pervent; } /** * 电池电量标定回调执行,充电和放电都在这里处理了,10s执行一次(修改在bsp_vbat_percent_init函数) */ static void vbat_percent_process(co_timer_t *timer, void *param) { if(vbat_cb.vbat_adc_last == 0){ sys_cb.vbat_percent = vbat_percent_convert(adc_cb.vbat_val); vbat_cb.vbat_adc_last = adc_cb.vbat_val; vbat_cb.vbat_adc_curr = adc_cb.vbat_val; return; } sys_cb.vbat = bsp_vbat_get_voltage(0); vbat_cb.vbat_adc_curr = adc_cb.vbat_val; if(CHARGE_DC_IN()){ //充电状态 if(bsp_charge_sta_get() == 2){ //硬件判断充满状态 if(adc_cb.vbat_val < vbat_percent_table[10]){ //如果硬件已经满了,对于个别一些烂电池可能始终没无法达到预设电压, 也认为其满了 vbat_cb.vbat_adc_curr = vbat_percent_table[10]; } } if(vbat_cb.vbat_adc_last < vbat_cb.vbat_adc_curr){ vbat_cb.vbat_adc_last += VBAT_PERCENT_STEP*4; } }else{ if(vbat_cb.vbat_adc_last > vbat_cb.vbat_adc_curr){ if(vbat_cb.vbat_adc_last - vbat_cb.vbat_adc_curr > 50) { vbat_cb.vbat_adc_last = vbat_cb.vbat_adc_curr; } vbat_cb.vbat_adc_last -= VBAT_PERCENT_STEP; if (bsp_system_is_sleep()) { sys_cb.vbat_percent = vbat_percent_convert(vbat_cb.vbat_adc_last); } } } if (!bsp_system_is_sleep()) { sys_cb.vbat_percent = vbat_percent_convert(vbat_cb.vbat_adc_last); } TRACE("bsp_system_is_sleep():%d,vbat_adc_last:%d vbat_adc_curr:%d vbat_percent:%d\n",bsp_system_is_sleep(), vbat_cb.vbat_adc_last, vbat_cb.vbat_adc_curr, sys_cb.vbat_percent); } /** * 电池百分比标定初始化 */ void bsp_vbat_percent_init(void) { static co_timer_t vbat_timer; memset(&vbat_cb, 0, sizeof(vbat_cb_t)); vbat_percent_process(NULL, NULL); co_timer_set(&vbat_timer, 5000, TIMER_REPEAT, LEVEL_LOW_PRI, vbat_percent_process, NULL); co_timer_set_sleep(&vbat_timer, true); } /** * 获取电池电量百分比 * 返回: 0~100 */ u16 bsp_vbat_percent_get(void) { return sys_cb.vbat_percent; } //ui使用这套 u8 tjd_charging_show_bat_ui_level(void) { u8 percent = bsp_vbat_percent_get(); u8 level; if (percent < 10) {//空电量 level = 0*10;//0-10 } else if (percent < 20) {//1格 level = 1*10;//10+ } else if (percent < 30) {//2格 level = 2*10;//20+ } else if (percent < 40) {//3格 level = 3*10;//30+ } else if (percent < 50) {//4格 level = 4*10;//40+ } else if (percent < 60) {//5格 level = 5*10;//50 } else if (percent < 70) {//6格 level = 6*10;//60+ } else if (percent < 90) {//7格 level = 7*10;//70+ } else if (percent < 90) {//8格 level = 8*10;//80 } else if(percent < 99) {//9格 level = 9*10; } else { level = 10*10; } /* if (get_charge_full_flag()) { level = 10*10; } */ return level/10; } #endif //VBAT_DETECT_EN