在一些应用场景中,Web应用程序需要获取访问者电脑上连接的硬件设备,即浏览器和串口通信。通常的做法是为这些硬件设备开发ActiveX控件,并将其嵌入到HTML网页中供InternetExplorer浏览器访问这些设备信息。而采用ActiveX控件要求浏览器必须为InternetExplorer,不兼容Chrome等其他浏览器。下面是结合广大网友资料的总结,顺便记录下实现的过程和碰到的问题。

一、使用mscomm32.ocx使用串口资源

该方法是使用微软的ActiveX控件MSCOMM32.ocx的串口控件对串口进行控制,但是ActiveX控件目前只针对IE浏览器支持较好,要想兼容其他浏览器可以去找下自定义ActiveX控件相关资料

二、用C#之类的自己写一个dll,然后使用

使用C#语言的控件对串口进行控制,然后使用JS+AJAX与C#进行交互获得串口数据,缺点就是数据同步方面可能相对稍有延迟,毕竟AJAX是一个异步传输的标准

三、用Node.js 的serial模块实现

暂无实际项目开发经验。附上别人家的代码一份供参考
http://www.qihuawu.com/serial-data-obtained-using-nodejs.html

四、使用Google的Chrome.serial实现

开发这位大神总结的很nice:https://www.jianshu.com/p/873b5403bf05

下面我详细说一下用微软的ActiveX控件实现串口通信的过程

1.注册MSCOMM32.ocx控件

A.下载控件https://github.com/davidanger/MSCOMM32
B.复制MSCOMM32.OCX 到 C:\WINDOWS\SysWOW64(
注意:如果是32位系统就是C:\WINDOWS\SysWOW32)
C.在C:\WINDOWS\SysWOW64(C:\WINDOWS\SysWOW32)搜索cmd.exe,以管理员身份运行,执行命令: regsvr32 mscomm32.ocx,弹出注册成功

2.设置注册表

A. 复制下面的内容,文件命名为mscomm.bat
copy mscomm*.* %windir%\system32\ /y
Regsvr32 %windir%\system32\mscomm32.ocx /s
Regsvr32 %windir%\system32\actxprxy.dll /s
Regsvr32 %windir%\system32\shdocvw.dll /s
Reg add"HKEY_CLASSES_ROOT\Licenses\4250E830-6AC2-11cf-8ADB-00AA00C00905" /v “” /d “kjljvjjjoquqmjjjvpqqkqmqykypoqjquoun” /f
pause
B.将文件复制到C:\Windows\SysWOW64 目录下
C.右击mscomm.bat 文件选择以管理员身份运行
D.出现如图:即操作成功,完成后即可关闭命令窗口

3.设置IE对ActiveX的安全控制

A.打开IE浏览器 — 设置 — Internet 选项 — 安全模块 — 自定义级别
B.自定义级别——安全——ActiveX控件和插件
C.如下图操作:




方点击确定,是,重启浏览器。

4.IE 管理项加载

A.新建文档,复制下面的内容,文件为mscomm.html

<html><head><title></title></head><body><OBJECT id=MSComm1 CLASSID="clsid:648A5600-2C6E-101B-82B6-000000000014" codebase="MSCOMM32.OCX" type="application/x-oleobject" style="LEFT:54px;TOP:14px"><PARAM   NAME="CommPort"   VALUE="3"/> <PARAM   NAME="DataBits"   VALUE="8"/> <PARAM   NAME="StopBits"   VALUE="1"/> <PARAM   NAME="BaudRate"   VALUE="9600"/> <PARAM   NAME="Settings"   VALUE="9600,N,8,1"/>     <PARAM   NAME="RTSEnable"   VALUE="1"/> <PARAM   NAME="DTREnable"   VALUE="1"/> <PARAM   NAME="Handshaking"   VALUE="0"/> <PARAM   NAME="NullDiscard"   VALUE="0"/> <PARAM   NAME="ParityReplace"   VALUE="?"/><PARAM   NAME="EOFEnable"   VALUE="0"/>       <PARAM   NAME="InputMode"   VALUE="0"/>    <PARAM   NAME="InBufferSize"   VALUE="1024"/>       <PARAM   NAME="InputLen"   VALUE="0"/>     <PARAM   NAME="OutBufferSize"   VALUE="512"/> <PARAM   NAME="SThreshold"   VALUE="0"/> <PARAM   NAME="RThreshold"   VALUE="1"/> </OBJECT></body>
</html>

B.在IE中运行mscomm.html

C.查看控件是否加载 设置——管理加载项——所有加载项

