使用NModbus开发串口主站时如何捕获写入寄存器后的Acknowledge响应
NModbus捕获写入寄存器Acknowledge响应解决方案
方案1:扩展现有SlaveException捕获逻辑
NModbus定义的SlaveExceptionCodes枚举中已经包含Acknowledge响应对应的编码0x05,默认情况下该响应会封装为SlaveException抛出,你可以在现有异常捕获分支中增加对应判断即可捕获:
private void ResetButton_Click(object sender, EventArgs e) { try { port.Open(); byte slaveId = Decimal.ToByte(numericMBID.Value); master.WriteSingleRegister(slaveId, 5000, Convert.ToUInt16(UserCodeText.Text)); } catch (SlaveException slaveex) { // 匹配Acknowledge响应 if (slaveex.SlaveExceptionCode == (byte)SlaveExceptionCodes.Acknowledge) { // 此处添加你的Acknowledge处理逻辑 MessageBox.Show("从站已确认接收请求,处理中"); } else { MessageBox.Show(slaveex.Message + slaveex.ToString()); } } catch (Exception ex) { MessageBox.Show(ex.Message, "Error!"); } finally { // 确保异常场景下串口也能正常关闭 if (port.IsOpen) { port.Close(); } } }
方案2:直接读取原始响应帧(适配所有自定义响应场景)
如果你的从站存在非标准响应逻辑,需要获取所有返回帧不被NModbus内部过滤,可以直接调用传输层接口手动收发请求,拿到完整响应内容自行解析:
// 构建写入单个寄存器的请求报文 var request = new WriteSingleRegisterRequest(slaveId, 5000, Convert.ToUInt16(UserCodeText.Text)); // 发送请求 master.Transport.Write(request); // 读取原始响应,不会被NModbus内部逻辑过滤,所有返回帧都能拿到 var response = master.Transport.ReadResponse(); // 自行判断响应类型,普通响应/异常响应/Acknowledge都可以自行解析 if (response is SlaveExceptionResponse slaveExResp) { if (slaveExResp.SlaveExceptionCode == (byte)SlaveExceptionCodes.Acknowledge) { // 处理Acknowledge逻辑 } }
注意事项
- 调整NModbus传输层的超时时间和重试次数,避免Acknowledge响应因为触发重试逻辑被丢弃:
master.Transport.Retries = 0; // 不需要重试的话设为0 master.Transport.Timeout = 1000; // 根据从站响应延迟调整超时阈值
- 串口操作必须添加finally块保证关闭,避免端口被占用无法再次连接。
内容的提问来源于stack exchange,提问作者GSmyrlis
相关产品推荐
相关产品推荐

