Arduino“SerialEvent”示例代码无法在我的 Arduino Nano 上运行。我无法接收串行数据。为什么?

2024-01-22

我正在按照教程进行操作串行事件 https://www.arduino.cc/en/Tutorial/BuiltInExamples/SerialEvent我正在尝试这段代码:

然而,当我发送我的Arduino 纳米 https://en.wikipedia.org/wiki/List_of_Arduino_boards_and_compatible_systems#Official串口数据,好像没有收到。当我通过串行向它发送消息时,它应该将其打印回 Arduino 串行监视器(串行控制台),但事实并非如此。为什么?我究竟做错了什么?

更多细节:

我需要从我的 PC 到 Arduino 进行实时通信。因此,我不能使用delay()在我的 Arduino 循环中。该项目包括从计算机发送消息toArduino并在Arduino中接收和解析它。这个示例代码看起来很完美,因为它没有使用delay()功能。不幸的是,它不起作用。我通过串口将文本字符串从计算机发送到 Arduino,但 Arduino 不会在串口监视器上打印任何内容。我的 Arduino 是 Nano ATmega328。

另外,我没有看到这个示例代码调用serialEvent()随时随地发挥作用。我该打电话到哪里serialEvent()?或者,它如何运行并被调用?

这是从上面的示例复制粘贴的代码:

String inputString = "";         // A string to hold incoming data
boolean stringComplete = false;  // Whether the string is complete

void setup() {
  // Initialize serial:
  Serial.begin(9600);

  // Reserve 200 bytes for the inputString:
  inputString.reserve(200);
}

void loop() {
  // Print the string when a newline arrives:
  if (stringComplete) {
    Serial.println(inputString);

    // Clear the string:
    inputString = "";
    stringComplete = false;
  }
}

/*
  SerialEvent occurs whenever a new data comes in the
  hardware serial RX.  This routine is run between each
  time loop() runs, so using delay inside loop can delay
  response.  Multiple bytes of data may be available.
 */
void serialEvent() {
  while (Serial.available()) {

    // Get the new byte:
    char inChar = (char)Serial.read();

    // Add it to the inputString:
    inputString += inChar;

    // If the incoming character is a newline, set a flag
    // so the main loop can do something about it:
    if (inChar == '\n') {
      stringComplete = true;
    }
  }
}

你需要一个\n在通过串口发送到 Arduino 的任何字符串的末尾:

注意这部分serialEvent()功能:

// if the incoming character is a newline, set a flag
// so the main loop can do something about it:
if (inChar == '\n') {
stringComplete = true;
} 

正如你所看到的,它正在寻找\n(换行)字符表示已收到完整字符串。那么你must包括换行符 (\n) 在您发送到 Arduino 的字符串末尾。