3.附上代码
<!DOCTYPE html>
<html><head><title>JavaScript串口测试</title><meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /><script ID=clientEventHandlersJS LANGUAGE=javascript>function MSComm1_OnComm() {switch(MSComm1.CommEvent) {case 1:{window.alert("Send OK!");break;} //发送事件case 2:{Receive();break;} //接收事件default:alert("Event Raised!" + MSComm1.CommEvent);;}}</script><script LANGUAGE=javascript FOR=MSComm1 EVENT=OnComm>// MSComm1控件每遇到 OnComm 事件就调用 MSComm1_OnComm()函数MSComm1_OnComm()</script><script language="JavaScript" type="text/JavaScript">String.prototype.Blength = function(){var arr = this.match(/[^\x00-\xff]/ig);return arr == null ? this.length : this.length + arr.length;}function OperatePort() {if(MSComm1.PortOpen == true) {try {MSComm1.PortOpen = false;document.getElementById("OperateButton").value = "打开串口";} catch(ex) {alert(ex.message);}} else {try {MSComm1.PortOpen = true;document.getElementById("OperateButton").value = "关闭串口";} catch(ex) {alert(ex.message);}}}function ConfigPort() {alert("串口状态:" + MSComm1.PortOpen);if(MSComm1.PortOpen == false) {try {MSComm1.CommPort = document.getElementById("ComName").value;alert(MSComm1.CommPort)MSComm1.Settings = document.getElementById("BaudRate").value.toString() + "," +document.getElementById("CheckBit").value.toString() + "," +document.getElementById("DataBits").value.toString() + "," +document.getElementById("StopBits").value.toString();MSComm1.OutBufferCount = 0; //清空发送缓冲区MSComm1.InBufferCount = 0; //滑空接收缓冲区 alert("已配置串口COM" + MSComm1.CommPort + "\n 参数:" + MSComm1.Settings);} catch(ex) {alert(ex.message);}} else {alert("请先关闭串口后再设置!");}}function Send() {//alert(document.getElementById("txtSend").value);var orgstr = document.getElementById("txtSend").value;var newstr = "";var hexflag = document.getElementById("isSendHex").checked;if(hexflag && orgstr != "") {if(orgstr.substr(0, 2) == "0x" || orgstr.substr(0, 2) == "0X") orgstr = orgstr.substring(2, orgstr.length);if(orgstr.length % 2 != 0) orgstr = "0" + orgstr;//alert(str2hex(orgstr));if((newstr = str2hex(orgstr)) == "") {alert("错误的16进制数");return false;}}try {MSComm1.Output = hexflag ? newstr : orgstr;  //alert(MSComm1.Output)} catch(ex) {alert(ex.message);}}function Receive() {//alert("InBufferCount::" + MSComm1.InBufferCount); // 缓冲区接收的字节document.getElementById("txtReceive").value += MSComm1.Input; //alert("InBufferCount::"+MSComm1.InBufferCount); }function ClearReceived() {document.getElementById("txtReceive").innerText = "";}function str2hex(s) {var a, b, d;var hexStr = '';for(var i = 0; i <s.length; i++) {d = s.charCodeAt(i);a = d % 16;b = (d - a) / 16;hexStr += '%' + "0123456789ABCDEF".charAt(b) + "0123456789ABCDEF".charAt(a);}//alert(hexStr);return hexStr;}function charCode(v) {return String.fromCharCode(v);}</script></head><body><form name="form1"><fieldset style="width:200px;height:250px;text-align:center;"><legend>配置串口</legend><div style="float:left;width:200px"><br/><span>串口号:</span><select name="ComName" id="ComName" style="width:75px"><option value="1">COM1</option><option value="2">COM2</option><option value="7" selected>COM7</option><option value="4">COM4</option><option value="5">COM5</option><option value="9">COM9</option></select><br/><span>波特率:</span><select name="BaudRate" id="BaudRate" style="width:75px"><option value="9600">9600</option><option value="57600">57600</option><option value="115200" selected>115200</option></select><br/><span>校验位:</span><select name="CheckBit" id="CheckBit" style="width:75px"><option value="N" selected>无NONE</option><option value="O">奇ODD</option><option value="E">偶EVEN</option></select><br/><span>数据位:</span><input type=text id="DataBits" name="DataBits" value=8 style="width:75px;height:20px"><br/><span>停止位:</span><input type=text id="StopBits" name="StopBits" value=1 style="width:75px;height:20px"><br/><br/><input type="button" id="ConfigButton" style="width:80px;height:30px;font-size:13px" name="ConfigButton" value="配置串口" onClick="ConfigPort()"><input type="button" id="OperateButton" style="width:80px;height:30px;font-size:13px" name="OperateButton" value="打开串口" onClick="OperatePort()"></div></fieldset><fieldset style="width:200px;height:250px;text-align:center;"><legend>发送区域</legend><div style="float:left;"><textarea id="txtSend" name="txtSend" style="width:200px;height:160px"></textarea><br/><span><input id="isSendHex" name="isSendHex" type="checkbox"  />16进制</span><input type="button" id="SendButton" style="width:100px;height:30px" name="SendButton" value="发送" onClick="Send()"></div></fieldset><fieldset style="width:200px;height:250px;text-align:center;"><legend>接收区域</legend><div style="float:left;"><textarea id="txtReceive" READONLY=TRUE name="txtReceive" style="width:200px;height:160px"></textarea><br/><span><input id="isReceiveHex" name="isReceiveHex" type="checkbox" />16进制</span><input type="button" id="ClearButton" style="width:100px;height:30px" name="ClearButton" value="清空" onClick="ClearReceived()"></div></fieldset></form><OBJECT id=MSComm1 CLASSID="clsid:648A5600-2C6E-101B-82B6-000000000014" codebase="MSCOMM32.OCX" type="application/x-oleobject" style="LEFT:54px;TOP:14px"><PARAM   NAME="CommPort"   VALUE="3"/> <PARAM   NAME="DataBits"   VALUE="8"/> <PARAM   NAME="StopBits"   VALUE="1"/> <PARAM   NAME="BaudRate"   VALUE="9600"/> <PARAM   NAME="Settings"   VALUE="9600,N,8,1"/>     <PARAM   NAME="RTSEnable"   VALUE="1"/> <PARAM   NAME="DTREnable"   VALUE="1"/> <PARAM   NAME="Handshaking"   VALUE="0"/> <PARAM   NAME="NullDiscard"   VALUE="0"/> <PARAM   NAME="ParityReplace"   VALUE="?"/><PARAM   NAME="EOFEnable"   VALUE="0"/>       <PARAM   NAME="InputMode"   VALUE="0"/>    <PARAM   NAME="InBufferSize"   VALUE="1024"/>       <PARAM   NAME="InputLen"   VALUE="0"/>     <PARAM   NAME="OutBufferSize"   VALUE="512"/> <PARAM   NAME="SThreshold"   VALUE="0"/> <PARAM   NAME="RThreshold"   VALUE="1"/> </OBJECT></body></html>
4.代码调试

没有实际的USb串口的话,即为模拟环境,注意模拟环境要安装虚拟串口
1)下载调试工具
Configure Virtural Serial Port 创建虚拟串口的 试用期 14天
串口调试精灵 调试串口的
2)虚拟调试方法
在Configure Virtural Serial Port 里添加端口,添加的端口都为一对

