为什么串行接收到的消息存储在字符数组中

Why Serial Received Message Getting Stored In Char Array

收到来自 Serial 的消息后,我的 Arduino 代码出现问题。

问题在于,在通过串行接收到消息 "START" 后,Arduino 继续执行函数 startSequence(),该函数使用两个随机数从二维矩阵中获取 8 个值并存储这些值在一个 char 数组中。

这里的问题是,即使这个 char 数组的大小已声明为 8,消息 "START" 也会附加到这个 char 数组的末尾,它根本不应该这样做, handleReceivedMessage(char *msg) 后应完全丢弃此消息。我的代码:

#include <Keypad.h>

const byte ROWS = 4;
const byte COLS = 4;

char hexaKeys[ROWS][COLS] = {
  {'1', '2', '3', 'A'},
  {'4', '5', '6', 'B'},
  {'7', '8', '9', 'C'},
  {'*', '0', '#', 'D'}
};
char newSecretCode[8];
char introducedSecretCode[8];

byte rowPins[ROWS] = {9, 8, 7, 6};
byte colPins[COLS] = {5, 4, 3, 2};

int secretCodeIndex = 0;

Keypad customKeypad = Keypad(makeKeymap(hexaKeys), rowPins, colPins, ROWS, COLS);

void setup() {
  Serial.begin(9600);
  delay(2000);  //Delay to allow initializations on Raspberry side
  Serial.println("COM:SETUP;INT_NAME:Keypad Puzzle;BAUD:9600");
  randomSeed(analogRead(0));
}

void loop() {
  if (Serial.available()) {
    processSerialMessage();
  }
  char customKey = customKeypad.getKey();
  if (customKey) {
    if (secretCodeIndex < 8) {
      introducedSecretCode[secretCodeIndex] = customKey;
      secretCodeIndex += 1;
    } else {
      secretCodeIndex = 0;
    }
  }
}

void processSerialMessage() {
  const int BUFF_SIZE = 32; // make it big enough to hold your longest command
  static char buffer[BUFF_SIZE + 1]; // +1 allows space for the null terminator
  static int length = 0; // number of characters currently in the buffer

  char c = Serial.read();
  if ((c == '\r') || (c == '\n')) {
    // end-of-line received
    if (length > 0) {
      handleReceivedMessage(buffer);
    }
    length = 0;
  }
  else {
    if (length < BUFF_SIZE) {
      buffer[length++] = c; // append the received character to the array
      buffer[length] = 0; // append the null terminator
    } else {
      // buffer full - discard the received character
    }
  }
}

void handleReceivedMessage(char *msg) {
  if (strcmp(msg, "START") == 0) {
    startSequence();
    Serial.println("COM:START_ACK;MSG:Set new code to " + String(newSecretCode));
  }else {
    // etc
  }
}

void startSequence() {
  for (int i = 0; i < 8; i++) {
    newSecretCode[i] = hexaKeys[random(0,ROWS)][random(0,COLS)];
  }
}

我已经看过一遍又一遍的代码,但我似乎无法弄清楚为什么我通过串行接收的消息设法附加到大小仅为 8 的数组的末尾。下面是一些正确的输出示例,但字符串末尾的 "START" 消息除外。

预先感谢大家的帮助,如果错误很明显,我深表歉意,但我一遍又一遍地检查这段代码,但似乎找不到它。

如果您希望 newSecretCode 充当字符串,则需要 null 终止。但最好不要使用 String class 来转换不需要转换的内容。这样打印:

void handleReceivedMessage(char *msg) {
  if (strcmp(msg, "START") == 0) {
    startSequence();
    Serial.println("COM:START_ACK;MSG:Set new code to " );
    for (int i=0; i<8; i++){
      Serial.print(newSecretCode[i]);
    }
  }else {
    // etc
  }
}

串行数据逐字节输出。另一端的接收器只看到连续的字节流。它不知道您是使用一个单独的 print 语句并在 String 上浪费了一堆资源,还是为每个字符使用了单独的 print 语句。