C#串口编程.doc
C#串口编程.txt两个人吵架,先说对不起的人,并不是认输了,并不是原谅了。他只是比对方更珍惜这份感情。 本文由陶一铭贡献 doc文档可能在WAP端浏览体验不佳。建议您优先选择TXT,或下载源文件到本机查看。 C#中串口通信编程 收藏 本文将介绍如何在.NET 平台下使用 C#创建串口通信程序, .NET 2.0 提供了串口通信的功能, 其命名 空间是 System.IO.Ports.这个新的框架不但可以访问计算机上的串口,还可以和串口设备进 行通信. 我们将使用标准的 RS 232 C 在 PC 间通信.它工作在全双工模式下,而且我们不打算使用 任何的握手 或流控制器,而是使用无 modem 连接. 命名空间 System.IO.Ports 命名空间中最重用的是 SerialPort 类. 创建 SerialPort 对象 通过创建 SerialPort 对象,我们可以在程序中控制串口通信的全过程. 我们将要用到的 SerialPort 类的方法: ReadLine():从输入缓冲区读一新行的值,如果没有,会返回 NULL WriteLine(string):写入输出缓冲 Open():打开一个新的串口连接 Close():关闭 Code: /create a Serial Port object SerialPort sp = new SerialPort (); 默认情况下,DataBits 值是 8,StopBits 是 1,通信端口是 COM1.这些都可以在下面的属 性中重新设置 : BaudRate:串口的波特率 StopBits:每个字节的停止位数量 ReadTimeout:当读操作没有完成时的停止时间.单位,毫秒 还有不少其它公共属性,自己查阅 MSDN. 串口的硬件知识 在数据传输的时候, 每个字节的数据通过单个的电缆线传输. 包包括开始位, 数据, 结束为. 一旦 开始位传出,后面就会传数据,可能是 5,6,7 或 8 位,就看你的设定了.发送和接收必须 设定同样 的波特率和数据位数. 无猫模式 没有 Modem 模式的电缆只是简单地交叉传送和接收线.同样 DTR & DSR, 和 RTS & CTS 也需要交叉. RS232 针图 这里,我们三条线.互连 2 和 3(一段的 2pin 连接 3pin) ,连接两端的 5pin. 示例程序 主程序 如果想使用默认属性,按"Save Status"按钮,如果想改变属性按"Property" .它会弹出下 图: 设定好之后,可以通信了. 主窗口的代码 Code: #region Using directives using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Windows.Forms; using System.IO.Ports; #endregion namespace Serialexpample partial class Form1 : Form /create instance of property page /property page is used to set values for stop bits and /baud rate PropertyPage pp = new PropertyPage(); /create an Serial Port object SerialPort sp = new SerialPort(); public Form1() InitializeComponent(); private void propertyButton_Click(object sender, EventArgs e) /show property dialog pp.ShowDialog(); propertyButton.Hide(); private void sendButton_Click(object sender, EventArgs e) try /write line to serial port sp.WriteLine(textBox.Text); /clear the text box textBox.Text = "" catch (System.Exception ex) baudRatelLabel.Text = ex.Message; private void ReadButton_Click(object sender, EventArgs e) try /clear the text box textBox.Text = "" /read serial port and displayed the data in text box textBox.Text = sp.ReadLine(); catch(System.Exception ex) baudRatelLabel.Text = ex.Message; private void Form1_Load(object sender, EventArgs e) private void Form1_FormClosing(object sender, FormClosingEventArgs e) MessageBox.Show("Do u want to Close the App"); sp.Close(); private void startCommButton_Click(object sender, EventArgs e) startCommButton.Hide(); sendButton.Show(); readButton.Show(); textBox.Show(); /when we want to save the status(value) private void saveStatusButton_Click_1(object sender, EventArgs e) /display values /if no property is set the default values if (pp.bRate = "" && pp.sBits = "") dataBitLabel.Text = "BaudRate = " + sp.BaudRate.ToString(); readTimeOutLabel.Text = "StopBits = " + sp.StopBits.ToString(); else dataBitLabel.Text = "BaudRate = " + pp.bRate; readTimeOutLabel.Text = "StopBits = " + pp.sBits; parityLabel.Text = "DataBits = " + sp.DataBits.ToString(); stopBitLabel.Text = "Parity = " + sp.Parity.ToString(); readTimeOutLabel.Text = "ReadTimeout = " + sp.ReadTimeout.ToString(); if (propertyButton.Visible = true) propertyButton.Hide(); saveStatusButton.Hide(); startCommButton.Show(); try /open serial port sp.Open(); /set read time out to 500 ms sp.ReadTimeout = 500; catch (System.Exception ex) baudRatelLabel.Text = ex.Message; 属性设置对话框代码: Code: #region Using directives using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Text; using System.Windows.Forms; #endregion namespace Serialexpample partial class PropertyPage : Form /variables for storing values of baud rate and stop bits private string baudR="" private string stopB="" /property for setting and getting baud rate and stop bits public string bRate get return baudR; set baudR = value; public string sBits get return stopB; set stopB = value; public PropertyPage() InitializeComponent(); private void cancelButton_Click(object sender, EventArgs e) this.bRate = "" this.sBits = "" /close form this.Close(); private void okButton_Click_1(object sender, EventArgs e) /here we set the value for stop bits and baud rate. this.bRate = BaudRateComboBox.Text; this.sBits = stopBitComboBox.Text; / this.Close(); 一.概述 在 Visual Studio 6.0 中编写串口通讯程序,一般都使用 Microsoft Communication Control(简 称 MSComm)的通讯控件,只要通 过对此控件的属性和事件进行相应编程操作,就可以轻 松地实现串口通讯.但在 Microsoft.Net 技术广泛应用的今天,Visual Studio.Net 没有将此控 件加入控件库,所以人们采用了许多方法在 Visual Studio.Net 来编写串口通讯程序:第一种 方法是通过采用 Visual Studio 6.0 中原来的 MSComm 控件这是最简单的,最方便的方法, 但需要注册;第二种方法是采用微软在.NET 推出了一个串口控件,基于.NET 的 P/Invoke 调用方法实现;第三种方法是自己用 API 写串口通信,虽然难度高,但可以方便实现自己 想要的各种功能. 现在微软推出了最新版本的 Visual Studio 2005 开发工具,可以不再采用第三方控件的方法 来设计串口通讯程序. NET Framework 2.0 类库包含了 SerialPort 类,方便地实现了所需要串 口通讯的多种功能,为了使 MSComm 编程方法快速转换到以 SerialPort 类为核心的串口通 讯的设计方法, 本文着重讨论了 Visual Studio 6.0 的 MSComm 控件和 SerialPort 类设计方法 的异同点. 二.SerialPort 常用属性,方法和事件 1.命名空间 System.IO.Ports 命名空间包含了控制串口重要的 SerialPort 类,该类提供了同步 I/O 和事件 驱动的 I/O,对管脚和中断状态的访问以及对串行驱动程序属性的访问,所以在程序代码起 始位置需加入 Using System.IO.Ports. 2.串口的通讯参数 串口通讯最常用的参数就是通讯端口号及通讯格式(波特率,数据位,停止位和校验位),在 MSComm 中相关的属性是 CommPort 和 Settings.SerialPort 类与 MSComm 有一些区别: a.通讯端口号 PortName属性获取或设置通信端口, 包括但不限于所有可用的 COM 端口, 请注意该属性 返回类型为 String,不是 Mscomm.CommPort 的 short 类型.通常情况下,PortName 正常返 回的值为 COM1,COM2,SerialPort 类最大支持的端口数突破了 CommPort 控件中 CommPort 属性不能超过 16 的限止,大大方便了用户串口设备的配置. b. 通讯格式 SerialPort 类对分别用BaudRate,Parity,DataBits,StopBits属性设置通讯格式中的波 特率,数据位,停止位和校验位,其中Parity和StopBits分别是枚举类型 Parity,StopBits, Parity 类型中枚举了 Odd(奇),Even(偶),Mark,None,Space,Parity 枚举了 None,One, OnePointFive,Two. SerialPort 类提供了七个重载的构造函数,既可以对已经实例化的 SerialPort 对象设置上述相 关属性的值, 也可以使用指定的端口名称, 波特率和奇偶校验位数据位和停止位直接初始化 SerialPort 类的新实例. 3.串口的打开和关闭 SerialPort 类没有采用 MSComm.PortOpen=True/False 设置属性值打开关闭串口, 相应的是调 用类的 Open()和 Close()方法. 4. 数据的发送和读取 Serial 类调用重载的 Write 和 WriteLine 方法发送数据,其中 WriteLine 可发送字符串并在字 符串末尾加入换行符,读取串口缓冲区的方法有许多,其中除了 ReadExisting 和 ReadTo,其 余的方法都是同步调用,线程被阻塞直到缓冲区有相应的数据或大于 ReadTimeOut 属性设 定的时间值后,引发 ReadExisting 异常. 5.DataReceived 事件 该 事 件 类 似 于 MSComm 控 件 中 的 OnComm 事 件 , DataReceived 事 件 在 接 收 到 了 ReceivedBytesThreshold设置的字符个数或接收到了文件结束字符并将其放入了输入缓冲 区时被触发.其中ReceivedBytesThreshold相当于 MSComm 控件的Rthreshold属性,该事 件的用法与 MsComm 控件的 OnComm 事件在 CommEvent 为 comEvSend 和 comEvEof 时是 一致的. 三.SerialPort 的使用 对于熟悉 MSComm 控件的程序设计者, SerialPort 类是相当容易上手的. 在进行串口通讯时, 一般的流程是设置通讯端口号及波特率,数据位,停止位和校验位,再打开端口连接,发送 数据,接收数据,最后关闭端口连接这样几个步骤. 数据接收的设计方法在这里比较重要,采用轮询的方法比较浪费时间,在 Visual Basic 中的 延时方法中一般会调用 API 并用 DOEvents 方法来处理,但程序不易控制,建议采用 DataReceived 事件触发的方法,合理的设置 ReceivedBytesThreshold 的值,若接收的是定长 的数据,则将 ReceivedBytesThreshold 设为接收数据的长度,若接收数据的结尾是固定的字 符或字符串则可采用 ReadTo 的方法或在 DataReceived 事件中判断接收的字符是否满足条 件. SerialPort 类读取数据的许多方法是同步阻塞调用,尽量避免在主线程中调用,可以使用异 步处理或线程间处理调用这些读取数据的方法. 由于 DataReceived 事件在辅线程被引发,当收到完整的一条数据,返回主线程处理或在窗 体上显示时,请注意跨线程的处理,C#可采用控件异步委托的方法 Control.BeginInvoke 及 同步委托的方法 Invoke. 四.结束语 在.NET 平台下熟练使用 SerialPort 类,可以很好地开发出串口通讯类程序,对于过去使用 MSComm 控件设计了一些通讯程序,也可以将 MSComm 控件替换为 SerialPort 类,当然为 了避免对以前的项目做大的改动,可以使用 SerialPort 类设计一些与 MSComm 控件具有相 同接口的类,在今后工业控制中,SerialPort 类将广泛地应用于串口通讯程序的设计中,发 挥着与 MSComm 控件一样的作用. 2.以类的方式 VB: 1) 定义 SerialPort 类实例 Dim SpCom As New System.IO.Ports.SerialPort() 2) 设置通讯端口号及波特率,数据位,停止位和校验位. SpCom.PortName = "COM1" SpCom.BaudRate = 9600 SpCom.Parity = IO.Ports.Parity.None SpCom.DataBits = 8 SpCom.StopBits = IO.Ports.StopBits.One 或是定义时直接初始化 Dim SpCom As New System.IO.Ports.SerialPort("COM1", 9600, IO.Ports.Parity.Even, 8, IO.Ports.StopBits.None) 3) 发送数据 SpCom.Write(TextSendData.Text) 4) a) 添加接受事件 在运行时将事件与事件处理程序相关联 AddHandler SpCom.DataReceived, AddressOf EventReceiveData 说明: AddressOf 创建引用特定过程的过程委托实例 AddressOf 运算符可以用作委托构造函数的操作数,或可以用在编译器能够确定委 类型的上下文中. b) 添加事件处理程序(签名一定要一致) Sub EventReceiveData(ByVal sender As Object, ByVal e As System.IO.Ports.SerialDataReceivedEventArgs) 5) 读取数据 Dim strT As String strT = SpCom.ReadExisting() C#: 1) 添加引用 using System.IO.Ports; 2) 定义 SerialPort 类实例 private SerialPort SpCom2 = new SpCom ("COM2", 9600,Parity.None, 8, StopBits.One); 3) 设置通讯端口号及波特率,数据位,停止位和校验位. SpCom.PortName = "COM1" SpCom.BaudRate = 9600; SpCom.Parity = IO.Ports.Parity.None; 托 SpCom.DataBits = 8; SpCom.StopBits = IO.Ports.StopBits.One; 或是定义时直接初始化 private SerialPort SpCom2 = new SpCom ("COM2", 9600,Parity.None, 8, StopBits.One); 4) 发送数据 SpCom.Write(TextSendData.Text); 5) a) 添加接受事件 在运行时将事件与事件处理程序相关联(通过委托实现) SpCom.DataReceived += new SerialDataReceivedEventHandler(SpCom2_DataReceived); 说明: SerialDataReceivedEventHandler 委托 表示将处理 SerialPort 对象的 DataReceived 事件的 方法 b) 添加事件处理程序(签名一定要一致) private void SpCom_DataReceived(object sender, SerialDataReceivedEventArgs e) 6) 读取数据 string data = SpCom .ReadExisting(); 本 文 来 自 CSDN 博 客 , 转 载 请 标 明 出 处 : using System; using System.IO.Ports; using System.Threading; public class PortChat static bool _continue; static SerialPort _serialPort; public static void Main() string name; string message; StringComparer stringComparer = StringComparer.OrdinalIgnoreCase; Thread readThread = new Thread(Read); / Create a new SerialPort object with default settings. _serialPort = new SerialPort(); / Allow the user to set the appropriate properties. _serialPort.PortName = SetPortName(_serialPort.PortName); _serialPort.BaudRate = SetPortBaudRate(_serialPort.BaudRate); _serialPort.Parity = SetPortParity(_serialPort.Parity); _serialPort.DataBits = SetPortDataBits(_serialPort.DataBits); _serialPort.StopBits = SetPortStopBits(_serialPort.StopBits); _serialPort.Handshake = SetPortHandshake(_serialPort.Handshake); / Set the read/write timeouts _serialPort.ReadTimeout = 500; _serialPort.WriteTimeout = 500; _serialPort.Open(); _continue = true; readThread.Start(); Console.Write("Name: "); name = Console.ReadLine(); Console.WriteLine("Type QUIT to exit"); while (_continue) message = Console.ReadLine(); if (stringComparer.Equals("quit", message) _continue = false; else _serialPort.WriteLine( String.Format("<0>: 1", name, message) ); readThread.Join(); _serialPort.Close(); public static void Read() while (_continue) try string message = _serialPort.ReadLine(); Console.WriteLine(message); catch (TimeoutException) public static string SetPortName(string defaultPortName) string portName; Console.WriteLine("Available Ports:"); foreach (string s in SerialPort.GetPortNames() Console.WriteLine(" 0", s); Console.Write("COM port(0): ", defaultPortName); portName = Console.ReadLine(); if (portName = "") portName = defaultPortName; return portName; public static int SetPortBaudRate(int defaultPortBaudRate) string baudRate; Console.Write("Baud Rate(0): ", defaultPortBaudRate); baudRate = Console.ReadLine(); if (baudRate = "") baudRate = defaultPortBaudRate.ToString(); return int.Parse(baudRate); public static Parity SetPortParity(Parity defaultPortParity) string parity; Console.WriteLine("Available Parity options:"); foreach (string s in Enum.GetNames(typeof(Parity) Console.WriteLine(" 0", s); Console.Write("Parity(0):", defaultPortParity.ToString(); parity = Console.ReadLine(); if (parity = "") parity = defaultPortParity.ToString(); return (Parity)Enum.Parse(typeof(Parity), parity); public static int SetPortDataBits(int defaultPortDataBits) string dataBits; Console.Write("Data Bits(0): ", defaultPortDataBits); dataBits = Console.ReadLine(); if (dataBits = "") dataBits = defaultPortDataBits.ToString(); return int.Parse(dataBits); public static StopBits SetPortStopBits(StopBits defaultPortStopBits) string stopBits; Console.WriteLine("Available Stop Bits options:"); foreach (string s in Enum.GetNames(typeof(StopBits) Console.WriteLine(" 0", s); Console.Write("Stop Bits(0):", defaultPortStopBits.ToString(); stopBits = Console.ReadLine(); if (stopBits = "") stopBits = defaultPortStopBits.ToString(); return (StopBits)Enum.Parse(typeof(StopBits), stopBits); public static Handshake SetPortHandshake(Handshake defaultPortHandshake) string handshake; Console.WriteLine("Available Handshake options:"); foreach (string s in Enum.GetNames(typeof(Handshake) Console.WriteLine(" 0", s); Console.Write("Stop Bits(0):", defaultPortHandshake.ToString(); handshake = Console.ReadLine(); if (handshake = "") handshake = defaultPortHandshake.ToString(); return (Handshake)Enum.Parse(typeof(Handshake), handshake);