二进制串行通信协议 - 得到意外响应
Posted
技术标签:
【中文标题】二进制串行通信协议 - 得到意外响应【英文标题】:Protocol for Serial Communication in binary - getting unexpected response 【发布时间】:2020-01-06 20:48:13 【问题描述】:我正在尝试在 Raspberry 上使用 Python3 与串行设备进行通信。协议如下:
-
主机发送命令字节(包含地址和数据类型)
设备回显命令字节
主机发送操作数字节(更多数据类型信息)
设备回显操作数字节以及数据的第一个字节
主机回显数据的第一个字节。设备发送第二个字节的数据。重复直到 5 个总数据字节
设备应该只接收和发送二进制文件(根据我一直在参考的过时手册),但是当我要求第二个数据字节时,我得到“\t”或其他一些奇怪的字符。命令、操作数和第一个数据字节似乎都可以正常工作。但在那之后,我开始得到一些意想不到的角色。
设备实际上是否以二进制以外的方式进行通信?
我的编码天赋仍处于初级阶段,因此请忽略过度使用打印命令。我是新手,请随意挑剔..
import serial
import time
import binascii
ser = serial.Serial(
port='/dev/ttyUSB0',\
baudrate=9600,\
parity=serial.PARITY_NONE,\
stopbits=serial.STOPBITS_ONE,\
bytesize=serial.EIGHTBITS,\
timeout = 2)
command=b"\x92"
operand =b"\x02"
sleepy = 0.2
data = bytearray()
while True:
ser.write(command) #send command byte
time.sleep(sleepy)
print(ser.read(1)) #recieve command byte
time.sleep(sleepy)
ser.write(operand) #send operand byte
time.sleep(sleepy)
echo = ser.read(2)#recieve operand byte & first data byte
print(echo)
time.sleep(sleepy)
data.append(echo[1])
ser.write(bytearray([echo[-1]])) #send first data byte echo
time.sleep(sleepy)
echo = ser.read(10) #recieve second data byte
print(echo)
time.sleep(sleepy)
data.append(echo[-1])
print(echo[-1])
ser.write(bytearray([echo[-1]])) #send second data byte echo
time.sleep(sleepy)
echo = ser.read(10) #recieve third data byte
print(echo)
time.sleep(sleepy)
data.append(echo[-1])
print(echo[-1])
ser.write(bytearray([echo[-1]])) #send third data byte echo
time.sleep(sleepy)
echo = ser.read(10) #recieve fourth data byte
print(echo)
time.sleep(sleepy)
data.append(echo[-1])
print(echo[-1])
ser.write(bytearray([echo[-1]])) #send fourth data byte echo
time.sleep(sleepy)
echo = ser.read(10) #recieve 5th data byte
print(echo)
time.sleep(sleepy)
data.append(echo[-1])
print(echo[-1])
print(data)
ser.close()
例如,当我运行它时,我得到数据数组“(b'\x04\x08hT^')”。 我总是得到第一个 \x04 但之后的字符是随机的。
【问题讨论】:
【参考方案1】:我已经让这个程序工作了。我仍在获取包含一些意外字符的数据,但使用 binascii.hexlify 后跟 ":08b".format(int(c[1], base=16)) 将其转换为我需要的 8 位二进制文件。下面来看看似乎有效的方法。就上下文而言,该程序从水分分析仪收集数据。所以底部的数学是将 40 位二进制转换为浮点值。
def get_h20():
data = bytearray()
echo = bytearray()
command=bytearray([146])
operand =bytearray([1])
sleepy = 0.02
ser = serial.Serial(
port='/dev/ttyUSB1',\
baudrate=9600,\
parity=serial.PARITY_NONE,\
stopbits=serial.STOPBITS_ONE,\
bytesize=serial.EIGHTBITS,\
timeout = 0)
data = bytearray()
ser.write(command) #send command byte
time.sleep(sleepy)
echo = ser.read(1) #recieve command byte
data = data + echo
ser.write(operand)
time.sleep(sleepy)
echo = ser.read(2)
data = data + echo
ser.write(bytearray([echo[-1]]))
time.sleep(sleepy)
echo = ser.read(1)
data = data + echo
ser.write(bytearray([echo[-1]]))
time.sleep(sleepy)
echo = ser.read(1)
data = data + echo
ser.write(bytearray([echo[-1]]))
time.sleep(sleepy)
echo = ser.read(1)
data = data + echo
ser.write(bytearray([echo[-1]]))
time.sleep(sleepy)
echo = ser.read(1)
data = data + echo
return(data)
ser.close()
将原始 h2o 数据转换为 ppb
def raw_to_ppb(数据):
raw_hex = str(binascii.hexlify(data[2:]))
c = [raw_hex[i:i+2] for i in range (0, len(raw_hex), 2)]
try:
byte1 = ":08b".format(int(c[1], base=16))
byte2 = ":08b".format(int(c[2], base=16))
byte3 = ":08b".format(int(c[3], base=16))
byte4 = ":08b".format(int(c[4], base=16))
byte5 = ":08b".format(int(c[5], base=16))
h20_bin = byte1+byte2+byte3+byte4+byte5
m1 = h20_bin[14:16]
m2 = h20_bin[17:24]
m3 = h20_bin[25:32]
m4 = h20_bin[33:40]
m = m1+m2+m3+m4
mantissa = (int(m[0])*2**22+int(m[1])*2**21+int(m[2])*2**20+int(m[3])*\
2**19+int(m[4])*2**18+int(m[5])*2**17+int(m[6])*2**16+int(m[7])*\
2**15+int(m[8])*2**14+int(m[9])*2**13+int(m[10])*2**12+int(m[11])*\
2**11+int(m[12])*2**10+int(m[13])*2**9+int(m[14])*2**8+int(m[15])*\
2**7+int(m[16])*2**6+int(m[17])*2**5+int(m[18])*2**4+int(m[19])*\
2**3+int(m[20])*2**2+int(m[21])*2**1+int(m[22])*2**0)/8388608
e1 = h20_bin[5:8]
e2 = h20_bin[9:14]
e = e1+e2
exponent = int(e,2)
sign = (-1)**(int(h20_bin[4],2))
h20_ppb = sign*(2**(exponent-127))*(1+mantissa)
return(str(h20_ppb))
except:
pass
我仍然想进一步了解从分析仪收到的数据格式。如果我从 get_h2o 函数打印数据变量,那么我仍然会得到奇怪的 "b'\x04\x08hT^" 响应......但 python 似乎知道如何处理它。
【讨论】:
以上是关于二进制串行通信协议 - 得到意外响应的主要内容,如果未能解决你的问题,请参考以下文章