串口通信
在.NET平台下创建C#串口通信程序,.NET 2.0提供了串口通信的功能,其命名空间是System.IO.Ports。这个新的框架不但可以访问计算机上的串口,还可以和串口设备进行通信。
创建C#串口通信程序之命名空间 System.IO.Ports命名空间中最重用的是SerialPort 类。 创建C#串口通信程序之创建SerialPort 对象 通过创建SerialPort 对象,我们可以在程序中控制串口通信的全过程。
正文
属性
| BaseStream | 获取 Stream 对象的基础 SerialPort 对象。 |
| BaudRate | 获取或设置串行波特率。 |
| BreakState | 获取或设置中断信号状态。 |
| BytesToRead | 获取接收缓冲区中数据的字节数。 |
| BytesToWrite | 获取发送缓冲区中数据的字节数。 |
| CDHolding | 获取端口的载波检测行的状态。 |
| CtsHolding | 获取“可以发送”行的状态。 |
| DataBits | 获取或设置每个字节的标准数据位长度。 |
| DiscardNull | 获取或设置一个值,该值指示 null 字节在端口和接收缓冲区之间传输时是否被忽略。 |
| DsrHolding | 获取数据设置就绪 (DSR) 信号的状态。 |
| DtrEnable | 获取或设置一个值,该值在串行通信过程中启用数据终端就绪 (DTR) 信号。 |
| Encoding | 获取或设置传输前后文本转换的字节编码。 |
| Handshake | 使用 Handshake 中的值获取或设置串行端口数据传输的握手协议。 |
| IsOpen | 获取一个值,该值指示 SerialPort 对象的打开或关闭状态。 |
| NewLine | 获取或设置用于解释 ReadLine() 和 WriteLine(String) 方法调用结束的值。 |
| Parity | 获取或设置奇偶校验检查协议。 |
| ParityReplace | 获取或设置一个字节,该字节在发生奇偶校验错误时替换数据流中的无效字节。 |
| PortName | 获取或设置通信端口,包括但不限于所有可用的 COM 端口。 |
| ReadBufferSize | 获取或设置 SerialPort 输入缓冲区的大小。 |
| ReadTimeout | 获取或设置读取操作未完成时发生超时之前的毫秒数。 |
| ReceivedBytesThreshold | 获取或设置 DataReceived 事件发生前内部输入缓冲区中的字节数。 |
| RtsEnable | 获取或设置一个值,该值指示在串行通信中是否启用请求发送 (RTS) 信号。 |
| StopBits | 获取或设置每个字节的标准停止位数。 |
| WriteBufferSize | 获取或设置串行端口输出缓冲区的大小。 |
| WriteTimeout | 获取或设置写入操作未完成时发生超时之前的毫秒数。 |
方法
| Close() | 关闭端口连接,将 IsOpen 属性设置为 false,并释放内部 Stream 对象。 |
| DiscardInBuffer() | 丢弃来自串行驱动程序的接收缓冲区的数据。 |
| DiscardOutBuffer() | 丢弃来自串行驱动程序的传输缓冲区的数据。 |
| GetPortNames() | 获取当前计算机的串行端口名的数组。 |
| Open() | 打开一个新的串行端口连接。 |
| Read(Byte[], Int32, Int32) | 从 SerialPort 输入缓冲区读取一些字节并将那些字节写入字节数组中指定的偏移量处。 |
| Read(Char[], Int32, Int32) | 从 SerialPort 输入缓冲区中读取一些字符,然后将这些字符写入字符数组中指定的偏移量处。 |
| ReadByte() | 从 SerialPort 输入缓冲区中同步读取一个字节。 |
| ReadChar() | 从 SerialPort 输入缓冲区中同步读取一个字符。 |
| ReadExisting() | 在编码的基础上,读取 SerialPort 对象的流和输入缓冲区中所有立即可用的字节。 |
| ReadLine() | 一直读取到输入缓冲区中的 NewLine 值。 |
| ReadTo(String) | 一直读取到输入缓冲区中的指定 value 的字符串。 |
| Write(Byte[], Int32, Int32) | 使用缓冲区中的数据将指定数量的字节写入串行端口。 |
| Write(Char[], Int32, Int32) | 使用缓冲区中的数据将指定数量的字符写入串行端口。 |
| Write(String) | 将指定的字符串写入串行端口。 |
| WriteLine(String) | 将指定的字符串和 NewLine 值写入输出缓冲区。 |
Nuget 安装System.IO.Ports

