高通ADC
adc dtsi中的属性配置详解:
qcom,pre-scaling的缩放的比例是1:1还是1:3主要和要读取的电压值范围有关系,如果参考电压为1.8V,需要读取的电压范围超过1.8V,那么就要选择1:3的adc通道,这样adc可读取的电压范围就变为0~5.4V
在adc通道选择时,高通主要分为四类通道:无内部上拉,上拉30K、上拉100K、上拉400K电阻。
怎样去选择这几种类型的adc通道呢?
- 读电压一般选择无内部上拉
- 读电流或者温度会选择上拉,上拉电阻的大小和外部下拉的电阻大小有关。
- 注意,经实际示波器抓adc信号,当配置adc通道为内部上拉时,万用表是量不出adc电压的,可能为了省电,这个adc信号是个脉冲,不是一个直流电平信号。
内部上拉的目的是给电路供电,在读温度时,adc外部接的NTC电阻,大概的原理图如下:
NTC电阻的阻值随着温度的变化而变化,所以NTC电阻的分压也会产生变化。
NTC电阻阻值和温度对照表
软件中的对应表:qcom-vadc-common.c
软件会进行计算出NTC电阻的分压,公式为:
1 | (ADC code * vref_vadc (1.875V)) / full_scale_code |
并通过对应表,读出相应的温度:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | static int qcom_vadc_scale_hw_calib_therm( const struct vadc_prescale_ratio *prescale, const struct adc_data *data, u16 adc_code, int *result_mdec) { s64 voltage = 0, result = 0; int ret; if (adc_code > VADC5_MAX_CODE) adc_code = 0; /* (ADC code * vref_vadc (1.875V)) / full_scale_code */ voltage = (s64) adc_code * ADC_HC_VDD_REF * 1000; voltage = div64_s64(voltage, (data->full_scale_code_volt * 1000)); ret = qcom_vadc_map_voltage_temp(adcmap_100k_104ef_104fb_1875_vref, ARRAY_SIZE(adcmap_100k_104ef_104fb_1875_vref), voltage, &result); if (ret) return ret; *result_mdec = result; return 0; } |
adcmap_100k_104ef_104fb_1875_vref表对应的是100k上拉和SCALE_HW_CALIB_XOTHERM
1 2 3 4 | case SCALE_HW_CALIB_THERM_100K_PULLUP: case SCALE_HW_CALIB_XOTHERM: return qcom_vadc_scale_hw_calib_therm(prescale, data, adc_code, result); |
由下面代码可知此adc的分辨率为0x70e4
1 2 3 4 5 6 7 8 9 | const struct adc_data data_pmic5 = { .full_scale_code_volt = 0x70e4, /* On PM8150B, IBAT LSB = 10A/32767 */ .full_scale_code_cur = 10000, .adc_chans = adc_chans_pmic5, .decimation = (unsigned int []) {250, 420, 840}, .hw_settle = (unsigned int []) {15, 100, 200, 300, 400, 500, 600, 700, 800, 900, 1, 2, 4, 6, 8, 10}, }; |
adc读出来的电压计算公式:
实际电压/1.875=raw值(adc值)/0x70e4(10进制为28900)。
驱动中添加ADC通道是的注意点:
这个ADC5_CHAN_VOLT的第二个参数为选择的分频系数,具体是按照下面这个表选择的,如果是1:1,则为0,其它的同理。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | static const struct vadc_prescale_ratio adc5_prescale_ratios[] = { {.num = 1, .den = 1}, {.num = 1, .den = 3}, {.num = 1, .den = 4}, {.num = 1, .den = 6}, {.num = 1, .den = 20}, {.num = 1, .den = 8}, {.num = 10, .den = 81}, {.num = 1, .den = 10}, {.num = 1, .den = 16}, {.num = 40, .den = 41}, /* PM7_SMB_TEMP */ /* Prescale ratios for current channels below */ {.num = 32, .den = 100}, /* IIN_FB, IIN_SMB */ {.num = 16, .den = 100}, /* ICHG_SMB */ {.num = 1280, .den = 4100}, /* IIN_SMB_new */ {.num = 640, .den = 4100}, /* ICHG_SMB_new */ {.num = 1000, .den = 305185}, /* ICHG_FB */ {.num = 1000, .den = 610370}, /* ICHG_FB_2X */ {.num = 1000, .den = 366220}, /* ICHG_FB ADC5_GEN3 */ {.num = 1000, .den = 732440} /* ICHG_FB_2X ADC5_GEN3 */ }; |
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 别再用vector<bool>了!Google高级工程师:这可能是STL最大的设计失误
· 单元测试从入门到精通
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 上周热点回顾(3.3-3.9)