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

今天要跟大家分享的是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只有一个,那只能分时复用了,下面给出实现代码

复制
 if(Vbat_Start_Tick++>=BASE_5S)

        {

                

        struct adc_cfg_t cfg;

        uint16_t result, ref_vol;

        

        memset((void*)&cfg, 0, sizeof(cfg));

        cfg.src = ADC_TRANS_SOURCE_VBAT;

        cfg.ref_sel = ADC_REFERENCE_INTERNAL;

        cfg.int_ref_cfg = ADC_INTERNAL_REF_1_2;

        cfg.clk_sel = ADC_SAMPLE_CLK_24M_DIV13;

        cfg.clk_div = 0x3f;

        adc_init(&cfg);

        adc_enable(NULL, NULL, 0);



        adc_get_result(ADC_TRANS_SOURCE_VBAT, 0, &result);

                ref_vol = adc_get_ref_voltage(ADC_REFERENCE_INTERNAL);

        vbat_voltage = (result * 4 * ref_vol) / 1024;                

                printf("vbat_vol=%d\r\n",vbat_voltage);



                        

                if(vbat_voltage<=3100)

                {

                        if(mdStateMach.FSM!=Charge)

                        {

                                SetStaticLED281x(Orange,1);

                        }

                        

                }else if(vbat_voltage<=2900)

                {

                        mdStateMach.FSM=Shutdown;

                }

                Vbat_Start_Tick=0;

                

        }else if(Vbat_Start_Tick==1){

                Switch_ADC_Soucer();

        }

这段代码是在10ms定时器中执行的, if(Vbat_Start_Tick++>=BASE_5S)这个条件是5S一个周期执行一次切换ADC转换源为VBAT,以检测VBAT电压,
vbat_voltage = (result * 4 * ref_vol) / 1024;这条公式算出的是mV电压,当5S之后又切换回ADC_TRANS_SOURCE_PAD。如下代码:
 

复制
    struct adc_cfg_t cfg;

    system_set_port_mux(GPIO_PORT_D, GPIO_BIT_4, PORTD4_FUNC_ADC0);

    memset((void*)&cfg, 0, sizeof(cfg));

    cfg.src = ADC_TRANS_SOURCE_PAD;

    cfg.ref_sel = ADC_REFERENCE_AVDD;

    cfg.channels = 0x01;  //ch0    一个 bit 表示一个通道:PD4=BIT0=通道 0、PD5=BIT1=通道 1、PD6=BIT2=通道 2、PD7=BIT3=通道 3;

    cfg.route.pad_to_sample = 1;

    cfg.clk_sel = ADC_SAMPLE_CLK_24M_DIV13;

    cfg.clk_div = 0x3f;

    adc_init(&cfg);

    adc_enable(NULL, NULL, 0);


最后我们再来看看adc_get_result(ADC_TRANS_SOURCE_PAD, 0x01, &Hxresul);这个函数,如下图: 


第一个参数,是ADC 采集的数据源,adc_trans_source_t 定义如下:

enum adc_trans_source_t {

    ADC_TRANS_SOURCE_VBAT,

    ADC_TRANS_SOURCE_PAD,

};

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的。
---------------------
作者:lilijin1995
链接:https://bbs.21ic.com/icview-3278320-1-1.html
来源:21ic.com
此文章已获得原创/原创奖标签,著作权归21ic所有,任何人未经允许禁止转载。

 

  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
### 回答1: 利用MATLAB来从四种三维Archimedean Copula函数中选取最优的三维copula函数,可以使用下面的代码: [U,V,W] = copulafit('t',[x1,y1,z1;x2,y2,z2;...;xn,yn,zn]); 其中,xi,yi,zi是观察值,U,V,W是Archimedean Copula函数的参数。 ### 回答2: 要从四种三维Archimedean Copula函数中选取最优的三维Copula函数,可以使用MATLAB编写代码。以下是用于实现此任务的一种可能方法: ```MATLAB clear all; close all; clc; % 生成模拟数据 n = 1000; % 样本数 u1 = rand(n, 1); % 第一个随机变量的样本 u2 = rand(n, 1); % 第二个随机变量的样本 u3 = rand(n, 1); % 第三个随机变量的样本 % 初始化模型评估指标 bestCopula = []; % 最优Copula函数 bestAIC = Inf; % 最小AIC值 % 遍历四种Archimedean Copula函数 archimedeanFamilies = {'Clayton', 'Frank', 'Gumbel', 'Ali-Mikhail-Haq'}; for i = 1:length(archimedeanFamilies) family = archimedeanFamilies{i}; % 拟合Copula函数 copula = fitcopula([u1, u2, u3], family); % 计算AIC值 [tCopula, ~] = kde([copula(u1, u2, u3)]); % 使用核密度估计做极大似然估计 logL = sum(log(pdf(tCopula, [u1, u2, u3]))); % 计算模型的对数似然估计 numParams = copulafitParamsNum(family); % 获取Copula模型的参数数量 aic = -2 * logL + 2 * numParams; % 计算AIC值 % 更新最优Copula函数和AIC值 if aic < bestAIC bestCopula = copula; bestAIC = aic; end end % 输出结果 disp('最优Copula函数:'); disp(bestCopula); disp('最小AIC值:'); disp(bestAIC); ``` 这段代码中首先生成了三个随机变量的样本数据u1、u2和u3。然后,通过遍历四种Archimedean Copula函数(Clayton、Frank、Gumbel和Ali-Mikhail-Haq),利用`fitcopula`函数拟合Copula函数。接着,使用核密度估计对模型进行极大似然估计,计算对数似然估计值和AIC值。最后,比较四种Copula函数的AIC值,选取AIC值最小的Copula函数作为最优Copula函数。这个最优Copula函数和相应的最小AIC值将在代码的最后输出。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值