Chinaunix首页 | 论坛 | 博客
  • 博客访问: 7933551
  • 博文数量: 124
  • 博客积分: 2880
  • 博客等级: 少校
  • 技术积分: 873
  • 用 户 组: 普通用户
  • 注册时间: 2009-09-16 17:08
文章分类

全部博文(124)

文章存档

2011年(28)

2010年(60)

2009年(36)

我的朋友

分类: C/C++

2009-09-18 14:47:29

 

13.1  串 口 控 制

串行口是计算机的标准接口,现在的PC机(个人电脑)一般至少有两个串行口COM1和COM2。串行口应用广泛,在数据通信、计算机网络以及分布式工业控制系统中,经常采用串行通信来交换数据和信息。本节通过几个实例,介绍串口应用的技术和方法。

实例418 通过串口发送数据

实例说明

文本框:  
图13.1  通过串口传递数据
现在大多数硬件设备均采用串口技术与计算机相连,因此串口的应用程序开发越来越普遍。例如,在计算机没有安装网卡的情况下,将本机上的一些信息数据传输到另一台计算机上,那么利用串口通信就可以实现。运行本程序,在“发送数据”文本框中输入要传送的数据,单击【发送】按钮,将传送的数据发送到所选择的端口号中;单击【接收】按钮,传递的数据被接收到“接收数据”文本框中。如图13.1所示。

技术要点

在.NET Framework 2.0中提供了SerialPort类,该类主要实现串口数据通信等。下面主要介绍该类的主要属性(表13.1)和方法(表13.2)。

表13.1                                                     SerialPort类的常用属性

名  称

说  明

BaseStream

获取 SerialPort 对象的基础 Stream 对象

BaudRate

获取或设置串行波特率

BreakState

获取或设置中断信号状态

BytesToRead

获取接收缓冲区中数据的字节数

BytesToWrite

获取发送缓冲区中数据的字节数

CDHolding

获取端口的载波检测行的状态

CtsHolding

获取“可以发送”行的状态

DataBits

获取或设置每个字节的标准数据位长度

DiscardNull

获取或设置一个值,该值指示 Null 字节在端口和接收缓冲区之间传输时是否被忽略

DsrHolding

获取数据设置就绪 (DSR) 信号的状态

DtrEnable

获取或设置一个值,该值在串行通信过程中启用数据终端就绪 (DTR) 信号

Encoding

获取或设置传输前后文本转换的字节编码

Handshake

获取或设置串行端口数据传输的握手协议

IsOpen

获取一个值,该值指示 SerialPort 对象的打开或关闭状态

NewLine

获取或设置用于解释 ReadLine( )和WriteLine( )方法调用结束的值

Parity

获取或设置奇偶校验检查协议

续表

名  称

说  明

ParityReplace

获取或设置一个字节,该字节在发生奇偶校验错误时替换数据流中的无效字节

PortName

获取或设置通信端口,包括但不限于所有可用的 COM 端口

ReadBufferSize

获取或设置 SerialPort 输入缓冲区的大小

ReadTimeout

获取或设置读取操作未完成时发生超时之前的毫秒数

ReceivedBytesThreshold

获取或设置 DataReceived 事件发生前内部输入缓冲区中的字节数

RtsEnable

获取或设置一个值,该值指示在串行通信中是否启用请求发送 (RTS) 信号

StopBits

获取或设置每个字节的标准停止位数

WriteBufferSize

获取或设置串行端口输出缓冲区的大小

WriteTimeout

获取或设置写入操作未完成时发生超时之前的毫秒数

表13.2                                                    SerialPort类的常用方法

方 法 名 称

说  明

Close

关闭端口连接,将 IsOpen 属性设置为False,并释放内部 Stream 对象

Open

打开一个新的串行端口连接

Read

从 SerialPort 输入缓冲区中读取

ReadByte

从 SerialPort 输入缓冲区中同步读取一个字节

ReadChar

从 SerialPort 输入缓冲区中同步读取一个字符

ReadLine

一直读取到输入缓冲区中的 NewLine 值

ReadTo

一直读取到输入缓冲区中指定 value 的字符串

Write

已重载。将数据写入串行端口输出缓冲区

WriteLine

将指定的字符串和 NewLine 值写入输出缓冲区

 注意:用跳线使串口的第2、3针连接,可以在本地计算机上实现串口通信,所以,通过串口的第2、3针的连接可以对程序进行检测。串口截面图如图13.2所示。

图13.2  串口截面图

实现过程

(1)新建一个项目,命名为Ex13_01,默认窗体为Form1。

(2)在Form1窗体中,主要添加两个Button控件,分别用于执行发送数据和接受数据,添加两个TextBox控件,用于输入发送数据和显示接收数据。

