根據高低溫試驗箱協議讀取資料
1.協議內容
8.1:通訊協議介紹
8.1.5 通訊設定
本通訊協議使用非同步序列通訊方式,1 個起始位、8 個資料位、2 個停止
位、無奇偶校驗資料通訊格式,其中資料位8 位,第1 位為最高位(MSB),第8
位為最低位(LSB)。
8.1.6 資料格式
通訊採用直接存取S7-200 V 儲存器資料的方式,所有的引數均放置於S7-200 V儲存器中,S7-200 中的資料型別為BYTE(位元組)、INT(有符號整數)、WORD(無符號整數)、DWORD(無符號長整)、LONG(有符號長整)、FLOAT
(浮點數)等格式,位操作按位元組方式操作,一個位元組8 個位。其中BYTE 長度
為1位元組;INT 和WORD為2位元組,先高後低;DWORD和LONG 為4位元組,
先高後低;浮點數為4位元組。詳細資料可參考西門子SIMATIC S7-200 可程式設計控
制器系統手冊。
8.1.7 讀引數命令
命令格式:>MMVDUUUUr
>:起始字元
MM:機號(在程式設計時因該轉換為16進位制資料)
VD:讀命令
UUUU:S7200 內部V 儲存器地址(在程式設計時因該轉換為16 進位制數
據)
r:回車字元
響應資料格式:<MMVDUUUUaabbccddee…r
<MMVDUUUU:響應命令頭
aabbccddee:從指定的V單元開始的128位元組,每2個字元代表一個位元組。
r:回車字元
8.1.8 PLC地址說明
引數名稱 | V地址單元 | 資料格式 | 資料說明 |
---|---|---|---|
執行狀態 | 904 | int | 0 停止 1 執行 2 暫停 |
溫度測量值 | 804 | float | 單位:℃ |
溼度測量值 | 860 | float | 單位:RH% |
2.使用串列埠助手除錯
- 串列埠助手設定
串列埠引數 | 引數值 |
---|---|
波特率 | 9600 |
資料位 | 8 |
停止位 | 2 |
校驗位 | 無 |
流控 | 無 |
- 除錯截圖
命令說明 要在命令後面新增回車,否則PLC無法識別命令。
>00VD0388 :獲取裝置執行狀態 返回結果: <00VD0388000000010000000200040000000000000000000000000000000000000000000000000000000000000000000000000000000000FA03B6000000FA0000FDDA0000
>00VD0324 :獲取溫度測量值 返回結果:<00VD032441EA980041EABDD541F6580041FBE0000000000044864400447EBA00000000000000000000000000000000000000000041C80000000000000000000000000000
>00VD035C :獲取溼度測量值 返回結果:<00VD035C00000000000000000000000001000400000000000000000000000000000000000000000000000000000000000000000100000002000400000000000000000000
根據命令返回結果,解析資料,獲取溫度測量值和溼度測量值。
1.由於返回結果為16進位制,需要將16進位制進行狀態。
2.溫度測量值和溼度測量值在返回結果中的位置分別為:41EA9800和00000000,需要將這兩個值轉換為float型別。
3.執行狀態在返回結果中的位置為:0000(擷取命令後4位),轉換為整數值為0。
4.溫度測量值為41EA9800(擷取命令後8位),轉換為浮點數為:29.324219。
5.溼度測量值為00000000(擷取命令後8位),轉換為浮點數為:0。
3.C# 使用 SerialPort 傳送命令接收資料
- 初始化串列埠資訊並開啟串列埠
private void OpenCom()
{
// 建立SerialPort物件
serialPort = new SerialPort(txtPort.Text.Trim(), 9600, Parity.None, 8, StopBits.Two);
serialPort.ReadTimeout = 1000; //串列埠讀取超時時間
serialPort.WriteTimeout = 1000; //串列埠寫入超時時間
// 開啟串列埠
serialPort.Open();
}
- 傳送命令並接收資料
public string SendOrderToPLC(string request)
{
string txt = string.Empty;
try
{
OpenCom();
// 將字串轉換為ASCII碼位元組陣列
byte[] asciiBytes = Encoding.ASCII.GetBytes(request);
// 傳送位元組陣列
serialPort.Write(asciiBytes, 0, asciiBytes.Length);
//等待資料接收完成 資料量小等待時間可小,資料量大等待時間長
Thread.Sleep(1000);
ASCIIEncoding ascii = new ASCIIEncoding();
byte[] readBuffer = new byte[serialPort.BytesToRead];
serialPort.Read(readBuffer, 0, readBuffer.Length);
if (readBuffer.Length > 14)
{
txt = ascii.GetString(readBuffer);
// 關閉串列埠
serialPort.Close();
return txt;
}
else
{
this.Invoke(new Action(() =>
{
this.labMes.Text = "No response received";
}));
serialPort.Close();
return txt;
}
}
catch (Exception ex)
{
txt = null;
this.Invoke(new Action(() =>
{
this.labMes.Text = ex.Message;
}));
return txt;
}
}
- 處理資料
處理裝置執行狀態資料
//獲取裝置執行狀態 ,取的是整數 所以16進製取4位;排除前面的<00VD0388命令
/*0 停止 1 執行 2 暫停
*/
var stringSub = result.Substring(9, 4);
var st = HexToDecimal(stringSub);
處理溫度資料
/*溫度取的是浮點數 所以16進製取8位;排除前面的 < 00VD0324命令 單位:℃
*/
var stringSub = result.Substring(9, 8);
var st = HexToDecimal(stringSub);
/*溼度取的是浮點數 所以16進製取8位;排除前面的 < 00VD035C命令 單位:RH%
*/
var stringSub = result.Substring(9, 8);
var st = HexToDecimal(stringSub);
4.資料轉換方法
/// <summary>
/// 將16進位制字串轉換為浮點數
/// </summary>
/// <param name="hex"></param>
/// <returns></returns>
static double HexToDecimal(string hex)
{
uint intValue = Convert.ToUInt32(hex, 16);
// 將整數值轉換為單精度浮點數
float floatValue = BitConverter.ToSingle(BitConverter.GetBytes(intValue), 0);
// 輸出結果
Console.WriteLine("Hex: " + hex);
Console.WriteLine("Float: " + floatValue);
return floatValue;
}