將SerialPort 封裝在內部,改善直接使用SerialPort Class 的問題。
改善後的 JgeComport Class :
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Windows.Forms;
using System.Linq;
using System.Text;
using System.IO.Ports;
using System.IO;
using System.Threading;
using System.Diagnostics;
namespace SBM75e_4
{
/// <summary>
/// 事件委派宣告
/// </summary>
public delegate void jgecomEventHandler(object sender, jgecomEventArgs e);
/// <summary>
/// 定義專用事件參數類別
/// </summary>
public class jgecomEventArgs : EventArgs
{
private string mComName;
private Stream mMSG = new MemoryStream();
//Byte[] mMSG = new Byte[1024];
//public jgecomEventArgs(byte[] msg, string commName)
public jgecomEventArgs(Stream msg, string commName)
{
MSG = msg;
NAME = commName;
}
public string NAME
{
get { return mComName; }
private set { mComName = value; }
}
//public byte[] MSG
public Stream MSG
{
get { return mMSG; }
private set { mMSG = value; }
}
}
// Invok 跳板的委派宣告
delegate void onInvok(Stream buffer);
class JgeComport
{
#region 靜態公用函式
/// <summary>
/// 將 Byte陣列 轉為 Stream
/// </summary>
/// <returns>Stream</returns>
public static Stream BytesToStream(byte[] bytes)
{
Stream stream = new MemoryStream(bytes);
return stream;
}
public static Stream BytesToStream(byte[] bytes, int Length)
{
Stream stream = new MemoryStream(bytes, 0, Length);
return stream;
}
/// <summary>
/// 將 Stream 轉為 Byte陣列
/// </summary>
public static byte[] StreamToBytes(Stream stream)
{
byte[] bytes = new byte[stream.Length];
stream.Read(bytes, 0, bytes.Length);
/*將 stream 指針指向開頭*/
stream.Seek(0, SeekOrigin.Begin);
return bytes;
}
#endregion
/// <summary>
/// 委派宣告
/// </summary>
private delegate void SetReceived(Stream msg, string ip);
/// <summary>
/// 委派欄位
/// </summary>
private SetReceived mSetReceivedDlg;
/// <summary>
/// Received 事件
/// </summary>
public event jgecomEventHandler Received;
/// <summary>
/// 委派處理函式
/// </summary>
private void OnReceivedText(Stream msg, string commName)
{
jgecomEventArgs e = new jgecomEventArgs(msg, commName);
if (Received != null) //. 當事件變數不為 null 則執行之
{
Received(this, e);
}
}
/// <summary>
/// 儲存擁有者
/// </summary>
private object mOwner;
//========================================================================
/// <summary>
/// SerialPort 物件,設為public 以便直接取用其屬性(偷懶的作法)
/// </summary>
private SerialPort comport;
/// <summary>
/// 內部使用變數
/// </summary>
private Boolean mReceiving; // 能讓DoReceive方法內的While迴圈停止
private Thread mRxThread; // Thread型別的變數 mRxThread,則是為了產生執行緒所宣告
/// <summary>
/// 建構式
/// </summary>
public JgeComport(object Owner)
{
mOwner = Owner;
mSetReceivedDlg = OnReceivedText;/*設定委派處理函式*/
comport = new SerialPort();
}
/// <summary>
/// Connect 方法-1
/// </summary>
public void Connect(string portName,int baudRate,Parity parity,int dataBits,StopBits stopBits)
{
comport.PortName = portName;
comport.BaudRate=baudRate;
comport.Parity=parity;
comport.DataBits=dataBits;
comport.StopBits = stopBits;
Connect();
}
/// <summary>
/// Connect 方法-2
/// </summary>
public void Connect()
{
if (!comport.IsOpen)
{
comport.Open();
// 產生執行緒來執行自訂的DoReceive方法
mReceiving = true;
mRxThread = new Thread(DoReceive);
//mRxThread = new Thread(DoReceiveEx);
mRxThread.IsBackground = true;
mRxThread.Start();
}
}
#region 以執行緒處裡Rx事件
/// <summary>
/// 以執行緒處裡Rx事件
/// </summary>
///
/* OnReceive 事件跳板 */
private void onInvoked(Stream buffer)
{
OnReceivedText(buffer, comport.PortName.ToString());
}
/* Rx 執行緒 */
private void DoReceive()
{
Byte[] buffer = new Byte[1024];
while (mReceiving)
{
if (comport.BytesToRead > 0)
{
Thread.Sleep(312); // Sleep 一段時間,用以讀取個多數據(該處可加入判斷式,進行更多的條件讀取)
Int32 length = comport.Read(buffer, 0, buffer.Length);
Array.Resize(ref buffer, length);
onInvok d = new onInvok(onInvoked);
/* Invoke */((System.Windows.Forms.Form)mOwner).Invoke(d, new Object[] { BytesToStream(buffer) });
Array.Resize(ref buffer, 1024);
}
Thread.Sleep(16);
}
}
#endregion
#region SerialPort 對應之屬性
/// <summary>
/// 要使用的連接埠 (例如 COM1)
/// </summary>
public string PortName
{
get
{
return comport.PortName;
}
set
{
comport.PortName = value;
}
}
/// <summary>
/// 傳輸速率: 2400,4800,9600,19200,38400,57600,115200
/// </summary>
public int BaudRate
{
get
{
return comport.BaudRate;
}
set
{
comport.BaudRate = value;
}
}
/// <summary>
/// System.IO.Ports.Parity
/// </summary>
public System.IO.Ports.Parity Parity
{
get
{
return comport.Parity;
}
set
{
comport.Parity = value;
}
}
/// <summary>
/// 資料位元值
/// </summary>
public int DataBits
{
get
{
return comport.DataBits;
}
set
{
comport.DataBits = value;
}
}
/// <summary>
/// System.IO.Ports.StopBits
/// </summary>
public System.IO.Ports.StopBits StopBits
{
get
{
return comport.StopBits;
}
set
{
comport.StopBits = value;
}
}
/// <summary>
/// 取得值,指出 SerialPort 物件的開啟或關閉狀態。
/// </summary>
public Boolean IsOpen
{
get
{
return comport.IsOpen;
}
set
{
}
}
#endregion
/// <summary>
/// 關閉連接埠連線
/// </summary>
public void Close()
{
comport.Close();
}
/// <summary>
/// 將指定的字串寫入序列埠
/// </summary>
public void Write(string text)
{
comport.Write(text);
}
/// <summary>
/// 使用緩衝區中的資料,將指定的位元組數目寫入序列埠。
/// </summary>
public void Write(byte[] buffer,int offset,int count)
{
comport.Write(buffer, offset, count);
}
/// <summary>
/// 使用緩衝區中的資料,將指定的字元數目寫入序列埠。
/// </summary>
public void Write(char[] buffer,int offset,int count)
{
comport.Write(buffer, offset, count);
}
/// <summary>
/// 使用Stream中的資料,將指定的字元數目寫入序列埠。
/// </summary>
public void Write(Stream buffer, int offset, int count)
{
byte[] bytes = new byte[buffer.Length];
comport.Write(bytes, offset, count);
}
/// <summary>
/// 將指定字串和 NewLine 值寫入輸出緩衝區
/// </summary>
public void WriteLine(String text)
{
comport.WriteLine(text);
}
}
}
使用該 Class
JgeComport My232 = new JgeComport(this);
My232.Connect("COM2", 57600, Parity.None, 8, StopBits.One);
My232.Received += this.onReceived;
string ss = "1234567890";
Byte[] bytes = System.Text.Encoding.ASCII.GetBytes(ss);
Stream stream = new MemoryStream(bytes);
My232.Write(ss);
My232.Write(bytes, 0, bytes.Length);
My232.Write(stream, 0, (int)(stream.Length));
事件程式
private void onReceived(object sender, jgecomEventArgs e)
{
switch (e.NAME.ToString())
{
case "COM2":
Byte[] bytes = new Byte[1024];
bytes = JgeComport.StreamToBytes(e.MSG);
string ss = System.Text.Encoding.ASCII.GetString(bytes);
textBox1.AppendText(ss + Environment.NewLine);
textBox1.Text += String.Format("{0}{1}", BitConverter.ToString(bytes), Environment.NewLine); //Environment.NewLine => \r\n
label2.Text = bytes.Length.ToString();
break;
default:
break;
}
}
ClassDiagram:
沒有留言:
張貼留言