【问题标题】:Can't get original value after sending by serial port串口发送后无法获取原始值
【发布时间】:2019-08-14 18:33:20
【问题描述】:

我编写了一个简单的代码,用于使用蓝牙串口发送 int 值。

发射器:

#include <SoftwareSerial.h>
#include "PWM.hpp"

PWM PWM(2);
SoftwareSerial BTSerial(8,9);

void setup()
{
  Serial.begin(9600);   
  Serial.println("Go");
  BTSerial.begin(9600);  
  BTSerial.write("AT+INQ\r\n");
  delay(10000); 
  BTSerial.write("AT+CONN1\r\n");
  delay(100);
  PWM.begin(true);
}

void loop()
{
  int pwmValue = PWM.getValue();
  Serial.println(pwmValue);
  BTSerial.write(pwmValue); 
  delay(100);
}

发射器部分Serial.println的输出是正确的:

1500

但在接收器部分不是。这是接收者的代码:

#include <SoftwareSerial.h>

SoftwareSerial BTSerial(8, 9);

void setup() {
  Serial.begin(9600);
  BTSerial.begin(9600);
  BTSerial.write("AT+NAME=Remote\r\n");
}

void loop() {

 if (BTSerial.available()) {
  int pwmValue = BTSerial.read();
  Serial.println(pwmValue);
 }

Serial.println 的错误输出是:

220

我认为问题在于类型转换。

【问题讨论】:

  • @EugeneSh。如果你有答案,请写在答案部分,而不是这里。谢谢。
  • 哦。对不起。我已经修复了它,但价值仍然是错误的。现在 220 不是 ⸮⸮,但这是错误的。正确值为1500

标签: c++ arduino c++14


【解决方案1】:

SoftwareSerial::read 正在返回单字节读取。 如果您以十六进制检查预期的1500,它是0x05DC,它的低字节是0xDC,它恰好是十进制的220

【讨论】:

  • 如何获取所有字节?
  • 我认为SoftwareSerial 一次只能读取一个字节。所以循环。
【解决方案2】:

使用write() 的多字节变体,您可以使用:

BTSerial.write(&pwmValue, sizeof pwmValue);

为了接收你需要一个循环:

union {
    int  i;
    char c[0];
} pwmValue;
int receivedBytes = 0;

void loop() {
    if (BTSerial.available()) {
        pwmValue.c[receivedBytes] = BTSerial.read();
        receivedBytes++;
        if (receivedBytes == sizeof pwmValue) {
            Serial.println(pwmValue.i);
            receivedBytes = 0;
        }
    }
}

【讨论】:

  • 哦,对不起。我被具有此重载变体的Serial.read() 误导了。我会编辑答案。
【解决方案3】:

在文档https://github.com/PaulStoffregen/SoftwareSerial/blob/master/SoftwareSerial.cpp 中,您可以看到这两个函数都与 uint_8t 一起工作——保证有 8 位(1 字节)。最多可容纳 256 个值,因此 1500 mod 256 为 220

看起来库准备只传输 char 大小的数据,因此您需要在两种大小上转换更大的数字。

用于发送 int:

int n = pwmValue;

while (n > 0) {
    int digit = n % 10;
    n = n / 10;
    BTSerial.write(digit);
}

用于接收 int:

int n = 0; //future result
int decs = 1;
int temp;

while ((temp = BTSerial.read()) != -1) {
    n += temp * decs;
    decs *= 10;
}

【讨论】:

  • write可以根据documentation处理多字节数据。
  • 有趣的是它不在链接的源代码中。也许不同的图书馆。
  • 所有方法都在基类 Print 中,并且使用纯虚拟 write(byte) 实现,必须在派生类中实现。并学习如何在 Stack Overflow 上写答案之前将多字节值分解为字节
  • 重点是,使用这种方法,您将有三个字节传输来传输单个字节,例如112 您将有三个相对较重的除以10以及三个模 10 操作。
  • 另一个问题:BTSerial.read() 如果没有可用字节,则返回-1
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2018-05-15
  • 2012-05-28
  • 1970-01-01
  • 2010-09-21
  • 2020-03-09
  • 2023-03-16
  • 1970-01-01
相关资源
最近更新 更多