1.随笔
由于项目需要开发一款上位机来将下位机传上来的光谱数据绘制成光谱图,特编写了这个光谱图绘制软件。下位机会定时上传一组数据到上位机,每一组数据超过一万字节,上位机每次接收一组数据,就需要判断数据接收是否准确,再绘制成光谱图,并实现图形更新。下面来看下相关代码。
2.串口事件及数据校验
串口事件函数部分的代码
private void SerialPort1_DataReceived(object sender, SerialDataReceivedEventArgs e)
{
if (serialPort1.IsOpen)
{
try
{
//读取数据
byte[] ReceiveBytes = new byte[12295]; //用于校验数据
int count = serialPort1.BytesToRead; //待读字节数
byte[] res = new byte[count];
serialPort1.Read(res, 0, count); //读到的数据存储到res
buffer.AddRange(res); //缓存数据
while(buffer.Count >= 2) //至少包含帧头1, 帧尾2
{
if (buffer[0] == '1') //帧头验证成功
{
if (buffer.Count < 12295)
{
break; //数据接收未完成
}
else
{
buffer.CopyTo(0, ReceiveBytes, 0, 12295);//得到完整数据,复制到ReceiveBytes中进行校验
buffer.RemoveRange(0, 12295); //复制完成后删除缓存数据
//开始校验
if (ReceiveBytes[12290] != '2') //帧尾验证失败
{
buffer.RemoveRange(0, buffer.Count);
continue;
}
else //帧尾验证成功
{
dataList.Enqueue(Encoding.ASCII.GetString(ReceiveBytes.ToArray()));
}
}
}
else //帧头验证失败
{
buffer.Clear();
}
}
}
catch
{
MessageBox.Show("错误!!!", "提示");
}
}
}
3.绘图部分
绘图控件引用的是Plot View控件,可实现放大缩小空能。使用定时器去读取检验后的数据列表,可以选择来一组数就绘制一次光谱图,也可以选择,多组数求平均值绘制成光谱图。
private void Timer1_Tick(object sender, EventArgs e) //定时器:图形显示事件
{
if (CountsSample == 1)
{
double temp;
if (dataList.Count > 0)
{
timer1.Stop();
var lineSer = plotView1.Model.Series[0] as LineSeries;
string str = dataList.Dequeue();
if (str[0] == '1' && str[12290] == '2')
{
string res = str.ToString(); //将字符转化成string
string[] data = res.Split(',');
if (data[0] == "1" && data[2049] == "2\r\n\r\n")
{
lineSer.Points.Clear();
for (int i = 1; i < 2049; i++)
{
temp = Convert.ToDouble(data[i]);
lineSer.Points.Add(new DataPoint(i, temp));
}
_myPlotModel.InvalidatePlot(true);
Thread.Sleep(100);
}
}
timer1.Start();
}
else
{
timer1.Stop();
timer1.Start();
}
}
else if (CountsSample != 1)
{
if (dataList.Count > CountsSample)
{
timer1.Stop();
double[] temp = new double[12295];
string str = "";
string[,] array = new string[CountsSample,2050];
var lineSer = plotView1.Model.Series[0] as LineSeries;
for (int i = 0; i <= CountsSample; i++)
{
str = dataList.Dequeue() + "," + str;
}
string res = str.ToString(); //将字符转化成string
string[] data = res.Split(',');
for (int i = 0; i < CountsSample; i++)
{
for (int j = 0; j < 2050; j++)
{
array[i,j] = data[j];
timer1.Stop();
data[j] = data[2050*(i+1)+j];
}
}
for (int i = 0; i < 2049; i++)
{
for (int j = 0; j < CountsSample; j++)
{
temp[i] = Convert.ToDouble(array[j,i]) + temp[i];
}
}
if (temp[0] == CountsSample )
{
lineSer.Points.Clear();
for (int i = 1; i < 2049; i++)
{
lineSer.Points.Add(new DataPoint(i, temp[i]/CountsSample));
}
_myPlotModel.InvalidatePlot(true);
Thread.Sleep(100);
}
timer1.Start();
}
else
{
timer1.Stop();
timer1.Start();
}
}
else
{
timer1.Stop();
timer1.Start();
}
}
4.结果显示
图形显示
数据显示