1. ISO15693协议与RFID高频标签基础高频RFID技术在日常生活中的应用越来越广泛从图书馆管理到物流追踪再到门禁系统都能看到它的身影。而ISO15693作为高频RFID领域的重要标准协议定义了13.56MHz频率下标签与读写器之间的通信规范。相比其他RFID协议ISO15693的最大特点是支持较远的读写距离通常可达1米左右和较快的传输速率。我第一次接触这个协议是在一个智能仓储项目中当时需要实现托盘级别的货物追踪。ISO15693标签的防碰撞特性让我们可以同时读取多个标签这大大提高了盘点效率。协议中规定的寻卡、读块、写块等基础操作配合应用族信息AFI的管理功能为不同场景提供了灵活的解决方案。典型的ISO15693标签内存结构分为多个数据块每个块通常包含4字节数据。标签出厂时会预置不可更改的唯一标识符UID而其他数据块则允许读写操作。理解这个内存结构对后续开发至关重要就像我们操作电脑内存时需要知道地址一样对标签的读写也需要指定正确的块地址。2. 开发环境搭建与硬件连接工欲善其事必先利其器。在开始编码前我们需要准备好开发环境。Python作为本项目的开发语言我推荐使用3.7及以上版本因为这个版本对串口操作的支持已经相当稳定。实际项目中我测试过多个版本发现3.7在稳定性和兼容性上表现最好。硬件方面你需要准备支持ISO15693协议的RFID读写器模块符合ISO15693标准的标签卡USB转串口线如果读写器使用串口通信一台性能足够的PC现代电脑基本都满足要求安装必要的Python库时除了基本的pyserial外我强烈建议安装hexdump这个实用工具库。当调试通信协议时它能帮我们直观地查看十六进制数据流。安装命令很简单pip install pyserial hexdump硬件连接时最容易踩的坑就是串口参数配置。根据我的经验大多数ISO15693模块使用以下参数波特率115200有些设备可能是9600数据位8停止位1无校验位连接好硬件后建议先用厂家提供的测试工具验证硬件是否正常工作这能避免后续开发中很多不必要的调试时间。3. 实现标签寻卡与识别寻卡是RFID操作的第一步相当于敲门说有人吗。在ISO15693协议中寻卡操作会返回标签的UID这个唯一标识符相当于标签的身份证号码。通过串口发送寻卡指令时需要注意指令的格式。典型的寻卡指令包括起始标志通常是0xEE指令码寻卡通常是0x01数据长度实际数据结束标志0x0D 0x0A这是我优化过的寻卡代码示例def find_tag(): find_cmd bytearray([0xEE, 0xCC, 0x01, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x0D, 0x0A]) with serial.Serial(COM4, 115200, timeout1) as ser: ser.write(find_cmd) time.sleep(0.5) # 适当等待响应 response ser.read_all() if len(response) 15: raise ValueError(无效的寻卡响应) uid response[7:15] print(f发现标签UID: {uid.hex().upper()}) return uid在实际项目中我发现几个常见问题需要注意响应等待时间不宜过短否则可能收不到完整响应多标签环境下需要处理防碰撞工业环境中需要注意电磁干扰问题4. 读取与修改应用族信息应用族信息AFI是ISO15693协议中一个很有用的功能它相当于给标签打上分类标记。比如在仓储管理中可以用AFI区分电子产品、食品、化学品等不同类别。读取AFI的指令格式与寻卡类似但指令码不同。这是我常用的读取AFI的函数def read_afi(uid): afi_cmd bytearray([0xEE, 0xCC, 0x0C, 0x01, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0D, 0x0A]) afi_cmd[7:15] uid # 填入UID with serial.Serial(COM4, 115200, timeout1) as ser: ser.write(afi_cmd) time.sleep(0.5) response ser.read_all() if len(response) 9: raise ValueError(无效的AFI响应) current_afi response[7] print(f当前AFI值: 0x{current_afi:02X}) return current_afi修改AFI时需要特别注意有些标签的AFI可能是只读的。修改前最好先确认标签支持该功能。修改AFI的代码与读取类似但需要发送写入指令和新的AFI值。5. 数据块的读写操作数据块读写是RFID开发中最常用的功能。ISO15693标签通常将内存分为多个块每个块4字节。读写时需要指定块地址。这是我封装的数据块读取函数def read_block(uid, block_addr): if not 0 block_addr 255: raise ValueError(块地址必须在0-255范围内) read_cmd bytearray([0xEE, 0xCC, 0x07, 0x01, 0x00, 0x00, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, block_addr, 0x00, 0x00, 0x0D, 0x0A]) read_cmd[7:15] uid with serial.Serial(COM4, 115200, timeout1) as ser: ser.write(read_cmd) time.sleep(0.5) response ser.read_all() if len(response) 19: raise ValueError(无效的读块响应) block_data response[7:19] print(f块 {block_addr} 数据: {block_data.hex()}) return block_data写入数据块时需要特别注意数据格式和长度。这里有个我踩过的坑某些标签要求写入数据必须是4字节的整数倍不足时需要补零。def write_block(uid, block_addr, data): if len(data) ! 4: raise ValueError(写入数据必须是4字节) write_cmd bytearray([0xEE, 0xCC, 0x08, 0x01, 0x00, 0x00, 0x16, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, block_addr, 0x00]) write_cmd[7:15] uid write_cmd[17:21] data write_cmd.extend([0x00, 0x00, 0x0D, 0x0A]) with serial.Serial(COM4, 115200, timeout1) as ser: ser.write(write_cmd) time.sleep(0.5) response ser.read_all() if len(response) 7: raise ValueError(写入操作失败) print(f块 {block_addr} 写入成功)6. 实战技巧与常见问题解决在实际项目开发中我积累了一些宝贵经验。首先是超时处理串口通信不稳定时特别重要。建议为每个操作设置合理的超时时间并实现重试机制。def robust_read(ser, expected_len, max_retry3): for _ in range(max_retry): response ser.read_all() if len(response) expected_len: return response time.sleep(0.5) raise TimeoutError(读取操作超时)其次是错误处理。RFID操作可能因各种原因失败比如标签离开读写范围、信号干扰等。好的错误处理能让程序更健壮。多标签环境下的防碰撞处理也很关键。ISO15693虽然支持防碰撞但在实际应用中还是可能遇到读取不全的情况。这时可以采用多次扫描的策略。最后分享一个性能优化技巧批量读取。与其逐个块读取不如一次读取多个连续块这能显著提高效率。不过要注意不同标签对最大读取长度的限制。7. 完整示例与应用场景让我们把这些功能整合成一个完整的示例实现标签识别、AFI读取和数据写入的全流程操作def full_demo(): try: # 1. 寻卡 print(正在寻找标签...) uid find_tag() # 2. 读取AFI print(\n读取应用族信息...) afi read_afi(uid) # 3. 修改AFI (如果需要) if afi ! 0x01: print(\n修改应用族信息为0x01...) write_afi(uid, 0x01) # 4. 写入测试数据 print(\n写入测试数据...) test_data bytes([0xAA, 0xBB, 0xCC, 0xDD]) write_block(uid, 0, test_data) # 5. 验证写入 print(\n验证写入数据...) read_data read_block(uid, 0) if read_data[:4] ! test_data: print(写入验证失败!) else: print(写入验证成功!) except Exception as e: print(f操作失败: {str(e)})这个完整流程可以应用于很多实际场景。比如在智能仓储中我们可以通过寻卡识别货物用AFI区分货物类别在数据块中存储生产日期、批次号等信息定期更新库存状态在另一个服装零售项目中我们使用类似的技术实现AFI区分服装类型上衣、裤子等第一个数据块存储颜色代码第二个数据块存储尺码第三个数据块存储价格这些应用都建立在本文介绍的基础操作之上通过灵活组合这些功能可以满足各种业务需求。
Python实战:基于ISO15693协议的RFID高频标签读写开发指南
发布时间:2026/5/27 22:38:43
1. ISO15693协议与RFID高频标签基础高频RFID技术在日常生活中的应用越来越广泛从图书馆管理到物流追踪再到门禁系统都能看到它的身影。而ISO15693作为高频RFID领域的重要标准协议定义了13.56MHz频率下标签与读写器之间的通信规范。相比其他RFID协议ISO15693的最大特点是支持较远的读写距离通常可达1米左右和较快的传输速率。我第一次接触这个协议是在一个智能仓储项目中当时需要实现托盘级别的货物追踪。ISO15693标签的防碰撞特性让我们可以同时读取多个标签这大大提高了盘点效率。协议中规定的寻卡、读块、写块等基础操作配合应用族信息AFI的管理功能为不同场景提供了灵活的解决方案。典型的ISO15693标签内存结构分为多个数据块每个块通常包含4字节数据。标签出厂时会预置不可更改的唯一标识符UID而其他数据块则允许读写操作。理解这个内存结构对后续开发至关重要就像我们操作电脑内存时需要知道地址一样对标签的读写也需要指定正确的块地址。2. 开发环境搭建与硬件连接工欲善其事必先利其器。在开始编码前我们需要准备好开发环境。Python作为本项目的开发语言我推荐使用3.7及以上版本因为这个版本对串口操作的支持已经相当稳定。实际项目中我测试过多个版本发现3.7在稳定性和兼容性上表现最好。硬件方面你需要准备支持ISO15693协议的RFID读写器模块符合ISO15693标准的标签卡USB转串口线如果读写器使用串口通信一台性能足够的PC现代电脑基本都满足要求安装必要的Python库时除了基本的pyserial外我强烈建议安装hexdump这个实用工具库。当调试通信协议时它能帮我们直观地查看十六进制数据流。安装命令很简单pip install pyserial hexdump硬件连接时最容易踩的坑就是串口参数配置。根据我的经验大多数ISO15693模块使用以下参数波特率115200有些设备可能是9600数据位8停止位1无校验位连接好硬件后建议先用厂家提供的测试工具验证硬件是否正常工作这能避免后续开发中很多不必要的调试时间。3. 实现标签寻卡与识别寻卡是RFID操作的第一步相当于敲门说有人吗。在ISO15693协议中寻卡操作会返回标签的UID这个唯一标识符相当于标签的身份证号码。通过串口发送寻卡指令时需要注意指令的格式。典型的寻卡指令包括起始标志通常是0xEE指令码寻卡通常是0x01数据长度实际数据结束标志0x0D 0x0A这是我优化过的寻卡代码示例def find_tag(): find_cmd bytearray([0xEE, 0xCC, 0x01, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x0D, 0x0A]) with serial.Serial(COM4, 115200, timeout1) as ser: ser.write(find_cmd) time.sleep(0.5) # 适当等待响应 response ser.read_all() if len(response) 15: raise ValueError(无效的寻卡响应) uid response[7:15] print(f发现标签UID: {uid.hex().upper()}) return uid在实际项目中我发现几个常见问题需要注意响应等待时间不宜过短否则可能收不到完整响应多标签环境下需要处理防碰撞工业环境中需要注意电磁干扰问题4. 读取与修改应用族信息应用族信息AFI是ISO15693协议中一个很有用的功能它相当于给标签打上分类标记。比如在仓储管理中可以用AFI区分电子产品、食品、化学品等不同类别。读取AFI的指令格式与寻卡类似但指令码不同。这是我常用的读取AFI的函数def read_afi(uid): afi_cmd bytearray([0xEE, 0xCC, 0x0C, 0x01, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0D, 0x0A]) afi_cmd[7:15] uid # 填入UID with serial.Serial(COM4, 115200, timeout1) as ser: ser.write(afi_cmd) time.sleep(0.5) response ser.read_all() if len(response) 9: raise ValueError(无效的AFI响应) current_afi response[7] print(f当前AFI值: 0x{current_afi:02X}) return current_afi修改AFI时需要特别注意有些标签的AFI可能是只读的。修改前最好先确认标签支持该功能。修改AFI的代码与读取类似但需要发送写入指令和新的AFI值。5. 数据块的读写操作数据块读写是RFID开发中最常用的功能。ISO15693标签通常将内存分为多个块每个块4字节。读写时需要指定块地址。这是我封装的数据块读取函数def read_block(uid, block_addr): if not 0 block_addr 255: raise ValueError(块地址必须在0-255范围内) read_cmd bytearray([0xEE, 0xCC, 0x07, 0x01, 0x00, 0x00, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, block_addr, 0x00, 0x00, 0x0D, 0x0A]) read_cmd[7:15] uid with serial.Serial(COM4, 115200, timeout1) as ser: ser.write(read_cmd) time.sleep(0.5) response ser.read_all() if len(response) 19: raise ValueError(无效的读块响应) block_data response[7:19] print(f块 {block_addr} 数据: {block_data.hex()}) return block_data写入数据块时需要特别注意数据格式和长度。这里有个我踩过的坑某些标签要求写入数据必须是4字节的整数倍不足时需要补零。def write_block(uid, block_addr, data): if len(data) ! 4: raise ValueError(写入数据必须是4字节) write_cmd bytearray([0xEE, 0xCC, 0x08, 0x01, 0x00, 0x00, 0x16, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, block_addr, 0x00]) write_cmd[7:15] uid write_cmd[17:21] data write_cmd.extend([0x00, 0x00, 0x0D, 0x0A]) with serial.Serial(COM4, 115200, timeout1) as ser: ser.write(write_cmd) time.sleep(0.5) response ser.read_all() if len(response) 7: raise ValueError(写入操作失败) print(f块 {block_addr} 写入成功)6. 实战技巧与常见问题解决在实际项目开发中我积累了一些宝贵经验。首先是超时处理串口通信不稳定时特别重要。建议为每个操作设置合理的超时时间并实现重试机制。def robust_read(ser, expected_len, max_retry3): for _ in range(max_retry): response ser.read_all() if len(response) expected_len: return response time.sleep(0.5) raise TimeoutError(读取操作超时)其次是错误处理。RFID操作可能因各种原因失败比如标签离开读写范围、信号干扰等。好的错误处理能让程序更健壮。多标签环境下的防碰撞处理也很关键。ISO15693虽然支持防碰撞但在实际应用中还是可能遇到读取不全的情况。这时可以采用多次扫描的策略。最后分享一个性能优化技巧批量读取。与其逐个块读取不如一次读取多个连续块这能显著提高效率。不过要注意不同标签对最大读取长度的限制。7. 完整示例与应用场景让我们把这些功能整合成一个完整的示例实现标签识别、AFI读取和数据写入的全流程操作def full_demo(): try: # 1. 寻卡 print(正在寻找标签...) uid find_tag() # 2. 读取AFI print(\n读取应用族信息...) afi read_afi(uid) # 3. 修改AFI (如果需要) if afi ! 0x01: print(\n修改应用族信息为0x01...) write_afi(uid, 0x01) # 4. 写入测试数据 print(\n写入测试数据...) test_data bytes([0xAA, 0xBB, 0xCC, 0xDD]) write_block(uid, 0, test_data) # 5. 验证写入 print(\n验证写入数据...) read_data read_block(uid, 0) if read_data[:4] ! test_data: print(写入验证失败!) else: print(写入验证成功!) except Exception as e: print(f操作失败: {str(e)})这个完整流程可以应用于很多实际场景。比如在智能仓储中我们可以通过寻卡识别货物用AFI区分货物类别在数据块中存储生产日期、批次号等信息定期更新库存状态在另一个服装零售项目中我们使用类似的技术实现AFI区分服装类型上衣、裤子等第一个数据块存储颜色代码第二个数据块存储尺码第三个数据块存储价格这些应用都建立在本文介绍的基础操作之上通过灵活组合这些功能可以满足各种业务需求。