C#串口通信實(shí)現(xiàn)方法
本文實(shí)例講述了C#串口通信實(shí)現(xiàn)方法。分享給大家供大家參考。具體方法如下:
通過(guò)COM1發(fā)送數(shù)據(jù),COM2接收數(shù)據(jù)。當(dāng)COM2接收完本次發(fā)送的數(shù)據(jù)后,向COM1發(fā)送信息通知COM1本次數(shù)據(jù)已發(fā)完,COM1接到通知后,再發(fā)下一段數(shù)據(jù)。這樣可以確保每次發(fā)送的數(shù)據(jù)都可以被正確接收。
代碼如下:
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.IO.Ports;
using System.Threading;
using Utils;
namespace 串口通信
{
public partial class Form1 : Form
{
#region 變量
/// <summary>
/// 啟動(dòng)還是停止,true起動(dòng),false停止
/// </summary>
public static bool start = true;
/// <summary>
/// 串口資源
/// </summary>
private static SerialPort serialPort1 = null;
/// <summary>
/// 串口資源
/// </summary>
private static SerialPort serialPort2 = null;
/// <summary>
/// 成功次數(shù)
/// </summary>
private static int successCount = 0;
/// <summary>
/// 失敗次數(shù)
/// </summary>
private static int errorCount = 0;
/// <summary>
/// 上次計(jì)算的總次數(shù)
/// </summary>
private static int lastCount = 0;
/// <summary>
/// 定時(shí)器
/// </summary>
private System.Windows.Forms.Timer timer = new System.Windows.Forms.Timer();
#endregion
#region Form1
public Form1()
{
InitializeComponent();
}
#endregion
#region Form1_Load
private void Form1_Load(object sender, EventArgs e)
{
serialPort1 = new SerialPort("COM1");
serialPort1.DataReceived += new SerialDataReceivedEventHandler(serialPort_DataReceived1);
serialPort1.Open();
serialPort2 = new SerialPort("COM2");
serialPort2.DataReceived += new SerialDataReceivedEventHandler(serialPort_DataReceived2);
serialPort2.Open();
}
#endregion
#region Form1_FormClosed
private void Form1_FormClosed(object sender, FormClosedEventArgs e)
{
serialPort1.Close();
serialPort1.Dispose();
serialPort2.Close();
serialPort2.Dispose();
}
#endregion
#region btnStart_Click
private void btnStart_Click(object sender, EventArgs e)
{
start = true;
SendData();
timer.Interval = 500;
timer.Tick += new EventHandler(delegate(object obj, EventArgs eventArgs)
{
if (lastCount == 0)
{
lastCount = successCount + errorCount;
}
else
{
int cnt = successCount + errorCount - lastCount;
cnt = Data.Length * cnt / 1024 * (1000 / timer.Interval);
double total = (successCount + errorCount) * Data.Length / 1024.0;
InvokeDelegate invokeDelegate = delegate()
{
label3.Text = cnt.ToString() + "KB/S " + total.ToString("#.0") + "KB";
};
InvokeUtil.Invoke(this, invokeDelegate);
lastCount = successCount + errorCount;
}
});
timer.Start();
}
#endregion
#region btnStop_Click
private void btnStop_Click(object sender, EventArgs e)
{
start = false;
timer.Stop();
timer.Dispose();
timer = new System.Windows.Forms.Timer();
}
#endregion
#region 接收串口數(shù)據(jù)事件
/// <summary>
/// 接收串口數(shù)據(jù)事件
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
public void serialPort_DataReceived1(object sender, SerialDataReceivedEventArgs e)
{
if (serialPort1.ReadLine() != null)
{
successCount++;
SendData();
}
}
/// <summary>
/// 接收串口數(shù)據(jù)事件
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
public void serialPort_DataReceived2(object sender, SerialDataReceivedEventArgs e)
{
List<byte> bList = new List<byte>();
int i = 0;
while (serialPort2.BytesToRead > 0)
{
byte[] bArr = new byte[serialPort2.BytesToRead];
i += serialPort2.Read(bArr, 0, bArr.Length);
bList.AddRange(bArr);
}
serialPort2.WriteLine("success");
string s = ASCIIEncoding.UTF8.GetString(bList.ToArray());
InvokeDelegate invokeDelegate = delegate()
{
textBox2.Text = s;
};
InvokeUtil.Invoke(this, invokeDelegate);
if (s != Str)
{
errorCount++;
invokeDelegate = delegate()
{
label2.Text = errorCount + "次不相等(失敗)";
};
InvokeUtil.Invoke(this, invokeDelegate);
}
else
{
invokeDelegate = delegate()
{
label1.Text = successCount + "次相等(成功)";
};
InvokeUtil.Invoke(this, invokeDelegate);
}
}
#endregion
#region 發(fā)送數(shù)據(jù)
private void SendData()
{
if (start)
{
Thread thread = new Thread(new ParameterizedThreadStart(delegate(object obj)
{
InvokeDelegate invokeDelegate = delegate()
{
textBox1.Text = Str;
};
InvokeUtil.Invoke(this, invokeDelegate);
serialPort1.Write(Data, 0, Data.Length);
}));
thread.Start();
}
}
#endregion
#region 數(shù)據(jù)
private static byte[] data = null;
/// <summary>
/// 數(shù)據(jù)
/// </summary>
private static byte[] Data
{
get
{
if (data == null)
{
data = ASCIIEncoding.UTF8.GetBytes(Str);
}
return data;
}
}
#endregion
#region 獲取字符串
private static string str = null;
/// <summary>
/// 字符串
/// </summary>
private static string Str
{
get
{
if (str == null)
{
StringBuilder sb = new StringBuilder();
for (int i = 0; i < 270; i++)
{
sb.Append("計(jì)算機(jī)程序");
}
str = sb.ToString();
}
return str;
}
}
#endregion
}
}
輔助代碼如下:
using System.Collections.Generic;
using System.Text;
using System.Windows.Forms;
namespace Utils
{
/// <summary>
/// 跨線程訪問(wèn)控件的委托
/// </summary>
public delegate void InvokeDelegate();
/// <summary>
/// 跨線程訪問(wèn)控件類
/// </summary>
public class InvokeUtil
{
/// <summary>
/// 跨線程訪問(wèn)控件
/// </summary>
/// <param name="ctrl">Form對(duì)象</param>
/// <param name="de">委托</param>
public static void Invoke(Control ctrl, Delegate de)
{
if (ctrl.IsHandleCreated)
{
ctrl.BeginInvoke(de);
}
}
}
}
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Win32;
using System.Security.Permissions;
using System.IO.Ports;
using System.Security;
namespace Utils
{
/// <summary>
/// 串口資源工具類
/// </summary>
public class SerialPortUtil
{
#region 獲取本機(jī)串口列表,包括虛擬串口
/// <summary>
/// 獲取本機(jī)串口列表,包括虛擬串口
/// </summary>
public static string[] GetCOMList()
{
List<string> list = new List<string>();
foreach (string portName in SerialPort.GetPortNames())
{
list.Add(portName);
}
return list.ToArray();
}
#endregion
#region 從注冊(cè)表獲取本機(jī)串口列表
/// <summary>
/// 從注冊(cè)表獲取本機(jī)串口列表
/// </summary>
public static string[] GetPortNames()
{
RegistryKey localMachine = null;
RegistryKey key2 = null;
string[] textArray = null;
//這里有個(gè)斷言,判斷該注冊(cè)表項(xiàng)是否存在
new RegistryPermission(RegistryPermissionAccess.Read, @"HKEY_LOCAL_MACHINE\HARDWARE\DEVICEMAP\SERIALCOMM").Assert();
try
{
localMachine = Registry.LocalMachine;
key2 = localMachine.OpenSubKey(@"HARDWARE\DEVICEMAP\SERIALCOMM", false);
if (key2 != null)
{
string[] valueNames = key2.GetValueNames();
textArray = new string[valueNames.Length];
for (int i = 0; i < valueNames.Length; i++)
{
textArray[i] = (string)key2.GetValue(valueNames[i]);
}
}
}
finally
{
if (localMachine != null)
{
localMachine.Close();
}
if (key2 != null)
{
key2.Close();
}
CodeAccessPermission.RevertAssert();
}
if (textArray == null)
{
textArray = new string[0];
}
return textArray;
}
#endregion
}
}
希望本文所述對(duì)大家的C#程序設(shè)計(jì)有所幫助。
相關(guān)文章
C# 實(shí)現(xiàn)在控制臺(tái)上換行輸出與不換行輸出
這篇文章主要介紹了C# 實(shí)現(xiàn)在控制臺(tái)上換行輸出與不換行輸出,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2021-04-04C#創(chuàng)建自定義控件及添加自定義屬性和事件使用實(shí)例詳解
這篇文章主要給大家介紹了關(guān)于C#創(chuàng)建自定義控件及添加自定義屬性和事件使用的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家學(xué)習(xí)或者使用C#具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2020-05-05基于params,ref,out的參數(shù)問(wèn)題詳解
本篇文章是對(duì)params,ref,out的參數(shù)問(wèn)題進(jìn)行了詳細(xì)的分析介紹,需要的朋友參考下2013-06-06分享C#操作內(nèi)存讀寫方法的主要實(shí)現(xiàn)代碼
這篇文章介紹了C#操作內(nèi)存讀寫方法的主要實(shí)現(xiàn)代碼,下面讓我們來(lái)看看具體的實(shí)例實(shí)現(xiàn),有需要的朋友可以參考一下2013-08-08C#實(shí)現(xiàn)從位圖到布隆過(guò)濾器的方法
布隆過(guò)濾器(Bloom filter)是一種特殊的 Hash Table,能夠以較小的存儲(chǔ)空間較快地判斷出數(shù)據(jù)是否存在。常用于允許一定誤判率的數(shù)據(jù)過(guò)濾及防止緩存擊穿及等場(chǎng)景,本文將以 C# 語(yǔ)言來(lái)實(shí)現(xiàn)一個(gè)簡(jiǎn)單的布隆過(guò)濾器,為簡(jiǎn)化說(shuō)明,設(shè)計(jì)得很簡(jiǎn)單,需要的朋友可以參考下2022-06-06C#調(diào)用C++DLL傳遞結(jié)構(gòu)體數(shù)組的終極解決方案
這篇文章主要介紹了C#調(diào)用C++DLL傳遞結(jié)構(gòu)體數(shù)組的終極解決方案的相關(guān)資料,需要的朋友可以參考下2017-01-01Unity實(shí)現(xiàn)游戲傷害數(shù)字顯示HUD的方法
游戲中收到傷害掉血,會(huì)有飄動(dòng)的傷害數(shù)值,本文主要介紹Unity實(shí)現(xiàn)游戲傷害數(shù)字顯示HUD的方法,文中通過(guò)示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2021-10-10