9

我需要使用 PIC 汇编语言在 8 位 PIC 微控制器(特别是 16F627A,但没关系)上的两个值之间随时间进行线性插值。尽管我在这里寻找的算法与实际代码一样多。

我需要取一个 8 位起始值、一个 8 位结束值和两者之间的位置(当前表示为 8 位数字 0-255,其中 0 表示输出应该是起始值,255 表示它应该是最终值值,但如果有更好的方法来表示它,那可能会改变)并计算插值。

现在 PIC 没有除法指令,所以我可以编写一个通用除法例程并在每一步有效地计算 (BA)/(x/255)+A,但我觉得可能有更好的方法来做到这一点一个微控制器,而不是我在 C++ 的 PC 上做的方式

有没有人有任何建议可以在这个硬件上有效地实现这个?

4

6 回答 6

7

您正在寻找的价值是(A*(255-x)+B*x)/255. 它只需要 8x8 乘法,最后除以 255,这可以通过简单地取和的高字节来近似。

在 0..128 范围内选择 x,不需要近似值:取(A*(128-x)+B*x)<<1.

于 2010-04-18T08:45:10.553 回答
2

假设您插入一系列值,其中前一个端点是新的起点:

(B-A)/(x/255)+A

听起来是个坏主意。如果您使用以 255 为底的定点表示,您将获得两次相同的插值。当 x=255 时得到 B,当 x=0 时得到 B 作为新的 A。

使用 256 作为定点系统。除法变为移位,但您需要 16 位算术和 16 位结果的 8x8 乘法。前面的问题可以通过简单地忽略高字节中的任何位x mod 256变为 0 来解决。这个建议使用 16 位乘法,但不能溢出。并且您不会在相同的 x 上插值两次。

interp = (a*(256 - x) + b*x) >> 8

256 - x当你得到0 - x.

PIC 在其指令集中缺少这些操作:

  • 左右移位。(逻辑和算术)
  • 任何形式的乘法。

您可以通过使用 rotate-right 来实现右移,然后使用 bitwise-and 屏蔽左侧的额外位。用 16 位结果进行 8x8 乘法的直接方法:

void mul16(
    unsigned char* hi, /* in: operand1, out: the most significant byte */
    unsigned char* lo  /* in: operand2, out: the least significant byte */
)
{
    unsigned char a,b;

    /* loop over the smallest value */
    a = (*hi <= *lo) ? *hi : *lo;
    b = (*hi <= *lo) ? *lo : *hi;
    *hi = *lo = 0;
    while(a){
        *lo+=b;
        if(*lo < b) /* unsigned overflow. Use the carry flag instead.*/
            *hi++;
        --a;
    }
}
于 2010-04-18T11:03:05.917 回答
2

Eric Bainville 和 Mads Elvheim 描述的技术可以正常工作;每个插值使用两个乘法。

Scott Dattalo 和 Tony Kubek 组合了一种超级优化的 PIC 特定插值技术,称为“扭曲”,它比每次插值两次乘法略快。

使用这种难以理解的技术值得跑得快一点吗?

于 2010-05-22T23:37:25.257 回答
1

插值

给定两个值XY,它基本上是:

(X+Y)/2

或者

X/2 + Y/2(防止 A+B 可能溢出寄存器大小的奇怪情况)

因此尝试以下操作:

(伪代码)

Initially A=MAX, B=MIN

Loop {

    Right-Shift A by 1-bit.

    Right-Shift B by 1-bit.

    C = ADD the two results.

    Check MSB of 8-bit interpolation value

    if MSB=0, then B=C

    if MSB=1, then A=C

    Left-Shift 8-bit interpolation value

}Repeat until 8-bit interpolation value becomes zero.

实际的代码同样简单。只有我不记得手头的寄存器和指令。

于 2010-04-18T08:52:19.927 回答
1

您可以使用 8.8 定点算法来做到这一点。然后范围 0..255 中的数字将被解释为 0.0 ... 0.996,您将能够对其进行乘法和归一化。

告诉我您是否需要更多详细信息,或者是否足以让您开始。

于 2010-04-18T08:36:02.253 回答
1

您可以将其描述为:

(B-A)*(256/(x+1))+A

使用 x=0..255 的取值范围,将 256/(x+1) 的值预先计算为表格中的定点数,然后编写通用乘法,调整二进制点的位置。这在空间上可能不小;我希望您需要一个 256 个 16 位值的条目表和乘法代码。(如果您不需要速度,这表明您的划分方法很好。)。但它只需要一次乘法和一次加法。

我的猜测是您不需要 X 的所有可能值。如果只有几个 X 值,您可以离线计算它们,对 X 的特定值进行案例选择,然后根据下式实现乘法固定的移位序列并为 X 的特定值添加。这在代码中可能非常有效,并且对于 PIC 来说非常快。

于 2010-04-18T08:37:44.970 回答