工控機通常都帶有很多串口(10個),而且可以通過Moxa卡擴展串口. 但Moxa的串口和電腦自帶的串口還是有點區別 C#裏面沒區別, 但之前VB6的MSComm控件有時就會有不一樣的地方.
支持串口通訊的儀錶,通常通訊指令分2種,一種是文本格式的,另一種是16進制格式的.
文本格式的,比如說有些儀器,查版本號發 *IDN? 就會返迴文本格式的結果,例如 XXX 8905,502-H19-1449,V1.38.02.18A2
16進制通訊的,比如青智的電流表,查詢電流用的命令格式 01是儀錶地址, 03是讀取的命令.1000是寄存器開始地址,000A是讀取長度, C10D是CRC校驗碼(多數使用CRC,也有儀器使用和校驗的)
青智
還有一種儀器是自帶MCU,就是一打開串口就自動上傳數據給上位機, 這種就不需要命令了.只需要定時讀取串口緩衝區的內容,按照報文的格式,分析出哪一段數據才是你需要的.
我常用的串口通訊工具有下面2個
在Github下載一個ComDBG的工具,這個是C#寫的,可以自己根據代碼擴展需要的功能,比如歷史發送記錄

另外可以用一個監控工具,串口監控精靈, 這個對於那些沒有代碼的exe(比如一些儀錶自帶有一些小軟件), 我們直接監控某個串口的收發信息.就知道對應的命令是什麼了.

我通常把串口通訊做成一個基類, 把打開/關閉串口,文本命令,16進制命令,CRC校驗,和校驗都寫到基類了,方便調用

下面是部分方法的代碼
public bool InitCom(int portNum,int BaudRate =9600)
{
//端口打開時無法設置「PortName」
if (!sp.IsOpen)
sp.PortName = "COM" + portNum.ToString();
else
{
if (sp.PortName != "COM" + portNum.ToString())
{
sp.Close();
sp.PortName = "COM" + portNum.ToString();
}
}
sp.BaudRate = BaudRate;//波特率
sp.Parity = Parity.None;//無奇偶校驗位
sp.StopBits = StopBits.One;//兩個停止位
sp.Handshake = Handshake.None;//控制協議
sp.WriteTimeout = 1000; /*Write time out*/
sp.ReceivedBytesThreshold = 1;//設置 DataReceived 事件發生前內部輸入緩衝區中的位元組數
return true;
}
//把一串命令,默認是文本string命令, 也可能是十六進制的數(空格分開),發到串口
protected bool SerialPortCmd(string command,ref string recvMsg,
int iDelay = 100, int RecvMsgLenParm= 2,bool IsCmdText =true)
{
DelaySec = iDelay;
RecvMsgLen = RecvMsgLenParm;
if (!openCom())
return false;
try
{
byte[] bytes;
if (IsCmdText)
bytes = Encoding.Default.GetBytes(command);
else
bytes = HexStringToBytes(command);
sp.Write(bytes, 0, bytes.Length);
}
catch (Exception ex)
{
Debug.Write(ex.ToString());
return false; //write failed
}
return DataReceived(IsCmdText, ref recvMsg);
}
private bool DataReceived(bool IsResultText,ref string result)
{
//Thread Safety explain in MSDN:
// Any public static (Shared in Visual Basic) members of this type are thread safe.
// Any instance members are not guaranteed to be thread safe.
// So, we need to synchronize I/O
lock (thisLock)
{
string RecvMsgBuffer;
int len = sp.BytesToRead;
if (len >= RecvMsgLen) //返回長度足夠了.
{
Byte[] data = new Byte[len];
try
{
sp.Read(data, 0, len);
}
catch (Exception ex)
{
throw ex;
}
if (IsResultText)
RecvMsgBuffer = Encoding.Default.GetString(data);
else
RecvMsgBuffer = BytesToHexString(data);
result = RecvMsgBuffer;
return true;
}
else
return false;
}
}
原創文章,作者:投稿專員,如若轉載,請註明出處:https://www.506064.com/zh-hk/n/223438.html