C#中使用SerialPort类实现简单串口编程
.NET提供了SerialPort类进行串口通信,使用很简单,连我这个.NET新手也能很快上手.以下是从网上找到并自己修改后的参考代码:
1
using
System;
2 using System.Collections.Generic;
3 using System.Linq;
4 using System.Text;
5 using System.Windows;
6 using System.Windows.Controls;
7 using System.Windows.Data;
8 using System.Windows.Documents;
9 using System.Windows.Input;
10 using System.Windows.Media;
11 using System.Windows.Media.Imaging;
12 using System.Windows.Navigation;
13 using System.Windows.Shapes;
14 using System.IO.Ports;
15
16 namespace CsharpComm
17 {
18 /// <summary>
19 /// Window1.xaml 的交互逻辑
20 /// </summary>
21 public partial class Window1 : Window
22 {
23 public Window1()
24 {
25 InitializeComponent();
26 }
27
28 // 定义 SerialPort对象
29 SerialPort port1;
30
31 // 初始化SerialPort对象方法.PortName为COM口名称,例如"COM1","COM2"等,注意是string类型
32 public void InitCOM( string PortName)
33 {
34 port1 = new SerialPort(PortName);
35 port1.BaudRate = 9600 ; // 波特率
36 port1.Parity = Parity.None; // 无奇偶校验位
37 port1.StopBits = StopBits.Two; // 两个停止位
38 port1.Handshake = Handshake.RequestToSend; // 控制协议
39 port1.ReceivedBytesThreshold = 4 ; // 设置 DataReceived 事件发生前内部输入缓冲区中的字节数
40 port1.DataReceived += new SerialDataReceivedEventHandler(port1_DataReceived); // DataReceived事件委托
41 }
42
43 // DataReceived事件委托方法
44 private void port1_DataReceived( object sender, SerialDataReceivedEventArgs e)
45 {
46 try
47 {
48 StringBuilder currentline = new StringBuilder();
49 // 循环接收数据
50 while (port1.BytesToRead > 0 )
51 {
52 char ch = ( char )port1.ReadByte();
53 currentline.Append(ch);
54 }
55 // 在这里对接收到的数据进行处理
56 //
57 currentline = new StringBuilder();
58 }
59 catch (Exception ex)
60 {
61 Console.WriteLine(ex.Message.ToString());
62 }
63
64 }
65
66 // 打开串口的方法
67 public void OpenPort()
68 {
69 try
70 {
71 port1.Open();
72 }
73 catch { }
74 if (port1.IsOpen)
75 {
76 Console.WriteLine( " the port is opened! " );
77 }
78 else
79 {
80 Console.WriteLine( " failure to open the port! " );
81 }
82 }
83
84 // 关闭串口的方法
85 public void ClosePort()
86 {
87 port1.Close();
88 if ( ! port1.IsOpen)
89 {
90 Console.WriteLine( " the port is already closed! " );
91 }
92 }
93
94 // 向串口发送数据
95 public void SendCommand( string CommandString)
96 {
97 byte [] WriteBuffer = Encoding.ASCII.GetBytes(CommandString);
98 port1.Write(WriteBuffer, 0 , WriteBuffer.Length);
99 }
100
101 // 调用实例
102 private void btnOpen_Click( object sender, RoutedEventArgs e)
103 {
104 // 我现在用的COM1端口,按需要可改成COM2,COM3
105 InitCOM( " COM1 " );
106 OpenPort();
107 }
108 }
109 }
2 using System.Collections.Generic;
3 using System.Linq;
4 using System.Text;
5 using System.Windows;
6 using System.Windows.Controls;
7 using System.Windows.Data;
8 using System.Windows.Documents;
9 using System.Windows.Input;
10 using System.Windows.Media;
11 using System.Windows.Media.Imaging;
12 using System.Windows.Navigation;
13 using System.Windows.Shapes;
14 using System.IO.Ports;
15
16 namespace CsharpComm
17 {
18 /// <summary>
19 /// Window1.xaml 的交互逻辑
20 /// </summary>
21 public partial class Window1 : Window
22 {
23 public Window1()
24 {
25 InitializeComponent();
26 }
27
28 // 定义 SerialPort对象
29 SerialPort port1;
30
31 // 初始化SerialPort对象方法.PortName为COM口名称,例如"COM1","COM2"等,注意是string类型
32 public void InitCOM( string PortName)
33 {
34 port1 = new SerialPort(PortName);
35 port1.BaudRate = 9600 ; // 波特率
36 port1.Parity = Parity.None; // 无奇偶校验位
37 port1.StopBits = StopBits.Two; // 两个停止位
38 port1.Handshake = Handshake.RequestToSend; // 控制协议
39 port1.ReceivedBytesThreshold = 4 ; // 设置 DataReceived 事件发生前内部输入缓冲区中的字节数
40 port1.DataReceived += new SerialDataReceivedEventHandler(port1_DataReceived); // DataReceived事件委托
41 }
42
43 // DataReceived事件委托方法
44 private void port1_DataReceived( object sender, SerialDataReceivedEventArgs e)
45 {
46 try
47 {
48 StringBuilder currentline = new StringBuilder();
49 // 循环接收数据
50 while (port1.BytesToRead > 0 )
51 {
52 char ch = ( char )port1.ReadByte();
53 currentline.Append(ch);
54 }
55 // 在这里对接收到的数据进行处理
56 //
57 currentline = new StringBuilder();
58 }
59 catch (Exception ex)
60 {
61 Console.WriteLine(ex.Message.ToString());
62 }
63
64 }
65
66 // 打开串口的方法
67 public void OpenPort()
68 {
69 try
70 {
71 port1.Open();
72 }
73 catch { }
74 if (port1.IsOpen)
75 {
76 Console.WriteLine( " the port is opened! " );
77 }
78 else
79 {
80 Console.WriteLine( " failure to open the port! " );
81 }
82 }
83
84 // 关闭串口的方法
85 public void ClosePort()
86 {
87 port1.Close();
88 if ( ! port1.IsOpen)
89 {
90 Console.WriteLine( " the port is already closed! " );
91 }
92 }
93
94 // 向串口发送数据
95 public void SendCommand( string CommandString)
96 {
97 byte [] WriteBuffer = Encoding.ASCII.GetBytes(CommandString);
98 port1.Write(WriteBuffer, 0 , WriteBuffer.Length);
99 }
100
101 // 调用实例
102 private void btnOpen_Click( object sender, RoutedEventArgs e)
103 {
104 // 我现在用的COM1端口,按需要可改成COM2,COM3
105 InitCOM( " COM1 " );
106 OpenPort();
107 }
108 }
109 }
值得注意的是:
1. port1.ReceivedBytesThreshold = 4; ReceivedBytesThreshold属性设置触发一次DataReceived事件时将接收到的数据字节数.由于我的硬件是一次发上来4个字节估设置为4.如果不能正确设置这个属性的话,在SerialPort对象第一次触发DataReceived事件时还是正确的(4个字节),但是从第二次触发之后都是一个字节触发一次DataReceived事件...为什么这样搞不清楚...
2.如果在 DataReceived 委托事件中使用了不是DataReceived委托事件所在线程创建的UI控件,函数等,需要使用到Dispatcher 类来达到线程安全,不然会报错.以下是MSDN中Dispatcher类的例子(XAML),简单明了:
1
private
delegate
void
AddTextDelegate(Panel p, String text);
2
3 private void AddText(Panel p, String text)
4 {
5 p.Children.Clear();
6 p.Children.Add( new TextBlock { Text = text });
7 }
8
9 private void TestBeginInvokeWithParameters(Panel p)
10 {
11 if (p.Dispatcher.CheckAccess()) AddText(p, " Added directly. " );
12 else p.Dispatcher.BeginInvoke(
13 new AddTextDelegate(AddText), p, " Added by Dispatcher. " );
14 }
2
3 private void AddText(Panel p, String text)
4 {
5 p.Children.Clear();
6 p.Children.Add( new TextBlock { Text = text });
7 }
8
9 private void TestBeginInvokeWithParameters(Panel p)
10 {
11 if (p.Dispatcher.CheckAccess()) AddText(p, " Added directly. " );
12 else p.Dispatcher.BeginInvoke(
13 new AddTextDelegate(AddText), p, " Added by Dispatcher. " );
14 }