1. 首页
  2. 技术文章

MTK平台ADC概述

目录

1.基本概念

2.MT6225 ADC简介

3.MT6253 ADC简介

4.两种操作模式

5.用于电池电量显示的ADC检测

5.1.主要流程图

5.2.流程说明

5.3.创建步聚

6.充电时ADC的检测

6.1充电时ADC的调度流程

7.工程模式查看电池电压ADC

8.MT6225平台区分USBCHARGERADC通道

9.ADC校准

10.ADC检测的主要API

11.ADC调度器的成员变量

1.基本概念

ADC ,即analog to digital converter,模拟信号至数字信号的转换器。主要的ADC转换算法有逐次逼近法,双积分法。它们一般由芯片内部的硬件电路实现,但外部的电路接法会有所不同。MTK平台ADC采样的可使用外部电路:

  

y=((a*x+b)/100)*factor(如adc_adc2vol()中的算式

x为ADC采样值,y为测量点的实际电压

如图2所示,(a*x+b)为A点的电压值,((a*x+b)/100)*factor才是我们要测量的Ui的电压值。由于ADC的量程有限,故需要进行分压才能测量比较大的电压,之后再根据分压电阻的比值转换成要测量点的电压。

a为每单位表示的电压。MTK的ADC量程为2.8V,ADC为10位的,故a=2800000/2^10=2734(uV)。通常为了扩大测量范围,需要把a扩大约一倍(记为a1),之后再通过factor校正。比如变成5524,是原来的2.02倍

b是偏移量,需要测量确定。

每一个ADC都有一组a,b值,在chr_parameter.c bmt_custom_chr_def[]结构体中的数组ADC_CALIDATA adc_cali_param[]给定

factor满足以下等式:factor*(R2+R1)/R1=100*a1/a

a1为adc_cali_param[]中的值,a为2734,R1,R2分压的两个电

 

2.MT6225 ADC简介

MT6225有7个ADC通道,主要有四个用途:

1.周期性地检测电池状态,vbat

2.充电时不断测量vbat,visense,vtmp,vcharger这四个ADC通道的值

3.usb-charger插入时检测usb的ADC以区分是USB还是charger

4.进入工程模式下的ADC菜单时不断读取电池电压ADC和电流

有两种操作模式:定时触发模式(上述的1,2)和即时触发模式(3,4)

 

3.MT6253 ADC简介

MT6253有6个ADC通道,0~2通道用于内部:0-电池电压,1—电池电流,2—充电电压;3~5通道可用于外部电压检测

主要有三个用途(区分usb还是charger不需要ADC):

1.周期性地检测电池状态(即电池电量显示)vbat

2.充电时不断测量vbat,visense,vtmp,vcharger这四个ADC通道的值

3.进入工程模式下的ADC菜单时不断读取电池电压ADC和电流

1和2属于定时触发模式;3为即时触发

 

4.两种操作模式

定时触发检测和即时触发检测(或称事件触发检测)。

定时触发检测:由AUXADC_CON0(0x8205_0000)寄存器设置,当对应位置为1时,对应的通道即为定时触发检测模式。如AUXADC_CON0 设为0x3f,则6个通道均为定时触发检测。定时的时间量在寄存器TDMA_AUXEV1中设置

 

即时触发检测:由AUXADC_CON1(0x8205_0008)寄存器设置,当对应位置为1时,对应的通道即为定时检测模式。如AUXADC_CON1 设为0x3f,则6个通道均为即时触发检测。

通道0~5 采样好的ADC值存储在寄存器AUXADC_DAT0(0x8205_0010)~AUXADC_DAT5(0x8205_0024)中

 

5.用于电池电量显示的ADC检测

5.1.主要流程图

5.2.流程说明

在开机进行到一定阶段后,UEM接收到消息ID(MSG_ID_MED_STARTUP_CNF),接着调度uemaud_startup_cnf_hdlr( ),最终通过函数uem_init_hardware_data( ),创建用于检测电池电压ADC的通道。此时的检测时间间隔和次数分别为ADC_BOOTUP_EVAL_PERIOD和ADC_BOOTUP_EVAL_COUNT。第一次检测完成后,通过函数uembmt_adc_measure_done_cnf_hdlr( )更新一次电池电量,并将检测时间间隔和次数改为:ADC_IDLE_EVAL_COUNT,ADC_IDLE_EVAL_PERIOD。之后保持ADC_IDLE_EVAL_COUNT* ADC_IDLE_EVAL_PERIOD的时间周期完成一次电池电压ADC的检测并更新电池图标。如果有来电,则在函数l4cuem_call_status_req_ind( )中将检测周期和次数更改为:ADC_TALKING_EVAL_COUNT,ADC_TALKING_EVAL_PERIOD;在通话期间保持这样的周期检测电池电压ADC和更新电池图标。通话结束结束后再把检测周期和次数更改为ADC_IDLE_EVAL_COUNT,ADC_IDLE_EVAL_PERIOD。

 

5.3.创建步聚

5.3.1.创建ADC通道:

adc_sche_id = adc_sche_create_object( MOD_UEM,   //创建该ADC所属模块

ADC_VBAT, //该ADC通道的物理ID

ADC_BOOTUP_EVAL_PERIOD, //检测时间间隔

(kal_uint8) ADC_BOOTUP_EVAL_COUNT, //检测次数

KAL_TRUE); //是否通过发送消息形式

 

uem_send_msg_to_bmt(MSG_ID_BMT_ADC_ADD_ITEM_REQ,  //消息ID

g_uem_cntx_p->adc_sche_id);    //逻辑ID

5.3.2.添加该ADC对应的完成回调函数和检测函数到ADC调度列表中:

adc_sche_add_item(ptr->adc_sche_id, //逻辑id

adc_sche_task_complete_callback, //完成的回调函数

adc_sche_measure); //检测函数

 

5.3.3.如果需要,则修改ADC的检测时间间隔和次数:

adc_sche_modify_parameters(ptr->adc_sche_id,

ptr->period,

ptr->evaluate_count);

 

5.3.4.从uemdrv_pmic_ind()到显示电池电量图标的过程:

uem_get_bat_status()获取电池状态è custom_cfg_vbat_level_regulator()将电池电压转换成相应的电池图标的格数等级è l4cuem_battery_status_ind(status_type, vbat_level)è BatteryStatusRsp()  case PMIC_VBAT_STATUS è BatteryStatusIndication()

 

电池等级格数对应的电压定义在

nvram_user_config.c  NVRAM_EF_CUST_HW_LEVEL_TBL_DEFAULT[ ]数组

 

6.充电时ADC的检测

在系统启动的初始阶段,bmt_task_main()中调用bmt_adc_init(),完成充电时四个ADC通道的创建工作。主要有:设置检测时间间隔和次数,建立与物理通道ID对应的逻辑ID,检测完成后的回调函数。充电器插入后,进入到bmt_charge_start(),之后进行BMT_CHRPRE_OFF()阶段的充电。检测Vbat,Visense,Vtemp,Vcharger这四个ADC值,都完成后通过bmt_measure_done()调度下一阶段的充电。

 

6.1充电时ADC的调度流程

 

7.工程模式查看电池电压ADC

当进入工程模式的ADC菜单时,系统会发出读取所有ADC通道的请求消息()MSG_ID_READ_ALL_ADC_CHANNEL_REQ,之后系统在aux_task_main ()中回应读取各个通道的ADC值,各读5次之后在MSG_ID_BMT_ADC_MEASURE_DONE_CONF分支取平均,并返回显示。

 

8.MT6225平台区分USB和CHARGER的ADC通道

在系统启动的初始阶段,bmt_task_main()中调用pmic_adpt_reg_chr_usb()完成USB_CHARGER的中断注册以及创建用于区分两者的ADC通道:

chr_usb_detect.chr_usb_adc_logical_id=adc_sche_create_object(MOD_BMT, chr_usb_detect.chr_usb_adc,10,3, KAL_TRUE);

 

有充电器或USB插入后跑到中断转入函数CHR_USB_EINT_HISR()的USB分支将检测CHRAGER_USB ADC 通道添加到ADC调度列表

adc_sche_add_item(chr_usb_detect.chr_usb_adc_logical_id,check_charger_or_usb,adc_sche_measure);

 

在判断是否USB的函数中读取该通道的ADC值,并从列表中删除

adc_sche_remove_item(chr_usb_detect.chr_usb_adc_logical_id);

 

volt= (kal_int32)VOL_RESULT[chr_usb_detect.chr_usb_adc_logical_id];

 

9.ADC校准

每次将ADC采样值转换成实际的电压值时,均使用Chr_parameter.c  bmt_custom_chr_def[]adc_cali_param(详情见函数adc_adc2vol())中保存的斜率和偏移量。

如果是正常开机,在NVRAM的值加载完后,发送消息ID:MSG_ID_NVRAM_READ_CNF,在bmt_main()中接收然后通过调度bmt_adc_set_adc_calibration_data()将nvram中(Nvram_common_config.c  NVRAM_EF_ADC_DEFAULT[])保存的ADC斜率和偏移量数据写到bmt_charing_para->adc_cali_param指向的内存单元中。

如果是USB模式启动(因插入USB而启动的系统),而在bmt_main( )中通过调度bmt_read_calibration_data()将NVRAM中的值写入bmt_charing_para->adc_cali_param。

校准时,同样是将NVRAM中的值重新写入bmt_charing_para->adc_cali_param

流程图如下:

 

10.ADC检测的主要API

 

kal_uint8 adc_sche_create_object(

module_type ownerid,

kal_uint8 adc_channel,

kal_uint32 period,

kal_uint8 evaluate_count,

kal_bool send_primitive  )

 

函数功能:创建一个ADC通道,用于读取ADC值。

输入参数:ownerid—创建该ADC通道所属模块的ID号;adc_channel—该ADC通道的物理通道;period—读取ADC值的时间间隔;evaluate_coun—读取次数(读取这么多次数后再取平均值);send_primitive—是否使用旗语(即是否使用消息传递)。故其调度周期为period* evaluate_coun

返回参数:adc_id—该ADC通道的逻辑ID值。

逻辑id值根据ADC创建的先后顺序而增加,即最开始创建的ADC通道逻辑值为0,最后创建的ADC通道逻辑值为最大。一个物理id可以有两个不同的逻辑id,但逻辑id必须是唯一的。

void adc_sche_add_item(

kal_uint8 adc_sche_id,

void (*mea_complete)(kal_uint8 adc_sche_id),

kal_timer_func_ptr mea_Callback)

 

函数功能:添加读取ADC值的测量函数和完成后的回调函数到ADC调度队列中

输入参数:adc_sche_id—要添加ADC的逻辑id; (*mea_complete)(kal_uint8 adc_sche_id)—ADC读取完成后的要调用的函数;mea_Callback—读取ADC值的函数

输出:无

 

void adc_sche_modify_parameters(

kal_uint8 adc_sche_id,

kal_uint32 period,

kal_uint8 evaluate_count)

函数功能:修改一个ADC的读取时间间隔和次数

输入参数:adc_sche_id—要改变的ADC逻辑id; period—修改后的读取时间间隔;evaluate_count—修改后的读取次数

返回:无

 

void adc_sche_remove_item(kal_uint8 adc_sche_id)

函数功能:从ADC调度队列中删除一个ADC通道

输入参数:要删除的ADC逻辑id

输出:无

 

 

显示电池电量和工程模式中查看电池电压所用ADC测量函数:

void adc_sche_measure(void* msg_ptr)

void adc_sche_readback(void* msg_ptr)

 

充电时检查四个ADC值(vbat, visense, vtemp, vcharger)的测量函数:

void bmt_adc_sche_measure(void* msg_ptr)

void bmt_adc_sche_readback(void* msg_ptr)

 

最底层的读取函数为:data=DRV_Reg(AUXADC_DAT(sel))

Sel要读取的通道值,AUXADC_DAT(sel)转换成存放该通道ADC值对应的寄存器地址,DRV_Reg()读出寄存器里面的值。

 

kal_uint16 ADC_GetData(kal_uint8 sel)

传入参数:sel—读取的通道

返回值:该通道的ADC值

 

专门给META用的两个读取ADC值函数:

kal_uint32 ADC_GetMeaData(kal_uint8 sel, kal_uint16 meacount)

输入参数:sel—要读取的ADC通道;meacount—要读取的次数

返回值:  该通道的ADC平均值

:此函数只能在其他任务执行前调用

 

kal_uint32 ADC_GetData2Meta(kal_uint8 sel, kal_uint16 meacount)

输入参数:sel—要读取的ADC通道;meacount—要读取的次数

返回值:  该通道所读次数的的ADC值总和

:此函数只能被META调用,否则会引起死机

 

11.ADC调度器的成员变量

adc_parameters[adc_id] ownerid 创建该ADC的模块
period 检测时间间隔
Adc_phy_id 物理通道编号
Adc_logic_id 逻辑通道编号
Evaluate_count 检测多少次再取一次平均
Send_primitive 是否启用消息机制添加或修改
Conti_measure 继续检测的标志变量
Adc_sche_event_id 调度事件编号
*Complete function 检测完成后调度的函数

 

adc_sche_sum[adc_id] 几次测量的累加值
adc_sche_count[adc_id] 该逻辑id检测的次数

 

adc_reg_status 每个逻辑id占一位,用0,1来标记该ADC通道的可读写状态

 

在调度adc_sche_create_object()时以上的成员被创建

调度adc_sche_modify_parameters()可修改period,Evaluate_count的值

adc_sche_add_item()时,给adc_reg_status的adc_id位置1,表示允许读写;Conti_measure置1,让*Complete指向具体的函数,adc_sche_sum[adc_id]和adc_sche_count[adc_id]清零。

adc_sche_remove_item()则是都进行跟adc_sche_add_item()相反的操作

版权声明:本文内容由互联网用户贡献,该文观点仅代表作者本人。本站不拥有所有权,不承担相关法律责任。如发现有侵权/违规的内容, 联系QQ1841324605,本站将立刻清除。

发表评论

您的电子邮箱地址不会被公开。 必填项已用*标注

联系我们

服务热线:130-0886-1890

QR code