找回密码
立即注册
搜索
热搜: Java Python Linux Go
发回帖 发新帖

2409

积分

0

好友

321

主题
发表于 1 小时前 | 查看: 3| 回复: 0

在进行嵌入式开发时,我们常常需要对模拟电压进行ADC采样。一个直接的想法是尽量简化ADC采样值换算到真实电压的过程,最好不涉及浮点运算,因为整数乘除法的计算成本相对较低。

原理

对于使用了分压电阻采样输入电压的情形,电路大概是这样:

ADC分压采样电路图

分压比例 $K$ 为:

分压比例K计算公式

ADC换算出来的电压还要再乘 $K$ 才是输入电压。设ADC的参考电压是 $V_{ref}$,分辨率10位,最大值1023,也就是把 $V_{ref}$ 一共分成1023份。那么从ADC值计算输入电压的公式如下:

ADC输入电压计算公式

要简化计算,我们的目标就是把ADC值要乘的系数变成整数,也就是要令:

ADC系数整数化公式

这个结果是整数。需要注意,整体除出来的结果是整数,并不代表里面每个因子都是整数。

选择参考电压

假设单片机供电电压为5V,所以参考电压不能超过5V,最大值就定为4.8V好了。分压比例 $K$ 不变时,参考电压越小,能测量的外部输入电压上限也越小。另外,参考电压越小,那么ADC每一级对应的电压也越小,理论上精度越高,但是对噪声也越敏感。所以参考电压也不能太小,这里随便把最小值定为3.3V。

参考电压可以通过TL431这类基准源产生:

TL431基准电压电路

参考电压的计算公式是:TL431输出电压公式

为了限制一下组合的数量,规定只能用两个电阻设置TL431的电压。那么按照E24数系,R1和 R2 的值只能在这些数字里面选:

    e24 = [1.0, 1.1, 1.2, 1.3, 1.5, 1.6, 1.8, 2.0, 2.2, 2.4, 2.7,
3.0, 3.3, 3.6, 3.9, 4.3, 4.7, 5.1, 5.6, 6.2, 6.8,
7.5, 8.2, 9.1]

限制条件是:最大电压4.8V,最小3.3V。我们可以写个脚本来搜索所有能拿两个电阻组合出来的电压:

# unit 是电压单位对应的放大倍数
def find_v(v_min, v_max, unit):
    print('v, r1, r2')
    v_list = []
    r_min = v_min / 2.5
    r_max = v_max / 2.5
    for r2 in e24:
        for r1 in e24:
            k = (r1 + r2) / r2
            if(k >= r_min and k <= r_max):
                v = 2.5 * k * unit
                print(f'{v}, {r1}, {r2}')
                v_list.append(v)
    return v_list

在计算中,电压的单位选择微伏(μV)。因为如果用V做单位,除非参考电压达到了上千伏,不然除以1023肯定都不是整数。所以 unit 参数用 1e6,运行:

vref = find_v(3.3, 4.8, 1e6)

输出的电压有几百种,用CSV格式,大概是这样:

v, r1, r2
4772727.2727272725, 1.0, 1.1
4583333.333333334, 1.0, 1.2
4791666.666666666, 1.1, 1.2
4423076.923076922, 1.0, 1.3
4615384.615384616, 1.1, 1.3
4166666.666666667, 1.0, 1.5
4333333.333333334, 1.1, 1.5
4500000.0, 1.2, 1.5
4666666.666666666, 1.3, 1.5
4062500.0, 1.0, 1.6
4218750.0, 1.1, 1.6
4374999.999999999, 1.2, 1.6
4531250.000000001, 1.3, 1.6
3888888.8888888885, 1.0, 1.8
4027777.7777777775, 1.1, 1.8
4166666.666666666, 1.2, 1.8
4305555.555555555, 1.3, 1.8
4583333.333333333, 1.5, 1.8
4722222.222222222, 1.6, 1.8
3750000.0, 1.0, 2.0
...

里面可能有重复的,但是不影响,之后要综合分压比例 $K$,从里面选一个。

选择分压电阻

