Python_Example_modbus协议 串口 _接收_处理_响应 实现程序
2018-09-13
Author: 楚格
IDE: Pycharm2018.02 Python 3.7
KeyWord : 串口数据发送与接收 modbus CAN
Explain:
思路:
1.打开串口 (Function_Serial_Info() # 打开串口)
2.循环接收数据 (Function_Receive_Data() # 接收函数)
3.处理数据(暂时是赋值,未作读取Excel处理)[数据的modbus以及添加]
4.响应数据(Function_Handle_Reveice() # 处理函数)
5发送数据(Function_Send_Data()#发送函数)
1------------------------------------------------------------------------------------------------------------------
1 __all__ = [] 2 3 import sys 4 import os 5 6 import re 7 import string 8 import binascii 9 import array 10 import signal 11 import serial 12 import time 13 from time import sleep 14 15 # ========================================= 16 17 18 ''' 19 # ------------------------------------------ 20 # 导入:本文件夹中 .py 模块 21 # 直接引用模块名称 22 # ------------------------------------------ 23 ''' 24 # preject module 25 from Testing_CRC import * 26 27 28 # ============================================================================ 29 30 31 32 ''' 33 # ============================================================================ 34 # Function: 串口设置 函数 35 # Explain : 36 # : 37 # ============================================================================ 38 ''' 39 def Function_Serial_Info(): 40 print('串口初始化 Function_Serial_Info') 41 # ----------------------------- 42 43 global global_var_serial_init 44 global global_var_serial_band 45 46 # 必须设置串口 47 local_var_serial_func = True 48 49 while local_var_serial_func: 50 51 print("默认请输入:1 \n重新输入为:2") 52 53 # default = input('您的请选择: ') 54 default = "1" # debug 55 56 if default == "1": 57 global_var_serial_init = serial.Serial(port="COM5", baudrate=115200, timeout=1) # 端口控制 58 local_var_serial_func = False # 结束执行 59 60 elif default == "2": 61 port = input('串口号(数字): ', ) # 端口号 62 63 local_var_serial_nunber = True 64 65 while local_var_serial_nunber: 66 print('可选波特率:1 = 9600 \n\t\t 2 = 115200') 67 global_var_serial_band = input('波特率序号: ') 68 69 if global_var_serial_band == "1": 70 global_var_serial_band = 9600 71 local_var_serial_nunber = False 72 73 elif global_var_serial_band == "2": 74 global_var_serial_band = 115200 75 local_var_serial_nunber = False 76 77 else: 78 print('超出范围:请重新选择波特率!') 79 local_var_serial_nunber = True 80 81 # 组装成串口初设信息 82 global_var_serial_init = serial.Serial(port="COM" + port, baudrate=global_var_serial_band, timeout=1) # 端口控制 83 84 local_var_serial_func = False # 结束执行 85 86 else: 87 print('超出选择范围,请重新选择序号!') 88 local_var_serial_func = True # 返回继续执行 89 90 # ------------------------------------------------------ 91 92 93 ''' 94 # ============================================================================ 95 # Function: 接受数据 函数 96 # Explain : 接受串口收到的数据 97 # : 98 # ============================================================================ 99 ''' 100 def Function_Receive_Data(): 101 print('Function_Receive_Data :') 102 # ====================================== 103 global global_var_receive_string # 作为获取到的数据 104 105 # 接收单次数据,外部进行处理 SINGLE #循环接收数据,内部进行处理 LOOP 106 FREQUENCY = True 107 SINGLE = False 108 LOOP = True 109 110 if FREQUENCY == SINGLE: 111 print(SINGLE) 112 # 待开发模块 113 114 elif FREQUENCY ==LOOP: 115 print('LOOP: ') 116 # ------------------------------------------------------ 117 line = global_var_serial_init.readline() # 读取全部内容 118 print("Len :", len(line), " Type :", type(line), " readline : %s" % line) 119 120 # 字节变成字符串,目的是方便处理数据 121 types_transform_string = line.hex() # 字节变成字符串 122 print("Len :", len(types_transform_string), type(types_transform_string), types_transform_string) 123 124 # ------------------------------------------------------ 125 # 数据名称变换 目的是作为全局变量 126 global_var_receive_string = types_transform_string 127 128 # return global_var_receive_string 129 130 else: 131 pass 132 # ------------------------------------------------------ 133 134 ''' 135 # ============================================================================ 136 # Function: 发送数据 函数 137 # Explain : 发送数据到串口 138 # golal_var_result_send_data 139 # ============================================================================ 140 ''' 141 def Function_Send_Data(send_data): 142 print('发送指令函数 Function_Send_Data') 143 # --------------------------- 144 print(''' 145 ---- Info of Send Data Parameter ---- 146 Send data : %s 147 Serial Port : %s 148 ''' % ( send_data,global_var_serial_init.port) 149 ) 150 151 # 判断是字符串还是字节 152 # or define b'string',bytes should be used not str 153 # serInstance.write(atCmdStr.encode('utf-8')) 154 155 local_var_send_data_buff =send_data 156 #-------------------------------------- 157 # 发送函数 核心语句 输出接口 158 global_var_serial_init.write(local_var_send_data_buff) 159 #-------------------------------------- 160 161 # global_var_serial_init.close() # 关闭串口 162 # global_var_serial_init.open() # 打开端口 163 # global_var_serial_init.isOpen() #串口是否被打开 164 # --------------------------------------------------------- 165 ''' 166 # ============================================================================ 167 # Function: 数据处理 函数 168 # Explain: 接收数据进行处理 169 # global_var_receive_string 170 # ============================================================================ 171 ''' 172 def Function_Handle_Reveice(): 173 print('Function_Handle_Reveice : ') 174 # ====================================== 175 # global global_var_send_data 176 global global_var_crc_value 177 178 local_var_handle_data = global_var_receive_string 179 180 # 字符串重新规整 剪断拼接字符串 181 DIVISION = 24 182 local_var_handle_data = local_var_handle_data[10:] +local_var_handle_data[:10] 183 local_var_Temp_1 =local_var_handle_data[ :DIVISION] # 新划分的数据 local_var_Temp_1 184 local_var_Temp_2 =local_var_handle_data[DIVISION: ] # 新划分的数据 local_var_Temp_2 185 186 print(''' 187 ---- info of new string ---- 188 local_var_Temp_1 : %s 189 CAN_ID : %s 190 Modbus_data : %s 191 local_var_Temp_2 : %s 192 CAN_ID : %s 193 Modbus_data : %s 194 ''' % (local_var_Temp_1,local_var_Temp_1[:8],local_var_Temp_1[8:], 195 local_var_Temp_2, local_var_Temp_2[:8], local_var_Temp_2[8:] 196 ) 197 ) 198 199 # 结果存留区 200 ''' 201 #--------------------------------------------------------------------------------------- 202 # 0x04 功能码请求报文格式说明 203 # 204 # 数据含义 设备地址 功能码 寄存器起始地址 寄存器数量 CRC校验码 205 # 字节数 1 1 2 2 2 (Bytes) 206 # 说明 0-255 0x04 0x0000-0xFFFF 1-125(0x7D) 207 # 208 # 0x04 功能码请求正常回复报文格式说明 209 # 210 # 数据含义 设备地址 功能码 字节数 数据内容 CRC校验码 211 # 字节数 1 1 1 2xN 2 (Bytes) 212 # 说明 0-255 0x04 2×N :2-250 N 为被请求的寄存器数 213 # --------------------------------------------------------------------------------------- 214 ''' 215 # request data format 216 L_DIVI = 0 217 result_CAN_ID = local_var_Temp_1[(L_DIVI + 0):(L_DIVI + 8)] 218 result_slave_address = local_var_Temp_1[(L_DIVI + 8):(L_DIVI + 10)] 219 result_slave_function = local_var_Temp_1[(L_DIVI + 10):(L_DIVI + 12)] 220 result_slave_register = local_var_Temp_1[(L_DIVI + 12):(L_DIVI + 16)] 221 result_slave_number = local_var_Temp_1[(L_DIVI + 16):(L_DIVI + 20)] 222 223 # 根据不同 result_CAN_ID 进行处理,包括组包 response data 224 225 if result_CAN_ID == '00000001': 226 print(result_CAN_ID,result_slave_register,result_slave_number) 227 ''' 228 # 保存CANID addr function REG && NUM (需要判断进行处理) 然后进行CRC 229 # 进行处理,先赋值,后变量读取,最后读取Excel 230 ''' 231 if (result_slave_register == '09c3') and (result_slave_number == '0052' ): 232 233 # 这里是Excel接口 后期可以读取data 填充 234 Local_temp_value = '080102030405060708'# CRC = 0x D4C9 235 236 #-------------------- 237 # 预处理目的:添加 CRC码 238 local_var_modbus_data = result_slave_address + result_slave_function + Local_temp_value 239 Pack_modbus_data = Function_HexString_Trans(local_var_modbus_data) 240 Pack_Buff_modbus_data = Function_Modbus_CRC(Pack_modbus_data,0) 241 242 Pack_Buff_CAN_data = result_CAN_ID # 作为格式对称保留 243 244 local_var_result_send_data = Function_HexString_Trans(Pack_Buff_CAN_data) + Pack_Buff_modbus_data 245 246 # * ************************* 247 if BOOT_DEBUG : # 开发层 248 print('result_return_data: ', local_var_result_send_data) 249 250 #-------------------------- 251 # handle data finish got together package 252 # 这是处理完成后,组包发送给串口 253 #------------------------------------------------------------------- 254 Function_Send_Data(local_var_result_send_data) # 核心 函数 255 #------------------------------------------------------------------- 256 257 elif result_CAN_ID == '00000002': 258 print('2'*111) 259 260 else: 261 pass 262 263 264 # ======================================================== 265 266 # --------------------------------------------------------- 267 268 ''' 269 # ============================================================================ 270 # Function: Modbus CRC 校验 函数 271 # Explain: 输入参数 列表 [1, 4, 8, 1, 2, 3, 4, 5, 6, 7, 8 ] 272 # 输出参数 列表 [1, 4, 8, 1, 2, 3, 4, 5, 6, 7, 8, 212, 201] 273 # check right: 1 wrong: 0 274 # 275 # ============================================================================ 276 ''' 277 def Function_Modbus_CRC(Pack_modbus_data,test_type): 278 print('Function_Modbus_CRC : ',) 279 #------------------------------------ 280 global global_var_modbus_data_buff 281 global global_var_modbus_check 282 283 if test_type == 0 : 284 # # CRC 校验 添加校验码 285 temp_crc_translate = CalCRC16(Pack_modbus_data, len(Pack_modbus_data)) # 核心步骤 286 # **************** 287 if BOOT_DEBUG: # 开发层 288 print('crc_transformation: ', temp_crc_translate, type(temp_crc_translate)) # Int没有Len 289 # ------------------------- 290 # # 注意添加先后顺序 先低 后高 291 Pack_modbus_data.append(int(hex(temp_crc_translate & 0xFF), 16)) 292 Pack_modbus_data.append(int(hex((temp_crc_translate >> 8) & 0xFF), 16)) 293 # print('Pack_Buff_modbus_data : ', len(Pack_modbus_data), type(Pack_modbus_data),Pack_modbus_data) # calculation value CRC 294 # ------------------------- 295 global_var_modbus_data_buff = Pack_modbus_data # 重新命名 296 297 return global_var_modbus_data_buff 298 299 # --------------------------------------------------------- 300 # CRC 校验检查 check 301 elif test_type == 1 : 302 303 temp_CRC_check = CheckCRC(Pack_modbus_data, len(Pack_modbus_data), 0) 304 305 if temp_CRC_check == 1: 306 print('Result :', temp_CRC_check) # check calculation value 307 print('CRC_Check : Right') 308 global_var_modbus_check = temp_CRC_check # 重新命名 309 310 return global_var_modbus_check 311 312 else: 313 print('Result :', temp_CRC_check) # check calculation value 314 print('CRC_Check : wrong') 315 global_var_modbus_check = temp_CRC_check # 重新命名 316 317 return global_var_modbus_check 318 319 # --------------------------------------------------------- 320 # --------------------------------------------------------- 321 ''' 322 # ============================================================================ 323 # 函数 数据转换 324 # Explain: 输入参数:data_trans 325 # 输出参数:global_var_trans_data 326 # 功能 :hex string转换为整形列表 327 # example: AT = '01F2AA0405' 328 # SEND_AT = Function_HexString_Trans(AT) 329 # print(SEND_AT) 330 # Function_Send_Data(SEND_AT) 331 # time.sleep(2) 332 # ============================================================================ 333 ''' 334 def Function_HexString_Trans(data_trans): 335 print('Function_HexString_Trans : ',) 336 #------------------------------------ 337 global global_var_trans_data 338 339 temp = bytearray.fromhex(data_trans) 340 global_var_trans_data= list(temp) 341 # print(global_var_trans_data) 342 343 return global_var_trans_data 344 345 # -------------------------------------------- 346 347 348 349 # ============================================================================ 350 351 352 ''' 353 # ============================================================================ 354 # 测试专用 355 # ============================================================================ 356 ''' 357 if __name__ == '__main__': 358 print('-------------------------------------') 359 print('=\t\t 欢迎进入 测试环境 \t\t\t=') 360 print('-------------------------------------\n') 361 362 Function_Serial_Info() # 打开串口 363 # 需要关闭窗口 364 # global_var_serial_init.close() # 关闭串口 365 # global_var_serial_init.open() # 打开端口 366 print(global_var_serial_init.isOpen()) 367 368 369 TEST_RUN = True # 测试层演示 370 USER_DEBUD = True # 用户层调试 False 371 BOOT_DEBUG = True # 开发层调试 False 372 373 # 一直收到数据 374 while True: 375 376 Function_Receive_Data() # 接收函数 377 Function_Handle_Reveice() # 处理函数 378 379 if TEST_RUN: 380 print('USER_DEBUD') 381 # -------------------------- 382 else: 383 pass 384 385 # global_var_serial_init.colse() 386 # ===============================================================
1 __all__ = ["CalCRC16","CheckCRC"] 2 3 # =============================================================== 4 import crcmod 5 6 7 8 # =============================================================== 9 ''' 10 # ====================================== 11 # 校验函数 函数 12 # ====================================== 13 ''' 14 def CalCRC16(data, length): 15 print(' 校验函数 CalCRC16') 16 print('显示输入参数:',data,'\t', length) 17 18 crc=0xFFFF # 初始值 变量申明 19 if length == 0: 20 length = 1 21 ## for j in data: 22 ## crc ^= j 23 24 j = 0 25 while length != 0: 26 crc ^= list.__getitem__(data, j) 27 #print('j=0x%02x, length=0x%02x, crc=0x%04x' %(j,length,crc)) 28 for i in range(0,8): 29 if crc & 1: 30 crc >>= 1 31 crc ^= 0xA001 32 else: 33 crc >>= 1 34 length -= 1 35 j += 1 36 ##if length == 0: 37 ## break 38 39 return crc 40 41 # =============================================================== 42 def CheckCRC(data, length, crctype): 43 print('校验CRC CheckCRC') 44 print('Length | Type | Data : ',length, type(data), data) 45 46 if length < 3: 47 print('The data len(%d) is less than 3!!!', length) 48 return 0 49 50 crc_res = 0 51 tmp=[0,0,0,0] 52 53 if crctype == 0: 54 crc_res = CalCRC16(data, length-2) 55 tmp[0] = crc_res & 0xFF 56 tmp[1] = (crc_res >> 8) & 0xFF 57 58 if data[length-2] == tmp[0] and data[length-1] == tmp[1]: 59 return 1 60 elif crctype == 1: 61 print('CRC32 is not support...') 62 63 return 0 64 # =============================================================== 65 66 67 68 69 70 # =============================================================== 71 ''' 72 #=============================================================== 73 # 测试专用 74 #=============================================================== 75 ''' 76 if __name__ == '__main__': 77 78 ## Name Identifier-name, Poly Reverse Init-value XOR-out Check 79 ## ['modbus','CrcModbus',0x18005,REVERSE,0xFFFF,0x0000,0x4B37] 80 ## crc16 = crcmod.mkCrcFun(0x18005, rev=True, initCrc=0xFFFF, xorOut=0x0000) # rev=True,False 81 82 crc16 = crcmod.mkCrcFun(0x18005, initCrc=0xFFFF,rev=True, xorOut=0x0000) # rev=True,False 83 crc_array = b'0xFE 0xFD' 84 crc_calc = crc16(crc_array) #计算得到的CRC 85 a=hex(crc_calc) 86 print(crc_calc,a) 87 print('\n') 88 89 # ========================================= 90 crc_value = [0x01, 0x04, 0x13, 0x87, 0x00, 0x30] 91 crc_transformation = CalCRC16(crc_value,len(crc_value)) 92 crc_calculation = hex(crc_transformation) 93 # print('crc_calculation:',crc_calculation) 94 tasd = [0x00,0x00] 95 tasd[0] = crc_transformation & 0xFF 96 tasd[1] = (crc_transformation >> 8) & 0xFF 97 H =hex(tasd[0]) 98 L =hex(tasd[1]) 99 H_value = int(H,16) 100 L_value = int(L,16) 101 crc_value.append(H_value) 102 crc_value.append(L_value) 103 print(crc_value) # calculation value CRC 104 105 # ======================================================== 106 print('\n') 107 # crc_value2 = [0x01, 0x04, 0x13, 0x87, 0x00, 0x30,0x44,0xB3] 108 # print('crc_value2:',crc_value2) 109 # crc_cheak=CheckCRC(crc_value2,len(crc_value2),0) 110 111 crc_check=CheckCRC(crc_value,len(crc_value),0) 112 if crc_check == 1: 113 print('Right') 114 else: 115 print('wrong') 116 117 print(crc_check) # check calculation value
愿:
可以帮助到您,
感谢您的阅读。