SerialPort 发送命令并获得响应
SerialPort to send command and to get response
我正在创建一个程序来处理一些使用串口的设备。我有文档,其中详细说明了如何通过端口发送命令。它工作得很好,但我应该得到一些关于设备状态的信息。我尝试了一切,但我对这些类型的开发没有信心。可能是我错过了什么。
来自文档:
一共21条命令,20条打开命令,1条读取状态命令
打开命令:
地址命令固定值(0x55)锁号
地址 0XF2 0X55 0X01
地址 0XF2 0X55 0X02
地址 0XF2 0X55 0X03
......
以上命令执行
成功 returns :
地址+0X59+0X59
失败returns:地址+0X5E+0X5E
/// <summary>
/// Send open lokcer door command
/// </summary>
/// <param name="boardAddress">0 means open left slave cabinet,1 means open right slave cabinet</param>
/// <param name="command"></param>
/// <returns></returns>
public byte[] OpenBox(byte boardAddress, byte command)
{
var openCommand = new byte[5];
openCommand[0] = (byte)(255 - boardAddress);
openCommand[0] = 0xF2;
openCommand[1] = 0x55;
openCommand[2] = command;
openCommand[3] = 0X00;
openCommand[4] = 0X00;
try
{
if (!serialPort.IsOpen)
{
//serialPort.WriteBufferSize = 5;
serialPort.Open();
}
serialPort.DiscardInBuffer();
serialPort.Write(openCommand, 0, 3);
return openCommand;
}
catch (ArgumentException ex)
{
throw new InvalidOperationException("Locker cell can not be opened.", ex);
}
}
它工作得很好,但最后 2 个字节 return 什么都没有。它们始终为 0X00。我也在使用 SerialPortDataReceived 但我总是在那里得到 0。
public void SerialPortDataReceived(object sender, SerialDataReceivedEventArgs e)
{
DBException.WriteLog("");
DBException.WriteLog("Serial port data received");
var sp = (SerialPort)sender;
DBException.WriteLog("Read existing = " + sp.ReadExisting());
try
{
DBException.WriteLog("Length = " + sp.BytesToRead);
if (serialPort.BytesToRead == 4)
{
var readBuffer = new byte[4];
sp.Read(readBuffer, 0, serialPort.BytesToRead);
DBException.WriteLog("Read serial port :" + readBuffer.ByteArrayToString());
// RaiseLockerStatusEvent(readBuffer.ByteArrayToString());
}
}
catch (Exception ex)
{
DBException.WriteLog(ex);
}
}
问题 1 如何获得成功或失败 return?我认为它们应该在最后 2 个字节中。
问题 2
如何获得所有状态?目前一无所获
文档:
读锁状态命令:Address + Data1 + Data2 + Data3
地址:0XF10X55
数据1 数据2 数据3
0000 锁 20 … 锁 17 锁 16 … 锁 9 锁 8 … 锁 1
前4位为固定数0000
样本:
0000 0000 0000 0001 0000 0001表示lock1和lock9打开,其他关闭
注:对于某些类型的电子锁,“1”表示关闭,“0”表示打开。
我的片段
/// <summary>
/// Send check machine(cabinet) status command
/// </summary>
/// <param name="address">0 means check left cabinet, 1 means check right cabinet </param>
/// <returns></returns>
public byte[] SendCheckLockControlStatueCommand(byte address)
{
lock (this)
{
var checkCommand = new byte[6];
checkCommand[0] = Convert.ToByte(255 - address);
checkCommand[1] = 0xF1;
checkCommand[2] = 0x55;
checkCommand[3] = 0x00;
checkCommand[4] = 0x00;
checkCommand[5] = 0x00;
try
{
if (!serialPort.IsOpen)
{
// serialPort.WriteBufferSize = 5;
serialPort.Open();
}
//Send inquiry command
serialPort.DiscardInBuffer();
// serialPort.DiscardOutBuffer();
serialPort.Write(checkCommand, 0, 6);
return checkCommand;
}
catch (ArgumentException ex)
{
throw new InvalidOperationException("Locker cell can not be opened.", ex);
}
}
}
永远不要像您那样使用异步 DataReceived
事件!您需要决定:是要同步通信还是异步通信。如果你想要后者,永远不要在 DataReceived
.
中调用甚至 wait
相反,将您收到的内容放入缓冲区,并在消息完成后立即处理。
此外,对 ReadExisting
的调用已经从那里的串行端口读取了所有内容,因此 Read
很可能会阻塞!
它应该看起来像这样:
List<byte> receivedBinaryData = new List<byte>();
public void SerialPortDataReceived(object sender, SerialDataReceivedEventArgs e)
{
var sp = (SerialPort)sender;
string availableData = sp.ReadExisting();
byte[] inputAsASCII = Encoding.ASCII.GetBytes(availableData);
DBException.WriteLog("");
DBException.WriteLog("Serial port data received");
DBException.WriteLog("Read existing = " + availableData);
try
{
// Add the bytes to the receivedBinaryData List
receivedBinaryData.AddRange(inputAsASCII);
// If the message length is reached or exceeded, do something
if (receivedBinaryData.Length >= 4)
....
}
catch (Exception ex)
{
DBException.WriteLog(ex);
}
}
我正在创建一个程序来处理一些使用串口的设备。我有文档,其中详细说明了如何通过端口发送命令。它工作得很好,但我应该得到一些关于设备状态的信息。我尝试了一切,但我对这些类型的开发没有信心。可能是我错过了什么。
来自文档:
一共21条命令,20条打开命令,1条读取状态命令
打开命令:
地址命令固定值(0x55)锁号
地址 0XF2 0X55 0X01
地址 0XF2 0X55 0X02
地址 0XF2 0X55 0X03
......
以上命令执行
成功 returns : 地址+0X59+0X59
失败returns:地址+0X5E+0X5E
/// <summary>
/// Send open lokcer door command
/// </summary>
/// <param name="boardAddress">0 means open left slave cabinet,1 means open right slave cabinet</param>
/// <param name="command"></param>
/// <returns></returns>
public byte[] OpenBox(byte boardAddress, byte command)
{
var openCommand = new byte[5];
openCommand[0] = (byte)(255 - boardAddress);
openCommand[0] = 0xF2;
openCommand[1] = 0x55;
openCommand[2] = command;
openCommand[3] = 0X00;
openCommand[4] = 0X00;
try
{
if (!serialPort.IsOpen)
{
//serialPort.WriteBufferSize = 5;
serialPort.Open();
}
serialPort.DiscardInBuffer();
serialPort.Write(openCommand, 0, 3);
return openCommand;
}
catch (ArgumentException ex)
{
throw new InvalidOperationException("Locker cell can not be opened.", ex);
}
}
它工作得很好,但最后 2 个字节 return 什么都没有。它们始终为 0X00。我也在使用 SerialPortDataReceived 但我总是在那里得到 0。
public void SerialPortDataReceived(object sender, SerialDataReceivedEventArgs e)
{
DBException.WriteLog("");
DBException.WriteLog("Serial port data received");
var sp = (SerialPort)sender;
DBException.WriteLog("Read existing = " + sp.ReadExisting());
try
{
DBException.WriteLog("Length = " + sp.BytesToRead);
if (serialPort.BytesToRead == 4)
{
var readBuffer = new byte[4];
sp.Read(readBuffer, 0, serialPort.BytesToRead);
DBException.WriteLog("Read serial port :" + readBuffer.ByteArrayToString());
// RaiseLockerStatusEvent(readBuffer.ByteArrayToString());
}
}
catch (Exception ex)
{
DBException.WriteLog(ex);
}
}
问题 1 如何获得成功或失败 return?我认为它们应该在最后 2 个字节中。
问题 2 如何获得所有状态?目前一无所获
文档:
读锁状态命令:Address + Data1 + Data2 + Data3 地址:0XF10X55 数据1 数据2 数据3 0000 锁 20 … 锁 17 锁 16 … 锁 9 锁 8 … 锁 1 前4位为固定数0000 样本: 0000 0000 0000 0001 0000 0001表示lock1和lock9打开,其他关闭 注:对于某些类型的电子锁,“1”表示关闭,“0”表示打开。
我的片段
/// <summary>
/// Send check machine(cabinet) status command
/// </summary>
/// <param name="address">0 means check left cabinet, 1 means check right cabinet </param>
/// <returns></returns>
public byte[] SendCheckLockControlStatueCommand(byte address)
{
lock (this)
{
var checkCommand = new byte[6];
checkCommand[0] = Convert.ToByte(255 - address);
checkCommand[1] = 0xF1;
checkCommand[2] = 0x55;
checkCommand[3] = 0x00;
checkCommand[4] = 0x00;
checkCommand[5] = 0x00;
try
{
if (!serialPort.IsOpen)
{
// serialPort.WriteBufferSize = 5;
serialPort.Open();
}
//Send inquiry command
serialPort.DiscardInBuffer();
// serialPort.DiscardOutBuffer();
serialPort.Write(checkCommand, 0, 6);
return checkCommand;
}
catch (ArgumentException ex)
{
throw new InvalidOperationException("Locker cell can not be opened.", ex);
}
}
}
永远不要像您那样使用异步 DataReceived
事件!您需要决定:是要同步通信还是异步通信。如果你想要后者,永远不要在 DataReceived
.
相反,将您收到的内容放入缓冲区,并在消息完成后立即处理。
此外,对 ReadExisting
的调用已经从那里的串行端口读取了所有内容,因此 Read
很可能会阻塞!
它应该看起来像这样:
List<byte> receivedBinaryData = new List<byte>();
public void SerialPortDataReceived(object sender, SerialDataReceivedEventArgs e)
{
var sp = (SerialPort)sender;
string availableData = sp.ReadExisting();
byte[] inputAsASCII = Encoding.ASCII.GetBytes(availableData);
DBException.WriteLog("");
DBException.WriteLog("Serial port data received");
DBException.WriteLog("Read existing = " + availableData);
try
{
// Add the bytes to the receivedBinaryData List
receivedBinaryData.AddRange(inputAsASCII);
// If the message length is reached or exceeded, do something
if (receivedBinaryData.Length >= 4)
....
}
catch (Exception ex)
{
DBException.WriteLog(ex);
}
}