第1章:读卡器硬件接口:串口(RS232)通信协议、USB HID模式、USB虚拟串口(CDC)模式对比
做POS机驱动开发,第一个绕不开的问题就是:读卡器到底用哪种接口连到主机?
我刚开始接触这个领域时,也以为随便选一种就行。后来踩了不少坑才明白——接口选错了,后面整个驱动框架都得推倒重来。今天咱们就把这三种主流接口掰开揉碎了讲清楚。
1.1 串口(RS232)通信协议
串口,说白了就是最传统的通信方式。POS机读卡器通过DB9或RJ45接口,用TX、RX、GND三根线就能干活。我最早做的几个项目全是RS232接口,那时候觉得这玩意儿又简单又可靠。
核心特点:
- 电气特性:RS232用±12V电平,抗干扰能力确实强。但传输距离也就15米左右,再远就不行了。
- 波特率:常见的是9600、19200、38400。我记得有个项目客户非要115200,结果线长了点就丢数据,最后老老实实降回38400。
- 数据格式:1位起始位 + 8位数据位 + 1位停止位,无校验。这是最通用的配置。
重要提示:RS232的RTS/CTS流控,很多读卡器其实不用。但如果你遇到数据丢包,先检查流控配置,别急着怀疑硬件。
驱动开发要点:
- Linux下用termios结构体配置串口参数
- Windows下用CreateFile打开COM口
- 数据收发用ReadFile/WriteFile
// Linux串口配置示例(关键部分)
struct termios options;
tcgetattr(fd, &options);
cfsetispeed(&options, B38400);
cfsetospeed(&options, B38400);
options.c_cflag |= (CLOCAL | CREAD);
options.c_cflag &= ~PARENB; // 无校验
options.c_cflag &= ~CSTOPB; // 1位停止位
options.c_cflag &= ~CSIZE;
options.c_cflag |= CS8; // 8位数据位
tcsetattr(fd, TCSANOW, &options);
个人经验:我习惯在串口初始化后先发一个查询命令,看看读卡器有没有回应。这招能快速判断硬件连接是否正常,省得后面排查半天。
1.2 USB HID模式
USB HID模式,说白了就是把读卡器伪装成一个键盘或鼠标。主机不需要装驱动,插上就能用。你想想看,这对用户来说多方便。
为什么会有这种模式?
早期POS机很多是Windows系统,用户不想装驱动。读卡器厂商就想到:既然系统自带HID驱动,那我把读卡器做成HID设备不就行了?
技术细节:
- 使用中断传输(Interrupt Transfer),延迟低
- 报告描述符(Report Descriptor)定义数据格式
- 数据包最大64字节(全速模式)
注意:HID模式有个坑——数据包大小受限。磁条卡数据如果超过64字节,需要分多次传输。我曾经遇到一个读卡器,三轨数据加起来快200字节,结果驱动里要处理分包和重组,代码写起来比串口麻烦多了。
驱动开发要点:
- Linux下用libusb或hidraw接口
- Windows下用HID API(如HidD_GetInputReport)
- 需要解析报告描述符,找到数据对应的Usage ID
// Linux HID读取示例(使用hidraw)
int fd = open("/dev/hidraw0", O_RDWR);
unsigned char buf[64];
int ret = read(fd, buf, sizeof(buf));
// buf[0]是报告ID,后面才是有效数据
避坑指南:我曾经遇到一个读卡器,HID报告里把磁道数据按ASCII码打包,但卡号是BCD码。结果读出来的数据全是乱码。后来仔细看了厂商的协议文档才发现——嗯,这坑踩得值。
1.3 USB虚拟串口(CDC)模式
USB虚拟串口,说白了就是USB接口模拟成串口。主机上会多出一个COM口(Windows)或ttyACM设备(Linux)。
为什么需要这种模式?
很多老式读卡器原本是RS232接口,但现代电脑没有串口了。厂商就在读卡器里加个USB转串口芯片,比如FT232、CP2102。这样硬件不用大改,驱动也兼容。
技术细节:
- 使用批量传输(Bulk Transfer),速度快
- 数据包最大512字节(高速模式)
- 支持流控(DTR/DSR、RTS/CTS)
重要提示:CDC模式的数据传输效率比HID高,因为批量传输没有HID那种64字节限制。但缺点是需要安装驱动(Windows下),Linux内核通常自带cdc_acm驱动。
驱动开发要点:
- Linux下设备节点是/dev/ttyACM0
- Windows下是COM3、COM4等
- 编程接口和RS232完全一样
// Windows CDC串口打开示例
HANDLE hCom = CreateFile(
"\\\\.\\COM3",
GENERIC_READ | GENERIC_WRITE,
0,
NULL,
OPEN_EXISTING,
0,
NULL);
// 配置参数和RS232一样
个人经验:我建议优先用CDC模式。原因很简单:代码可以和RS232复用,移植成本低。而且数据吞吐量大,适合高速读卡场景。
1.4 三种接口对比总结
| 对比项 | RS232串口 | USB HID | USB CDC |
|---|---|---|---|
| 物理接口 | DB9/RJ45 | USB Type-A | USB Type-A |
| 驱动需求 | 需要串口驱动 | 系统自带 | 需要CDC驱动 |
| 最大数据包 | 无限制(流式) | 64字节 | 512字节 |
| 传输延迟 | 低 | 低 | 中 |
| 抗干扰 | 强(±12V) | 中 | 中 |
| 开发难度 | 低 | 中 | 低 |
| 适用场景 | 工业环境、长距离 | 免驱需求 | 高速、兼容性 |
最后提醒:选接口时别只看技术参数。我见过一个项目,明明用CDC最合适,但客户非要HID模式,理由是「不用装驱动」。结果数据分包处理搞了两个月,得不偿失。你想想看,有时候「方便用户」和「方便开发」之间得找个平衡点。
好了,这一章就讲到这里。下一章咱们聊聊磁条卡的数据格式——三轨数据到底长什么样,怎么解析。到时候我会拿一个真实的读卡器数据包来拆解,保证你看完就能上手。