串口通信(Serial Communications)的概念非常简单,串口按位(bit)发送和接收字节。尽管比按字节(byte)的并行通信慢,但是串口可以在使用一根线发送数据的同时用另一根线接收数据。它很简单并且能够实现远距离通信。由于串口通信是异步的,端口能够在一根线上发送数据同时在另一根线上接收数据。其他线用于握手,但不是必须的。串口通信最重要的参数是波特率、数据位、停止位和奇偶校验。对于两个进行通信的端口,这些参数必须匹配。
-
using System;
-
using System.IO.Ports;
-
using System.Text;
-
-
namespace PortControlDemo
-
{
-
public class PortControlHelper
-
{
-
#region 字段/属性/委托
-
/// <summary>
-
/// 串行端口对象
-
/// </summary>
-
private SerialPort sp;
-
-
/// <summary>
-
/// 串口接收数据委托
-
/// </summary>
-
public delegate void ComReceiveDataHandler(string data);
-
-
public ComReceiveDataHandler OnComReceiveDataHandler = null;
-
-
/// <summary>
-
/// 端口名称数组
-
/// </summary>
-
public string[] PortNameArr { get; set; }
-
-
/// <summary>
-
/// 串口通信开启状态
-
/// </summary>
-
public bool PortState { get; set; } = false;
-
-
/// <summary>
-
/// 编码类型
-
/// </summary>
-
public Encoding EncodingType { get; set; } = Encoding.ASCII;
-
#endregion
-
-
#region 方法
-
public PortControlHelper()
-
{
-
PortNameArr = SerialPort.GetPortNames();
-
sp = new SerialPort();
-
sp.DataReceived += new SerialDataReceivedEventHandler(DataReceived);
-
}
-
-
/// <summary>
-
/// 打开端口
-
/// </summary>
-
/// <param name="portName">端口名称</param>
-
/// <param name="boudRate">波特率</param>
-
/// <param name="dataBit">数据位</param>
-
/// <param name="stopBit">停止位</param>
-
/// <param name="timeout">超时时间</param>
-
public void OpenPort(string portName , int boudRate = 115200, int dataBit = 8, int stopBit = 1, int timeout = 5000)
-
{
-
try
-
{
-
sp.PortName = portName;
-
sp.BaudRate = boudRate;
-
sp.DataBits = dataBit;
-
sp.StopBits = (StopBits)stopBit;
-
sp.ReadTimeout = timeout;
-
sp.Open();
-
PortState = true;
-
}
-
catch (Exception e)
-
{
-
throw e;
-
}
-
}
-
-
/// <summary>
-
/// 关闭端口
-
/// </summary>
-
public void ClosePort()
-
{
-
try
-
{
-
sp.Close();
-
PortState = false;
-
}
-
catch (Exception e)
-
{
-
throw e;
-
}
-
}
-
-
/// <summary>
-
/// 发送数据
-
/// </summary>
-
/// <param name="sendData"></param>
-
public void SendData(string sendData)
-
{
-
try
-
{
-
sp.Encoding = EncodingType;
-
sp.Write(sendData);
-
}
-
catch (Exception e)
-
{
-
throw e;
-
}
-
}
-
-
/// <summary>
-
/// 接收数据回调用
-
/// </summary>
-
/// <param name="sender"></param>
-
/// <param name="e"></param>
-
private void DataReceived(object sender, SerialDataReceivedEventArgs e)
-
{
-
byte[] buffer = new byte[sp.BytesToRead];
-
sp.Read(buffer, 0, buffer.Length);
-
string str = EncodingType.GetString(buffer);
-
if (OnComReceiveDataHandler != null)
-
{
-
OnComReceiveDataHandler(str);
-
}
-
}
-
#endregion
-
}
-
}
本界面主要功能是操作两个串口,一个发送数据另一个接收数据。左侧设置两串口的一些参数,设置完成后点击"打开发送接收串口",如两串口成功打开,右侧便可操作发送和接受数据。
-
using System;
-
using System.Windows.Forms;
-
-
namespace PortControlDemo
-
{
-
public partial class FrmPortControl : Form
-
{
-
#region 字段/属性
-
int[] BaudRateArr = new int[] { 110, 300, 1200, 2400, 4800, 115200 };
-
int[] DataBitArr = new int[] { 6, 7, 8 };
-
int[] StopBitArr = new int[] { 1, 2, 3};
-
int[] TimeoutArr = new int[] { 500, 1000, 2000, 5000, 10000 };
-
object[] CheckBitArr = new object[] { "None"};
-
private bool ReceiveState = false;
-
private PortControlHelper pchSend;
-
private PortControlHelper pchReceive;
-
#endregion
-
-
#region 方法
-
/// <summary>
-
/// 初始化控件
-
/// </summary>
-
private void InitView()
-
{
-
cb_portNameSend.DataSource = pchSend.PortNameArr;
-
cb_portNameReceive.DataSource = pchReceive.PortNameArr;
-
cb_baudRate.DataSource = BaudRateArr;
-
cb_dataBit.DataSource = DataBitArr;
-
cb_stopBit.DataSource = StopBitArr;
-
cb_checkBit.DataSource = CheckBitArr;
-
cb_timeout.DataSource = TimeoutArr;
-
FreshBtnState(pchSend.PortState && pchReceive.PortState);
-
}
-
-
/// <summary>
-
/// 刷新按钮状态
-
/// </summary>
-
/// <param name="state"></param>
-
private void FreshBtnState(bool state)
-
{
-
if (state)
-
{
-
Btn_open.Text = "关闭发送接收串口";
-
Btn_send.Enabled = true;
-
Btn_receive.Enabled = true;
-
}
-
else
-
{
-
Btn_open.Text = "打开发送接收串口";
-
Btn_send.Enabled = false;
-
Btn_receive.Enabled = false;
-
}
-
}
-
#endregion
-
-
#region 事件
-
public FrmPortControl()
-
{
-
InitializeComponent();
-
pchSend = new PortControlHelper();
-
pchReceive = new PortControlHelper();
-
InitView();
-
}
-
-
/// <summary>
-
/// 点击 发送数据 按钮,发送文本内数据
-
/// </summary>
-
/// <param name="sender"></param>
-
/// <param name="e"></param>
-
private void Btn_send_Click(object sender, EventArgs e)
-
{
-
pchSend.SendData(tb_send.Text);
-
}
-
-
/// <summary>
-
/// 点击 开始接收 按钮,开始监听串口接收入口数据
-
/// </summary>
-
/// <param name="sender"></param>
-
/// <param name="e"></param>
-
private void Btn_receive_Click(object sender, EventArgs e)
-
{
-
if (ReceiveState)
-
{
-
pchReceive.OnComReceiveDataHandler -= new PortControlHelper.ComReceiveDataHandler(ComReceiveData);
-
Btn_receive.Text = "开始接收";
-
ReceiveState = false;
-
}
-
else
-
{
-
-
pchReceive.OnComReceiveDataHandler += new PortControlHelper.ComReceiveDataHandler(ComReceiveData);
-
Btn_receive.Text = "停止接收";
-
ReceiveState = true;
-
}
-
}
-
-
/// <summary>
-
/// 开启或关闭 两个通信的串口,刷新按钮状态
-
/// </summary>
-
/// <param name="sender"></param>
-
/// <param name="e"></param>
-
private void Btn_open_Click(object sender, EventArgs e)
-
{
-
if (pchSend.PortState)
-
{
-
pchSend.ClosePort();
-
pchReceive.ClosePort();
-
}
-
else
-
{
-
pchSend.OpenPort(cb_portNameSend.Text, int.Parse(cb_baudRate.Text),
-
int.Parse(cb_dataBit.Text), int.Parse(cb_stopBit.Text),
-
int.Parse(cb_timeout.Text));
-
pchReceive.OpenPort(cb_portNameReceive.Text, int.Parse(cb_baudRate.Text),
-
int.Parse(cb_dataBit.Text), int.Parse(cb_stopBit.Text),
-
int.Parse(cb_timeout.Text));
-
-
}
-
FreshBtnState(pchSend.PortState && pchReceive.PortState);
-
pchReceive.OnComReceiveDataHandler += new PortControlHelper.ComReceiveDataHandler(ComReceiveData);
-
Btn_receive.Text = "停止接收";
-
ReceiveState = true;
-
}
-
-
/// <summary>
-
/// 接收到的数据,写入文本框内
-
/// </summary>
-
/// <param name="data"></param>
-
private void ComReceiveData(string data)
-
{
-
this.Invoke(new EventHandler(delegate
-
{
-
tb_receive.AppendText($"接收:{data}\n");
-
}));
-
}
-
#endregion
-
}
-
}