程序分析示波器波形(实现解析示波器波形文件)

之前的文章中对示波器波形文件进行了解析,见参考链接示波器波形数据文件(trc,dat文件)解析。其实,我们对trc或者dat文件的解析主要是通过上位机,对数据进行我们想要的处理,因此,本文我们将一下用C#实现文件的解析。

之前的文章中,我们知道,trc文件可以用十六进制的格式打开,然后进行每个Byte的解析。dat文件可以通过文件流的形式打开,即ASCII的形式打开。因此,对于trc文件我们主要使用BINaryReader来实现解析,dat文件通过StreamReader打开即可。

//打开trc文件 FileStream bin_stream = new FileStream(file_name,FileMode.Open); BinaryReader bin_reader = new BinaryReader(bin_stream); //打开dat文件 StreamReader read_file = new StreamReader(file_name);

对于十六进制文件格式的操作,可以具体参考我之前的文章。C#学习随笔—操作BIN文件(读,写,替代),注意:BIN文件的操作实质上也是十六进制码的操作。我这里大概列一下简单的读操作:

bin_reader.Readbytes(346)//读取346个bytes

对于文本文件格式的操作,基本如下:

read_file.ReadLine();//读取一行STRING字符串

上面是比较基本的文件操作方法,我们本文不做过多叙述,只说我们会用到的。

然后在解析文件过程中,会用到byte[]转换为Float型,byte[]转换为word(int16),byte[]转换为ASCII string,byte转换为ASCII。

BitConverter.ToUInt32(数组名,数组的开始的index);//byte[]转换为UInt32 BitConverter.ToInt16(数组名,数组的开始的index);//byte[]转换为Int16 BitConverter.ToSingle(数组名,数组开始的index);//byte[]转换为Float Encoding.ASCII.GetString(数组名,数组开始的index,长度);//Byte[]转换为ASCII String字符 (char);//Byte转换为ASCII码,直接强制数据类型转换

然后我们要将数据类型显示到Winform的Chart图表中。

Chart图标的操作,我在这儿不做详细叙述,我这里也只是对数据的初步显示,不做炫酷的操作。效果图如下所示:

程序分析示波器波形(实现解析示波器波形文件)(1)

直接上源码:

