pySerial+SIM800模块AT命令异常:读缓冲区存在历史写缓冲数据
解决pySerial向SIM800模块发送AT命令返回旧数据的问题
嘿,我之前用pySerial操作SIM800的时候也碰到过一模一样的坑——发新命令却返回上一次的输出,甚至是上一条命令本身,折腾了好一会儿才搞明白原因。先看看你遇到的情况和代码:
发送命令后,返回的信息是前一次命令的输出(有时甚至是前一次命令本身)。代码如下:
import time import serial ser = serial.Serial() ser.port = "/dev/ttyAMA0" ser.baudrate = 9600 ser.open() def readData(): buffer = "" while True: oneByte = ser.read(1) if oneByte == b"\n": return buffer else: buffer += oneByte.decode("ascii")
问题根源分析
主要有两个核心问题:
- 串口缓冲区残留未读数据:SIM800返回的响应往往有多行(比如AT命令的内容响应+
OK确认),但你的readData函数读到第一个\n就直接返回了,剩下的数据会留在串口的输入缓冲区里,下次读取时就会先拿到这些旧数据。 - 发送命令前未清空缓冲区:如果模块启动后有残留的欢迎信息,或者之前的命令响应没读完,新命令的响应就会被旧数据混杂甚至覆盖。
解决方案
我调整了代码,针对性解决这两个问题:
- 每次发送命令前清空缓冲区:用
ser.flushInput()清空输入缓冲区,确保不会读到历史遗留数据 - 改进读取函数:读取所有可用数据,直到超时(避免死循环),同时支持多行响应的完整读取
- 规范AT命令格式:SIM800的AT命令需要以
\r\n结尾,确保模块能正确识别并响应
修改后的完整代码:
import time import serial ser = serial.Serial() ser.port = "/dev/ttyAMA0" ser.baudrate = 9600 # 设置超时,避免read()一直阻塞 ser.timeout = 1 ser.open() def read_all_data(): buffer = "" # 循环读取所有可用数据,直到超时无新数据 while True: # 读取当前所有可用字节,避免逐字节读取的低效 data = ser.read(ser.in_waiting or 1) if not data: break # 忽略解码错误,避免特殊字符导致程序崩溃 buffer += data.decode("ascii", errors="ignore") return buffer def send_at_command(cmd): # 发送前清空输入缓冲区,确保读不到旧数据 ser.flushInput() # 发送带标准结尾的AT命令 ser.write(f"{cmd}\r\n".encode()) # 给模块预留响应时间,复杂命令可以适当延长 time.sleep(0.5) # 读取完整响应 response = read_all_data() print(f"命令: {cmd}\n响应:\n{response}") return response # 测试示例 send_at_command("AT") send_at_command("AT+CSQ")
额外提示
- 如果初始化后还是偶尔出现旧数据,可以在串口打开后先执行一次
read_all_data(),把模块启动时的欢迎信息(比如READY)读干净 - 超时时间可以根据模块响应速度调整,比如发送短信、查询网络状态这类复杂命令,可能需要把超时设置为2-3秒
内容的提问来源于stack exchange,提问作者fistameeny
相关产品推荐
相关产品推荐

