为了测试,我想制作一个尽可能小的草图。问题是,当我编译BareMinimum草图(具有空的设置和循环)时,Uno会得到466个字节,Leonardo会得到4,242个字节。有什么办法可以编写自己的没有额外功能的代码(即millis()
和的Timer0 delay()
)。我还希望能够禁用Leonardo的键盘/鼠标功能。
为了测试,我想制作一个尽可能小的草图。问题是,当我编译BareMinimum草图(具有空的设置和循环)时,Uno会得到466个字节,Leonardo会得到4,242个字节。有什么办法可以编写自己的没有额外功能的代码(即millis()
和的Timer0 delay()
)。我还希望能够禁用Leonardo的键盘/鼠标功能。
Answers:
您应该能够按照https://github.com/arduino/Arduino/wiki/Arduino-IDE-1.5---3rd-party-Hardware-specification使用自定义的board.txt文件创建自己的电路板定义。如我所见,莱昂纳多的定义中有几个USB功能。我希望4K的编译包含基于这些标志而不是处理器类型。
boards.txt将使用上载的地方,Leonardo的引导程序部分以及uno的构建部分。
所有这些都假设核心库构建不使用处理器特定的标志来包含USB功能。
如果得到这样的工作。回发,我相信其他人也会对此感兴趣。
我最近在一个库演示中遇到了这种4K使用限制,该限制实际上使UNO达到极限,必须放入一个
#if !defined(__AVR_ATmega32U4__)
...
草图中的大量额外功能,以适合Leonardo。
我以为(错误的)认为这是4K的原因,是因为当我通过Leo上的USB CDC时,我仍然包含Serial.print。但是我看到一个空草图的内存转储之后它们仍然在那里。
C:\Users\mflaga\AppData\Local\Temp\build8958339595868119500.tmp>avr-objdump -d sketch_feb13a.cpp.elf > sketch_feb13a.cpp.elf.lst
有道理。由于Leonardo仍然需要USB-CDC客户端(4K)来检测来自AVR-DUDE的1200波特连接,以触发远程重启。
因此,在构建中没有USB的情况下制作自定义board.txt时,也需要
leonardo.upload.use_1200bps_touch=true
删除。
一旦加载到目标上,这将要求上载与目标的手动重置同步。由于失去了远程重启的能力。
我最近想做到这一点。由于没有很好的方法,所以我结束了为Stino崇高文本arduino插件编写补丁的工作。随后它被接受,因此应该在任何最新的Stino安装中使用。
这为Stino添加了一个新选项:
使用此模式会产生如下的编译结果:
对于Uno:
二进制草图大小:172字节(最大32256字节,百分之0.53)。
估计的内存使用量:0字节(最大1024字节,0.00%)。
为了莱昂纳多
二进制草图大小:240个字节(最大28672个字节,为0.84%)。
估计的内存使用量:0字节(最大2560字节,0.00%)。
实际上,使用上面的编译输出对leonardo进行编程可能不是一个好主意,因为它可能会破坏自动重置功能,但是如果需要,可以这样做。向mpflaga致谢,因为他在回答中指出了这一点。
请注意,内存报告实际上是不正确的,但这是一个单独的问题。
用于上面的代码是:
int main()
{
while (1)
{
}
}
一些注意事项:
milis()
或类似。#include <Arduino.h>
。main
。您永远不会从返回main
。如果您需要安装程序,它会放在之前while (1)
。尽管它取决于您的草图,但是您可以通过使用方法重用代码来减小大小。
采取以下代码:
int led = 13;
int val;
void setup() {
pinMode(led, OUTPUT);
}
void loop() {
digitalWrite(led, HIGH); // turn the LED on (HIGH is the voltage level)
delay(1000); // wait for a second
digitalWrite(led, LOW); // turn the LED off by making the voltage LOW
delay(1000); // wait for a second
digitalWrite(led, HIGH); // turn the LED on (HIGH is the voltage level)
delay(1000); // wait for a second
digitalWrite(led, LOW); // turn the LED off by making the voltage LOW
delay(1000); // wait for a second
digitalWrite(led, HIGH); // turn the LED on (HIGH is the voltage level)
delay(1000); // wait for a second
digitalWrite(led, LOW); // turn the LED off by making the voltage LOW
delay(1000); // wait for a second
digitalWrite(led, HIGH); // turn the LED on (HIGH is the voltage level)
delay(1000); // wait for a second
digitalWrite(led, LOW); // turn the LED off by making the voltage LOW
delay(1000); // wait for a second
val = digitalRead(10);
}
Arduino Uno上的1,322字节 现在让我们缩小一点:
int led = 13;
int val;
void setup() {
pinMode(led, OUTPUT);
}
void loop() {
for(uint8_t i = 0; i < 8; i++) {
blink(HIGH);
blink(LOW);
}
val = digitalRead(10);
}
void blink(uint8_t state) {
digitalWrite(led, state); // turn the LED to the right state
delay(1000); // wait for a second
}
1,194字节。大约减少了10%!
无论如何,尽管它不会大大缩小草图,但是当您超出限制两个字节时,或者只是想制作一个更紧凑的草图而又不丧失任何功能时,它有时可能是最简单的路线。并非适用于所有情况,但有时会有用。
@annonomus企鹅,当然可以。尽管代码可以编译为1180字节的flash + 13字节的RAM,可以在我的计算机上使用uno,但我们可以对其进行改进:)因此,我们接受高尔夫挑战赛,并且这里还有一些有用的技巧,因为我们从事学习。
步骤1:降低可变需求。使用一个int作为led端口似乎有点过大,我们当然在arduino上没有65535个可寻址的IO端口:)因此,我们只是为了好玩而将其更改为一个字节。稍后,我们将其更改为#define,但以显示使用太大的变量类型的影响。
byte led = 13;
int val;
void setup() {
pinMode(led, OUTPUT);
}
void loop() {
blink();
val = digitalRead(10);
}
void blink() {
digitalWrite(led, HIGH); // turn the LED on (HIGH is the voltage level)
delay(1000); // wait for a second
digitalWrite(led, LOW); // turn the LED off by making the voltage LOW
delay(1000); // wait for a second
}
编译为1172字节+ 13字节RAM。由于该字节(而不是整数)所需的操作较少,因此可以节省8个字节的闪存。我希望有12个字节的ram,但是还可以。没那么多,但是保存的每个字节都是好的。
步骤2:何时将变量转换为定义。例如,不需要led字节,引脚不会自行解焊。
#define LED 13
int val;
void setup() {
pinMode(LED, OUTPUT);
}
void loop() {
blink();
val = digitalRead(10);
}
void blink() {
digitalWrite(LED, HIGH); // turn the LED on (HIGH is the voltage level)
delay(1000); // wait for a second
digitalWrite(LED, LOW); // turn the LED off by making the voltage LOW
delay(1000); // wait for a second
}
编译为1142字节的Flash + 11字节的RAM。已保存38个字节。这是由于获取int值所需的寄存器操作较少。另外,我们从RAM中节省了2个字节。(仍然想知道为什么该字节没有被编译成ram少1个字节.....)
步骤3:优化代码。我看到2个延迟。我想知道是否将其更改为1延迟会节省空间,但是我必须弄清楚LED引脚的值并进行切换(反转)。我们可以使用digitalRead()做到这一点,但是会节省空间吗?
#define LED 13
int val;
void setup() {
pinMode(LED, OUTPUT);
}
void loop() {
blink();
val = digitalRead(10);
}
void blink() {
digitalWrite(LED, !digitalRead(LED)); // toggle the led based on read value
delay(1000); // wait for a second and spare yourself the other delay
}
编译为1134字节+ 11字节ram 好极了!另外8个字节。这样一来,总共有46个字节,少了2行代码。
关于减小代码大小的另一个通用技巧。不要使用String类。非常庞大,了解如何处理char数组,strcpy(),strcmp()。如果您所拥有的只是一些基本的字符串操作,那么String类的用法通常只是浪费闪存和RAM上的空间。