我最近遇到了一个问题,使用便宜的 16 位 uC(MSP430 系列),我必须根据 10 位 ADC 读取生成一个对数间隔的输出值。这样做的原因是我需要在整数空间的低端进行细粒度控制,同时需要使用较大的值,尽管精度较低,(对我来说,2^15 之间的差异我的反馈循环中的 2^16 影响不大)。我以前从未这样做过,也没有运气在网上找到示例,所以我想出了一个小方案来在我的操作受限的 uC 上执行此操作。
使用我这里的方法,ADC 结果仅通过整数乘法/加法/求和和按位移位在两个最接近的整数二次幂之间进行线性插值(如下所述)。
我的问题是,有没有比这更好的(更快/更少的操作)方法来生成一个平滑的(或平滑的)数据集,在整数分辨率上对数间隔?我没有在网上找到任何东西,因此我首先尝试从头开始。
N 是微控制器的对数分辨率,(这里假设为 16 位)。M 是 ADC 的整数分辨率(这里假设为 10 位)。ADC_READ 是 ADC 在给定时间读取的值。在支持浮点运算的 uC 上,这样做很简单:
x = N / M #16/1024
y = (float) ADC_READ / M #ADC_READ/1024
result = 2 ^ ( x * y )
在下面的所有图中,这是一组“理想”值。“结果”值由以下变量生成:
unsigned int returnValue( adcRead ){
unsigned int e;
unsigned int a;
unsigned int rise;
unsigned int base;
unsigned int xoffset;
unsigned int yoffset;
e = adcRead >> 6;
a = 1 << e;
rise = ( 1 << (e + 1) ) - ( 1 << e );
base = e << 6;
xoffset = adcRead - base;
yoffset = ( rise >> rise_shift ) * (xoffset >> offset_shift); //this is an operation to prevent rolling over. rise_shift + offset_shift = M/N, here = 6
result = a + yoffset;
return result;
}
额外的声明和什么不是为了可读性。假设最终产品是浓缩的。基本上,它按预期进行,根据rise_shift 和offset_shift 的值,在低端具有不同程度的离散化,在高端具有不同程度的平滑度。在这里,它们都等于 3: 这里rise_shift = 2,offset_shift = 4 这里rise_shift = 4,offset_shift = 2 我有兴趣看看是否有人提出或知道更好的方法。目前,我只需要每秒运行大约 20-30 次这段代码,所以我显然没有遇到任何延迟。但是,使用 16MHz 时钟并使用此处的信息,我估计整个操作最多需要 ~110 个时钟周期,或 ~7us。这是 ADC 读取时间的比例,约为 4us。
谢谢
编辑:“更好”我并不一定意味着更快,(显然已经相当快了)。立即,人们看到低端具有相当大的离散化到 2 的整数次方,这是为了防止滚动的移位操作造成的。除了查找表(建议如下)之外,如何改进这一点的答案并不是立竿见影的。