1. 程式人生 > >串列埠通訊與NJH框架

串列埠通訊與NJH框架

 

NJH框架

  1     public class BaseSerialPort {
  2 
  3         #region 欄位
  4         private const int msgMaxLength = 512;//通訊協議中最長的指令的位元組數目,制定的通訊協議最長指令不得超過msgMaxLength
  5         private object locker = new object();//在串列埠接收資料的執行緒中使用,保證資料接收正確
  6         
  7         private byte[] byteMsgRecv;//
使用位元組協議時,用於接收資料 8 private string strMsgRecv;//使用字元協議時,用於接收資料 9 10 private AutoResetEvent waiterForRsp = new AutoResetEvent(false);//用於同步使用者的Logic執行緒和串列埠的DataReceived執行緒 11 private int usingSource = 0;//保證一條指令的互動完整性,或多條指令組成的模組的互動完整性 12 13 public SerialPort _device {
14 get; private set; 15 } 16 private Encoding encoding;//字元編碼 17 #endregion 18 19 #region 建構函式 20 /// <summary> 21 /// 使用位元組型通訊協議呼叫此建構函式 22 /// </summary> 23 /// <param name="portName">串列埠名</param> 24 ///
<param name="baudRate">波特率</param> 25 /// <param name="dataBits">資料位</param> 26 /// <param name="stopBits">停止位</param> 27 /// <param name="parity">奇偶校驗</param> 28 public BaseSerialPort(string portName, int baudRate, int dataBits, StopBits stopBits, Parity parity) { 29 this._device = new SerialPort(); 30 this._device.PortName = portName; 31 this._device.BaudRate = baudRate; 32 this._device.DataBits = dataBits; 33 this._device.StopBits = stopBits; 34 this._device.Parity = parity; 35 this._device.DataReceived += Device_DataReceived; 36 this.encoding = null; 37 } 38 /// <summary> 39 /// 使用字串型通訊協議呼叫此建構函式 40 /// </summary> 41 /// <param name="portName">串列埠名</param> 42 /// <param name="baudRate">波特率</param> 43 /// <param name="dataBits">資料位</param> 44 /// <param name="stopBits">停止位</param> 45 /// <param name="parity">奇偶校驗</param> 46 public BaseSerialPort(string portName, int baudRate, int dataBits, StopBits stopBits, Parity parity, Encoding encoding) { 47 this._device = new SerialPort(); 48 this._device.PortName = portName; 49 this._device.BaudRate = baudRate; 50 this._device.DataBits = dataBits; 51 this._device.StopBits = stopBits; 52 this._device.Parity = parity; 53 this._device.DataReceived += Device_DataReceived; 54 this.encoding = encoding; 55 } 56 #endregion 57 58 #region 連線裝置 59 public void Connect() { 60 try { 61 if (!this._device.IsOpen) { 62 this._device.Open(); 63 } 64 } 65 catch { 66 throw new Exception(string.Format("埠{0}已被佔用或被拒絕訪問",this._device.PortName)); 67 } 68 } 69 #endregion 70 71 #region 關閉連線 72 public void Close() { 73 if (this._device.IsOpen) { 74 this._device.Close(); 75 } 76 } 77 #endregion 78 79 #region 接收資料 80 public void Device_DataReceived(object sender, SerialDataReceivedEventArgs e) { 81 lock (locker) { 82 if (_device.BytesToRead > 0) { 83 byte[] buff = new byte[msgMaxLength]; 84 int startIndex = 0; 85 while (_device.BytesToRead > 0) { 86 int count = _device.Read(buff, startIndex, _device.BytesToRead); 87 startIndex += count; 88 Thread.Sleep(10); 89 } 90 91 byte[] msg = new byte[startIndex]; 92 Array.Copy(buff, msg, startIndex); 93 94 if (this.encoding == null) { 95 this.byteMsgRecv = msg; 96 } 97 else { 98 string strMsg = this.encoding.GetString(msg); 99 this.strMsgRecv = strMsg; 100 } 101 waiterForRsp.Set(); 102 } 103 } 104 } 105 #endregion 106 107 #region 傳送訊息 108 public void SendMsg(byte[] msg) { 109 this.Connect(); 110 this._device.Write(msg, 0, msg.Length); 111 } 112 113 public void SendMsg(string msg) { 114 this.Connect(); 115 byte[] msgToByte = this.encoding.GetBytes(msg); 116 this._device.Write(msgToByte, 0, msgToByte.Length); 117 } 118 #endregion 119 120 #region 原子操作 121 /// <summary> 122 /// 接收裝置的響應訊息(位元組型通訊協議) 123 /// </summary> 124 /// <param name="timeOut">等待裝置回覆的最大時長</param> 125 /// <param name="msg">收到的裝置的回覆</param> 126 /// <returns></returns> 127 public bool RecvRsp(int timeOut, out byte[] msg) { 128 bool isInTime = waiterForRsp.WaitOne(timeOut); 129 byte[] buff = new byte[byteMsgRecv.Length]; 130 Array.Copy(byteMsgRecv, buff, byteMsgRecv.Length); 131 msg = buff; 132 return isInTime; 133 } 134 /// <summary> 135 /// 接收裝置的響應訊息(字元型通訊協議) 136 /// </summary> 137 /// <param name="timeOut">等待裝置回覆的最大時長</param> 138 /// <param name="msg">收到的裝置的回覆</param> 139 /// <returns></returns> 140 public bool RecvRsp(int timeOut, out string msg) { 141 bool isInTime = waiterForRsp.WaitOne(timeOut); 142 msg = strMsgRecv; 143 return isInTime; 144 } 145 146 public void OccupyRoute() { 147 while (Interlocked.Exchange(ref usingSource, 1) == 1) 148 ; 149 } 150 151 public void AbandonRoute() { 152 Interlocked.Exchange(ref usingSource, 0); 153 } 154 #endregion 155 }
View Code

使用方法:

1,適用場景

上位機和裝置通過協議傳送和接收資料互動,從而達到上位機控制裝置的目的。

2,使用方法

(1)示例

現在有個需求:上位機軟體包括一個點膠機控制器,用來控制點膠機的開始吐膠,停止吐膠,真空壓力值等行為。

 1     /// <summary>
 2     /// 點膠機控制器
 3     /// </summary>
 4     class DispenserControler {
 5         //串列埠
 6         private BaseSerialPort port = new BaseSerialPort("COM1", 9600, 8, StopBits.One, Parity.None,Encoding.ASCII);
 7 
 8         public void Init() {
 9             port.Connect();
10         }
11         //吐膠
12         public void TuJiao() {
13             port.OccupyRoute();
14             port.SendMsg("tu jiao");
15             string msg;
16             bool res = port.RecvRsp(20000, out msg);
17             if (res == false) {
18                 Console.WriteLine("OVER TIME");
19             }
20             else {
21                 Console.WriteLine(msg);
22             }
23         }
24         public void ShutDown() {
25             port.Close();
26         }
27     }
View Code