分压电阻的选择也有限制,就是分压比例不能太大。很简单,太大的话输入到ADC的电压太低,测量精度下降。预定输入电压最大30V左右,所以分压比例定为6倍以上,在满足输入电压范围的前提下越小越好。

分压比例大于2,R2肯定大于下拉电阻R1,R2的值可以比R1大一个数量级。比如,若 $K = 10$$R1 = 1k$,那么 $R2$$10k$,所以 $R2$ 的取值范围要增加一倍。

bigger = e24 + [r * 10 for r in e24]

bigger$R2$ 的取值范围。然后再写一段脚本,暴力搜索两个分压电阻和参考电压的组合,让公式(3)的结果 $d$ 是整数:

def find_k(vref_list):
    print('k, r1, r2, d, vref')
    for r2 in e24:
        for r1 in bigger:
            if(r1 < r2):
                continue

            k = (r1 + r2) / r2
            for v in vref_list:
                d = v * k / (2**10-1)
                if(abs(int(d)- d)<1e-8):
                    print(f'{k}, {r1}, {r2}, {int(d)}, {v}')

运行:

find_k(vref)

这下满足要求的结果就不太多了:

k, r2, r1, d, vref
6.6, 5.6, 1.0, 25000, 3875000.0
31.0, 30.0, 1.0, 125000, 4125000.0
31.0, 30.0, 1.0, 100000, 3300000.0000000005
31.0, 33.0, 1.1, 125000, 4125000.0
31.0, 33.0, 1.1, 100000, 3300000.0000000005
31.000000000000004, 36.0, 1.2, 125000, 4125000.0
31.000000000000004, 36.0, 1.2, 100000, 3300000.0000000005
30.999999999999996, 39.0, 1.3, 100000, 3300000.0000000005
46.5, 91.0, 2.0, 187500, 4125000.0
46.5, 91.0, 2.0, 150000, 3300000.0000000005
4.125, 7.5, 2.4, 15625, 3875000.0
6.2, 39.0, 7.5, 25000, 4125000.0
6.2, 39.0, 7.5, 20000, 3300000.0000000005

一共就上面这些。从第一列开始,k 是分压比例;r2r1 是对应的电阻取值;d 是ADC要乘的系数,单位是微伏;vref 是选中的参考电压。运气不错,刚好有很接近6的比值:

k, r2, r1, d, vref
6.6, 5.6, 1.0, 25000, 3875000.0
6.2, 39.0, 7.5, 25000, 4125000.0

第一组参考电压3.875V,分压比例6.6,ADC系数是25mV,也就是ADC每一级对应的输入电压是25mV。第二组参考电压4.125V,比例6.2,ADC系数相同。虽然第二组似乎更理想,分压比例更接近6,但是我选择了第一组。有两点原因:

  1. 第二组两个电阻都是不太常用的值,第一组里的1kΩ很常用;
  2. 第二组里的39kΩ电阻感觉有点大了,可能会影响ADC采样速度;

如果考虑上两个电阻串联、并联当一个电阻用的情况,组合的规模估计会增加好几个数量级,有可能过滤出全部由常用阻值构成的组合,这里就不进一步展开了。顺便一提,对应3.875V,TL431的两个电阻分别是1.1kΩ和2.0kΩ。

缺点

这么设计能够成功的前提是电阻和参考电压的精度都比较高,所以程序里可以直接用25mV作为理想值来计算;或者测量精度要求不高,但也不那么低。如果项目后期需要引入外部高精度基准电压来校准ADC系数,那么前期的这番整数化优化就失去了意义,反而可能带来限制。在云栈社区的技术讨论中,我们经常需要在系统设计的早期就在性能、成本和复杂度之间做出权衡。




上一篇:cmux:专为 AI 编码打造的开源 macOS 终端,用垂直标签告别混乱
下一篇:硬件研发总监如何系统化推进核心技术攻关:全流程指南与实践模板
您需要登录后才可以回帖 登录 | 立即注册

手机版|小黑屋|网站地图|云栈社区 ( 苏ICP备2022046150号-2 )

GMT+8, 2026-3-27 04:53 , Processed in 0.517506 second(s), 41 queries , Gzip On.

Powered by Discuz! X3.5

© 2025-2026 云栈社区.

快速回复 返回顶部 返回列表