发布时间:2025-06-24 18:24:46 作者:北方职教升学中心 阅读量:017
对于这个API谷歌有提供示例工程:
在线使用:https://googlechromelabs.github.io/serial-terminal/
项目地址:https://github.com/GoogleChromeLabs/serial-terminal
下面这个项目做的挺不错的,直接拿来用也很好:
在线使用:https://itldg.github.io/web-serial-debug/
项目地址:https://gitee.com/itldg/web-serial-debug or https://github.com/itldg/web-serial-debug
使用说明
使用下面方法可以侦测电脑上串口设备插入与拔出:
// 全局串口设备插入事件navigator.serial.onconnect=(event)=>{console.log("Serial connected: ",event.target);};// 全局串口设备拔出事件navigator.serial.ondisconnect=(event)=>{console.log("Serial disconnected: ",event.target);};// 也可以对单个的串口设备设置插入与拔出事件
使用下面方法可以显示电脑上的串口设备选择授权,或者显示已授权的串口设备列表:
// requestPort方法将显示一个包含已连接设备列表的对话框,用户选择可以并授予其中一个设备访问权限// 对于USB虚拟串口而言该方法还可以传入一个过滤器,指定PID&VID的串口constport =awaitnavigator.serial.requestPort();// port.forget(); // 取消授权// port.getInfo() // 获取PID&VID (对于蓝牙串口好像是显示服务号)// getDevices方法可以返回已连接的授权过的设备列表constports =awaitnavigator.serial.getPorts();
使用 open 方法打开选中的串口设备后就可以进行数据交互了:
// open时可以传入串口参数awaitport.open({baudRate:115200,// bufferSize: 255, // 读写缓存,默认255// dataBits: 8, // 数据位,默认8// flowControl: none, // 流控制,默认无// parity: none, // 校验,默认无// stopBits: 1, // 停止位,默认1});
打开后就可以发送数据了:
constencoder =newTextEncoder();// const data= new Uint8Array(length);constwriter =port.writable.getWriter();awaitwriter.write(encoder.encode("PING"));// await writer.write(data);writer.releaseLock();
同样可以设置数据接收:
while(port.readable){constreader =port.readable.getReader();try{while(true){const{value,done }=awaitreader.read();if(done){// |reader| has been canceled.break;}// Do something with |value|…}}catch(error){// Handle |error|…}finally{reader.releaseLock();}}
数据接收本身很简单,但需要注意的是在关闭串口前需要释放 reader 对象。Edge、目前在浏览器上直接使用电脑上的串口设备了,这篇文章将介绍相关内容。
代码与演示
<!DOCTYPEhtml><htmllang="en"><head><metacharset="UTF-8"><metaname="viewport"content="width=device-width, initial-scale=1.0"><title>Web Serial API Test</title><style>*{margin:0;padding:0;}button,textarea{margin:1rem;margin-bottom:0;padding:0.5rem;width:20rem;}textarea{resize:none;overflow-y:scroll;overflow-x:hidden;height:5rem;}</style><script>if("serial"innavigator){// alert("Your browser support Web Serial API."); // 浏览器不支持 Web Serial API}else{alert("Your browser is not support Web Serial API.");}// 全局串口设备插入事件navigator.serial.onconnect=(event)=>{console.log("Serial port connected: ",event.target);};// 全局串口设备拔出事件navigator.serial.ondisconnect=(event)=>{console.log("Serial port disconnected: ",event.target);};</script></head><body><buttonid="btnSelect">select</button><br><buttonid="btnOpen">open</button><br><buttonid="btnClose">close</button><br><buttonid="btnSend">send</button><br><textareaid="iptOutput">D0 D1 D2 D3 D4 D5 D6 D7</textarea><br><textareaid="iptInput"readonly></textarea><script>constbtnSelect =document.querySelector("#btnSelect");constbtnOpen =document.querySelector("#btnOpen");constbtnClose =document.querySelector("#btnClose");constbtnSend =document.querySelector("#btnSend");constiptOutput =document.querySelector("#iptOutput");constiptInput =document.querySelector("#iptInput");letport =null;letreader =null;letreading =false;// 选择串口btnSelect.onclick=async()=>{try{port =awaitnavigator.serial.requestPort();// 弹出系统串口列表对话框,选择一个串口进行连接letports =awaitnavigator.serial.getPorts();// 获取已连接的授权过的设备列表console.log(ports);// await port.forget(); // 取消授权// console.log(port.getInfo()); // 打印PID&VID (对于蓝牙串口好像是显示服务号)}catch(e){console.log(e);// The prompt has been dismissed without selecting a device.}};functionupdateInputData(data){letarray =newUint8Array(data);// event.data.buffer就是接收到的inputreport包数据了lethexstr ="";for(constdata ofarray){hexstr +=(Array(2).join(0)+data.toString(16).toUpperCase()).slice(-2)+" ";// 将字节数据转换成(XX )形式字符串}iptInput.value +=hexstr;iptInput.scrollTop =iptInput.scrollHeight;// 滚动到底部}// 读取数据asyncfunctionlistenReceived(){if(reading){console.log("On reading.");return;}reading =true;while(port.readable &&reading){reader =port.readable.getReader();try{while(true){const{value,done }=awaitreader.read();if(done){// |reader| has been canceled.break;}// 需要特别注意的是:实际使用中即使对端是按一个个包发送的串口数据,接收时收到的也可能是分多段收到的updateInputData(value);}}catch(e){console.log(e);}finally{reader.releaseLock();}}awaitport.close();// 关闭串口port =null;console.log("Port closed.");}// 打开串口btnOpen.onclick=async()=>{if(port ===null){console.log("Not selected.");return;}awaitport.open({baudRate:115200,// bufferSize: 255, // 读写缓存,默认255// dataBits: 8, // 数据位,默认8// flowControl: none, // 流控制,默认无// parity: none, // 校验,默认无// stopBits: 1, // 停止位,默认1});listenReceived();console.log("Port opened.");}// 关闭串口btnClose.onclick=async()=>{if((port ===null)||(!port.writable)){console.log("Not opened.");return;}if(reading){reading =false;reader?.cancel();}}// 获取发送窗口十六进制字符串转换为字节数组functiongetOutputData(){letoutputDatastr =iptOutput.value.replace(/\s+/g,"");// 去除所有空白字符if(outputDatastr.length %2==0&&/^[0-9a-fA-F]+$/.test(outputDatastr)){// 获取字节数组长度constbyteLength =outputDatastr.length /2;// 创建字节数组constoutputData =newUint8Array(byteLength);// 将字符串转成字节数组数据for(leti =0;i <byteLength;i++){outputData[i]=parseInt(outputDatastr.substr(i *2,2),16);}// 返回数据returnoutputData;}else{throw"Data is not even or 0-9、相关资料
Web Serial API 相关内容参考如下:
https://developer.mozilla.org/en-US/docs/Web/API/Serial
https://developer.mozilla.org/en-US/docs/Web/API/SerialPort
https://wicg.github.io/serial/
这个API目前还处于实验性质,只有电脑上的Chrome、A-F"
;}}// 发送数据btnSend.onclick=async()=>{if((port ===null)||(!port.writable)){console.log("Not opened.");return;}constwriter =port.writable.getWriter();awaitwriter.write(getOutputData());// 发送数据writer.releaseLock();}</script></body></html>
下面测试时我将串口的TX/RT短接在一起,发送什么数据就会收到什么数据:
总结
使用 Web Serial API 访问串口非常方便,目前来说唯一的问题是这还是实验性质的功能,可能之后接口还会变动,需要根据实际情况进行调整。
下面是关闭串口操作:
// 使用 await port.close(); 即可关闭串口,如果正在读写数据,需要先释放相关资源letkeepReading =true;letreader;asyncfunctionreadUntilClosed(){while(port.readable &&keepReading){reader =port.readable.getReader();try{while(true){const{value,done }=awaitreader.read();if(done){// |reader| has been canceled.break;}// Do something with |value|...}}catch(error){// Handle |error|...}finally{reader.releaseLock();}}awaitport.close();}constclosed =readUntilClosed();// Sometime later...keepReading =false;reader.cancel();awaitclosed;
除了上面内容外还可以使用 setSignals 和 getSignals 来设置和获取流控制情况。a-f、