使用pyserial向Arduino写入数据遇权限拒绝错误,求排查方案
Arduino串口权限错误(PermissionError 13)排查方案
问题描述
我尝试使用pyserial库向连接在USB端口(COM6)的Arduino发送1或0以控制LED亮灭,Arduino端代码正常,整套流程在朋友电脑上可正常运行,但我的设备执行ser = serial.Serial("COM6", 9600)时,抛出错误:
serial.serialutil.SerialException: could not open port 'COM6': PermissionError(13, 'Access is denied.', None, 5)
已关闭所有可能占用串口的程序(包括Arduino IDE),并更新、重启电脑,问题仍未解决。
Arduino控制代码
#define LED_PIN 12 void setup() { // 初始化9600波特率的串口通信 Serial.begin(9600); pinMode(LED_PIN, OUTPUT); } void loop() { if (Serial.available() > 0) { char cmd = Serial.read(); if (cmd == '1') { digitalWrite(LED_PIN, HIGH); Serial.println("LED turned on!"); } else if (cmd == '0') { digitalWrite(LED_PIN, LOW); Serial.println("LED turned off!"); } } }
Flask-Python控制代码
import numpy from flask import Flask, render_template, session, redirect from functools import wraps import pymongo import serial app = Flask(__name__) # 设置密钥 app.secret_key = ... # 数据库连接 client = pymongo.MongoClient(...) db = client.user_login_system # 登录验证装饰器 def login_required(f): @wraps(f) def wrap(*arg, **kwargs): if 'logged_in' in session: return f(*arg, **kwargs) else: return redirect('/') return wrap # 导入其他路由 from user import routes # 首页路由 @app.route('/') def home(): return render_template('home.html') # 仪表盘路由(需登录) @app.route('/dashboard/') @login_required def dashbaord(): return render_template("dashboard.html", status='OFF') # 全局初始化串口连接 ser = serial.Serial("COM6", 9600) # LED开启路由 @app.route('/turn_on/') def turn_on(): ser.write(b'1') return render_template("dashboard.html", status="LED is ON") # LED关闭路由 @app.route('/turn_off/') def turn_off(): ser.write(b'0') return render_template("dashboard.html", status="LED is off")
故障排查建议
- 确认串口编号准确性:打开设备管理器(Win+X → 设备管理器),展开「端口(COM和LPT)」,核实Arduino对应的串口是否为COM6,设备重启或重新插拔后端口号可能变动。
- 以管理员身份运行程序:右键点击Python脚本或终端,选择「以管理员身份运行」,普通用户权限可能无法访问串口设备。
- 检查串口驱动状态:在设备管理器中查看Arduino对应的串口设备是否有黄色感叹号,若有则卸载驱动后重新安装Arduino官方驱动。
- 清理后台隐藏进程:打开任务管理器(Ctrl+Shift+Esc),切换到「详细信息」标签,搜索并结束所有涉及串口通信的进程(如串口调试工具、残留的Python进程),再重试。
- 调整串口初始化时机:当前代码在Flask启动时就全局初始化串口,若程序多次重启会导致串口被占用。建议将串口初始化移至路由函数内,使用上下文管理器确保连接关闭:
@app.route('/turn_on/') def turn_on(): with serial.Serial("COM6", 9600, timeout=1) as ser: ser.write(b'1') return render_template("dashboard.html", status="LED is ON") - 测试基础串口连通性:先运行极简脚本排除Flask框架影响:
import serial try: ser = serial.Serial("COM6", 9600, timeout=2) print("串口打开成功") ser.write(b'1') print(ser.readline().decode('utf-8')) ser.close() except Exception as e: print(f"错误:{e}") - 更换USB端口/数据线:换一个USB接口连接Arduino,或更换支持数据传输的USB线(部分廉价线仅支持充电)。
- 禁用系统串口服务:Windows的Serial Console服务可能占用串口,管理员身份打开CMD执行以下命令后重启电脑:
reg add HKLM\SYSTEM\CurrentControlSet\Services\Serial /v Start /t REG_DWORD /d 4 /f
内容的提问来源于stack exchange,提问作者Clubbed2Death
相关产品推荐
相关产品推荐

