0

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

问题在于,在通过串行接收到消息“START”后,Arduino 继续执行该函数startSequence(),该函数使用两个随机数从 2D 矩阵中获取 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”消息。

发送产生的输出

提前感谢大家的帮助,如果错误很明显,我很抱歉,但我一遍又一遍地浏览了这段代码,似乎找不到它。

4

1 回答 1

1

如果您希望它充当字符串,则需要 null 终止 newSecretCode。但最好不要使用 String 类来转换不需要转换的东西。以这种方式打印:

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
  }
}

串行数据逐字节输出。另一端的接收器只看到一个连续的字节流。它不知道您是否使用单个打印语句和一堆资源浪费在字符串上,或者您是否使用每个字符的单独打印语句来执行此操作。

于 2020-04-24T17:31:07.907 回答