Docklight和Arduino串行通信(通过RS232发送十六进制)

时间:2017-05-28 15:33:06

标签: arduino serial-port nodemcu

我有以下代码(我使用的是Arduino IDE和带有MAX3232的NodeMCU):

#include <SoftwareSerial.h>

SoftwareSerial RS232Serial(D1, D2); // RX | TX

void setup() {
  Serial.begin(9600);
  while (!Serial);

  RS232Serial.begin(9600);
  while (!RS232Serial);
}

void loop() {

  Serial.println("Sending msg...");
  char msg[] = {0x7E, 0x00, 0x78, 0xF0, 0x7E};

  RS232Serial.write(msg, sizeof(msg));

  Serial.println("Waiting incomming message:");
  while(RS232Serial.available() <= 0) {
    delay(1);
  }

  while(RS232Serial.available() > 0) {
    Serial.print(RS232Serial.read(), HEX);
  }

  Serial.println("");

  Serial.println("------------ END -----------");

}

我正在使用Docklight来测试通信。到目前为止,我能够收到NodeMCU板首先发送的HEX char msg[] = {0x7E, 0x00, 0x78, 0xF0, 0x7E};。但我无法从Docklight正确接收数据。

我试图从Docklight发送的HEX是7E 00 00 70 15 7E。使用串行监视器进行调试,有时我只收到7E,有时收到0FF,而不是完整的邮件。波特率,开始/停止位和奇偶校验设置为默认值。

我的代码出了什么问题?

2 个答案:

答案 0 :(得分:2)

不按预期工作的一个原因是:

  • 只要接收缓冲区中出现一个字节,就会处理答案。

Docklight应用笔记Arduino Serial Communication中有一个相关示例 - 请查看第5页的代码清单。它使用Arduino SerialEvent() function来收集每字节字节的传入电报。只有在收到电报标记结束后(这里:换行&#34; \ n&#34;字符),它才会设置一个标志,告诉主循环()中的代码对累积的数据电报做某事。

Docklight示例中使用的SerialEvent方法不是必须的。你也可以单独解决这个内部循环()。但你肯定需要改变

  while(RS232Serial.available() <= 0) {

...

  while(RS232Serial.available() > 0) {

部件将等待直到收到完整电报(或发生超时)。

现在让我感到恼火的是你写的有时会收到&#34; 0FF&#34;即使你从来没有从Docklight发送它。这可能表明实际的RS232通信仍然存在第二个问题,但如果没有额外的信息,很难猜测。

但如上所述重新处理电报接收部分应该已经使事情更加清晰,然后是&#34; 0FF&#34;可能更明显。

答案 1 :(得分:0)

while(RS232Serial.available() <= 0) {
  delay(1);
}

您只是在等待串行缓冲区至少有1个字节,但是当您致电RS232Serial.available()时,无法保证您的完整消息(6个字节)会出现。

在尝试读取之前,您应该等待串行缓冲区累积至少6个字节。

while(RS232Serial.available() < 6) {
  delay(1);
}

他们可以通过以下方式阅读完整的缓冲区:

while(RS232Serial.available() > 0) {
  Serial.print(RS232Serial.read(), HEX);
}

或只有6个字节:

for (int i=0; i<6; i++) {
  Serial.print(RS232Serial.read(), HEX);
}

我不知道您的0FF,但Serial.print(RS232Serial.read(), HEX)没有填充十六进制字符串,这实际上可能是00 0F 0F00 FF

您应该用以下字符打印出字节:

byte b = RS232Serial.read();
if (b < 16) Serial.print('0'); // zero pad
Serial.print(b, HEX);
Serial.print(' '); // add space after each byte