#include "basic_include.h" #include "dev/adc/hgadc_v0.h" #ifdef PIN_FROM_PARAM #include "pin_param.h" #endif #include "lib/lmac/lmac.h" struct bat_det_priv { struct os_work work; struct hgadc_v0 *adc_dev; uint32_t bat_det_io; float vol; uint32_t _update_fme_adc_val; uint8_t level; uint8_t get_value; uint32_t adc_raw; }; struct bat_det_priv *g_bat_det_priv_data = NULL; static int32 bat_detect_work(struct os_work *work) { #if WIFI_FEM_CHIP void * ops = NULL; #endif struct bat_det_priv *bat_det_priv_data = (struct bat_det_priv *)work; uint32_t adc_value = 0; adc_get_value((struct adc_device *)bat_det_priv_data->adc_dev, bat_det_priv_data->bat_det_io, &adc_value); bat_det_priv_data->adc_raw = adc_value; bat_det_priv_data->get_value = 1; bat_det_priv_data->vol = (float)adc_value * 3 / 2048 * 2; bat_det_priv_data->_update_fme_adc_val = adc_value * 3 * 2 / 5; if (bat_det_priv_data->_update_fme_adc_val > 2047) { bat_det_priv_data->_update_fme_adc_val = 2047; } os_printf("---- battery adc:%d vol:%.2fV _update_fme_adc_val:%.2fV adc_val:%d----\n", adc_value, (float)adc_value * 3 / 2048 * 2, (float)bat_det_priv_data->_update_fme_adc_val * 5 / 2048, bat_det_priv_data->_update_fme_adc_val); // bat_det_priv_data->vol = 4; #if WIFI_FEM_CHIP lmac_update_fem_voltage(ops, (uint32_t)(5 * (1 << 10))); #endif os_run_work_delay(&bat_det_priv_data->work, 5000); return 0; } int bat_get_level() { /* 如果未初始化,返回0 */ if (!g_bat_det_priv_data) { return 0; } /* 使用 ADC 阈值表 阈值单位为 ADC 读数,避免浮点运算。加入整型 hysteresis 防跳变。 */ uint8_t res = 0; static uint8_t first_count = 1; static const uint16_t thresholds_adc[] = {1125, 1185, 1245, 1305, 1365}; const int max_level = sizeof(thresholds_adc) / sizeof(thresholds_adc[0]); const uint16_t hysteresis_adc = 10; /* ADC 单位去抖 */ uint32_t adc = g_bat_det_priv_data->adc_raw; /* 计算候选等级 */ int cand = 0; if(g_bat_det_priv_data->get_value == 0) { return 4; } while (cand < max_level && adc > thresholds_adc[cand]) { cand++; } if (cand > (max_level - 1)) { cand = max_level - 1; } if (first_count) { first_count = 0; g_bat_det_priv_data->level = (uint8_t)cand; return cand; } int prev = (int)g_bat_det_priv_data->level; if (cand == prev) { return (uint8_t)prev; } if (cand > prev) { /* 上升:需要超过阈值 + hysteresis 才更新 */ if (adc >= (uint32_t)thresholds_adc[prev] + hysteresis_adc) { g_bat_det_priv_data->level = (uint8_t)cand; res = (uint8_t)cand; } else { res = (uint8_t)prev; } } else { /* cand < prev */ /* 下降:需要低于阈值 - hysteresis 才更新 */ if (adc <= (uint32_t)thresholds_adc[prev] - hysteresis_adc) { g_bat_det_priv_data->level = (uint8_t)cand; res = (uint8_t)cand; } else { res = (uint8_t)prev; } } return res; } void bat_ad_init() { struct bat_det_priv *bat_det_priv_data = (struct bat_det_priv*)os_zalloc(sizeof(struct bat_det_priv)); if (!bat_det_priv_data) { os_printf("bat ad init err!!!!!!!!!!!!!\n"); return ; } g_bat_det_priv_data = bat_det_priv_data; bat_det_priv_data->adc_dev = (struct hgadc_v0*)dev_get(HG_ADC0_DEVID); bat_det_priv_data->bat_det_io = MACRO_PIN(BAT_ADC_IO); adc_open((struct adc_device *)bat_det_priv_data->adc_dev); gpio_set_mode(bat_det_priv_data->bat_det_io, GPIO_PULL_NONE, GPIO_PULL_LEVEL_NONE); adc_add_channel((struct adc_device *)bat_det_priv_data->adc_dev, bat_det_priv_data->bat_det_io); OS_WORK_INIT(&bat_det_priv_data->work, bat_detect_work, 0); os_run_work_delay(&bat_det_priv_data->work, 1000); }