【问题标题】:What is the fastest way to do division in C for 8bit MCUs?对于 8 位 MCU,用 C 语言进行除法的最快方法是什么?
【发布时间】:2010-04-30 13:46:20
【问题描述】:

我正在为使用 8 位 mcu(8051 架构)的设备开发固件。我正在使用 SDCC(小型设备 C 编译器)。我有一个功能,用于设置我的电路驱动的步进电机的速度。通过将所需值加载到定时器的重载寄存器中来设置速度。我有一个变量 MotorSpeed,它在 0 到 1200 的范围内,表示电机每秒的脉冲数。我将 MotorSpeed 转换为正确的 16 位重载值的函数如下所示。我知道浮点运算非常慢,我想知道是否有更快的方法来做到这一点......

void SetSpeed()
{
    float t = MotorSpeed;
    unsigned int j = 0;
    t = 1/t ;
    t = t / 0.000001;
    j = MaxInt - t;
    TMR3RL = j;      // Set reload register for desired freq
    return;
}

【问题讨论】:

  • 它真的在 0 到 1200 的范围内吗?您当前的代码似乎会遇到除以零的问题。

标签: c binary division 8051


【解决方案1】:

如果我理解正确的话你想计算表达式

MaxInt - 1000000/MotorSpeed

其中 MotorSpeed 是 0 到 1200 之间的数字,表示每秒的脉冲数。

如果您的编译器支持浮点运算,则它必须支持整数除法。你为什么不试试呢。如果速度 > 15 没有问题,但对于 0 到 15 范围内的速度,结果是否定的。这意味着,如果计数器为 16 位宽并且以 1MHz 的速率递增,则根本不可能生成频率低于 16Hz 的脉冲。您是否有额外的预分频器可以减少增量频率? (我不知道 8051)。

【讨论】:

  • 这似乎是最直接的方法。对于MotorSpeed < 16,设置TMR3RL = 0。对于所有其他输入值,这只需要一个整数除法和一个减法,这应该非常快(将除法的结果转换为 16 位数字也可以加快代码速度)。 8051 只有 8 位 ALU 寄存器,因此编译器必须提供额外的代码来处理 16 位或更大数字的算术运算。有人提到的“乘以 65536”方法至少需要 32 位算术,由于需要所有额外的代码,这会慢得多。
  • 这对我来说似乎是正确的答案 - 需要除法,但不需要浮点除法。如果您想将所有计算保持在 16 位值内,但以电机速度非常慢的精度为代价,您可以使用MaxInt - 65449 / ((MotorSpeed * 43 + 328) / 657)(还需要 bta 对MotorSpeed < 16 的建议测试,以避免被零除)。
【解决方案2】:

经典的方法是使用定点,在除法之前按比例放大,并将其全部作为整数。

j = (MotorSpeed * 65536) / 1200;

这仍然需要实际除法(除以 1200),但至少它是全整数。缩放应该非常快,因为可以使用移位来实现。

【讨论】:

  • 对不起,为什么要除以 1200?
  • @Jordan S:因为你说变量的值在 0..1200 范围内。您想要的是 (MotorSpeed/1200) * 65536,但您不能将第一项评估为 int。
  • 如果我正确理解了计时器的工作原理,它会将寄存器递增到 65535,然后,它不会溢出到 0,而是加载 Jordan 尝试计算的初始值并进一步递增。如果我正确理解常数 0.000001,则寄存器以 1 MHz 的速率递增
  • 猜测一下,这会将 65K 归一化为“最大值”,然后整数除以得到小数部分?
【解决方案3】:

关于固定点展开是正确的。

我在 8051 上为 SDCC 编写了一个使用 32 位数字的固定库。只需确定您想要的分数精度,然后对这些值应用适当的偏移即可。

例如,我的定点库使用 2 个字节作为小数空间。

所以每个数字 x 都表示为x * 65535。您可以使用普通的有符号长加减法。

对于乘法和除法,您需要调整偏移量。简单的乘法会得到(x * 65535) * (y * 65535)。只需分解并计算出每个数字部分的偏移量,然后将它们全部加起来。

只需将您的定点数分解为字节或 16 位整数,然后分段处理。

看看this article on embedded.com

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-09-16
    • 1970-01-01
    • 1970-01-01
    • 2017-04-16
    • 2020-04-07
    • 2012-04-12
    • 1970-01-01
    相关资源
    最近更新 更多