【发布时间】:2015-12-20 01:49:12
【问题描述】:
我希望有人可以帮助我诊断出我正在经历的这种奇怪行为。我正在为 Arduino Due 编程并使用Adafruit FONA modem。有问题的代码提交要通过调制解调器发送的字节数组。 sendData 正在接受unsigned char[],我将其转换为void*。 data_len 是写入缓冲区的字节数,而不是缓冲区本身的大小。
我正在使用的板不使用 printf/sprintf 打印到标准输出。相反,这是使用Serial.print 和Serial.println 完成的。 Serial 这里是一个 Arduino 类,而不是标准的 C++ 类。 sprintf_ByteArray 我写信是为了检查字节缓冲区的内容,结果反映为十六进制字节。
正如我提到的,我的最终目标是将数据写入调制解调器。这是在fonaSerial->println 和fonaSerial->write 调用中完成的。第一个发出调制解调器命令,其中包含要写入的数据大小。第二个写入数据。
但我遇到了一些奇怪的事情。打印data 和String message 的结果如下所示。对我来说莫名其妙的是,message 只包含data 的最后 119 个字节。起初,这并没有让我感到惊讶,因为data 包含空字节,我认为这些都是罪魁祸首。但是,message 实际上包含空字节!而且,我希望 message 代表 data 的前 N 个字节,直到第一个空字节。
最后:我将data 转换为uint8_t* 并传递给fonaSerial->write。最初我一直在传递一个字符串,但在我遇到问题后,我决定尝试这种替代方法。然后我将此数据发送到我正在运行的服务器。服务器也仅获得 119 字节的有效负载。
为了记录,早些时候我成功发送了一个较小的有效载荷。我不知道我现在在做什么导致问题。
bool sendData(void *data, size_t data_len) {
char tmp[1024] = {0};
Serial.print("data_len=");Serial.println(data_len);
sprintf_ByteArray(tmp, (unsigned char*) data, data_len);
Serial.print("Payload (void*)=");Serial.println(tmp);
String message = (const char*) data;
Serial.print("Payload (String)=");Serial.println(message);
fonaSerial->print(F("AT+CIPSEND="));
fonaSerial->println(data_len);
fona.readline(3000);
fonaSerial->write((uint8_t*) data, data_len);
fonaSerial->flush();
fona.readline(3000); // wait up to 3 seconds to send the data
Serial.print (F("\t<--- ")); Serial.println(fona.replybuffer);
return (strcmp(fona.replybuffer, "SEND OK") == 0);
}
Payload (void*)= 8a a5 62 69 64 00 69 63 6f 6e 64 69 74 69 6f 6e 01 67 62 61 74 74 65 72 79 18 1d 65 73 74 61 74 65 02 69 74 69 6d 65 73 74 61 6d 70 19 0f 95 a5 62 69 64 01 69 63 6f 6e 64 69 74 69 6f 6e 01 67 62 61 74 74 65 72 79 18 42 65 73 74 61 74 65 62 69 74 69 6d 65 73 74 61 6d 70 19 0f 97 a5 62 69 64 02 69 63 6f 6e 64 69 74 69 6f 6e 00 67 62 61 74 74 65 72 79 18 29 65 73 74 61 74 65 06 69 74 69 6d 65 73 74 61 6d 70 19 0f 98 a5 62 69 64 03 69 63 6f 6e 64 69 74 69 6f 6e 01 67 62 61 74 74 65 72 79 18 26 65 73 74 61 74 65 01 69 74 69 6d 65 73 74 61 6d 70 19 0f 99 a5 62 69 64 04 69 63 6f 6e 64 69 74 69 6f 6e 01 67 62 61 74 74 65 72 79 18 2f 65 73 74 61 74 65 62 69 74 69 6d 65 73 74 61 6d 70 19 0f 9a a5 62 69 64 05 69 63 6f 6e 64 69 74 69 6f 6e 01 67 62 61 74 74 65 72 79 18 1d 65 73 74 61 74 65 06 69 74 69 6d 65 73 74 61 6d 70 19 0f 9c a5 62 69 64 18 42 69 63 6f 6e 64 69 74 69 6f 6e 18 75 67 62 61 74 74 65 72 79 18 69 65 73 74 61 74 65 18 6c 69 74 69 6d 65 73 74 61 6d 70 1a 67 6e 69 64 a5 62 69 64 18 20 69 63 6f 6e 64 69 74 69 6f 6e 18 6c 67 62 61 74 74 65 [72 79 18 6f 65 73 74 61 74 65 18 74 69 74 69 6d 65 73 74 61 6d 70 1a 00 6e 39 20 a5 62 69 64 62 69 63 6f 6e 64 69 74 69 6f 6e 00 67 62 61 74 74 65 72 79 18 40 65 73 74 61 74 65 74 69 74 69 6d 65 73 74 61 6d 70 19 0f a0 a5 62 69 64 74 69 63 6f 6e 64 69 74 69 6f 6e 00 67 62 61 74 74 65 72 79 18 43 65 73 74 61 74 65 74 69 74 69 6d 65 73 74 61 6d 70 19 0f a1]
长度 471
Payload (String)= 72 79 18 6f 65 73 74 61 74 65 18 74 69 74 69 6d 65 73 74 61 6d 70 1a 00 6e 39 20 a5 62 69 64 62 69 63 6f 6e 64 69 74 69 6f 6e 00 67 62 61 74 74 65 72 79 18 40 65 73 74 61 74 65 74 69 74 69 6d 65 73 74 61 6d 70 19 0f a0 a5 62 69 64 74 69 63 6f 6e 64 69 74 69 6f 6e 00 67 62 61 74 74 65 72 79 18 43 65 73 74 61 74 65 74 69 74 69 6d 65 73 74 61 6d 70 19 0f a1
长度 119
【问题讨论】:
-
@Olaf 准确地说,它是 C++。 IDE 只是通过在将代码发送到 avr-gcc 之前将代码包装在其他一些标头和内容中来隐藏这一点。仅使用 avr-gcc 和您自己的编程芯片就完全可以使用 Arudino 代码。有点痛,但我以前做过。
-
@Chris 我不知道,但可能是打印中涉及的缓冲区在读取数据之前就已满?在这种情况下,我希望长时间写入会用最新信息填充较早的数据。例如,如果您通过串行发送数据,但没有在数据到达后立即读取,则串行缓冲区可能充当队列,并在其已满时丢弃较旧的字节。
-
如果是 C 或 C++ 标记它会增加可见性
-
在我看来,有 3 个方面需要调查。首先,如果您的 String 对象构造正确。 String 类是否具有“长度”或“大小”属性/功能?结果是你所期望的吗?第二个方面是 Serial.println 是否将字符串的值正确发送到串行端口。手动构造一个类似长度的字符串并使用相同的代码打印它(代替打印字符串以保持一致性的当前代码)。最后,如上所述,串行输出的缓冲区可能已满并转储数据。尝试删除第一个...
-
...打印您发送 void* 数据的位置,然后查看字符串是否按照您的预期打印。缓冲区一可能是问题所在。您说 119 字节是一个奇数,但是您正在向 Serial.print 发送 1800+ 字节的数据(如果您包含的输出几乎是逐字记录的话)。可能有一个 1024 字节的缓冲区,其中一些缓冲区在尝试第二次打印之前被清空。
标签: arduino arduino-due