串口写
private void btnWrite_Click(object sender, EventArgs e){SerialPort serialPort = new SerialPort();serialPort.PortName = "COM1";//串口名称serialPort.BaudRate = 9600; //获取或设置波特率serialPort.Parity = Parity.Even;//获取或设置校验位serialPort.DataBits = 8;//获取或设置数据位默认值8serialPort.StopBits = StopBits.One;// 停止位serialPort.Open();serialPort.Write("A");serialPort.Close();}
串口读
SerialPort serialPort = new SerialPort();private void btnRead_Click(object sender, EventArgs e){byte[] a = System.Text.Encoding.ASCII.GetBytes(" ");serialPort.PortName = "COM1";//串口名称serialPort.BaudRate = 9600; //获取或设置波特率serialPort.Parity = Parity.None;//获取或设置校验位serialPort.DataBits = 8;//获取或设置数据位默认值8serialPort.StopBits = StopBits.One;// 停止位serialPort.DataReceived += SerialPort_DataReceived;serialPort.Open();}private void SerialPort_DataReceived(object sender, SerialDataReceivedEventArgs e){byte[] b = new byte[8];int A = serialPort.Read(b, 0, 8);this.Invoke(() =>{string s = ByteToHex(b);txtValue.Text += s+System.Environment.NewLine;});}public string ByteToHex(byte[] Bytes){string str = string.Empty;foreach (byte Byte in Bytes){str += String.Format("{0:X2}", Byte) + " ";}return str.Trim();}

一个完整例子

using System.IO.Ports;namespace SCOM{public partial class FrmMain : Form{SerialPort serialPort;public FrmMain(){InitializeComponent();Init();}private void LoadPorts(){cboPort.Items.Clear();string[] port = System.IO.Ports.SerialPort.GetPortNames();foreach (var item in port){cboPort.Items.Add(item);}cboPort.SelectedIndex = 0;}private void Init(){LoadPorts();object[] baudRate = { 4800, 9600, 19200, 38400, 57600, 115200, 230400 };cboBaudRate.Items.AddRange(baudRate);cboBaudRate.SelectedIndex = 1;cboDataBits.Items.Add(7);cboDataBits.Items.Add(8);cboDataBits.SelectedIndex = 1;cboStopBits.Items.Add("One");cboStopBits.Items.Add("OnePointFive");cboStopBits.Items.Add("Two");cboStopBits.SelectedIndex = 0;//ParitycboParity.Items.Add("None");cboParity.Items.Add("Even");cboParity.Items.Add("Mark");cboParity.Items.Add("Odd");cboParity.Items.Add("Space");cboParity.SelectedIndex = 0;cboHandshaking.Items.Add("None");cboHandshaking.Items.Add("XOnXOff");cboHandshaking.Items.Add("RequestToSend");cboHandshaking.Items.Add("RequestToSendXOnXOff");cboHandshaking.SelectedIndex = 0;btnClosePort.Enabled = false;}private void btnRefresh_Click(object sender, EventArgs e){LoadPorts();}private void btnOpenPort_Click(object sender, EventArgs e){if (serialPort == null){serialPort = new SerialPort();}serialPort.PortName = cboPort.Text;//串口名称serialPort.BaudRate = int.Parse(cboBaudRate.Text); //获取或设置波特率serialPort.Parity = (Parity)Enum.Parse(typeof(Parity), cboParity.Text);//获取或设置校验位serialPort.DataBits = int.Parse(cboDataBits.Text);//获取或设置数据位默认值8serialPort.StopBits = (StopBits)Enum.Parse(typeof(StopBits), cboStopBits.Text);// 停止位serialPort.Handshake = (Handshake)Enum.Parse(typeof(Handshake), cboHandshaking.Text);// 握手协议serialPort.DataReceived += SerialPort_DataReceived;serialPort.Open();stsMain_lblStatus.Text = "端口已打开";btnOpenPort.Enabled = false;btnClosePort.Enabled = true;}private void SerialPort_DataReceived(object sender, SerialDataReceivedEventArgs e){this.Invoke(new Action(() =>{byte[] b = new byte[8];int A = serialPort.Read(b, 0, 8);string s = "";if (rdoHex.Checked){s = ByteToHex(b);}else{s = System.Text.Encoding.Default.GetString(b);}txtReceive.AppendText(System.Environment.NewLine+ s);}));}private void btnClosePort_Click(object sender, EventArgs e){if (serialPort != null && serialPort.IsOpen){serialPort.DataReceived -= SerialPort_DataReceived;serialPort.Close();stsMain_lblStatus.Text = "端口已关闭";btnOpenPort.Enabled = true;btnClosePort.Enabled = false;}}private void btnSend_Click(object sender, EventArgs e){if (serialPort == null || !serialPort.IsOpen){return;}serialPort.Write(txtSend.Text);}private string ByteToHex(byte[] Bytes){string str = string.Empty;foreach (byte Byte in Bytes){str += String.Format("{0:X2}", Byte) + " ";}return str.Trim();}}}