基于x86汇编通过串口传输16位数据的问题排查
问题分析与修复方案
你的核心问题在于依赖固定延迟同步收发字节,这完全不可靠——COM口通信时序由波特率决定,固定的loop延迟无法适配不同波特率或系统运行差异,极易导致接收端读取到错误字节(比如未等第二个字节传输完成就读取,或是读到下一次传输的数据)。此外,代码未检查COM口状态寄存器确认数据就绪,进一步放大了出错概率。
问题点拆解
- 无状态校验:接收时直接执行
in al, dx,未确认COM口数据寄存器就绪,可能读取无效数据 - 固定延迟不可靠:
cx=200的循环延迟在不同系统、波特率下时长不一致,无法保证字节传输同步 - 字节序未明确:虽数据最大值为8(16位下高字节为0),但收发双方需严格遵循相同字节序(小端/大端)
修复后的代码
接收子程序(带硬件状态检查)
receive proc mov data_in, 0 ; 初始化接收变量 mov dx, 03FDH ; COM1线路状态寄存器地址 wait_first_byte: in al, dx test al, 01H ; 检查DR位(数据就绪标志) jz wait_first_byte ; 未就绪则循环等待 mov dx, 03F8H ; COM1数据寄存器 in al, dx mov byte ptr data_in, al ; 存储低字节 wait_second_byte: mov dx, 03FDH in al, dx test al, 01H jz wait_second_byte mov dx, 03F8H in al, dx mov byte ptr data_in + 1, al ; 存储高字节 ret receive endp
发送子程序(带发送完成校验)
transmit proc mov dx, 03FDH ; 线路状态寄存器 wait_tx_empty_first: in al, dx test al, 20H ; 检查THRE位(发送保持寄存器空标志) jz wait_tx_empty_first mov dx, 03F8H mov al, byte ptr data_out ; 发送低字节 out dx, al wait_tx_empty_second: mov dx, 03FDH in al, dx test al, 20H jz wait_tx_empty_second mov dx, 03F8H mov al, byte ptr data_out + 1 ; 发送高字节 out dx, al ret transmit endp
关键改进说明
- 硬件状态同步:通过读取
03FDH线路状态寄存器的对应标志位,确保数据就绪(接收)或发送寄存器空闲(发送),这是COM口通信的标准可靠做法,彻底替代不可靠的固定延迟 - 明确字节顺序:代码采用先低字节、后高字节的小端模式收发,若你的数据存储为大端,只需调换两个字节的读写顺序即可
- 适配性提升:完全基于硬件状态判断,可适配任意波特率和系统环境
另外,由于你的数据最大值为8(二进制00001000),16位数据的高字节始终为0,可优化收发逻辑:仅传输低字节,接收时直接将高字节置0,能减少一半通信时间,前提是双方提前约定该规则。
内容的提问来源于stack exchange,提问作者zizo
相关产品推荐
相关产品推荐