教程(https://www.arduino.cc/en/Tutorial/BuiltInExamples/SerialEvent https://www.arduino.cc/en/Tutorial/BuiltInExamples/SerialEvent)还指出(强调):

这个例子演示了使用serialEvent()功能。该函数在结束时自动调用loop()当缓冲区中有可用串行数据时。在这种情况下,找到的每个字符都会添加到字符串中直到找到换行符。然后打印该字符串并将其设置回 null。

If using the Arduino Serial Monitor, be sure to choose the "Newline" option from the dropdown at the bottom. Then, whenever you type something in the bar at the top and press Enter, it will automatically append a \n to the end of your string to the Arduino when you send it. enter image description here

如果通过串口将数据从 C、C++、Python、Java 或其他程序发送到 Arduino,请再次确保包含\n在你的字符串末尾到Arduino。

如何serialEvent()无论如何都会被打电话吗?

回答这个问题:

另外,我没有看到这个示例代码调用serialEvent()随时随地发挥作用。我该打电话到哪里serialEvent()?或者,它如何运行并被调用?

简而言之,您定义的事实serialEvent()功能at all使其被 Arduino 核心代码自动调用。如果你不定义它,它不会被调用。如果你定义它,它就会。这是因为你的定义serialEvent()是强大的并且超越weak one 在 HardwareSerial.cpp 中声明 https://github.com/arduino/ArduinoCore-avr/blob/master/cores/arduino/HardwareSerial.cpp#L45:

// SerialEvent functions are weak, so when the user doesn't define them,
// the linker just sets their address to 0 (which is checked below).
// The Serialx_available is just a wrapper around Serialx.available(),
// but we can refer to it weakly so we don't pull in the entire
// HardwareSerial instance if the user doesn't also refer to it.
#if defined(HAVE_HWSERIAL0)
  void serialEvent() __attribute__((weak)); // <======
  bool Serial0_available() __attribute__((weak));
#endif

所以,如果你定义一个serialEvent()函数,这使得该函数的地址非零(而如果它只是 gccweak声明,它将保持为零),使得这个if陈述正确,所以serialEvent()被叫到在 - 的里面serialEventRun()功能: https://github.com/arduino/ArduinoCore-avr/blob/master/cores/arduino/HardwareSerial.cpp#L67

void serialEventRun(void)
{
#if defined(HAVE_HWSERIAL0)
  if (Serial0_available && serialEvent && Serial0_available()) serialEvent();
  // ...
#endif
}

并且,这又被称为在Arduino中main()在这里发挥作用 https://github.com/arduino/ArduinoCore-avr/blob/master/cores/arduino/main.cpp#L47:

for (;;) {
    loop();
    if (serialEventRun) serialEventRun();
}

那么,让我们再回顾一下这个问题。如果你不定义serialEvent(),那么它唯一的声明是这样的:

void serialEvent() __attribute__((weak));

这是一个弱声明,因此它只会为函数提供一个程序空间内存地址0(零)如果它从未被定义。这意味着这if陈述是错误的,所以serialEvent()内部从未被调用过serialEventRun():

if (Serial0_available && serialEvent && Serial0_available()) serialEvent();

如果是这样的话,那么serialEventRun()不包含任何内容,并且显然还给出了程序空间地址0(零)因为它无关。这使得这个if中的声明main()函数为假,并且serialEventRun()也永远不会被调用:

for (;;) {
    loop();
    if (serialEventRun) serialEventRun();
}

不要使用serialEvent() at all

就我个人而言,我认为你不应该使用serialEvent根本不。只需将逻辑添加到loop()直接运行,就像这样。您可以获得完全相同的效果,并且可以自己手动控制。请注意,only我所做的改变是:

  1. 我重命名了serialEvent()功能为readSerial().
  2. 我添加了readSerial()呼叫您的顶部loop()功能。

就是这样!这是包含这些更改的代码。我刚刚在基于 ATmega328 的 Pro Mini 上进行了测试,它工作正常,可以正确打印出任何换行符(\n我发送给它的以 ) 结尾的字符串,也与此示例中未修改的代码相同。

String inputString = "";         // a String to hold incoming data
bool stringComplete = false;  // whether the string is complete

void setup() {
  // initialize serial:
  Serial.begin(9600);
  // reserve 200 bytes for the inputString:
  inputString.reserve(200);
}

void loop() {
  readSerial();
  // print the string when a newline arrives:
  if (stringComplete) {
    Serial.println(inputString);
    // clear the string:
    inputString = "";
    stringComplete = false;
  }
}

void readSerial() {
  while (Serial.available()) {
    // get the new byte:
    char inChar = (char)Serial.read();
    // add it to the inputString:
    inputString += inChar;
    // if the incoming character is a newline, set a flag so the main loop can
    // do something about it:
    if (inChar == '\n') {
      stringComplete = true;
    }
  }
}

为什么他们让弱者serialEvent()当您只需要手动控制它时,它还能发挥作用吗?我不知道。这可能是一件方便的事情:如果你这样做的话,它可以节省你几行代码(覆盖weak函数调用)用于多个串行事件调用,例如serialEvent(), serialEvent1(), serialEvent2(), and serialEvent3()。然而,为了更明显的控制,我只需手动创建自己的函数并在loop()相反,就像我上面所做的那样。

其他参考资料:

  1. gcc weak功能属性:https://gcc.gnu.org/onlinedocs/gcc-3.2/gcc/Function-Attributes.html https://gcc.gnu.org/onlinedocs/gcc-3.2/gcc/Function-Attributes.html(关于此的最新 gcc 文档现在在这里:https://gcc.gnu.org/onlinedocs/gcc/Common-Function-Attributes.html#index-weak-function-attribute https://gcc.gnu.org/onlinedocs/gcc/Common-Function-Attributes.html#index-weak-function-attribute):

    weak

    The weak属性导致声明作为弱符号而不是全局符号发出。这主要用于定义可以在用户代码中覆盖的库函数,尽管它也可以与非函数声明一起使用。 ELF 目标支持弱符号,使用 GNU 汇编器和链接器时 a.out 目标也支持弱符号。

  2. From my eRCAGuy_hello_world https://github.com/ElectricRCAircraftGuy/eRCaGuy_hello_world回购协议,这是我的check_addr_of_weak_undefined_funcs.cpp https://github.com/ElectricRCAircraftGuy/eRCaGuy_hello_world/blob/master/cpp/check_addr_of_weak_undefined_funcs.cpp我向自己证明的文件weak已声明但未定义的函数确实具有等于 nil 的地址(即:零,或0).

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Arduino“SerialEvent”示例代码无法在我的 Arduino Nano 上运行。我无法接收串行数据。为什么? 的相关文章

  • Arduino:字符串到整数得到奇怪的值

    我想转换一个String to an int 我所能找到的就是你必须将 String 转换为 char 数组 然后将该数组转换为int 但我的代码产生奇怪的值 我无法弄清楚问题是什么 void ledDimm String command
  • printf 的包装

    我在Arduino下编码 我想开发串行打印格式化功能 所以我尝试使用sprintf未知大小的缓冲区 基本上 我们可以避免谈论 Arduino 及其串行输出 并考虑将文本写入缓冲区 然后使用printf 我试过这个 include
  • 读取串行端口 - 忽略在一定时间内写入串行端口的部分数据

    我想定期读取串行端口上的数据和Arduino 所以本质上是这样的 读一读 Wait 读一读 Wait Take etc 我面临的问题是端口将缓冲其信息 因此一旦我调用等待函数 串行端口上的数据就会开始缓冲 等待函数完成后 我尝试再次读取数据
  • Android 和 Arduino 都通过蓝牙接收奇怪的值

    我正在 Android 端使用 BluetoothChat 代码使用聊天框向 Arduino UNO 发送开 关信号 我发送 110 119 或下面定义的其他情况 但是当我显示接收到的值时 它显示奇怪的Arduino 串行监视器中的值 即
  • Arduino:使用串口和软件串口与蓝牙模块

    我的目的是使用 Arduino 通过 HC 05 蓝牙模块在 PC 和 Android 设备之间建立通信 我使用 PC 和 Arduino 串行监视器 之间的 USB 通信以及 SoftwareSerial 来连接到 HC 05 我的问题是
  • Java RXTX 库不加载本机库

    基本上我想使用 Arduino 编写一个简单的通信工具java 的 RXTX 库 http rxtx qbang org wiki index php Main Page并且在加载动态库时严重失败 我的系统规格 操作系统 OS X 优胜美地
  • 经典蓝牙 (2.1) 设备可实现的最小数据包延迟是多少?

    我正在使用 RN42 http www microchip com wwwproducts en RN42 http www microchip com wwwproducts en RN42 蓝牙模块以 115200 波特率 UART S
  • Arduino从SD卡读取最后一行

    我对 Arduino 业务还很陌生 如何从 SD 卡读取最后一行 通过以下代码片段 我可以读取第一行 n 之前的所有字符 现在我想添加一个 向后 声明 或其他内容 到目前为止我的代码 include
  • 在Python中快速绘制数据

    我正在尝试使用 arduino 绘制来自 mpu6050 imu 的数据 MPU6050 发送数据的速度比绘图快 Arduino 代码从串口提供 6 个数据 即偏航 俯仰 滚动 轴 ay 和 az 我需要快速情节的建议 Python代码 i
  • Arduino 上的 Serial 和 Stream 有什么区别,Serial.write 是如何实现的?

    我很难理解串行和流这两个术语之间的区别 串行不是流的一种吗 我对作业有一些我不明白的问题 计算机通过使用 流或串行 读取 彼此发送的数据来确定每个字节的含义 Also Serial write 我也很困惑 它返回一个字节的数据 对吗 一个字
  • 将浮点数转换为字节数组的 C 函数

    我正在尝试创建一个函数来接受浮点变量并将其转换为字节数组 我找到了一段有效的代码片段 但如果可能的话 希望在函数中重用它 我也在使用 Arduino 环境 但我知道它接受大多数 C 语言 目前工作 float variable 1 11 b
  • 使用 Java 控制 Arduino

    我正在寻找一个LED http en wikipedia org wiki Light emitting diode用Java程序打开和关闭 我用 C 完成了这个项目大约 5 分钟 但用 Java 似乎更具挑战性 我让 Arduino 等待
  • 通过iPhone音频插孔读取数据

    我正在寻找一种方法来读取通过 iPhone 的音频插孔从 Arduino 发送的原始数据 我搜索了很多并发现this https github com sanjibahmad Is Headphone Plugged In tree mas
  • 从 iBeacon 接收 BLE 信号到 Bluno(arduino with BLE)

    我想从 iBeacon 到 Bluno 接收 rssi 信号和 UUID Arduino 板具有 BLE 对此有一些疑问 有没有从 BLE 到 BLE 接收 UUID 和 rssi 的解决方案 两个BLE设备可以互相通信吗 我想找一些网站来
  • 当我启动程序时,Arduino IDE (Win10) 崩溃

    我的 Arduino IDE Win10 上的版本为 1 8 12 在启动时崩溃 运行arduino debug exe我收到此错误消息 C Program Files x86 Arduino gt arduino debug exe Se
  • Arduino C++ 代码:可以使用虚函数和异常吗?

    跟进这条评论 https stackoverflow com questions 452139 writing firmware assembly or high level 452401从问题中编写固件 汇编还是高级 https stac
  • 带 firebase 的 Nodemcu(ESP8266)

    这是我上传到 ESP8266 以连接到 firebase 的代码 include
  • Arduino 串行输出丢弃字符

    当我尝试为我的 Arduino Uno 编写一些代码时 我遇到了一个奇怪的串行输出 我有这个原始代码 MyClass myclass void setup Serial Begin 9600 Serial println Starting
  • Arduino CLI 编译器“ino”和一些基本草图导致编译错误

    我正在尝试使用 cli 编译器 ino 编译基本的以太网 UDP Sketch 我从他们的 github 存储库下载了最新版本 ino init然后是 src sketch ino 的内容 include
  • Arduino 上的串行消息到整数

    我希望我的 Arduino 通过串行通信接收一个整数 你能帮我解决这个问题吗 它应该是这样的形式 int value strtoint Serial read 有多种方法可以读取整数Serial 很大程度上取决于数据发送时的编码方式 Ser

随机推荐