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和事件驱动的I/O、对管脚和中断状态的访问以及对串行驱动程序属性的访问。另外,SerialPort类的功能可以包装在内部Stream对象中,可通过BaseStream属性访问,并且可以传递给包装或使用流的类。
下面列举其一些常用的属性、方法及事件:
- 属性
- BaudRate——串口数据传输波特率设置
- DataBits——每个字节的标准数据位长度
- 方法
- GetPortNames()——获取当前计算机的串行端口名称数组
- Open()——打开一个新的串行端口连接
- 事件
- 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<string>(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 = BitConverter.ToUInt16(pointBytes, 0);
//触发单点收到数据事件
pointComing(this, new EventArgs());
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 = File.CreateText(newFileName);
//将一点写入TXT文件中
dataWriter.WriteLine(point);