防盗镇楼 本文地址: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同时工作,但是波特率需要精挑细选.
因为底层定时器或同时接收干扰之类的问题吧,导致各种使用限制.
具体看下文档吧.我也没细看…