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 值是8StopBits 1,通信端口是COM1。这些都可以在下面的属性中重新设置



BaudRate
:串口的波特率
StopBits
:每个字节的停止位数量
ReadTimeout
:当读操作没有完成时的停止时间。单位,毫秒

还有不少其它公共属性,自己查阅MSDN

串口的硬件知识

在数据传输的时候,每个字节的数据通过单个的电缆线传输。包包括开始位,数据,结束为。一旦

开始位传出,后面就会传数据,可能是5678位,就看你的设定了。发送和接收必须设定同样

的波特率和数据位数。

无猫模式

没有Modem模式的电缆只是简单地交叉传送和接收线。同样DTR & DSR, RTS & CTS也需要交叉。

RS232
针图




这里,我们三条线。互连23(一段的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();

  • 1
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值