3)实际串口调试方法
待更新…

5.问题汇总

安装虚拟端口
https://www.cnblogs.com/javatiandi/p/11180765.html

设置虚拟端口
https://jingyan.baidu.com/article/4ae03de31828973eff9e6b8e.html

调试方法
https://blog.csdn.net/u013769695/article/details/80408139

串口调试助手怎么知道串口打开是否成功
https://zhidao.baidu.com/question/2053929245831631307.html

解决IE的Automation 服务器不能创建对象的问题
http://xinzhi.wenda.so.com/a/1539093807203701
http://www.qiuyexitong.com/article/1024.html

模块"scrrun.dll"已加载,但对DllRegisterServer的调用失败,错误代码为0x80004005
https://zhidao.baidu.com/question/537433274.html

算是个最完整的实例:
https://www.cnblogs.com/x-j-p/p/7819724.html

控件参数详解
https://blog.csdn.net/dongyue786/article/details/8177047

通信常见问题
https://www.iteye.com/blog/linuxgao-1925099

HTML/JS/浏览器与串口通信(一)相关推荐

  1. js 串口通信mscomm接收undefined_串口通信帧的同步方法(识别一帧数据的起始结束)42...

    串口通信是单片机和DSP等嵌入式系统之间,以及嵌入式系统与PC机或无线模块之间的一种非常重要且普遍使用的通信方式.在嵌入式系统的硬件结构中,通常只有一个8位或16位的CPU,不仅要完成主流程的工作,同 ...

  2. js 串口通信mscomm接收undefined_VB串口通信应用开发入门知识讲解

    VB是一门功能强大.简单易学的程序语言.它可以方便快捷地编制适用于数据处理.多媒体等方面的程序,而且利用ActiveX控件中的MSComm部件还能十分方便地开发出使用计算机串口的通信程序. 今天,我们 ...

  3. matlab上位机串口通信,MATLAB GUIDE 上位机串口通信开发 绘制图形

    本人因项目需求,需要开发这个串口通信上位机界面,用于实时绘制串口发送过来的数据.本人之前基本没使用过MATLAB,也就知道个zeros(100)这种在命令行窗口中输入的函数.至于MATLAB能开发图形 ...

  4. qt linux 串口eventdriven,详解 Qt 串口通信程序全程图文 (1)

    Qt 串口通信程序全程图文 是本文介绍的内容,在Qt中并没有特定的串口控制类,现在大部分人使用的是第三方写的qextserialport类,我们这里也是使用的该类.我们可以去 http://sourc ...

  5. Java实现串口通信的小样例

    用Java实现串口通信(windows系统下),须要用到sun提供的串口包 javacomm20-win32.zip.当中要用到三个文件,配置例如以下: 1.comm.jar放置到 JAVA_HOME ...

  6. 详解 Qt 串口通信程序全程图文 (2)

    Qt 串口通信程序全程图文是本文介绍的内容,上一部分中已经介绍了实现最简单的串口接收程序的编写,下面将对程序内容进行分析. 1.首先应说明操作串口的流程 步骤一:设置串口参数,如:波特率,数据位,奇偶 ...

  7. 详解 Qt 串口通信程序全程图文 (1)

    Qt 串口通信程序全程图文 是本文介绍的内容,在Qt中并没有特定的串口控制类,现在大部分人使用的是第三方写的qextserialport类,我们这里也是使用的该类.我们可以去 http://sourc ...

  8. QT中串口通信程序(转)

    (说明:我们的编程环境是windows xp下,在Qt Creator中进行,如果在Linux下或直接用源码编写,程序稍有不同,请自己改动.) 在Qt中并没有特定的串口控制类,现在大部分人使用的是第三 ...

  9. 【转】Qt串口通信专题教程

    查看以前的教程:Qt编写串口通信程序全程图文讲解 查看Wincom和Lincom介绍:Qt跨平台串口通信软件Wincom与Lincom 下载软件,文档和源码:资源下载 --------------20 ...

