一根串口线,两个串口转USB口,一台电脑完成硬件串口通信测试。
用一个电脑链接串口数据线测试发送和接收,一台电脑9针串口有限,所以需要转USB口,我的台式机主机前面的两个USB口是相通的,都插入从设备管理器看到只有一个COM口硬件,将另一端串口转USB口插入电脑主机后面的USB口,出现了另一个COM口,可以先开启两个串口助手程序,分别配置两个COM进行通讯,发现接发信息无误,测试成功。下面以COM3、COM4口为例。
应用程序串口通信测试
- 应用程序连COM3口,串口助手连COM4口;
- COM4口发送16进制身高体重数据
- 175,65,26.5 对应 31 37 35 2C 36 35 2C 32 36 2E 35,增加开始位02,结束位03,02 31 37 35 2C 36 35 2C 32 36 2E 35 03;
- 字符串转16进制工具https://www.mokuge.com/tool/asciito16/;
- 02到浏览器以字符方式接收被转换为”\n0002”;03被转换为”\n0003”;
- !注意串口助手的坑!我用了三个串口助手,其中两个都有问题,第一个只触发一次OnComm事件就不触发了,估计是加入了握手程序;第二个每次发送数据的解码方式不一样出现乱码情况,第三个串口助手程序(ComPort)才基本满足我的测试需求,没有出现上述问题。
-
MSComm1.InputMode = 0; //ComInputModeText:0 , ComInputModeBinary:1;
ComInputModeBinary的方式MSComm1.Input始终为Undefined,换了串口助手还没有测试
- 因为传输数据的长度不固定,发送数据以一定的频率连续发送,数据处理有两种方式,一种是一次接收全部数据,mscomm1.Rthreshold设置为超过一次数据的大小,到达设置的大小触发oncomm事件,Comscomm1.InputLen = 0表示一次读取全部缓存区数据;另外一种,mscomm1.Rthreshold=1,并不断地读取缓存区的数据进行拼接,条件是”\002”开始”\0003”结束,然后当接收到完整一段数据,完成数据处理,清空缓存区,具体逻辑代码如下:
function Receive() {
var str = MSComm1.Input + ""; //硬件处理程序非常快,一开始就要接收Input数据否则可能丢失!!
/************receive for all******************************
var start = str.indexOf("\u0002");
var end = str.indexOf("\u0003");
if (start < end) {
var arr = str.substring(start, end).split(",");
for (var i = 0; i < rowsData.length; i++) {
if (rowsData[i].PackItemName == '身高') {
rowsData[i].Description = arr[0];
updateRow(i, rowsData[i]);
}
if (rowsData[i].PackItemName == '体重') {
rowsData[i].Description = arr[1];
updateRow(i, rowsData[i]);
}
if (rowsData[i].PackItemName == '体重指数') {
rowsData[i].Description = arr[2];
updateRow(i, rowsData[i]);
}
}
MSComm1.OutBufferCount =0; //清空发送缓冲区
MSComm1.InBufferCount = 0; //滑空接收缓冲区
}
*/
/*****************************receive one by one**************/
if (str.indexOf("\u0002") > -1 && !isStartRead) {
isStartRead = true;
receiveData = str;
} else if (str.indexOf("\u0003") > -1 && isStartRead) {
receiveData += str;
isStartRead = false;
//"\u0002175,65,26.5\u0003"
var start = receiveData.indexOf("\u0002");
var end = receiveData.indexOf("\u0003");
if (start < end) {
MSComm1.Output = "SendSuccess"; //todo 正式环境去掉
var arr = receiveData.substring(start, end).split(",");
for (var i = 0; i < rowsData.length; i++) {
if (rowsData[i].PackItemName == '身高') {
rowsData[i].Description = arr[0];
updateRow(i, rowsData[i]);
}
if (rowsData[i].PackItemName == '体重') {
rowsData[i].Description = arr[1];
updateRow(i, rowsData[i]);
}
if (rowsData[i].PackItemName == '体重指数') {
rowsData[i].Description = arr[2];
updateRow(i, rowsData[i]);
}
}
receiveData = "";
MSComm1.OutBufferCount = 0; //清空发送缓冲区
MSComm1.InBufferCount = 0; //滑空接收缓冲区
}
} else {
if (isStartRead) {
receiveData += str;
}
}
}
过程中遇到的问题
1. 注册Mscomm32.oxc 可以参考这篇解决大部分问题
[关于使用MSCOMM32.OCX控件心得及js调用实例](https://blog.csdn.net/huanghuangtongxue/article/details/77427675)
2. MSComm1.Settings设置不起作用,始终是默认值 “9600,N,8,1”
发现是校验参数的问题,串口助手普遍显示校验位为空时None,参数只识别 N,所以这个参数得注意。
一开始担心是插件的问题,网上没搜到这个问题,所以先排除插件问题
然后猜测可能是页面上的object对象初始化已经完成,js更改不起作用,于是将波特率等参数写入param,发现运行没有问题
最后发现是校验位参数影响的问题
3. 采用缓冲区有数据即触发接受的方式,如果不是连续发送,很可能不能完全接收想要的字符,采用连续发送,必须根据开始标识和结束标识 截取有效数据,采用固定字节触发,对于长度可变的数据不适用
Param设置:
<object classid="clsid:648A5600-2C6E-101B-82B6-000000000014" id=MSComm1 codebase="MSCOMM32.OCX" type="application/x-oleobject" >
<param name="CommPort" value="4" /> <!-- 端口号 -->
<param name="DTREnable" value="1" />
<param name="Handshaking" value="0" />
<param name="InBufferSize" value="1024" />
<param name="InputLen" value="0" />
<param name="NullDiscard" value="0" />
<param name="OutBufferSize" value="512" />
<param name="ParityReplace" value="?" />
<param name="RThreshold" value="1" /> <!-- -->
<param name="RTSEnable" value="1" />
<param name="SThreshold" value="2" />
<param name="EOFEnable" value="0" />
<param name="InputMode" value="1" /><!-- binary 1,ascii 0 -->
<param name="DataBits" value="8" />
<param name="StopBits" value="1" />
<param name="BaudRate" value="9600" />
<param name="Settings" value="9600,N,8,1" /> <!-- 波特率,校验位等 -->
</object>
————————————————
版权声明:本文为CSDN博主「iteye_6793」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/iteye_6793/article/details/82525638
JS设置:
MSComm1.CommPort = config.ComPort;
//MSComm1.BaudRate = 4800;
//MSComm1.DataBits = 8;
//MSComm1.StopBits = 1;
MSComm1.Settings = config.ComSpeed + ',' + config.ComVerify + ',' + config.DataBits + ',' + config.ComStop;
MSComm1.InputLen = 0;
MSComm1.RThreshold = 1;
MSComm1.InBufferSize = 4096;
MSComm1.OutBufferCount = 0; //清空发送缓冲区
MSComm1.InBufferCount = 0; //滑空接收缓冲区
MSComm1.InputMode = 0; //ComInputModeText:0 , ComInputModeBinary:1;
MSComm1.PortOpen = true;
$("#btn_SerialPort").text("关闭串口");
4. 本地串口通信可以远程到服务器不行
注意:需要将浏览器的Activex 启动,才能使用 ie安全级别设置IE选项--安全--自定义级别--ActiveX控件和插件--均选“启用”或者“提示”。
ActiveX 开启就可以了
5. 远程客户机进行测试仍然不通信
因为我们本机有 4250E830-6AC2-11cf-8ADB-00AA00C00905 这个键,但是可能是注册方式的问题,客户机没有,加上就好了
运行RegEdit.Exe打开系统注册表在HKEY_CLASSES_ROOT/Licenses下建立4250E830-6AC2-11cf-8ADB-00AA00C00905支键。并将其默认值改为kjljvjjjoquqmjjjvpqqkqmqykypoqjquoun完成注册即可解决注册码的问题.
或者
reg add "HKCR\Licenses\4250E830-6AC2-11cf-8ADB-00AA00C00905" /v "" /d "kjljvjjjoquqmjjjvpqqkqmqykypoqjquoun"