python的pyserial模块接收串口助手发送HEX过来接收到非16进制乱码问题

本文介绍如何解决Python在使用pyserial进行串口通信时遇到的HEX值乱码问题,通过创建映射字典进行解码,确保正确接收十六进制数据。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

        python在调用pyserial通信的时候,接收到串口调试助手或者设备发送过来的HEX值,在特定位置会出现错误编码,接收到的不是十六进制数据,而是一些乱符号,' ', '!', '"', '#', '$', '%', '&', '\'', '(', ')', '*', '+', ',', '-', '.', '/'等等,这个是因为serial中没有对应的解码机制,python中带有的decode()解码对特定的一部分HEX值可以解决,对于其他是不能解决的,如果我们要正确接收HEX值应该如果解决呢?在这里HEX值只需要写两位。

        解决这个问题我们首先要是到ASCII与HEX的关系,这里有两个映射表,分别对应发送端的HEX值和接收端的HEX值,在这里涉及到的转换命名如下:发送端以ascii_data命名,接收端以hex_data命名。

ascii_data = [['00', '01', '02', '03', '04', '05', '06', '07', '08', '09', '0A', '0B', '0C', '0D', '0E', '0F'],
              ['10', '11', '12', '13', '14', '15', '16', '17', '18', '19', '1A', '1B', '1C', '1D', '1E', '1F'],
              ['20', '21', '22', '23', '24', '25', '26', '27', '28', '29', '2A', '2B', '2C', '2D', '2E', '2F'],
              ['30', '31', '32', '33', '34', '35', '36', '37', '38', '39', '3A', '3B', '3C', '3D', '3E', '3F'],
              ['40', '41', '42', '43', '44', '45', '46', '47', '48', '49', '4A', '4B', '4C', '4D', '4E', '4F'],
              ['50', '51', '52', '53', '54', '55', '56', '57', '58', '59', '5A', '5B', '5C', '5D', '5E', '5F'],
              ['60', '61', '62', '63', '64', '65', '66', '67', '68', '69', '6A', '6B', '6C', '6D', '6E', '6F'],
              ['70', '71', '72', '73', '74', '75', '76', '77', '78', '79', '7A', '7B', '7C', '7D', '7E', '7F'],
              ['80', '81', '82', '83', '84', '85', '86', '87', '88', '89', '8A', '8B', '8C', '8D', '8E', '8F'],
              ['90', '91', '92', '93', '94', '95', '96', '97', '98', '99', '9A', '9B', '9C', '9D', '9E', '9F'],
              ['A0', 'A1', 'A2', 'A3', 'A4', 'A5', 'A6', 'A7', 'A8', 'A9', 'AA', 'AB', 'AC', 'AD', 'AE', 'AF'],
              ['B0', 'B1', 'B2', 'B3', 'B4', 'B5', 'B6', 'B7', 'B8', 'B9', 'BA', 'BB', 'BC', 'BD', 'BE', 'BF'],
              ['C0', 'C1', 'C2', 'C3', 'C4', 'C5', 'C6', 'C7', 'C8', 'C9', 'CA', 'CB', 'CC', 'CD', 'CE', 'CF'],
              ['D0', 'D1', 'D2', 'D3', 'D4', 'D5', 'D6', 'D7', 'D8', 'D9', 'DA', 'DB', 'DC', 'DD', 'DE', 'DF'],
              ['E0', 'E1', 'E2', 'E3', 'E4', 'E5', 'E6', 'E7', 'E8', 'E9', 'EA', 'EB', 'EC', 'ED', 'EE', 'EF'],
              ['F0', 'F1', 'F2', 'F3', 'F4', 'F5', 'F6', 'F7', 'F8', 'F9', 'FA', 'FB', 'FC', 'FD', 'FE', 'FF']]

