[Arduino]解决多个软件串口SoftwareSerial无法接收问题

防盗镇楼 本文地址:https://superliii.blog.csdn.net/article/details/147236745

前言

奇了个大怪,我想用Nano采集两个传感器的数据,发现软串口数据没有返回??

经调试发现只要第二个SoftwareSerial.begin(),第一个SoftwareSerial就无法接收.这很反直觉…

发现问题

所以去看了下SoftwareSerial文档,上面明确标注了

SoftwareSerial 库具有以下已知限制:

  • 它不能同时发送和接收数据。
  • 如果使用多个软件串行端口,则一次只能有一个端口接收数据。
  • 并非 Mega 和 Mega 2560 板上的所有引脚都支持更改中断,因此只有以下引脚可用于 RX:10、11、12、13、14、15、50、51、52、53、A8 (62)、A9 (63)、A10 (64)、A11 (65)、A12 (66)、A13 (67)、A14 (68)、A15 (69)。 并非 Leonardo 和 Micro 板上的所有引脚都支持更改中断,因此只有以下引脚可用于 RX:8、9、10、11、14 (MISO)、15 (SCK)、16 (MOSI)。
  • 在 Arduino 或 Genuino 101 板上,当前最大 RX 速度为 57600bps。
  • 在 Arduino 或 Genuino 101 板上,RX 在数字引脚 13 上不起作用。

那么什么是"一次只能有一个端口接收数据"呢?我们再来看看SoftwareSerial.listen()这个函数:

  • 使选定的 SoftwareSerial 对象能够侦听。一次只能侦听一个 SoftwareSerial 对象;到达其他端口的数据将被丢弃。在调用 listen() 函数期间,将丢弃已收到的任何数据(除非给定实例已在侦听)。
  • 如果它替换另一个,则返回 true。

所以,作者暗示我们可以通过portOne.listen();portTwo.listen();之间的切换,来实现多个软串口的数据接收.

我们再来看看官方案例代码:

#include <SoftwareSerial.h>
// software serial #1: RX = digital pin 10, TX = digital pin 11

SoftwareSerial portOne(10, 11);

// software serial #2: RX = digital pin 8, TX = digital pin 9
// on the Mega, use other pins instead, since 8 and 9 don't work on the Mega

SoftwareSerial portTwo(8, 9);

void setup() {

  // Open serial communications and wait for port to open:

  Serial.begin(9600);

  while (!Serial) {

    ; // wait for serial port to connect. Needed for native USB port only

  }

  // Start each software serial port

  portOne.begin(9600);

  portTwo.begin(9600);
}

void loop() {

  // By default, the last initialized port is listening.

  // when you want to listen on a port, explicitly select it:

  portOne.listen();

  Serial.println("Data from port one:");

  // while there is data coming in, read it

  // and send to the hardware serial port:

  while (portOne.available() > 0) {

    char inByte = portOne.read();

    Serial.write(inByte);

  }

  // blank line to separate data from the two ports:

  Serial.println();

  // Now listen on the second port

  portTwo.listen();

  // while there is data coming in, read it

  // and send to the hardware serial port:

  Serial.println("Data from port two:");

  while (portTwo.available() > 0) {

    char inByte = portTwo.read();

    Serial.write(inByte);

  }

  // blank line to separate data from the two ports:

  Serial.println();
}

一目了然了吧.

解决

方案一:分时通信(上述官方案例)

如果你传感器是主动不停的发送数据,可以通过不停的在两个串口间切换完成数据同步.
这种方法有一定几率丢失数据,因为同时数据抵达的话,SoftwareSerial同时只能有一个接收端口.
另外还需注意验证数据完整性.

方案二:轮询切换

如果你的两个传感器都属于"一问一答"机制,那么可以改造成:
在发送查询指令前,切换到该传感器的软串口.

方案三: 主从切换

我的硬件是433无线通信+微波雷达,要实现通过433模块发送雷达参数设置
因为443模块需要持续监听远程指令,所以433模块为主机,雷达为从机.
当主机433模块接收到设置指令,处理转发给从机雷达
从机雷达串口发送数据前,切换到雷达的软串口监听,等待一帧数据或超时后切换回主机433继续监听下一个指令.
(别问我为啥不用8266,因为引脚不够)

方案四:使用AltSoftSerial库

AltSoftSerial 使用定时器硬件模拟额外的串行端口, 允许您与另一个串行设备通信。

时间有限,这里只是提一嘴.这个库还需伙伴们自行研究.
它可以与SoftwareSerial和Serial同时工作,但是波特率需要精挑细选.
因为底层定时器或同时接收干扰之类的问题吧,导致各种使用限制.
具体看下文档吧.我也没细看…

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值