Embedded 简单串行点对点通信协议

Embedded 简单串行点对点通信协议,embedded,serial-port,protocols,Embedded,Serial Port,Protocols,我需要两个设备(一台PC和一台微控制器)之间的简单通信协议。PC必须向micro发送一些命令和参数。micro必须传输字节数组(来自传感器的数据) 数据必须是(除了奇偶校验,我想我还需要一些其他的数据校正方法) 有没有标准的解决方案?(我只需要一个想法,而不是完整的解决方案) 请注意,如有任何建议,我们将不胜感激。P.P.S抱歉,有语法错误,希望你能理解 编辑1。我还没有决定是主/从协议还是双方都可以启动通信。电脑必须知道micro何时完成了工作,并可以发送数据。如果数据准备就绪,它可以连续轮询

我需要两个设备(一台PC和一台微控制器)之间的简单通信协议。PC必须向micro发送一些命令和参数。micro必须传输字节数组(来自传感器的数据)

数据必须是(除了奇偶校验,我想我还需要一些其他的数据校正方法)

有没有标准的解决方案?(我只需要一个想法,而不是完整的解决方案)

请注意,如有任何建议,我们将不胜感激。P.P.S抱歉,有语法错误,希望你能理解

编辑1。我还没有决定是主/从协议还是双方都可以启动通信。电脑必须知道micro何时完成了工作,并可以发送数据。如果数据准备就绪,它可以连续轮询micro,或者在作业完成时micro可以发送数据。我不知道哪一个更好更简单

编辑2。硬件和协议。由于PC中使用了C串行标准,我将使用。我将只使用RxD、TxD和GND信号。我不能使用额外的电线,因为微控制器AFAIK不支持它们。顺便说一句,我用的是ATmega128芯片

因此,我将使用固定波特率、8位数据、2位停止位而不进行奇偶校验(或使用?)

。这就是我的问题主要关心的。谢谢你的建议,还有协议。我将对此进行研究。

我将使用。我过去在这方面运气很好。对于点对点串行,我只需要使用,而忘记所有其他控制内容,因为这可能会有点过头

除了使用HDLC对数据包进行成帧之外。我的数据包格式如下。这就是使用802.11传递选项的方式

U8 cmd;
U8 len;
u8 payload[len];
每个命令包的总大小为len+2

然后定义如下命令

#define TRIGGER_SENSOR 0x01
#define SENSOR_RESPONSE 0x02
另一个优点是,您可以添加新命令,如果您正确地设计解析器以忽略未定义的命令,那么您将具有一些向后兼容性

因此,将所有这些放在一起,数据包将如下所示

 // total packet length minus flags len+4
 U8 sflag;   //0x7e start of packet end of packet flag from HDLC
 U8 cmd;     //tells the other side what to do.
 U8 len;     // payload length
 U8 payload[len];  // could be zero len
 U16 crc;
 U8 eflag;   //end of frame flag
然后,系统将监控串行流中的标志0x7e,当该标志存在时,您将检查其长度是否为pklen>=4和pklen=len+4,以及crc是否有效。注意:不要仅仅依靠crc来检测小数据包,你会得到很多误报,也会检查长度。如果长度或crc不匹配,只需重置长度和crc,然后开始解码新帧。如果匹配,则将数据包复制到新的缓冲区,并将其传递给命令处理函数。收到标志时,始终重置长度和crc

对于命令处理功能,请抓取cmd和len,然后使用开关处理每种类型的命令。我还要求特定事件发送响应,以便系统的行为类似于事件驱动的远程过程调用

因此,例如,传感器设备可以有一个定时器或响应命令来读取读数。然后,它将格式化一个数据包并将其发送到PC,PC将响应它已收到该数据包。如果没有,则传感器设备可以在超时时重新发送


此外,当您进行网络传输时,您应该将其设计为网络堆栈,就像as点一样,不要忘记。我关于HDLC的帖子是和。

您没有具体说明微控制器的行为,但是从micro传输的所有内容都是对PC命令的直接响应吗?如果这样做,那么您似乎可以使用某种主/从协议(这通常是最简单的解决方案)。如果双方都可以启动通信,则需要更通用的数据链路层协议。这是一个经典的协议。尽管完整的协议对于您的需求来说可能是一种过分的做法,但您至少可以使用相同的帧格式。您还可以看看是否有一些有用的部分。

这里有一个替代协议:

u8  Sync          // A constant value which always marks the start of a packet
u16 Length        // Number of bytes in payload
u8  Data[Length]  // The payload
u16 Crc           // CRC
使用RS232/UART,因为PC(串行端口)和处理器(UART)已经可以以最小的麻烦处理(只需要一个芯片或类似的芯片来进行电平转换)

使用RS232/UART,如果不相关,您不必担心主/从机。如有必要,可使用流量控制

建议的PC软件:可以自己编写,也可以用于简单的监控(评估版是免费的)

对于更大的错误检查,最简单的是奇偶校验,或者如果您需要更强大的功能,也许

在任何情况下,无论你做什么:保持简单

编辑:在PC上使用RS232比以前更容易,因为您现在可以使用USB到RS232/TTL转换器。一端插入电脑的USB插座,显示为普通串行端口;另一个输出5伏或3.3伏信号,可直接连接到处理器,无需电平转换


我们使用的是FDTI芯片,它非常适合这种应用。

RS232协议很棘手。使用HDLC的建议是一个很好的建议,但它不是整个解决方案。您还需要决定其他事项:

  • 如何确定两个设备之间的波特率?汽车旅馆?预定义,还是设置解释
  • 你会在软件或硬件或两者中进行流量控制吗?注意,如果使用硬件流控制,则必须确保电缆正确构建
  • 说到电缆,这对RS233来说是一个巨大的痛苦。根据设备的不同,您可能需要使用直通电缆、交叉电缆或变型电缆
  • 使用基于软件的流量控制机制是有效的,因为它允许使用最简单的电缆-仅三线(TX、RX和common)
  • 你选择7位还是8位的单词
  • 硬件奇偶校验或软件错误检查
我建议您使用8个数据位,无硬件奇偶校验,1个停止bi
publish("someTopic","someMessage")
publish_f32("foo",1.23e-4)
publish_u32("bar",56789)
// Add an indexing meaning to the topic
publish("foo:1",45) // foo with index = 1
publish("foo:2",56) // foo with index = 2

// Add a grouping meaning to the topic
publish("bar/foo",67) // foo is under group 'bar'

// Combine
publish("bar/foo:45",54)
// your device's uart library function signatures (usually you already have them)
int32_t read(void * buf, uint32_t sizeToRead);
int32_t readable();
int32_t write(void * buf, uint32_t sizeToWrite);
int32_t writeable();
// At the beginning of main function, this is the ONLY code you have to add to support a new device with telemetry
TM_transport transport;
transport.read = read;
transport.write = write;
transport.readable = readable;
transport.writeable = writeable;

// Init telemetry with the transport structure
init_telemetry(&transport);  

// and you're good to start publishing
publish_i32("foobar",...
import runner
import pytelemetry.pytelemetry as tm
import pytelemetry.transports.serialtransport as transports
import time

transport = transports.SerialTransport()
telemetry = tm.pytelemetry(transport)
app = runner.Runner(transport,telemetry)

def printer(topic, data):
    print(topic," : ", data)

options = dict()
options['port'] = "COM20"
options['baudrate'] = 9600

app.connect(options)

telemetry.subscribe(None, printer)
telemetry.publish('bar',1354,'int32')
time.sleep(3)

app.terminate()
pytlm