使用 SerialPort 及 ZedGraph 快速实现串口数据实时显示
0 引子
在采样速率要求不高的情况下(粗略计算,以串口最大 115200 的传输速
率,也即~14K byte/s 计,则采样频率应该小于 7K,加上其他额外的开销,
在 16 位单片机上,采样速率应 该小于 5K 左右),使用串口进行实时数据采
集的方案是比较简单易行的。因为,各类编程语 言或开发环境都有对串口编
程的支持。在 windows 平台上,早期的 Visual Studio 6 环境下, 即可以使用
Win32 API 实现串口编程,也可以使用微软提供的 MSComm 控件来实现,到了
2005 年微软推出 .NET 2.0 后 ,直接加入了一非常好用的串口控件 — —
SerialPort ,在 System.IO.Ports 名字空间下。
另外一个问题便是数据采集后的绘图显示,无论是基于 MFC 的 GDI 或
是基于.NET 的 GDI+,虽然都可以方便的实现绘图功能,但程序设计量大(如
坐标,刻度,多条曲线,多个 窗口,屏幕推移等功能),还要处理一些如双
缓冲的技术(在.NET 的非精简版本中,绘图 API 中已经自动包含了双缓冲功
能),多数第三方控件厂商都推出了五花八门,各具特色的绘图 控件,使
用起来非常方便,但却要花费一定的成本,对于学生或小的实验项目而言,
只好望 而却步。而开源绘图控件——ZedGraph 即可让开发者深入的学习各类
GDI+编程技巧,又提 供了可与大多数高价的第三方控件相媲美的强大功能。
1 SerialPort 简介
SerialPort 类用于控制串行端口文件资源。SerialPort 类提供同步 I/O 和事件驱
动
、
对管脚和中断状态的访问以及对串行驱动程序属性的访问。另外,SerialPort
类
以
包装在内部 Stream 对象中,可通过 BaseStream 属性访问,并且可以传递给包
装
的
类。
I/O
的
能
用
可
流
功
使
的
或
下面列举其一些常用的属性、方法及事件:
1. 属性
BaudRate——串口数据传输波特率
设
置
DataBits——每个字节的标准数据位
长
度
2. 方法
GetPortNames()——获取当前计算机的串行端口名
称数组 Open()——打开一个新的串行端口连接
3. 事件
DataReceived——表示将处理 SerialPort 对象的数据接收事件的方法
2 ZedGraph 简介
ZedGraph 是一个非常优秀的开源的作图控件
来源:http://sourceforge.net/project/showfiles.php?group_id=114675
例子资源:http://zedgraph.org/wiki/index.php?title=Sample_Graphs
3 系统实现
3.1 系统框图
3.2 关键代码
1
初 始 化
ZedGraph
控 件
void zedGraphInit()
{
GraphPane myPane = dataChart.GraphPane;
// 设置坐标名称
myPane.Title.Text
myPane.XAxis.Title.Text
myPane.YAxis.Title.Text
=
//将曲线加入绘图框中
" 串 口 测 试 数 据 ";
";
" 原 始 采 样 值 ";
点
数
=
=
"
list1 = new PointPairList();
myPane.AddCurve("Data", list1, Color.Red, SymbolType.None); //更
新绘图区域
dataChart.AxisChange();
}
2. 查看系统中存在的串口
//获取系统中存在的串口列表
string[] portsArray = SerialPort.GetPortNames();
//按名称排序(COM11 或排在 COM2 的前面,对串口数目超过 10 的系统,需要改进)
Array.Sort(portsArray);
//将串口列表添加到下拉框中
foreach (string port in portsArray)
{
comboBoxPortName.Items.Add(port);
}
3. 打开串口
操作前需要进行一些必要的判断,如串口是否存在,或是否已经被打开
comPort.Open();
4.
开 始 监 听 串 口
//清除缓存
comPort.DiscardInBuffer();
//开启串口数据监听,由 comPort_DataReceived 处理数据
comPort.DataReceived += new SerialDataReceivedEventHandler(comPort_DataReceived);
5. 数据解析
//将 2 个字节做为一个点
byte[] pointBytes = onePoint.ToArray();
//16 进 制 转 换 成 short 数 据 类 型 ( 16 位 )
point
0);
//触发单点收到数据事件
pointComing(this, new EventArgs());
BitConverter.ToUInt16(pointBytes,
=
6. 绘图
//移动坐标轴
if (dataCount > range)
{
dataChart.GraphPane.XAxis.Scale.Min = dataCount
range;
dataChart.GraphPane.XAxis.Scale.Max = dataCount + 25;
-
}
//将单片加入曲线点列表
list1.Add(dataCount, point);
// 更 新 坐 标 轴 , 重 新 绘 制 图 形 区 域
dataChart.AxisChange();
dataChart.Invalidate();
7. 保存数据
使用 TextWriter 类,可以方便的进行 TXT 文件的
读写。 //首先声明 TextWriter 对象
TextWriter dataWriter;
//用当前的时间做为文件名
string newFileName = @"datas\" + DateTime.Now.ToString("yyyy-MM-dd hh-mm-ss") + ".txt"; //初
始化 TextWriter 对象
dataWriter
//将一点写入 TXT 文件中
dataWriter.WriteLine(point);
File.CreateText(newFileName);
=