AVR 的高效逆 (1/x)

电器工程 avr 算术除法
2022-01-06 09:10:20

我试图找到一种有效的方法来计算 AVR 的逆(或近似)。

我正在尝试计算步进电机的脉冲周期,以便可以线性改变速度。周期与速度( )的倒数成正比p = K/v,但我想不出一种即时计算的好方法。

我的公式是

p = 202/v + 298; // p in us; v varies from 1->100

在 Arduino 上进行测试,该除法似乎完全被忽略了,保持p固定不变298(尽管在 avr-gcc 中可能会有所不同)。我也尝试过v在一个循环中求和,直到它超过202,并计算循环,但这很慢。

我可以生成一个查找表并将其存储在闪存中,但我想知道是否还有其他方法。

编辑:也许标题应该是“有效划分”......

更新:正如 pingswept 指出的那样,我将周期映射到速度的公式不正确。但主要问题是除法运算。

编辑 2:在进一步调查中,divide 正在处理 arduino,问题是由于上面的公式不正确和其他地方的 int 溢出。

4个回答

关于除法的一件好事是,或多或少每个人都在这样做。这是 C 语言的一个非常核心的特性,即使微控制器没有硬件除法指令,像 AVR-GCC(由 Arduino IDE 调用)这样的编译器也会选择可用的最佳除法算法。

换句话说,你不需要担心除法是如何实现的,除非你有一个非常奇怪的特殊情况。


如果您确实担心,那么您可能会喜欢阅读 Atmel 官方建议的除法算法(一种针对代码大小进行了优化,另一种针对执行速度进行了优化;既不占用任何数据存储器)。他们在:

http://www.atmel.com/dyn/resources/prod_documents/doc0936.pdf

这是 Atmel 页面上列出的应用说明“AVR200:乘除例程”,用于其(相当大的)Atmega 处理器,如标准 Arduinos 中使用的 Atmega 168 和 Atmega 328。数据表和应用笔记列表位于:

http://www.atmel.com/dyn/products/product_card.asp?part_id=4720

在我看来,您所需要的只是一个 100 条目的查找表。没有比这更快的了。

#define VALUE_FOR_V_EQUALS_ZERO 0
uint16_t formula_lookup[100] = {VALUE_FOR_V_EQUALS_ZERO, 500, 399, 365, 348, ..., 300};

...

//"calculate" formula
p = formula_lookup[v > 67 ? 67 : v];

编辑你实际上只有一个 68 值的查找表,因为大于 67 的 v 值总是评估为 300。

Henry Warren所著的“Hackers Delight”一书和他的网站hackersdelight.org中提到了一些非常好的技术。有关在除以常数时适用于较小微控制器的技术,请查看此文件

您的功能似乎不会给出您想要的结果。例如,值 50 返回大约 302,而 100 返回大约 300。这两个结果几乎不会导致电机速度发生变化。

如果我对您的理解正确,您确实在寻找一种将数字 1-100 映射到 300-500(大约)范围的快速方法,例如 1 映射到 500 和 100 映射到 300。

也许尝试:p = 500 - (2 * v)

但我可能会误解——你是在计算恒定频率方波的导通时间吗?什么是298?