最新文章

  1. Android ViewTreeObserver简介-------------转
  2. Bzoj4016/洛谷P2993 [FJOI2014] 最短路径树问题(最短路径问题+长链剖分/点分治)
  3. Android系统Surface机制的SurfaceFlinger服务渲染应用程序UI的过程分析
  4. Mac 打开、编辑 .bash_profile 文件
  5. 服务器lIS绑定网站,DataList 中动态绑定服务器子控件的代码
  6. matlab实验符号计算答案,实验五matlab符号计算
  7. 在新项目中要思考的技术点
  8. Nginx 过滤模块
  9. aix查看oracle进程内存,Aix 查看进程占用内存大小(按从大小排列)
  10. c++ primer plus 之函数及函数指针
  11. 黑苹果升级驱动后WIFI不能启动的解决
  12. 智能运动手环设计构思
  13. python给pdf右上角盖章
  14. html中pc端与移动端区别,盘点移动端和PC端交互设计上的区别
  15. ruoyi默认的端口8080被占用,修改前后端端口号
  16. 阿里大手子评:入门到大成!GitHub新上线并发编程深度解析实战PDF
  17. 在华为之后,再有中国芯片赶超美国芯片,美国的图谋将再次失败
  18. win10微软图标点击无反应_win10系统任务栏开始菜单等系统图标点击无反应的解决方法...
  19. 逃离一线城市程序员的Plan B
  20. 怎么退出自适应巡航_减少系统干扰 体验ACC自适应巡航

热门文章

  1. 如何使用AD账号登录腾讯企业邮箱?
  2. C++: 情侣最美身高差(团体程序设计天梯赛)
  3. Nexus Repository Manager 3 远程命令执行漏洞(CVE-2020-10204),CVE-2020-11444 越权漏洞
  4. MATLAB 迷宫游戏
  5. 抖音文案标题怎么写,抖音标题怎么写才能上热门:国仁楠哥
  6. 诱导年轻人自杀的蓝鲸死亡游戏创始人Philip Budeikin认罪伏法
  7. javascript 45种缓动效果BY司徒正美
  8. 1582年日历怎么了_1582年日历图片
  9. Bribe the Prisoners(2009 Round 1C C)
  10. UPDATE和DELETE