第一:我从一个由于时间限制无法完成它的人那里继承了这个项目。
该代码包含100多个声明的数组,每个数组包含一组INT。这些阵列都是独一无二的。
byte arr_foo[] = {2, 5, 6, 8, 3};
byte arr_bar[] = {1, 7};
byte arr_baz[] = {6, 10, 9, 11, 7, 8, 3};
这些INT与电路板上的特定LED有关 - 总共有11个。并且阵列代表这些LED应该点亮的特定序列。
他们试图做的是编写一个例程,当给定一个数组名称时,该例程将获取该数组的内容并处理INT。好吧,将数组名称作为字符串传递然后与变量匹配不起作用。这就是他们传递的地方,说他们没时间搞清楚。
所以我正在考虑这个并想,为什么不是一个二维数组呢?我很快就遇到了麻烦。
byte seqs[][7] = {
{2, 5, 6, 8, 3},
{1, 7},
{6, 10, 9, 11, 7, 8, 3}
}
虽然原则上这是有效的,但这里的问题是它用尾随零填充每个数组,因为我告诉它每个都有[7]元素。这会导致浪费大量内存并耗尽内存。
所以我被困住了。我不知道如何处理100多个单独的数组,除了编写100多个单独的例程以便稍后调用。我也无法弄清楚如何提高效率。
然后是问题,随着更多序列的添加,我可能会在以后耗尽内存。那么什么呢?添加一个外部i2c闪存,并在那里推送东西?从来没有处理过这个问题,我不知道如何实现它,以什么格式存储值,以及如何实现它。我是否正确,必须首先编写一个程序,将所有数据加载到内存中,上传并运行它,然后将实际程序放在微控制器上处理该数据?
所以我想我要求两件事:处理大量(小)数组的更好方法是什么,并且能够在调用它们的例程中使用它们,如果我最好将这些数据推送到外部闪存,它们应该以什么格式存储?
将数据放入2D阵列根本不会节省任何空间。
现在,您将这些值存储到2k的SRAM中。更改这些声明以使用PROGMEM关键字,因此它们存储在有更多空间的地方。
使用PROGMEM指示编译器将此数据加载到内存的闪存部分:
const PROGMEM uint8_t arr_foo[] = { 2, 5, 6, 8, 3 };
但是,需要通过函数调用访问数据,您不能直接使用它。
for (byte k = 0; k < 5; k++)
{
uint8_t next_led = pgm_read_byte_near( arr_foo + k );
// Do something with next_led
}
如果这些阵列形成一个应该点亮的LED模式,而其他阵列被关闭,你可以将所有LED的状态存储在uint16_t
中,并在PROGMEM
中有一个数组。 (如Kingsley的回答)
如果您不熟悉HEX表示法,可以使用二进制格式。
const PROGMEM uint_16_t patterns[] = {
// BA9876543210 Led Pins
0b000101101100, //foo: 2, 5, 6, 8, 3
0b000010000010, //bar: 1, 7
0b111111001000, //baz: 6, 10, 9, 11, 7, 8, 3
// ...
};
我想知道你的数字的顺序,所以我不确定这个猜测是否正确。所以现在没有更多细节如何使用这种方法
对我而言,您的意见完全改变了您的问题的意图。
正如我现在读到的那样,不需要一种特殊的“名称”数据来识别数组。你想要的似乎只是将不同的数组作为函数参数传递。
这通常是通过指针完成的,有两点需要注意:
例:
如果要将T
类型的元素数组传递给函数,可以声明函数接受指向T
的指针:
void somefunc(uint8_t* arr, uint8_t arrLength) {
for ( uint8_t i = 0; i < arrLength; i++ ) {
uint8_t value = arr[i];
value = *(arr+i); // equivalent to arr[i]
}
}
或者等价的
void somefunc(uint8_t arr[], uint8_t arrLength) {
...
}
然后通过简单地传递数组变量和相应的数组长度来调用该函数
uint8_t arr_foo[] = { 1,2,3,4,5 };
uint8_t arr_bar[] = { 1,2 };
somefunc(arr_foo,5);
somefunc(arr_bar,2);
数组的常量数据可以放入PROGMEM
以节省RAM,但正如其他人所说,读取访问稍微复杂一些,需要用C ++调用pgm_read_...()
。 (AVR gcc仅支持C中的__flash
-qualified数据,而不支持C ++。)
然后是问题,随着更多序列的添加,我可能会在以后耗尽内存。
请注意,“Arduino”AVR具有32kb的闪存。如果每个序列消耗15个字节,它可能仍然可以保存1000或2000个这些项目以及您的程序。
什么呢?添加一个外部i2c闪存,并在那里推送东西?从来没有处理过这个问题,我不知道如何实现它,以什么格式存储值,以及如何实现它。
如果在某些时候实际上用完了闪存,你仍然可以使用任何形式的外部存储。
一种常见的解决方案是SPI闪存,它可以在兆位范围内使用。 Winbond是一家知名供应商。只需搜索“Arduino SPI flash”模块和库。
更复杂的方法是支持SD卡作为外部存储器。但除非你真的想存储千兆字节的数据,否则可能不值得。
我是否正确,必须首先编写一个程序,将所有数据加载到内存中,上传并运行它,然后将实际程序放在微控制器上处理该数据?
这绝对是一种方法。如果您的代码空间允许,您可以选择在应用程序中包含写入外部闪存的例程,例如某种引导加载程序,这样您就可以切换到“上传外部闪存数据”模式而无需重新刷新微控制器。