代码之家  ›  专栏  ›  技术社区  ›  jcoder

基于8bit单片机的线性插值

  •  9
  • jcoder  · 技术社区  · 16 年前

    我需要用pic汇编语言在8位pic微控制器(特别是16f627a,但这不重要)上的两个值之间进行线性插值。尽管我在这里寻找的算法和实际的代码一样多。

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

    现在PIC没有一个除法指令,所以我可以编码一个通用的除法程序,并有效地计算(B-A)/(X/255)+A在每一步,但我觉得可能有一个更好的方式,这样做的微控制器比我在PC上这样做的方式。

    有人对在这个硬件上有效地实现这个有什么建议吗?

    6 回复  |  直到 16 年前
        1
  •  7
  •   Eric Bainville    16 年前

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

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

        2
  •  2
  •   Mads Elvheim    16 年前

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

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

    听起来是个坏主意。如果使用基255作为定点表示,则会得到两次相同的插值。当x=255时得到b,当x=0时得到新的a。

    使用256作为定点系统。除法变为移位,但需要16位算术运算和8×8乘法运算以及16位结果。上一个问题可以通过简单地忽略较高字节中的任何位来解决 x mod 256 变成0。此建议使用16位乘法,但不能溢出。你不能在同一个x上插值两次。

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

    256 - x 当你得到 0 - x .

    pic的指令集中缺少这些操作:

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

    您可以使用rotate right来进行右移,然后使用按位和来屏蔽左侧多余的位。用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;
        }
    }
    
        3
  •  1
  •   GDR    16 年前

    你可以用8.8定点算法来做。然后0到255之间的数字将被解释为0.0…0.996,您就可以对其进行乘法和规格化。

    告诉我你是否需要更多的细节或者是否足够开始。

        4
  •  1
  •   Ira Baxter    16 年前

    您可以将其描述为:

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

    使用x=0..255的值范围,将256/(x+1)的值作为表中的定点数预计算,然后对通用乘法进行编码,调整二进制点的位置。这可能不是很小的空格;我希望您需要一个包含16位值和乘法代码的256条目表。(如果你不需要速度,这表明你的除法是好的。)但只需要一个乘法和一个加法。

    我的猜测是,你不需要所有可能的x值。如果只有几个x值,你可以离线计算它们,对x的特定值做一个case选择,然后按照固定的移位序列和x的特定值的加法来实现乘法。这很可能是代码效率很高,拍照速度也很快。

        5
  •  1
  •   Bill the Lizard    16 年前

    插值

    给定两个值 X 和; Y ,基本上是:

    (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.
    

    实际的代码同样简单。只是我不记得那些登记册和说明书。

        6
  •  1
  •   David Cary    16 年前

    Eric Bainville和Mads Elvheim所描述的技术将运行良好;每个插值使用两个倍数。

    Scott Dattalo和Tony Kubek提出了一种超优化的特定于pic的插值技术,称为“ twist “这比每次插值两倍稍快。

    使用这种难以理解的技术是否值得运行得更快一点?

    推荐文章