hex_data = [['\\x00', '\\x01', '\\x02', '\\x03', '\\x04', '\\x05', '\\x06', '\\x07', '\\x08', '\\t', '\\n', '\\x0b', '\\x0c','\\r', '\\x0e', '\\x0f'],
    ['\\x10', '\\x11', '\\x12', '\\x13', '\\x14', '\\x15', '\\x16', '\\x17', '\\x18', '\\x19', '\\x1a', '\\x1b', '\\x1c', '\\x1d', '\\x1e', '\\x1f'],
    [' ', '!', '"', '#', '$', '%', '&', '\'', '(', ')', '*', '+', ',', '-', '.', '/'],
    ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9', ':', ';', '<', '=', '>', '?'],
    ['@', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O'],
    ['P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', '[', '\\\\', ']', '^', '_'],
    ['`', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o'],
    ['p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', '{', '|', '}', '~', '\\x7f'],
    ['\\x80', '\\x81', '\\x82', '\\x83', '\\x84', '\\x85', '\\x86', '\\x87', '\\x88', '\\x89', '\\x8a', '\\x8b', '\\x8c', '\\x8d', '\\x8e', '\\x8f'],
    ['\\x90', '\\x91', '\\x92', '\\x93', '\\x94', '\\x95', '\\x96', '\\x97', '\\x98', '\\x99', '\\x9a', '\\x9b', '\\x9c', '\\x9d', '\\x9e', '\\x9f'],
    ['\\xa0', '\\xa1', '\\xa2', '\\xa3', '\\xa4', '\\xa5', '\\xa6', '\\xa7', '\\xa8', '\\xa9', '\\xaa', '\\xab', '\\xac', '\\xad', '\\xae', '\\xaf'],
    ['\\xb0', '\\xb1', '\\xb2', '\\xb3', '\\xb4', '\\xb5', '\\xb6', '\\xb7', '\\xb8', '\\xb9', '\\xba', '\\xbb', '\\xbc', '\\xbd', '\\xbe', '\\xbf'],
    ['\\xc0', '\\xc1', '\\xc2', '\\xc3', '\\xc4', '\\xc5', '\\xc6', '\\xc7', '\\xc8', '\\xc9', '\\xca', '\\xcb', '\\xcc', '\\xcd', '\\xce', '\\xcf'],
    ['\\xd0', '\\xd1', '\\xd2', '\\xd3', '\\xd4', '\\xd5', '\\xd6', '\\xd7', '\\xd8', '\\xd9', '\\xda', '\\xdb', '\\xdc', '\\xdd', '\\xde', '\\xdf'],
    ['\\xe0', '\\xe1', '\\xe2', '\\xe3', '\\xe4', '\\xe5', '\\xe6', '\\xe7', '\\xe8', '\\xe9', '\\xea', '\\xeb', '\\xec', '\\xed', '\\xee', '\\xef'],
    ['\\xf0', '\\xf1', '\\xf2', '\\xf3', '\\xf4', '\\xf5', '\\xf6', '\\xf7', '\\xf8', '\\xf9', '\\xfa', '\\xfb', '\\xfc', '\\xfd', '\\xfe', '\\xff']]

        有了这两张表,如果我们是接收串口助手或者设备发送过来的数据出现16进制乱码的时候,我们可以通过ascii_to_hex_dict和hex_to_ascii_dict两张字典进行解码。字典打吗如下:

    def ascii_to_hex_dict(ascii_data=ascii_data,hex_data=hex_data):#对应的字典编码
        ascii_to_hex_dict={}
        for i in range(len(ascii_data)):
            for j in range(len(ascii_data[0])):
                name=ascii_data[i][j]
                name_value=hex_data[i][j]
                ascii_to_hex_dict[name]=name_value
        return ascii_to_hex_dict

    def hex_to_ascii_dict(ascii_data=ascii_data,hex_data=hex_data):#对应的字典编码
        hex_to_ascii_dict={}
        for i in range(len(ascii_data)):
            for j in range(len(ascii_data[0])):
                name=hex_data[i][j]
                name_value=ascii_data[i][j]
                hex_to_ascii_dict[name]=name_value
        return hex_to_ascii_dict

        调用这两个字典后,会有一个返回值,我们只需要向返回值中输入需要解码的单个字符就行。tmp=hex_to_ascii_dict()可以解决串口调试助手发送过来的HEX值出现乱码的问题,在serial采用read接收单个字符,将接收的字符进行data=str(data)[:-1][2:]处理后,打印print(tmp[data])就可以显示正确的HEX值了;另外一个的使用相同。如果数据多,要接收一串数据,自己通过数组将接收到的单个数据append到数组中,并做相应判断来判断当前数据是否是自己想要的数据。

        此外,在python中有这么一些数据转换关系函数:ord,hex,int,chr等,根据需要可以自己百度查询一下,或者官网查询使用。下面是16进制,10进制,ASCII,HEX的转换。

    def hex_to_dec(string_num):#16进制变成10进制
        # print(string_num.upper())#如果输入的16进制中有小写,则通过upper将小写字符换成大写字符
        # int('A',16)#将16进制的转化成10进制
        result=str(int(string_num.upper(), 16))
        return result

    def dec_to_hex(string_num):#10进制变成16进制,('10')
        base = [str(x) for x in range(10)] + [chr(x) for x in range(ord('A'), ord('A') + 6)]#对应的16进制编码(0-9,A-F)
        num = int(string_num)#对输入的数据进行int转化
        mid = []
        while True:#通过不断的除以16取余数实现10进制转16进制
            if num == 0: break#如果商为0则停止循环
            num, rem = divmod(num, 16)#对输入的10进制数进行:取整,取余
            mid.append(base[rem])#将余数转化成对应的16进制数,并添加到数组中
        return ''.join([str(x) for x in mid[::-1]])#字符串拼接并取反,最后返回16进制数

    def to_hexstring(data='TEST'):
        result=''
        for i in data:
            tmp=hex(ord(i))[2:].upper()
            if len(tmp)==1:
                result += str(0)+str(tmp) + ' '
            else:
                result+=str(tmp)+' '
        return result

    def to_asciistring(data='54 5174'):
        data=data.split(' ')
        result=''
        datalength=len(data)
        for i in range(datalength):
            print(data[i])
            tmp = chr(int(data[i], 16))
            result += tmp
        return result


 

 

<think>好的,我现在需要帮助用户解决关于松下设备通过RS232通信的问题。首先,我得理清用户的需求。用户提到了松下设备的RS232通信协议实现方法,可能他们正在尝试建立这样的通信,但不确定具体步骤或协议细节。 首先,我应该回忆一下松下设备常用的通信协议。根据之前的引用,特别是引用[1]提到的MINAS标准协议Modbus-RTU,这可能是一个关键点。用户的问题中可能涉及松下伺服驱动器或类似设备,因为MINAS是松下伺服的一个系列。所以,松下设备可能使用MINAS标准协议或Modbus-RTU,具体需要根据设备型号设置确认。 接下来,用户需要知道实现方法,包括硬件连接软件编程。硬件方面,RS232需要正确的接线,比如TX、RX、GND的连接,以及波特率、数据位等参数的设置。软件方面,可能需要使用Python或Java等语言,结合相应的库,比如Python的pymodbus或serial库,或者Java的RXTX库,如引用[2][3]提到的。 然后,我需要考虑用户可能遇到的常见问题,比如通信协议选择不正确、参数配置错误、接线问题等,这些都需要在回答中给出解决方案或排查步骤。 另外,引用[2]提到了Python中使用Modbus-RTU的步骤,包括确定协议、安装库、建立连接等,这可能适用于松下设备如果支持Modbus的情况。而如果设备使用的是MINAS协议,可能需要查阅松下具体的文档,因为协议细节可能不同。 用户可能没有明确说明设备的具体型号,所以在回答中需要建议他们查阅设备手册,确认通信协议的设置,比如参数Pr5.37的设置,如引用[1]中的0、1、2选项。这一步很关键,因为协议不同,实现方法也会不同。 最后,需要提供具体的代示例,比如Python中使用pyserial行通信,或者使用Modbus-RTU的示例,帮助用户快速上手。同时,列出常见问题及解决方法,帮助用户自行排查问题。 总结下来,回答的结构应该是先介绍协议类型,然后分步骤说明实现方法,包括硬件软件部分,接着给出代示例,最后是常见问题解答相关问题推荐。需要确保所有技术细节准确,比如波特率、数据位等参数,以及引用的正确性,如引用相关的协议设置库。</think>### 松下RS232通信协议及实现方法 #### 1. 松下设备RS232通信协议类型 松下设备(如伺服驱动器、PLC等)通常支持以下两种通信协议: - **MINAS标准协议**:松下私有协议,专用于伺服驱动器控制,支持参数读写实时状态监控[^1] - **Modbus-RTU协议**:标准工业协议,适用于RS232/RS485通信,需在设备参数中设置为`Pr5.37=1`(RS232一对一通信)[^1] #### 2. 实现步骤 ##### 硬件准备 1. **接线规范** - 设备端:`TXD`(发送端)、`RXD`(接收端)、`GND`(地线) - 电脑端:通过USB转RS232转换器连接,需交叉连接(设备TXD接转换器RXD,设备RXD接转换器TXD) - 波特率:常见为`9600`或`115200`,数据位`8`,停止位`1`,无校验[^3] 2. **设备参数设置** 通过设备操作面板设置: - 通信协议选择:设置参数`Pr5.37` $$ \text{Pr5.37}=0 \rightarrow \text{MINAS协议},\quad \text{Pr5.37}=1 \rightarrow \text{Modbus-RTU} $$ - 波特率匹配:设置参数`Pr5.38`(如`9600`) ##### 软件实现(以Python为例) **使用MINAS协议示例**: ```python import serial # 初始化串口 ser = serial.Serial( port='COM3', # 端口号 baudrate=9600, # 波特率 bytesize=serial.EIGHTBITS, parity=serial.PARITY_NONE, stopbits=serial.STOPBITS_ONE ) # 发送指令(读取当前位置) command = bytes.fromhex('02 30 31 03 0D') # 示例指令 ser.write(command) # 接收响应 response = ser.read(10) print("Received:", response.hex()) ``` **使用Modbus-RTU协议示例**(需安装`pymodbus`): ```python from pymodbus.client import ModbusSerialClient client = ModbusSerialClient( method='rtu', port='COM3', baudrate=9600, timeout=1 ) # 读取保持寄存器(地址0x0001) result = client.read_holding_registers(address=0x0001, count=1, unit=1) print("Register value:", result.registers[0]) ``` #### 3. 常见问题及解决 | 问题现象 | 可能原因 | 解决方法 | |------------------------|-------------------------|------------------------------| | 通信超时/无响应 | 接线错误 | 检查TXD/RXD是否交叉连接 | | 数据乱码 | 波特率不匹配 | 核对设备参数`Pr5.38`设置 | | Modbus通信失败 | 从站地址未设置 | 确认设备Modbus地址(默认1) | #### 4. 协议格式说明(MINAS) - **指令结构**:`STX` + 指令代 + 数据 + `ETX` + `CR` 例如:$STX=0x02$, $ETX=0x03$, $CR=0x0D$ - **数据格式**:16进制字节流,如设置目标位置为1000: $$ \text{指令} = 02\ 37\ 31\ 01\ 00\ 03\ 0D $$
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值