【发布时间】:2013-12-24 07:18:39
【问题描述】:
我正在开发 OSX Mavericks、标准 Arduino.app 和 Arduino 2560 板。
这是迄今为止我遇到过的最奇怪的错误。
长话短说,这段代码:
#include "Arduino.h"
#include "Bitstreamer.h"
#include "TimerOne.h"
#include "BusyWaitByteProtocol.h"
Bitstreamer::Bitstreamer(int pin)
{
_pin = pin;
stage = 0;
bitholder = new boolean[8];
bitindex = 0;
bp = new BusyWaitByteProtocol (128);
}
Bitstreamer* Bitstreamer::Daemonholder = NULL;
void Bitstreamer::RunDaemon()
{
Bitstreamer::Daemonholder->Run();
}
void Bitstreamer::Listen()
{
myTurn = false;
Init();
}
void Bitstreamer::Shout()
{
myTurn = true;
Init();
}
void Bitstreamer::Init()
{
Daemonholder = this;
Timer1.initialize(cycleRate);
Timer1.attachInterrupt(RunDaemon);
stage++;
screamcounter = 0;
bitcounter = 0;
lastbit = false;
}
void Bitstreamer::Run()
{
if (stage == 1)
{
//We are initializing the protocol. If we are the shouter, scream for a bit. If we are the listener, wait for scream to end.
//The scream really just serves as an initial syncronizer.
if (myTurn)
{
pinMode(_pin, OUTPUT);
digitalWrite(_pin, HIGH);
}
else
{
pinMode(_pin, INPUT);
}
stage++;
}
else if (stage == 2)
{
if (myTurn)
{
screamcounter++;
if (screamcounter > 100)
{
digitalWrite(_pin, LOW);
stage++;
}
}
else
{
int state = digitalRead(_pin);
if (state == 1)
{
screamcounter++;
}
else
{
if (screamcounter > 30)
{
stage++;
}
screamcounter = 0;
}
}
}
else if (stage == 3)
{
if (myTurn)
{
bitcounter++;
if (bitcounter == 0)
{
digitalWrite(_pin, bitholder[bitindex]?HIGH:LOW);
}
else
{
if (bitcounter >= resendrate)
{
bitcounter = -1;
bitindex++;
}
if (bitindex >= 8)
{
bitindex = 0;
uint8_t nb = bp->RequestByte();
ReadBits(nb, bitholder);
//Swap turns as well
}
}
}
else
{
boolean state = (digitalRead(_pin) != 1);
if (state != lastbit)
{
float bits = ((float)bitcounter)/((float)resendrate);
int finalbits = round(bits);
debugstring = String(debugstring + String(state) + String(" ") + String(finalbits) + String("\n"));
//Process received bits
for (int i = 0; i < finalbits; i++)
{
bitholder[bitindex] = state;
bitindex++;
if (bitindex >= 8)
{
bitindex = 0;
uint8_t nb = WriteBits(bitholder);
bp->ProcessByte(nb);
//Swap turns
}
}
lastbit = state;
bitcounter = 0;
}
else
{
bitcounter++;
}
}
}
/*
if (myTurn)
{
if (hitcount < hits + 3)
{
digitalWrite(_pin, ((hitcount++)<hits)?HIGH:LOW);
}
else
{
hitcount = 0;
hits++;
lhits = hits;
}
}
else
{
int state = digitalRead(_pin);
if (state == 0)
{
hitcount++;
}
else
{
hitcount = 0;
hits++;
}
//lhits = hits;
if (hitcount >= 3)
{
lhits = hits;
hits = 0;
}
}
*/
}
byte Bitstreamer::Read()
{
//Load from incoming byte buffer
return 0;
}
void Bitstreamer::Write(byte b)
{
//Send to outgoing byte buffer
}
void Bitstreamer::ReadBits(uint8_t b, boolean* bitarray)
{
//DRAGONHERE: For loop would have been less code, but required initialization of another variable, and slightly more complicated logic for the processor
//Also, not having it in a for loop makes it easier for others to understand
bitarray[0] = (b & 1) != 0; // 1 = 00000001, IE 1st bit. (1 & b) lets only 1st bit through. != 0 checks if zero.
bitarray[1] = (b & 2) != 0; // 1 = 00000010, IE 2nd bit. (2 & b) lets only 2nd bit through. != 0 checks if zero.
bitarray[2] = (b & 4) != 0; // 1 = 00000100, IE 3rd bit. (4 & b) lets only 3rd bit through. != 0 checks if zero.
bitarray[3] = (b & 8) != 0; // 1 = 00001000, IE 4th bit. (8 & b) lets only 4th bit through. != 0 checks if zero.
bitarray[4] = (b & 16) != 0; // 1 = 00010000, IE 5th bit. (16 & b) lets only 5th bit through. != 0 checks if zero.
bitarray[5] = (b & 32) != 0; // 1 = 00100000, IE 6th bit. (32 & b) lets only 6th bit through. != 0 checks if zero.
bitarray[6] = (b & 64) != 0; // 1 = 01000000, IE 7th bit. (64 & b) lets only 7th bit through. != 0 checks if zero.
bitarray[7] = (b & 128) != 0; // 1 = 10000000, IE 8th bit. (128 & b) lets only 8th bit through. != 0 checks if zero.
//PLEASE NOTE: These explainations are based on the assumption that the bit order on Arduino is MSB-Left.
//Notably, this method of exploding bits will actually dynamically adjust to the bit order of the given system.
}
uint8_t Bitstreamer::WriteBits(boolean* b)
{
//DRAGONHERE: same as above
return
(b[0]? 1 : 0) +
(b[1]? 2 : 0) +
(b[2]? 4 : 0) +
(b[3]? 8 : 0) +
(b[4]? 16 : 0) +
(b[5]? 32 : 0) +
(b[6]? 64 : 0) +
(b[7]? 128 : 0);
}
编译正常,上传到 Arduino,并按预期工作。
但是这段代码:
#include "Arduino.h"
#include "Bitstreamer.h"
#include "TimerOne.h"
#include "BusyWaitByteProtocol.h"
Bitstreamer::Bitstreamer(int pin)
{
_pin = pin;
stage = 0;
bitholder = new boolean[8];
bitindex = 0;
bp = new BusyWaitByteProtocol (128);
}
Bitstreamer* Bitstreamer::Daemonholder = NULL;
void Bitstreamer::RunDaemon()
{
Bitstreamer::Daemonholder->Run();
}
void Bitstreamer::Listen()
{
myTurn = false;
Init();
}
void Bitstreamer::Shout()
{
myTurn = true;
Init();
}
void Bitstreamer::Init()
{
Daemonholder = this;
Timer1.initialize(cycleRate);
Timer1.attachInterrupt(RunDaemon);
stage++;
screamcounter = 0;
bitcounter = 0;
lastbit = false;
}
void Bitstreamer::Run()
{
if (stage == 1)
{
//We are initializing the protocol. If we are the shouter, scream for a bit. If we are the listener, wait for scream to end.
//The scream really just serves as an initial syncronizer.
if (myTurn)
{
pinMode(_pin, OUTPUT);
digitalWrite(_pin, HIGH);
}
else
{
pinMode(_pin, INPUT);
}
stage++;
}
else if (stage == 2)
{
if (myTurn)
{
screamcounter++;
if (screamcounter > 100)
{
digitalWrite(_pin, LOW);
stage++;
}
}
else
{
int state = digitalRead(_pin);
if (state == 1)
{
screamcounter++;
}
else
{
if (screamcounter > 30)
{
stage++;
}
screamcounter = 0;
}
}
}
else if (stage == 3)
{
if (myTurn)
{
bitcounter++;
if (bitcounter == 1)
{
digitalWrite(_pin, bitholder[bitindex]?HIGH:LOW);
}
else
{
if (bitcounter >= resendrate)
{
bitcounter = 0;
bitindex++;
}
if (bitindex >= 8)
{
bitindex = 0;
uint8_t nb = bp->RequestByte();
ReadBits(nb, bitholder);
//Swap turns as well
}
}
}
else
{
boolean state = (digitalRead(_pin) != 1);
if (state != lastbit)
{
float bits = ((float)bitcounter)/((float)resendrate);
int finalbits = round(bits);
debugstring = String(debugstring + String(state) + String(" ") + String(finalbits) + String("\n"));
//Process received bits
for (int i = 0; i < finalbits; i++)
{
bitholder[bitindex] = state;
bitindex++;
if (bitindex >= 8)
{
bitindex = 0;
uint8_t nb = WriteBits(bitholder);
bp->ProcessByte(nb);
//Swap turns
}
}
lastbit = state;
bitcounter = 0;
}
else
{
bitcounter++;
}
}
}
/*
if (myTurn)
{
if (hitcount < hits + 3)
{
digitalWrite(_pin, ((hitcount++)<hits)?HIGH:LOW);
}
else
{
hitcount = 0;
hits++;
lhits = hits;
}
}
else
{
int state = digitalRead(_pin);
if (state == 0)
{
hitcount++;
}
else
{
hitcount = 0;
hits++;
}
//lhits = hits;
if (hitcount >= 3)
{
lhits = hits;
hits = 0;
}
}
*/
}
byte Bitstreamer::Read()
{
//Load from incoming byte buffer
return 0;
}
void Bitstreamer::Write(byte b)
{
//Send to outgoing byte buffer
}
void Bitstreamer::ReadBits(uint8_t b, boolean* bitarray)
{
//DRAGONHERE: For loop would have been less code, but required initialization of another variable, and slightly more complicated logic for the processor
//Also, not having it in a for loop makes it easier for others to understand
bitarray[0] = (b & 1) != 0; // 1 = 00000001, IE 1st bit. (1 & b) lets only 1st bit through. != 0 checks if zero.
bitarray[1] = (b & 2) != 0; // 1 = 00000010, IE 2nd bit. (2 & b) lets only 2nd bit through. != 0 checks if zero.
bitarray[2] = (b & 4) != 0; // 1 = 00000100, IE 3rd bit. (4 & b) lets only 3rd bit through. != 0 checks if zero.
bitarray[3] = (b & 8) != 0; // 1 = 00001000, IE 4th bit. (8 & b) lets only 4th bit through. != 0 checks if zero.
bitarray[4] = (b & 16) != 0; // 1 = 00010000, IE 5th bit. (16 & b) lets only 5th bit through. != 0 checks if zero.
bitarray[5] = (b & 32) != 0; // 1 = 00100000, IE 6th bit. (32 & b) lets only 6th bit through. != 0 checks if zero.
bitarray[6] = (b & 64) != 0; // 1 = 01000000, IE 7th bit. (64 & b) lets only 7th bit through. != 0 checks if zero.
bitarray[7] = (b & 128) != 0; // 1 = 10000000, IE 8th bit. (128 & b) lets only 8th bit through. != 0 checks if zero.
//PLEASE NOTE: These explainations are based on the assumption that the bit order on Arduino is MSB-Left.
//Notably, this method of exploding bits will actually dynamically adjust to the bit order of the given system.
}
uint8_t Bitstreamer::WriteBits(boolean* b)
{
//DRAGONHERE: same as above
return
(b[0]? 1 : 0) +
(b[1]? 2 : 0) +
(b[2]? 4 : 0) +
(b[3]? 8 : 0) +
(b[4]? 16 : 0) +
(b[5]? 32 : 0) +
(b[6]? 64 : 0) +
(b[7]? 128 : 0);
}
编译失败并报错:
/Applications/Arduino.app/Contents/Resources/Java/hardware/tools/avr/bin/../lib/gcc/avr/4.3.2/../../../../avr /lib/avr6/crtm2560.o: 在 .text.__vector_36 部分中定义的函数
__vector_default': (.vectors+0x90): relocation truncated to fit: R_AVR_13_PCREL against symbol__vector_36' core.a(HardwareSerial.cpp.o)
区别?你会笑的……
在 工作 段代码中,我有:
Line #98: if (bitcounter == 0)
Line #106: bitcounter = -1;
在 not-working 代码段中,我有:
Line #98: if (bitcounter == 1)
Line #106: bitcounter = 0;
这实际上是仅有的两个区别。坦率地说,我不明白为什么以善良的名义这不起作用。更好的是:
Line #98: if (bitcounter == 0)
Line #106: bitcounter = 0;
还有:
Line #98: if (bitcounter == 1)
Line #106: bitcounter = -1;
甚至:
Line #98: if (bitcounter == 0)
Line #106: bitcounter = 1;
所有工作。正是 1 和 0 的唯一组合,按此顺序,导致我的编译器发疯。
有人能够解释这里到底出了什么问题吗?我对此感到非常不安,我只能想到发生这种情况的一个原因——也许我的程序在 arduino 上占用了太多内存?没有。原来的工作代码占用了,我引用:
二进制草图大小:10,178 字节(最大 258,048 字节)
很抱歉,我只是不明白如何在我的程序中更改两个常量会使最终的二进制大小总共增加 247,870 字节。
那么,我到底做错了什么?我是否偶然发现了编译器中的一些疯狂错误?这是我的代码以某种方式编译为与一些实施不佳的开发人员信号相同的二进制模式的结果,该信号调整了 Arduino 上的程序上传接收器系统上的设置?或者对这个谜团有更合乎逻辑的答案吗?
【问题讨论】:
标签: c++ compiler-errors arduino