Files
TAIXIN/sdk/app/battery_adc_detect/battery_det.c

137 lines
3.9 KiB
C
Raw Normal View History

#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);
}