对于 8 位 MCU,用 C 语言进行除法运算最快的方法是什么?
我正在为使用 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;
}
I am working on the firmware for a device that uses an 8bit mcu (8051 architecture). I am using SDCC (Small Device C Compiler). I have a function that I use to set the speed of a stepper motor that my circuit is driving. The speed is set by loading a desired value into the reload register for a timer. I have a variable, MotorSpeed that is in the range of 0 to 1200 which represents pulses per second to the motor. My function to convert MotorSpeed to the correct 16bit reload value is shown below. I know that float point operations are pretty slow and I am wondering if there is a faster way of doing this...
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;
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
如果我理解正确的话,您想要计算表达式
,其中 MotorSpeed 是 0 到 1200 之间的数字,表示每秒的脉冲数。
如果您的编译器支持浮点运算,它必须支持整数除法。你为什么不尝试一下呢。如果速度> 15 没有问题,但对于 0 到 15 范围内的速度,结果为负。这意味着如果计数器是 16 位宽并且以 1MHz 的速率递增,则根本不可能生成频率低于 16 Hz 的脉冲。您是否有额外的预分频器可以降低增量频率? (我不知道8051)。
If I understand correctly what's going on You want to calculate the expression
where MotorSpeed is a number form 0 to 1200 and represents number of pulses per second.
If Your compiler supports floating point arithmetic it must support integer division. Why don't You try that. If the speed is > 15 There is no problem, but for speeds in the range 0 to 15 the result is negative. It means that it's simply impossible to generate pulses with lower frequency than 16 Hz, if the counter is 16 bit wide and it's incremented at the rate of 1MHz. Do you have an additional prescaler that allows to reduce the frequency of increments? (I don't know 8051).
经典的方法是使用定点,在除法之前按比例放大,并将其全部作为整数进行。
这仍然需要实际除法(除以 1200),但至少是全整数。缩放应该非常快,因为可以使用移位来实现。
The classic way is to use fixed-point, by scaling up before dividing, and doing it all as integer.
This still requires actual division (by 1200), but at least it's all-integer. The scaling should be very quick, since it's possible to implement using a shift.
unwind 关于定点是正确的。
我在 8051 上为 SDCC 编写了一个使用 32 位数字的固定库。只需确定您想要的分数精度,并对值应用适当的移位即可。
例如,我的定点库使用 2 个字节作为小数空间。
因此每个数字 x 都表示为
x * 65535
。您可以使用正常的有符号长加法和减法。对于乘法和除法,您需要调整偏移量。简单的乘法将得到
(x * 65535) * (y * 65535)
。只需分解并分解出数字每个部分的偏移量并将它们全部相加即可。只需将定点数分解为字节或 16 位整数,然后分段处理它们即可。
请查看embedded.com 上的这篇文章。
unwind is right about fixed point.
I wrote a fixed library for SDCC on the 8051 that uses 32 bit numbers. Simply determine what precision you want in your fractions and apply the appropriate shift to the values.
For example, my fixed point library uses 2 bytes for fractional space.
So each number x is represented as
x * 65535
. You can use normal signed long addition and subraction.For multiplication and division you need to adjust for the offset. Simple multiplication would give
(x * 65535) * (y * 65535)
. Just break up and factor out the offset for each part of the numbers and add them all up.Just break up your fixed point number into bytes or 16 bit ints and work on them in pieces.
Take a look at this article on embedded.com.