最近学习用C#写了一个串口测试软件,从串口接收数据,并将数据绘制成波形图,在实际程序中使用的控件是chart(measurement studio2015中的waveformgraph不是很好用)测试时发现,chart在绘制了1000-2000个数据点之后,程序运行会出现异常,当我注释了向chart添加数据的函数之后,运行没有异常发生。异常提醒是 : “System.InvalidOperationException”类型的未经处理的异常在System.Windows.Forms.DataVisualization.dll中发生。不知道各位有没有好的解决办法。
异常贴图与代码如下:
代码如下:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;using System.Runtime.InteropServices;
using System.Windows.Forms.DataVisualization.Charting;
using System.IO;
using System.IO.Ports;
using NationalInstruments;
//using NationalInstruments.Controls.Data;
namespace HRM200Test
{ public partial class Form1 : Form
{
int Timercount = 0;//用于定时器计数
byte[] gDataToSend = new byte[2] { 0x00, 0x00 }; //数据发送
public Form1()
{
InitializeComponent();
System.Windows.Forms.Control.CheckForIllegalCrossThreadCalls = false;
// timer1.Start();
}
internal class flagclass
{
public static int button1_click_flag = 0 ;
public static int button4_click_flag = 0 ;
public static int button5_click_flag = 0;
public static int PCR_Run_flag = 0;
public static int StepCnt = 0;
public static int LoopCnt = 0;
public static int TimeValue = 0;
public static int Predegeneration_flag = 0;
public static int DaRxCnt = 0 ;
public static byte[] DataRxBuf = new byte[50];
public static byte[] TemperByte = new byte[5];
}
private void button1_Click(object sender, EventArgs e)
{
if (flagclass.button1_click_flag == 0)
{
try
{
serialPort1.PortName = comboBox1.Text;
serialPort1.BaudRate = Convert.ToInt32(comboBox2.Text,10);//十进制数据转换
serialPort1.Open();
flagclass.button1_click_flag = 1;
button1.BackColor = SystemColors.ActiveCaption;
button1.Text = "关闭串口";
}
catch
{
MessageBox.Show("端口错误,请检查串口", "错误");
}
}
else
{
try
{ serialPort1.Close();//关闭串口
button1.Text = "打开串口";
button1.Enabled = true;//打开串口按钮可用
button1.BackColor = SystemColors.InactiveBorder;
flagclass.button1_click_flag = 0;
}
catch (Exception)//Exception err)//一般情况下关闭串口不会出错,所以不需要加处理程序
{ }
}
} private void Form1_Load(object sender, EventArgs e)
{
SearchAndAddSerialToComboBox(serialPort1, comboBox1);
comboBox2.SelectedIndex = 3;
button4.Enabled = false;
ChartInit();
} private void serialPort1_DataReceived(object sender, SerialDataReceivedEventArgs e)
{
int LEN = 50;
Int16 i = 0;
float[] fdata = new float[4] ;
byte[] crcvalue = new byte[2] { 0x00, 0x00 };
byte[] buffer1 = new byte[LEN];
int[] buf1 = new int[100];
LEN = 0;
LEN = serialPort1.BytesToRead;
serialPort1.Read(buffer1, 0, LEN);
if (buffer1[0] == 0x41 && buffer1[1] == 0x04 && CRC16_2(buffer1)[0] == buffer1[18] && CRC16_2(buffer1)[1] == buffer1[19])
{
for (int j = 0; j < 4; j++)
{
flagclass.TemperByte[3] = buffer1[j * 4 + 2];
flagclass.TemperByte[2] = buffer1[j * 4 + 3];
flagclass.TemperByte[1] = buffer1[j * 4 + 4];
flagclass.TemperByte[0] = buffer1[j * 4 + 5];
fdata[j] = BitConverter.ToSingle(flagclass.TemperByte, 0) ;
}
try
{
chart2.Series[0].Points.AddY( fdata[1]);
textBox11.Text = fdata[1].ToString();
if ( (chart2.ChartAreas[0].AxisX.Maximum - chart2.ChartAreas[0].AxisX.Minimum) >= 1024)
chart2.ChartAreas[0].AxisX.Minimum = chart2.ChartAreas[0].AxisX.Maximum - 1024;
}
catch {
MessageBox.Show(" error!","zzZ");
}
}
else
{
string str1 = System.Text.Encoding.Default.GetString(buffer1); //buffer1.ToString();
textBox1.AppendText(str1);//添加内容
textBox1.Text.ToArray();
} }
private void SendDataToSerialPort(SerialPort MyPort, byte[] DataToSend) //单字节发送数据
{
const byte Nlen = 0x07 ;
byte[] crcvalue = new byte[2] { 0x00, 0x00 };
crcvalue[0] = CRC16(DataToSend)[0];
crcvalue[1] = CRC16(DataToSend)[1];
byte[] DatasToWrite = new byte[Nlen] { 0x54 , DataToSend[0], DataToSend[1], crcvalue[0], crcvalue[1], 0x0D ,0x0A }; //数据包
if (serialPort1.IsOpen)
{
try
{
// MyPort.WriteLine("");
MyPort.Write(DatasToWrite, 0, Nlen); //发数据
}
catch
{
MessageBox.Show("串口数据写入错误", "错误");
}
}
} private void SearchAndAddSerialToComboBox(SerialPort MyPort, ComboBox MyBox)
{ //将可用端口号添加到ComboBox
string Buffer; //缓存
MyBox.Items.Clear(); //清空ComboBox内容
for (int i = 1; i < 40; i++) //循环
{
try //核心原理是依靠try和catch完成遍历
{
Buffer = "COM" + i.ToString();
MyPort.PortName = Buffer;
MyPort.Open(); //如果失败,后面的代码不会执行
MyBox.Items.Add(Buffer); //打开成功,添加至下俩列表
MyPort.Close(); //关闭
}
catch
{
}
}
} public static byte[] CRC16(byte[] data )//string sInputString)
{
int len = data.Length;
if (len > 0)
{
ushort crc = 0xFFFF; for (int i = 0; i < len; i++)
{
crc = (ushort)(crc ^ (data[i]));
for (int j = 0; j < 8; j++)
{
crc = (crc & 1) != 0 ? (ushort)((crc >> 1) ^ 0xA001) : (ushort)(crc >> 1);
}
}
byte hi = (byte)((crc & 0xFF00) >> 8); //高位置
byte lo = (byte)(crc & 0x00FF); //低位置yindu return new byte[] { hi, lo };
}
return new byte[] { 0, 0 };
}
public static byte[] CRC16_2(byte[] data)//string sInputString)
{
// byte[] data = System.Text.ASCIIEncoding.ASCII.GetBytes(sInputString);
int len = 18;
if (len > 0)
{
ushort crc = 0xFFFF; for (int i = 2; i < len; i++)
{
crc = (ushort)(crc ^ ( (byte) data[i]));
for (int j = 0; j < 8; j++)
{
crc = (crc & 1) != 0 ? (ushort)((crc >> 1) ^ 0xA001) : (ushort)(crc >> 1);
}
}
byte hi = (byte)((crc & 0xFF00) >> 8); //高位置
byte lo = (byte)(crc & 0x00FF); //低位置yindu return new byte[] { hi, lo };
}
return new byte[] { 0, 0 };
}
// ASCII码转为字符串
public static string ByteToString(byte[] arr, bool isReverse)
{
try
{
byte hi = arr[0], lo = arr[1];
return Convert.ToString(isReverse ? hi + lo * 0x100 : hi * 0x100 + lo, 16).ToUpper().PadLeft(4, '0');
}
catch (Exception ex) {
MessageBox.Show("123", "错123误");
throw (ex); }
} private void button3_Click(object sender, EventArgs e)
{
textBox1.Text = "";
} private void button2_Click(object sender, EventArgs e)
{
// MessageBox.Show("正在扫描,请等待..."); SearchAndAddSerialToComboBox(serialPort1, comboBox1);
serialPort1.DataReceived += new SerialDataReceivedEventHandler(serialPort1_DataReceived);//必须手动添加事件处理程序
MessageBox.Show(" 扫描完成!", "提示");
} private void ChartInit()
{ chart2.Series[0].Points.Add(0);
chart2.Series[0].Color = Color.Red; chart2.ChartAreas[0].AxisY.Minimum = 0;
chart2.ChartAreas[0].AxisY.Maximum = 100;
chart2.ChartAreas[0].AxisY.Interval = 10; chart2.ChartAreas[0].AxisX.MajorGrid.LineDashStyle = ChartDashStyle.Dash;//网格刻线为虚线、白色
chart2.ChartAreas[0].AxisY.MajorGrid.LineDashStyle = ChartDashStyle.Dash;//网格刻线为虚线、白色
chart2.ChartAreas[0].AxisX.LineDashStyle = ChartDashStyle.Solid;//坐标轴 为实线
chart2.ChartAreas[0].AxisY.LineDashStyle = ChartDashStyle.Solid;//坐标轴 为实线
} }
}
异常贴图与代码如下:
代码如下:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;using System.Runtime.InteropServices;
using System.Windows.Forms.DataVisualization.Charting;
using System.IO;
using System.IO.Ports;
using NationalInstruments;
//using NationalInstruments.Controls.Data;
namespace HRM200Test
{ public partial class Form1 : Form
{
int Timercount = 0;//用于定时器计数
byte[] gDataToSend = new byte[2] { 0x00, 0x00 }; //数据发送
public Form1()
{
InitializeComponent();
System.Windows.Forms.Control.CheckForIllegalCrossThreadCalls = false;
// timer1.Start();
}
internal class flagclass
{
public static int button1_click_flag = 0 ;
public static int button4_click_flag = 0 ;
public static int button5_click_flag = 0;
public static int PCR_Run_flag = 0;
public static int StepCnt = 0;
public static int LoopCnt = 0;
public static int TimeValue = 0;
public static int Predegeneration_flag = 0;
public static int DaRxCnt = 0 ;
public static byte[] DataRxBuf = new byte[50];
public static byte[] TemperByte = new byte[5];
}
private void button1_Click(object sender, EventArgs e)
{
if (flagclass.button1_click_flag == 0)
{
try
{
serialPort1.PortName = comboBox1.Text;
serialPort1.BaudRate = Convert.ToInt32(comboBox2.Text,10);//十进制数据转换
serialPort1.Open();
flagclass.button1_click_flag = 1;
button1.BackColor = SystemColors.ActiveCaption;
button1.Text = "关闭串口";
}
catch
{
MessageBox.Show("端口错误,请检查串口", "错误");
}
}
else
{
try
{ serialPort1.Close();//关闭串口
button1.Text = "打开串口";
button1.Enabled = true;//打开串口按钮可用
button1.BackColor = SystemColors.InactiveBorder;
flagclass.button1_click_flag = 0;
}
catch (Exception)//Exception err)//一般情况下关闭串口不会出错,所以不需要加处理程序
{ }
}
} private void Form1_Load(object sender, EventArgs e)
{
SearchAndAddSerialToComboBox(serialPort1, comboBox1);
comboBox2.SelectedIndex = 3;
button4.Enabled = false;
ChartInit();
} private void serialPort1_DataReceived(object sender, SerialDataReceivedEventArgs e)
{
int LEN = 50;
Int16 i = 0;
float[] fdata = new float[4] ;
byte[] crcvalue = new byte[2] { 0x00, 0x00 };
byte[] buffer1 = new byte[LEN];
int[] buf1 = new int[100];
LEN = 0;
LEN = serialPort1.BytesToRead;
serialPort1.Read(buffer1, 0, LEN);
if (buffer1[0] == 0x41 && buffer1[1] == 0x04 && CRC16_2(buffer1)[0] == buffer1[18] && CRC16_2(buffer1)[1] == buffer1[19])
{
for (int j = 0; j < 4; j++)
{
flagclass.TemperByte[3] = buffer1[j * 4 + 2];
flagclass.TemperByte[2] = buffer1[j * 4 + 3];
flagclass.TemperByte[1] = buffer1[j * 4 + 4];
flagclass.TemperByte[0] = buffer1[j * 4 + 5];
fdata[j] = BitConverter.ToSingle(flagclass.TemperByte, 0) ;
}
try
{
chart2.Series[0].Points.AddY( fdata[1]);
textBox11.Text = fdata[1].ToString();
if ( (chart2.ChartAreas[0].AxisX.Maximum - chart2.ChartAreas[0].AxisX.Minimum) >= 1024)
chart2.ChartAreas[0].AxisX.Minimum = chart2.ChartAreas[0].AxisX.Maximum - 1024;
}
catch {
MessageBox.Show(" error!","zzZ");
}
}
else
{
string str1 = System.Text.Encoding.Default.GetString(buffer1); //buffer1.ToString();
textBox1.AppendText(str1);//添加内容
textBox1.Text.ToArray();
} }
private void SendDataToSerialPort(SerialPort MyPort, byte[] DataToSend) //单字节发送数据
{
const byte Nlen = 0x07 ;
byte[] crcvalue = new byte[2] { 0x00, 0x00 };
crcvalue[0] = CRC16(DataToSend)[0];
crcvalue[1] = CRC16(DataToSend)[1];
byte[] DatasToWrite = new byte[Nlen] { 0x54 , DataToSend[0], DataToSend[1], crcvalue[0], crcvalue[1], 0x0D ,0x0A }; //数据包
if (serialPort1.IsOpen)
{
try
{
// MyPort.WriteLine("");
MyPort.Write(DatasToWrite, 0, Nlen); //发数据
}
catch
{
MessageBox.Show("串口数据写入错误", "错误");
}
}
} private void SearchAndAddSerialToComboBox(SerialPort MyPort, ComboBox MyBox)
{ //将可用端口号添加到ComboBox
string Buffer; //缓存
MyBox.Items.Clear(); //清空ComboBox内容
for (int i = 1; i < 40; i++) //循环
{
try //核心原理是依靠try和catch完成遍历
{
Buffer = "COM" + i.ToString();
MyPort.PortName = Buffer;
MyPort.Open(); //如果失败,后面的代码不会执行
MyBox.Items.Add(Buffer); //打开成功,添加至下俩列表
MyPort.Close(); //关闭
}
catch
{
}
}
} public static byte[] CRC16(byte[] data )//string sInputString)
{
int len = data.Length;
if (len > 0)
{
ushort crc = 0xFFFF; for (int i = 0; i < len; i++)
{
crc = (ushort)(crc ^ (data[i]));
for (int j = 0; j < 8; j++)
{
crc = (crc & 1) != 0 ? (ushort)((crc >> 1) ^ 0xA001) : (ushort)(crc >> 1);
}
}
byte hi = (byte)((crc & 0xFF00) >> 8); //高位置
byte lo = (byte)(crc & 0x00FF); //低位置yindu return new byte[] { hi, lo };
}
return new byte[] { 0, 0 };
}
public static byte[] CRC16_2(byte[] data)//string sInputString)
{
// byte[] data = System.Text.ASCIIEncoding.ASCII.GetBytes(sInputString);
int len = 18;
if (len > 0)
{
ushort crc = 0xFFFF; for (int i = 2; i < len; i++)
{
crc = (ushort)(crc ^ ( (byte) data[i]));
for (int j = 0; j < 8; j++)
{
crc = (crc & 1) != 0 ? (ushort)((crc >> 1) ^ 0xA001) : (ushort)(crc >> 1);
}
}
byte hi = (byte)((crc & 0xFF00) >> 8); //高位置
byte lo = (byte)(crc & 0x00FF); //低位置yindu return new byte[] { hi, lo };
}
return new byte[] { 0, 0 };
}
// ASCII码转为字符串
public static string ByteToString(byte[] arr, bool isReverse)
{
try
{
byte hi = arr[0], lo = arr[1];
return Convert.ToString(isReverse ? hi + lo * 0x100 : hi * 0x100 + lo, 16).ToUpper().PadLeft(4, '0');
}
catch (Exception ex) {
MessageBox.Show("123", "错123误");
throw (ex); }
} private void button3_Click(object sender, EventArgs e)
{
textBox1.Text = "";
} private void button2_Click(object sender, EventArgs e)
{
// MessageBox.Show("正在扫描,请等待..."); SearchAndAddSerialToComboBox(serialPort1, comboBox1);
serialPort1.DataReceived += new SerialDataReceivedEventHandler(serialPort1_DataReceived);//必须手动添加事件处理程序
MessageBox.Show(" 扫描完成!", "提示");
} private void ChartInit()
{ chart2.Series[0].Points.Add(0);
chart2.Series[0].Color = Color.Red; chart2.ChartAreas[0].AxisY.Minimum = 0;
chart2.ChartAreas[0].AxisY.Maximum = 100;
chart2.ChartAreas[0].AxisY.Interval = 10; chart2.ChartAreas[0].AxisX.MajorGrid.LineDashStyle = ChartDashStyle.Dash;//网格刻线为虚线、白色
chart2.ChartAreas[0].AxisY.MajorGrid.LineDashStyle = ChartDashStyle.Dash;//网格刻线为虚线、白色
chart2.ChartAreas[0].AxisX.LineDashStyle = ChartDashStyle.Solid;//坐标轴 为实线
chart2.ChartAreas[0].AxisY.LineDashStyle = ChartDashStyle.Solid;//坐标轴 为实线
} }
}
就是这句“chart2.Series[0].Points.AddY( fdata[1]); ”,注释掉没事了,但也不显示波形了。
而且我也没有在循环中使用 System.Windows.Forms.DataVisualization.dll 中的类或函数呀?
chart2.Series[0].Points.AddY( fdata[1]);
textBox11.Text = fdata[1].ToString();
if ( (chart2.ChartAreas[0].AxisX.Maximum - chart2.ChartAreas[0].AxisX.Minimum) >= 1024)
chart2.ChartAreas[0].AxisX.Minimum = chart2.ChartAreas[0].AxisX.Maximum - 1024;
懂了,明天把这两部分分开写,试试看效果。今天下午有事,暂时测不了。thx.
我异步用chart画折线图的时候也有这个问题,后面我把集合数据从大到小遍历就好了