(3)主要程序代码。

        private void button1_Click(object sender, EventArgs e)

        {

            serialPort1.PortName = "COM1";

            serialPort1.BaudRate = 9600;

            serialPort1.Open();

            byte[] data = Encoding.Unicode.GetBytes(textBox1.Text);

            string str = Convert.ToBase64String(data);

            serialPort1.WriteLine(str);

            MessageBox.Show("数据发送成功!","系统提示");

        }

        private void button2_Click(object sender, EventArgs e)

        {

            byte[] data = Convert.FromBase64String(serialPort1.ReadLine());

            textBox2.Text = Encoding.Unicode.GetString(data);

            serialPort1.Close();

            MessageBox.Show("数据接收成功!","系统提示");

        }

举一反三

根据本实例,读者可以实现以下功能。

*  远程监控对方计算机屏幕。

*  下位机控制程序。

实例419 通过串口关闭对方计算机

实例说明

文本框:  
图13.3  控制对方计算机关闭
在网络应用程序中,主要通过网卡实现数据的传输,因此可以利用套接字技术实现远程关闭计算机。如果计算机中没有安装网卡,该如何实现远程关闭计算机呢?本例实现了利用串口关闭对方计算机,程序运行结果如图13.3所示。

技术要点

本实例使用SerialPort类的属性和方法,请参见实例“通过串口发送数据”。下面主要介绍SerialPort类的DataReceived 事件,DataReceived 事件为本实例的主要使用技术。DataReceived事件表示将处理 SerialPort 对象的数据接收事件的方法。串行接收事件可以由 SerialData 枚举中的任何项引起,是否引发此事件由操作系统决定,所以不一定会报告所有奇偶校验错误。

 注意:本实例从开发到测试,都是由本地计算机完成的,用户只需要使用跳线将串口的第2、3针连接,可以在本地计算机上实现串口通信。跳线连接请参见图13.2。

实现过程

(1)新建一个项目,命名为Ex13_02,默认窗体为Form1。

(2)在Form1窗体中,主要添加两个Button控件,分别用于打开通信串口和关闭对方计算机。

(3)主要程序代码。

        private void button1_Click(object sender, EventArgs e)

        {

            //打开串口

            serialPort1.PortName = "COM1";

            serialPort1.Open();

            button1.Enabled = false;

            button2.Enabled = true;

        }   //数据接收事件,等待接收关机命令

        private void serialPort1_DataReceived(object sender, SerialDataReceivedEventArgs e)

        {

            byte[] data = Convert.FromBase64String(serialPort1.ReadLine());

            string str = Encoding.Unicode.GetString(data);

            serialPort1.Close();

            if (str == "关机")

            {

                Process p = new Process();

                p.StartInfo.FileName = "cmd.exe";

                p.StartInfo.UseShellExecute = false;

                p.StartInfo.RedirectStandardInput = true;

                p.StartInfo.RedirectStandardOutput = true;

                p.StartInfo.RedirectStandardError = true;

                p.StartInfo.CreateNoWindow = true;

                p.Start();

                p.StandardInput.WriteLine("shutdown /s");

                p.StandardInput.WriteLine("exit");

            }

        }   //发送关机命令

        private void button2_Click(object sender, EventArgs e)

        {

            if (button2.Text == "关闭计算机")

            {

                //发送关机命令数据

                byte[] data = Encoding.Unicode.GetBytes("关机");

                string str = Convert.ToBase64String(data);

                serialPort1.WriteLine(str);

                button2.Text = "取消关机";

            }

            else

            {

                button2.Text = "关闭计算机";

                button1.Enabled = true;

                button2.Enabled = false;

                //取消关机

                Process p = new Process();

                p.StartInfo.FileName = "cmd.exe";

                p.StartInfo.UseShellExecute = false;

                p.StartInfo.RedirectStandardInput = true;

                p.StartInfo.RedirectStandardOutput = true;

                p.StartInfo.RedirectStandardError = true;

                p.StartInfo.CreateNoWindow = true;

                p.Start();

                p.StandardInput.WriteLine("shutdown /a");

                p.StandardInput.WriteLine("exit");

            }

        }

举一反三

根据本实例,读者可以实现以下功能。

*  远程控制对方计算机操作。

*  定时控制对方计算机关闭。

 
 
 
 

上次的C#的串口编程没有写这个,这次补充上去,就比较完整了。开始自己写写也不太会用事件来读取串口传来的信息:就想着用另外的线程来读取,用事件轻松挺多了。直接点的代码

serialPort1.DataReceived += new System.IO.Ports.SerialDataReceivedEventHandler(serialPort1_DataReceived);
//对你的serialPort1 注册一个事件委托

public void serialPort1_DataReceived(object sender, System.IO.Ports.SerialDataReceivedEventArgs e)
{

this.textBox2.Invoke(new MethodInvoker(delegate(){
     textBox2.AppendText(serialPort1.ReadExisting());//这里用多行文本进行显示
     textBox2.ScrollToCaret();
                        }));
}

居然忘记了,不同于ui线程的委托,把Invoke加上去了,不然又出错了。

阅读(15947) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~