using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Windows.Forms; using System.IO; namespace Cellwise_Debug_Tool { public partial class SoftwareToolWindows : Form { //TRC 文件各个数据类型占用字节数 public const int LONG_LENGTH = 4; public const int WORD_LENGTH = 2; public const int FLOAT_LENGTH = 4; public const int DOUBLE_LENGTH = 8; public const int BYTE_LENGTH = 1; //Chart控件中显示的最大数据点数 public const int MAX_SHOW_LENGTH = 100000; //trc文件的数据解析,具体可以参考上一篇文章 public enum trc_file_offset { KEY_WORD_OFFSET = 0x000B, TEMPLETE_VERSION_OFFSET = 0x001B, DATA_TYPE_OFFSET= 0x002B, DATA_HIGH_LOW_OFFSET = 0x002D, WAVEDESC_LENGTH_OFFSET = 0x002F, USERTEXT_LENGTH_OFFSET = 0x0033, TRIGTIME_LENGTH_OFFSET = 0x003B, RISTIME_LENGTH_OFFSET = 0x003F, DATA_ARRAY_1_OFFSET = 0x0047, DATA_ARRAY_2_OFFSET = 0x004B, INSTRUMENT_NAME_OFFSET = 0x0057, INSTRUMENT_NUM_OFFSET = 0x0067, CHANNEL_LABEL_OFFSET = 0x006B, DATA_ARRAY_1_POINT_LENGTH_OFFSET = 0x007F, OSC_DISPLAY_POINT_LENGTH_OFFSET = 0x0083, FIRST_VALID_INDEX_OFFSET = 0x0087, LAST_VALID_INDEX_OFFSET = 0x008B, VERTICAL_GAIN_OFFSET = 0x00A7, VERTICAL_OFFSET_OFFSET = 0x00AB, HORIZ_INTERVAL_OFFSET = 0x00BB, VERTICAL_UNIT_OFFSET = 0x00CF, HORIZ_UNIT_OFFSET = 0x00FF, TIMEBASE_OFFSET = 0x014F, PROBE_RES_SETTING_OFFSET = 0x0151, VERTICAL_DIV_OFFSET = 0x0157, BANDLIMIT_ENABLE_OFFSET = 0x0159, CHANNEL_NUM_OFFSET = 0x0163, MAX_WAVEDESC_OFFSET = 0x164, }; public enum message_info { FORMAT_ERROR, STRING_OUT, } public struct software_status_t { public byte[] header_byte; public byte point_type;//00-->Byte,01-->Word public UInt32 user_text_length; public UInt32 trig_time_length; public UInt32 ris_time_length; public UInt32 point_length; public float horiz_interval; public byte horiz_unit; public byte vertical_unit; public float vertical_gain; public float vertical_offset; public DataTable data_value; } software_status_t software_status; public SoftwareToolWindows() { InitializeComponent(); app_init(); } //用户配置初始化 private void app_init() { software_status.header_byte = new byte[512]; ChartInit(); } //Chart控件初始化 private void ChartInit() { #region SetChartProperty Waveform.BackColor = Color.White; Waveform.BackGradientStyle = System.Windows.Forms.DataVisualization.Charting.GradientStyle.None; Waveform.BorderlineColor = Color.Black; Waveform.BorderlineDashStyle = System.Windows.Forms.DataVisualization.Charting.ChartDashStyle.Solid; Waveform.BorderlineWidth = 1; Waveform.BorderSkin.SkinStyle = System.Windows.Forms.DataVisualization.Charting.BorderSkinStyle.None; #endregion #region SetTitleProperty System.Windows.Forms.DataVisualization.Charting.Title title = new System.Windows.Forms.DataVisualization.Charting.Title(); title.Text = "Waveform"; title.Font = new Font("Times New Roman", 10, FontStyle.Regular); title.Alignment = ContentAlignment.TopCenter; title.TextStyle = System.Windows.Forms.DataVisualization.Charting.TextStyle.Default; Waveform.Titles.Add(title); #endregion #region SetChartAreaProperty //handle in the Form #endregion #region SetLegandProperty //handle in the Form #endregion } //Trc Dat File 对话框处理函数 private void FileBrowse_Click(object sender, EventArgs e) { OpenFileDialog open_file = new OpenFileDialog(); open_file.Filter = "波形文件|*.trc|数据文件|*.dat";//只需要trc文件或者dat文件 if (open_file.ShowDialog() == DialogResult.OK) { FilePath.Text = open_file.FileName; if (open_file.FilterIndex == 1)//波形数据文件 .trc文件 { trc_file_convert_to_data(open_file.FileName,Waveform); } else if(open_file.FilterIndex == 2)//波形数据文件 .dat { dat_file_convert_to_data(open_file.FileName, Waveform); } } } //trc文件解析函数 //file_name trc文件路径 //Chart Chart控件,trc文件数据输出至Chart控件 private void trc_file_convert_to_data(string file_name,System.Windows.Forms.DataVisualization.Charting.Chart dataChart) { FileStream bin_stream = new FileStream(file_name,FileMode.Open); BinaryReader bin_reader = new BinaryReader(bin_stream); try { software_status.header_byte = bin_reader.ReadBytes((int)trc_file_offset.MAX_WAVEDESC_OFFSET 1); string trc_file_log = System.Text.Encoding.ASCII.GetString(software_status.header_byte,(int)trc_file_offset.KEY_WORD_OFFSET,8); if (trc_file_log == "WAVEDESC") { message_info_output(false, message_info.STRING_OUT, "FILE LOG: WAVEDESC"); string trc_file_version = System.Text.Encoding.ASCII.GetString(software_status.header_byte, (int)trc_file_offset.TEMPLETE_VERSION_OFFSET, 10); if (trc_file_version == "LECROY_2_3") { message_info_output(false, message_info.STRING_OUT, "FILE Version: Lecroy_2_3"); message_info_output(false, message_info.STRING_OUT, "INSTRUMENT NAME: " Encoding.ASCII.GetString(software_status.header_byte, (int)trc_file_offset.INSTRUMENT_NAME_OFFSET, 14)); message_info_output(false, message_info.STRING_OUT, "INSTRUMENT NUMBER: " (BitConverter.ToUInt32(software_status.header_byte,(int)trc_file_offset.INSTRUMENT_NUM_OFFSET)).ToString()); software_status.point_length = BitConverter.ToUInt32(software_status.header_byte, (int)trc_file_offset.DATA_ARRAY_1_POINT_LENGTH_OFFSET); software_status.horiz_interval = BitConverter.ToSingle(software_status.header_byte, (int)trc_file_offset.HORIZ_INTERVAL_OFFSET); software_status.horiz_unit = software_status.header_byte[(int)trc_file_offset.HORIZ_UNIT_OFFSET]; software_status.vertical_unit = software_status.header_byte[(int)trc_file_offset.VERTICAL_OFFSET_OFFSET]; software_status.vertical_gain = BitConverter.ToSingle(software_status.header_byte, (int)trc_file_offset.VERTICAL_GAIN_OFFSET); software_status.vertical_offset = BitConverter.ToSingle(software_status.header_byte, (int)trc_file_offset.VERTICAL_OFFSET_OFFSET); message_info_output(false, message_info.STRING_OUT, "DATA POINT LENGTH: " software_status.point_length.ToString()); message_info_output(false, message_info.STRING_OUT, "HORIZ INTERVAL: " software_status.horiz_interval.ToString("F15") ((char)software_status.horiz_unit).ToString()); software_status.user_text_length = BitConverter.ToUInt32(software_status.header_byte, (int)trc_file_offset.USERTEXT_LENGTH_OFFSET); software_status.trig_time_length = BitConverter.ToUInt32(software_status.header_byte, (int)trc_file_offset.TRIGTIME_LENGTH_OFFSET); software_status.ris_time_length = BitConverter.ToUInt32(software_status.header_byte, (int)trc_file_offset.RISTIME_LENGTH_OFFSET); if (software_status.user_text_length > 0) { bin_reader.ReadBytes((int)software_status.user_text_length); } else { message_info_output(false, message_info.STRING_OUT, "USER_TEXT AREA is Empty!"); } if (software_status.trig_time_length > 0) { bin_reader.ReadBytes((int)software_status.trig_time_length); } else { message_info_output(false, message_info.STRING_OUT, "TRIG_TIME AREA is Empty!"); } if (software_status.ris_time_length > 0) { bin_reader.ReadBytes((int)software_status.ris_time_length); } else { message_info_output(false, message_info.STRING_OUT, "RIS_TIME AREA is Empty!"); } software_status.point_type = software_status.header_byte[(int)trc_file_offset.DATA_TYPE_OFFSET]; software_status.data_value = new DataTable(); software_status.data_value.Columns.Add("Times", typeof(float)); software_status.data_value.Columns.Add("Value", typeof(float)); DataRow row_value; int y_value=0; byte[] y_value_byte = new byte[2]; float finial_value; for (int temp = 0; (temp < MAX_SHOW_LENGTH)&&(temp<software_status.point_length); temp ) { row_value = software_status.data_value.NewRow(); row_value["Times"] = temp * software_status.horiz_interval; if (software_status.point_type == 0x00) { y_value = bin_reader.ReadByte(); } else if (software_status.point_type == 0x01) { y_value_byte = bin_reader.ReadBytes(2); y_value = BitConverter.ToInt16(y_value_byte, 0); } finial_value = y_value * software_status.vertical_gain - software_status.vertical_offset; row_value["Value"] = finial_value; software_status.data_value.Rows.Add(row_value); Waveform.Series[0].Points.AddXY((temp * software_status.horiz_interval), finial_value); } message_info_output(false, message_info.STRING_OUT, "Load DataTable Finished!"); } else { message_info_output(true, message_info.STRING_OUT, "FILE Version:Lecroy_2_3,this tool don't support this version!"); } } else { message_info_output(true, message_info.STRING_OUT, "FILE LOG ERROR! FILE LOG:" trc_file_log); } } catch { MessageBox.Show("File Load Failed!"); } finally { bin_reader.Close(); bin_stream.Close(); } } //dat文件解析函数 //file_name:dat 文件路径 //Chart Chart控件,dat文件数据输出至Chart控件 private void dat_file_convert_to_data(string file_name, System.Windows.Forms.DataVisualization.Charting.Chart dataChart) { StreamReader read_file = new StreamReader(file_name); try { Int32 line_length = 0; string line_context; software_status.data_value = new DataTable(); software_status.data_value.Columns.Add("Times", typeof(float)); software_status.data_value.Columns.Add("Value", typeof(float)); DataRow row_value ; while ((!read_file.EndOfStream) && (line_length < MAX_SHOW_LENGTH)) { line_context = read_file.ReadLine(); row_value = software_status.data_value.NewRow(); row_value["Times"] = float.Parse(line_context.Substring(0, line_context.IndexOf(" "))); row_value["Value"] = float.Parse(line_context.Substring(line_context.IndexOf(" ") 1, line_context.Length - line_context.IndexOf(" ") - 1)); software_status.data_value.Rows.Add(row_value); Waveform.Series[0].Points.AddXY(row_value["Times"], row_value["Value"]); line_length ; } message_info_output(false, message_info.STRING_OUT, "Load DataTable Finished!"); } catch { MessageBox.Show("File Load Failed!"); } finally { read_file.Close(); } } //richtextbox 控件的Information显示 //red_flag:输出字体是否为红色,默认为黑色 //info 数字信息的类型,见上面定义的message_info //context 仅对于message info为STRING_OUT有效 private void message_info_output(bool red_flag,message_info info,string context) { if (red_flag) { MessageInfo.SelectionColor = Color.Red; } switch (info) { case message_info.FORMAT_ERROR: break; case message_info.STRING_OUT: MessageInfo.AppendText(context "\r\n"); break; default: break; } MessageInfo.SelectionColor = Color.Black; MessageInfo.ScrollToCaret(); } } }

当然了,这个上位机处理软件还是可以优化的,比如,Chart的显示,如果数据点数超过10万个点,数据加载会变慢,非常影响用户体验。这些问题,我准备找时间来优化,到时候分享出来供大家参考。

,

免责声明:本文仅代表文章作者的个人观点,与本站无关。其原创性、真实性以及文中陈述文字和内容未经本站证实,对本文以及其中全部或者部分内容文字的真实性、完整性和原创性本站不作任何保证或承诺,请读者仅作参考,并自行核实相关内容。文章投诉邮箱:anhduc.ph@yahoo.com

    分享
    投诉
    首页