返回列表 发新帖我要提问本帖赏金: 25.00元(功能说明)

FR8012HAQ利用ADC实现检测电池电压检测的解决方案

[复制链接]
1334|0
 楼主| lilijin1995 发表于 2023-1-13 09:21 | 显示全部楼层 |阅读模式
本帖最后由 lilijin1995 于 2023-1-13 16:04 编辑

今天要跟大家分享的是FR8012HAQ利用ADC实现检测电池电压检测的解决方案。
FR8012HAQ是富芮坤的一款通用蓝牙芯片。特性介绍如下图:


我们再来看FR8012HAQ的PMU,它强大的地方还在于内置了充电模块。

FR801xH具有完整的集成电源管理单元(PMU),包括单电感单输出(SISO) DC-DC转换器,用于系统不同功率域的各种ldo,用于电池充电的恒流恒压(CCCV)充电器,充电检测电路,中断控制器,开关逻辑,BLE睡眠计数器,RTC,看守狗,键盘扫描,QDEC, PWM,校准块和GPIO监视器。模拟电源管理单元(PMU)的系统原理图如下图所示。

PMU虽然强大,但是我们的电池电压的检测没用到,我们主要是利用ADC的电池监控功能,
下面我们来看看这个款芯片的ADC特性:
SARADC的主要特性如下:
  • 10位动态ADC, 1MHz采样率。
  • 电池监控功能
  • 8通道单端输入
  • 支持32字节FIFO深度四路模拟输入
  • 支持固定通道模式和循环通道扫描模式
由ADC特性可以看到,它的采样率还是可以的,但是精度只有10位,有点拉胯了。
我们因为要用到ADC的外部通道,而且又要用到它的电池监控功能,但是ADC只有一个,那只能分时复用了,下面给出实现代码
  1. if(Vbat_Start_Tick++>=BASE_5S)
  2.         {
  3.                
  4.         struct adc_cfg_t cfg;
  5.         uint16_t result, ref_vol;
  6.         
  7.         memset((void*)&cfg, 0, sizeof(cfg));
  8.         cfg.src = ADC_TRANS_SOURCE_VBAT;
  9.         cfg.ref_sel = ADC_REFERENCE_INTERNAL;
  10.         cfg.int_ref_cfg = ADC_INTERNAL_REF_1_2;
  11.         cfg.clk_sel = ADC_SAMPLE_CLK_24M_DIV13;
  12.         cfg.clk_div = 0x3f;
  13.         adc_init(&cfg);
  14.         adc_enable(NULL, NULL, 0);

  15.         adc_get_result(ADC_TRANS_SOURCE_VBAT, 0, &result);
  16.                 ref_vol = adc_get_ref_voltage(ADC_REFERENCE_INTERNAL);
  17.         vbat_voltage = (result * 4 * ref_vol) / 1024;               
  18.                 printf("vbat_vol=%d\r\n",vbat_voltage);

  19.                         
  20.                 if(vbat_voltage<=3100)
  21.                 {
  22.                         if(mdStateMach.FSM!=Charge)
  23.                         {
  24.                                 SetStaticLED281x(Orange,1);
  25.                         }
  26.                         
  27.                 }else if(vbat_voltage<=2900)
  28.                 {
  29.                         mdStateMach.FSM=Shutdown;
  30.                 }
  31.                 Vbat_Start_Tick=0;
  32.                
  33.         }else if(Vbat_Start_Tick==1){
  34.                 Switch_ADC_Soucer();
  35.         }
这段代码是在10ms定时器中执行的, if(Vbat_Start_Tick++>=BASE_5S)这个条件是5S一个周期执行一次切换ADC转换源为VBAT,以检测VBAT电压,
vbat_voltage = (result * 4 * ref_vol) / 1024;这条公式算出的是mV电压,当5S之后又切换回ADC_TRANS_SOURCE_PAD。如下代码:

  1.     struct adc_cfg_t cfg;
  2.     system_set_port_mux(GPIO_PORT_D, GPIO_BIT_4, PORTD4_FUNC_ADC0);
  3.     memset((void*)&cfg, 0, sizeof(cfg));
  4.     cfg.src = ADC_TRANS_SOURCE_PAD;
  5.     cfg.ref_sel = ADC_REFERENCE_AVDD;
  6.     cfg.channels = 0x01;  //ch0    一个 bit 表示一个通道:PD4=BIT0=通道 0、PD5=BIT1=通道 1、PD6=BIT2=通道 2、PD7=BIT3=通道 3;
  7.     cfg.route.pad_to_sample = 1;
  8.     cfg.clk_sel = ADC_SAMPLE_CLK_24M_DIV13;
  9.     cfg.clk_div = 0x3f;
  10.     adc_init(&cfg);
  11.     adc_enable(NULL, NULL, 0);

最后我们再来看看adc_get_result(ADC_TRANS_SOURCE_PAD, 0x01, &Hxresul);这个函数,如下图:
第一个参数,是ADC 采集的数据源,adc_trans_source_t 定义如下:
  1. enum adc_trans_source_t {
  2.     ADC_TRANS_SOURCE_VBAT,
  3.     ADC_TRANS_SOURCE_PAD,
  4. };
ADC_TRANS_SOURCE_VBAT是采集电池电压的。
ADC_TRANS_SOURCE_PAD可以采集外部输入电压。

第二个参数是,配置的是ADC的通道数的,第0位表示ch0,第1位表示ch1,置1开启通道,清零关闭。
第三个参数是采样结果,按照配置的顺序摆放。
如配置通道0和1,那么数组temp[4]中temp[0]、temp[2]表示通道0数据,temp[1]、temp[3]表示通道2的。

---------end-----------------





本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?注册

×

打赏榜单

21ic小管家 打赏了 25.00 元 2023-02-08
理由:签约作者奖励

您需要登录后才可以回帖 登录 | 注册

本版积分规则

56

主题

165

帖子

8

粉丝
快速回复 在线客服 返回列表 返回顶部