在嵌入式(PIC)环境中工作,使用c。
进行编程我必须跟踪变量(历史记录)的1000个值并返回这些值的移动平均值。我只是想知道如果我使用数组或1000个16位变量,它在速度,ROM和RAM使用方面是否更有效。对此有一个不同的答案吗?或者我必须尝试两者并看看哪种方法效果最好?
感谢。
编辑: 嗯......我已经遇到了另一个问题。编译器将我限制为最大值为256的数组。
EDIT2:
为了澄清......代码每秒发射大约1000次。每次计算并存储history [n](或history_n)的值。每次我需要计算1000个最近历史值(包括当前值)的平均值。所以(history[1000] + history[999] + ... + history[1] + history[0]) / 1000;
或其他相似之处。显然,每次我需要踢出最老的并添加最新的。
EDIT3:
我重新编写代码,现在256个数组大小不是问题。现在大约100的样本大小是合适的。
答案 0 :(得分:4)
假设你需要保留历史记录,并给出256元素数组限制,这是一种管理它的方法:
int history1[256];
int history2[256];
int history3[256];
int history4[256];
int* arrays[] = {history1,history2,history3,history4}
int idx=0;
int sum = 0;
int n = 0;
int updateAverage(int newValue)
{
int ai = (idx++)>>8;
int* target = arrays[ai]+(idx&0xFF);
sum -=*target;
*target = newValue;
sum += *target;
n++;
n=n<1000?n:1000;
idx = (idx<1000)?idx:0;
return sum/n;
}
答案 1 :(得分:2)
我不确定我是否完全理解你的问题。您是否要求为“短历史[1000]”和“简历1,历史2,...,历史1000;”生成的代码之间存在差异?
两者都应使用相似数量的RAM:每个条目将存储在单个文件寄存器中(假设您使用的是16位PIC)。计算后者平均值的代码虽然很难看,但可能需要相当多的ROM,因为它需要单独引用每个值(而不是仅仅偏移基数)。
编辑: 256元素限制的原因是因为PIC上的文件寄存器分页。只能通过偏移基址寄存器来处理更大的数组,因为您可能需要请求更改页面。
你绝对需要计算一个平均值吗?或者你可以做一个整体平均值?如果整体平均值没问题,那么使用Alphaneo答案的变体:只需保留总和,以及在两个变量中收集的值的数量,并在需要平均值时划分。
答案 2 :(得分:1)
如果使用数组,生成的代码将会小得多。我不确定这个,但我认为数组访问会使用更少的内存,因为你不必跟踪多个变量,你只需要指向一个Chunk的指针。如果您的堆栈大小是个问题,那么堆上的Array可能是最好的方法,因为C变量存储在堆栈中。
答案 3 :(得分:1)
如果您想通过将其存储在数组中来计算平均值,那么肯定比在运行时计算更昂贵。
原因-1:如果您在运行时计算它,您将继续添加例如查看以下流程
init-0: _tempSum_ = 0
step-1: Read current value to _currVal_
step-2: Add current value to _tempSum_
step-3: Check if we have required of values _num_ (eg. 1000), if not goto-1
step-4: Calculate _avg_ = _tempSum_ / _num_ and return
step-5: goto init-0
如果存储在1000个值的临时数组中,实际上你将完成从init-0到步骤5的所有步骤,除了你最终将使用1000值数组。
根据阵列访问时间可能会慢一点......所以要小心
答案 4 :(得分:1)
首先,您可以更改链接器文件以允许更大的部分。然后,您必须使用编译指示将历史数组放在该部分中。
其次,数组方法要好得多。要提高性能,还需要一个32位整数来保持历史数组的运行总和。
对于历史记录功能的每次触发,您将从HistoryRunningTotal中减去最旧的值并添加新的历史记录值。您还需要一个OldestHistoryIndex变量来跟踪最新值的位置(并覆盖旧历史记录)。
答案 5 :(得分:0)
如果你有1000个值的足够内存,那么为什么不静态分配内存,制作一个旋转缓冲区并移动一个指针来计算总和。 (如果运行的平均值不是你需要的)。只需继续将新值放在最旧的值上,计算1000个值的总和除以1000.实际上有两个指针,一个用于插入新值,另一个用于迭代整个缓冲区。
答案 6 :(得分:0)
编译器将数组限制为256?那太糟糕了。这给程序员带来了负担,编译器确实应该照顾它。你确定没有编译器选项,例如一个“大”的记忆模型?如果没有,请研究不同的微观和/或编译器。
或者,为了保持较小,请考虑使用小型IIR滤波器而不是大型FIR滤波器。
无论如何,要回答你原来的问题:数组是这种算法的合理选择,因为它具有合理(可维护)代码和小代码大小的好处。
答案 7 :(得分:0)
如果数组是动态分配的,那么使用静态变量会更快。如果数组是静态分配的,那么编译器应该能够将其优化为与静态变量等效的快速。尝试使用一些简单的代码并对其进行分析。