力科(Lecroy)示波器专用波形文件(轨迹文件/trace文件/.trc文件)在MATLAB上的解析与回写

读取出来的量的具体含义可以查阅力科官方有关 trace 的定义文件 LeCroyWaveformTemplate_2_3.pdf

使用方法:

1、用下面的类定义,声明一个 Trace 对象

2、用 Read 方法读取即可

3、用 ADCSamples2Voltage 方法提取波形数据(原始数据为 ADC 采样数值)

4、如需回写,需要先用 Voltage2ADCSamples 方法将已有的波形数据转换为 ADC 采样值,再用 Write 方法写入到新文件

Trace 类定义(文件头+数据段):

classdef Trace < handle
	properties
		HeadOffset		= 11
		HEADER			= '#9020000350'		%文件头,主要用于指示文件大小,数值为9e10+文件字节长度(不包括此文件头的11个字节)
		DESCRIPTOR_NAME = 'WAVEDESC'		%解释器, 16B, s, 0-15
		TEMPLATE_NAME	= 'LECROY_2_3'		%模板名, 16B, s, 16-31
		COMM_TYPE		= 1					%2B, enum, 32-33
		COMM_ORDER		= 1					%2B, enum, 34-35 小端
		%各块长度(字节)
		WAVE_DESCRIPTOR	= 346				%文件头WAVEDSEC块的长度,4B, long, 36-39
		USER_TEXT		= 0					%用户文本块的长度,4B, long, 40-43
		RES_DESC1		= 0					%保留,4B, long, 44-47
		%各序列长度(字节)
		TRIGTIME_ARRAY	= 0					%4B,long,48-51
		RIS_TIME_ARRAY	= 0					%4B,long,52-55
		RES_ARRAY_1		= 0					%保留,4B,long,56-59
		WAVE_ARRAY_1	= 20000004			%4B,long,60-63,数据列1
		WAVE_ARRAY_2	= 0					%4B,long,64-67,数据列2
		RES_ARRAY_2		= 0					%4B,long,68-71,保留2
		RES_ARRAY_3		= 0					%4B,long,72-75,保留3
		%仪器信息
		INSTRUMENT_NAME	= 'LECROYWaveRunner'%16B,s,76-91
		INSTRUMENT_NUMBER					%4B, long, 92-95 仪器编号
		TRACE_LABEL		= repmat(char(0),1,16)	%16B, s, 96-111
		RESERVED1		= 10000002			%4B, 保留, 112-115,数值等于WAVE_ARRAY_COUNT,原因我也不知道
		%波形信息
		WAVE_ARRAY_COUNT= 10000002			%数据长度,4B, long, 116-119
		PNTS_PER_SCREEN	= 10000000			%屏幕上的数据长度,等于上面的值-2, 4B, long, 120-123
		FIRST_VALID_PNT	= 0					%需要跳过的数据点数,置0即可,4B, long, 124-127
		LAST_VALID_PNT	= 10000001			%WAVE_ARRAY_COUNT-1,4B, long, 128-131
		FIRST_POINT		= 0					%第一个数据点,填0即可,4B,132-135
		SPARSING_FACTOR	= 1					%填1即可,4B ,136-139
		SEGMENT_INDEX	= 0					%数据段索引,填0即可,4B, 140-143
		SUBARRAY_COUNT	= 1					%获取到的数据段数,4B, 144-147
		SWEEPS_PER_ACQ	= 1					%Average或Extrema专用,否则填1, 4B, 148-151
		POINTS_PER_PAIR	= 0					%2B, 152-153,峰值检测专用,这两个不用改
		PAIR_OFFSET		= 0					%2B, 154-155
		VERTICAL_GAIN	= 1.373120030621067e-04	%4B f 156-159 垂直轴增益 原数据=数据*增益+偏移
		VERTICAL_OFFSET	= 0					%4B f 160-163 垂直轴偏移
		MAX_VALUE		= 28875				%波形图网格的最大最小值, 4B f 164-167
		MIN_VALUE		= -29131			%4B f 168-171
		NOMINAL_BITS	= 8					%2B 172-173 不用改
		NOM_SUBARRAY_COUNT = 1				%2B 174-175
		HORIZ_INTERVAL	= 1e-10				%4B f 176-179 采样点间隔
		HORIZ_OFFSET	= -5e-4				%8B double 180-187
		PIXEL_OFFSET	= -5e-4				%8B d 188-195
		VERTUNIT		= ['V', repmat(char(0),1,47)]		%196-243 单位定义, 48B
		HORUNIT			= ['S', repmat(char(0),1,47)]		%244-291 单位定义, 48B
		HORIZ_UNCERTAINTY = 1e-12			%4B f 292-295 不确定性 单位为秒
		TRIGGER_TIME						%24B f 296-311触发时间戳
		ACQ_DURATION	= 0					%4B f 312-315
		RECORD_TYPE		= 0					%2B 316-317 波形类型,一般填0即可
		PROCESSING_DONE	= 0					%2B 318-319
		RESERVED5		= 0					%2B 320-321
		RIS_SWEEPS		= 1					%2B 322-323
		TIMEBASE		= 24				%2B 324-325 水平轴栅格时长
		VERT_COUPLING	= 0					%2B 326-327 耦合方式
		PROBE_ATT		= 1					%4B f 328-331 探针衰减
		FIXED_VERT_GAIN	= 18				%2B 332-333 垂直轴固定增益
		BANDWIDTH_LIMIT	= 0					%2B 334-335 带宽显示,填0即可
		VERTICAL_VERNIER= 1 				%4B f 336-339
		ACQ_VERT_OFFSET	= 0					%4B f 340-343
		WAVE_SOURCE		= -1				%2B 344-345 波形通道
		%用户文本块
		TEXT								%视上面定义的长度而定
		%TRIGTIME
		TRIGGER_T							%8B f 原名结尾是TIME,但与前面定义重复,故改为T
		TRIGGER_OFFSET						%8B f
		%RISTIME
		RIS_OFFSET							%8B f
		%DATA_ARRAY_1
		DATA_ARRAY_1
		%DATA_ARRAT_2
		DATA_ARRAY_2
		%SIMPLE
		SIMPLE
		%DUAL
		DUAL
	end

	methods
		function self = Trace()
			return;
		end
		%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
		function Read(self,fn)
			fid=fopen(fn,'r');
			if fid==-1 
   				fprintf('ERROR: file not found: %s\n', fn);
   				return;
			end
			data = fread(fid,50);
			self.HeadOffset = strfind(char(data(1:50)'), self.DESCRIPTOR_NAME) - 1;  %找到文件头并返回偏移量
			fseek(fid, self.HeadOffset+34, 'bof');	%指针定位到指定项
			self.COMM_ORDER = fread(fid,1,'int16');
			fclose(fid);
			if self.COMM_ORDER	%根据文件数据格式重新读入
				fid = fopen(fn,'r','ieee-le');		% LOFIRST ,小端数据
			else 
				fid = fopen(fn,'r','ieee-be');		% HIFIRST ,大端数据
			end
			fseek(fid, 0 ,'bof');
			self.HEADER = ReadStringN(fid, 0, 11);
			templateName = ReadString(fid, self.HeadOffset+16);
			if ~strcmp( deblank(templateName), self.TEMPLATE_NAME)
				error('Unsupported Template');
			end
			%开始读入文件信息
			self.COMM_TYPE			= ReadWord(fid, self.HeadOffset+32);
			self.WAVE_DESCRIPTOR	= ReadLong(fid, self.HeadOffset+36);
			self.USER_TEXT			= ReadLong(fid, self.HeadOffset+40);
			self.RES_DESC1			= ReadLong(fid, self.HeadOffset+44);
			self.TRIGTIME_ARRAY		= ReadLong(fid, self.HeadOffset+48);
			self.RIS_TIME_ARRAY		= ReadLong(fid, self.HeadOffset+52);
			self.RES_ARRAY_1		= ReadLong(fid, self.HeadOffset+56);
			self.WAVE_ARRAY_1		= ReadLong(fid, self.HeadOffset+60);
			self.WAVE_ARRAY_2		= ReadLong(fid, self.HeadOffset+64);
			self.RES_ARRAY_2		= ReadLong(fid, self.HeadOffset+68);
			self.RES_ARRAY_3		= ReadLong(fid, self.HeadOffset+72);
			%开始读入仪器信息
			self.INSTRUMENT_NAME	= ReadString(fid, self.HeadOffset+76);
			self.INSTRUMENT_NUMBER	= ReadLong(fid, self.HeadOffset+92);
			self.TRACE_LABEL		= ReadString(fid, self.HeadOffset+96);
			self.RESERVED1			= ReadLong(fid, self.HeadOffset+112);
			%开始读入波形信息
			self.WAVE_ARRAY_COUNT	= ReadLong(fid, self.HeadOffset+116);
			self.PNTS_PER_SCREEN	= ReadLong(fid, self.HeadOffset+120);
			self.FIRST_VALID_PNT	= ReadLong(fid, self.HeadOffset+124);
			self.LAST_VALID_PNT		= ReadLong(fid, self.HeadOffset+128);
			self.FIRST_POINT		= ReadLong(fid, self.HeadOffset+132);
			self.SPARSING_FACTOR	= ReadLong(fid, self.HeadOffset+136);
			self.SEGMENT_INDEX		= ReadLong(fid, self.HeadOffset+140);
			self.SUBARRAY_COUNT		= ReadLong(fid, self.HeadOffset+144);
			self.SWEEPS_PER_ACQ		= ReadLong(fid, self.HeadOffset+148);
			self.POINTS_PER_PAIR	= ReadWord(fid, self.HeadOffset+152);
			self.PAIR_OFFSET		= ReadWord(fid, self.HeadOffset+154);
			self.VERTICAL_GAIN		= ReadFloat(fid, self.HeadOffset+156);
			self.VERTICAL_OFFSET	= ReadFloat(fid, self.HeadOffset+160);
			self.MAX_VALUE			= ReadFloat(fid, self.HeadOffset+164);
			self.MIN_VALUE			= ReadFloat(fid, self.HeadOffset+168);
			self.NOMINAL_BITS		= ReadWord(fid, self.HeadOffset+172);
			self.NOM_SUBARRAY_COUNT = ReadWord(fid, self.HeadOffset+174);
			self.HORIZ_INTERVAL		= ReadFloat(fid, self.HeadOffset+176);
			self.HORIZ_OFFSET		= ReadDouble(fid, self.HeadOffset+180);
			self.PIXEL_OFFSET		= ReadDouble(fid, self.HeadOffset+188);
			self.VERTUNIT			= ReadStringN(fid, self.HeadOffset+196, 48);
			self.HORUNIT			= ReadStringN(fid, self.HeadOffset+244, 48);
			self.HORIZ_UNCERTAINTY	= ReadFloat(fid, self.HeadOffset+292);
			self.TRIGGER_TIME		= ReadTimestamp(fid,self.HeadOffset+296);
			self.ACQ_DURATION		= ReadLong(fid, self.HeadOffset+312);
			self.RECORD_TYPE		= ReadWord(fid, self.HeadOffset+316);
			self.PROCESSING_DONE	= ReadWord(fid, self.HeadOffset+318);
			self.RESERVED5			= ReadWord(fid, self.HeadOffset+320);
			self.RIS_SWEEPS			= ReadWord(fid, self.HeadOffset+322);
			self.TIMEBASE			= ReadWord(fid, self.HeadOffset+324);
			self.VERT_COUPLING		= ReadWord(fid, self.HeadOffset+326);
			self.PROBE_ATT			= ReadFloat(fid, self.HeadOffset+328);
			self.FIXED_VERT_GAIN	= ReadWord(fid, self.HeadOffset+332);
			self.BANDWIDTH_LIMIT	= ReadWord(fid, self.HeadOffset+334);
			self.VERTICAL_VERNIER	= ReadFloat(fid, self.HeadOffset+336);
			self.ACQ_VERT_OFFSET	= ReadFloat(fid, self.HeadOffset+340);
			self.WAVE_SOURCE		= ReadWord(fid, self.HeadOffset+344);
			%开始读入数据
			self.TEXT				= ReadStringN(fid, self.HeadOffset+346, self.USER_TEXT);
			if self.RECORD_TYPE == 0 %single sweep
				fseek(fid, self.HeadOffset + self.WAVE_DESCRIPTOR + self.USER_TEXT, 'bof');
				if self.COMM_TYPE %2B
					self.DATA_ARRAY_1 = fread(fid, self.WAVE_ARRAY_1, 'int16');
				else %1B
					self.DATA_ARRAY_1 = fread(fid, self.WAVE_ARRAY_1, 'int8');
				end
			else 
				error('Unsupported Record Type');
			end
			fclose(fid);
		end
		%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
		function Write(self,fn,wvfm)
			self.Voltage2ADCSamples(wvfm);	%转换数据
			if self.COMM_ORDER
				fid = fopen(fn,'w','ieee-le');
			else
				fid = fopen(fn,'w','ieee-be');
			end
			fseek(fid,0,'bof');
			self.HEADER = strcat('#', num2str( 9000000000 + self.WAVE_DESCRIPTOR + self.WAVE_ARRAY_1 ));
			fwrite(fid, self.HEADER, 'char*1');
			fwrite(fid, self.DESCRIPTOR_NAME,'char*1');
			fwrite(fid, repmat(char(0),1,8),'char*1');	%补\0
			fwrite(fid, self.TEMPLATE_NAME,'char*1');
			fwrite(fid, repmat(char(0),1,6),'char*1');
			fwrite(fid, self.COMM_TYPE, 'int16');
			fwrite(fid, self.COMM_ORDER, 'int16');
			fwrite(fid, self.WAVE_DESCRIPTOR, 'int32');
			fwrite(fid, self.USER_TEXT, 'int32');
			fwrite(fid, self.RES_DESC1, 'int32');
			fwrite(fid, self.TRIGTIME_ARRAY, 'int32');
			fwrite(fid, self.RIS_TIME_ARRAY, 'int32');
			fwrite(fid, self.RES_ARRAY_1, 'int32');
			fwrite(fid, self.WAVE_ARRAY_1, 'int32');
			fwrite(fid, self.WAVE_ARRAY_2, 'int32');
			fwrite(fid, self.RES_ARRAY_2, 'int32');
			fwrite(fid, self.RES_ARRAY_3, 'int32');
			fwrite(fid, self.INSTRUMENT_NAME, 'char*1');
			fwrite(fid, self.INSTRUMENT_NUMBER, 'int32');
			fwrite(fid, self.TRACE_LABEL, 'char*1');
			fwrite(fid, self.RESERVED1, 'int32');
			fwrite(fid, self.WAVE_ARRAY_COUNT, 'int32');
			fwrite(fid, self.PNTS_PER_SCREEN, 'int32');
			fwrite(fid, self.FIRST_VALID_PNT, 'int32');
			fwrite(fid, self.LAST_VALID_PNT, 'int32');
			fwrite(fid, self.FIRST_POINT, 'int32');
			fwrite(fid, self.SPARSING_FACTOR, 'int32');
			fwrite(fid, self.SEGMENT_INDEX, 'int32');
			fwrite(fid, self.SUBARRAY_COUNT, 'int32');
			fwrite(fid, self.SWEEPS_PER_ACQ, 'int32');
			fwrite(fid, self.POINTS_PER_PAIR, 'int16');
			fwrite(fid, self.PAIR_OFFSET, 'int16');
			fwrite(fid, self.VERTICAL_GAIN, 'float');
			fwrite(fid, self.VERTICAL_OFFSET, 'float');
			fwrite(fid, self.MAX_VALUE, 'float');
			fwrite(fid, self.MIN_VALUE, 'float');
			fwrite(fid, self.NOMINAL_BITS, 'int16');
			fwrite(fid, self.NOM_SUBARRAY_COUNT, 'int16');
			fwrite(fid, self.HORIZ_INTERVAL, 'float');
			fwrite(fid, self.HORIZ_OFFSET, 'double');
			fwrite(fid, self.PIXEL_OFFSET, 'double');
			fwrite(fid, self.VERTUNIT, 'char*1');
			fwrite(fid, self.HORUNIT, 'char*1');
			fwrite(fid, self.HORIZ_UNCERTAINTY, 'float');
			timestamp = datetime('now');
			fwrite(fid, second(timestamp), 'float64'); %时间戳
			fwrite(fid, minute(timestamp), 'int8');
			fwrite(fid, hour(timestamp), 'int8');
			fwrite(fid, day(timestamp), 'int8');
			fwrite(fid, month(timestamp), 'int8');
			fwrite(fid, year(timestamp), 'int32');
			fwrite(fid, self.ACQ_DURATION, 'int32');
			fwrite(fid, self.RECORD_TYPE, 'int16');
			fwrite(fid, self.PROCESSING_DONE, 'int16');
			fwrite(fid, self.RESERVED5, 'int16');
			fwrite(fid, self.RIS_SWEEPS, 'int16');
			fwrite(fid, self.TIMEBASE, 'int16');
			fwrite(fid, self.VERT_COUPLING, 'int16');
			fwrite(fid, self.PROBE_ATT, 'float');
			fwrite(fid, self.FIXED_VERT_GAIN, 'int16');
			fwrite(fid, self.BANDWIDTH_LIMIT, 'int16');
			fwrite(fid, self.VERTICAL_VERNIER, 'float');
			fwrite(fid, self.ACQ_VERT_OFFSET, 'float');
			fwrite(fid, self.WAVE_SOURCE, 'int16');
			if self.USER_TEXT ~= 0
				fwrite(fid, self.TEXT, 'char*1');
			end
			if self.COMM_ORDER
				fwrite(fid, self.DATA_ARRAY_1, 'int16');
			else
				fwrite(fid, self.DATA_ARRAY_1, 'int8');
			end
			fclose(fid);
		end
		%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
		% 恢复波形数据
		function [x,y] = ADCSamples2Voltage(self)
			y = self.VERTICAL_GAIN * self.DATA_ARRAY_1 - self.VERTICAL_OFFSET;
			x = (0:self.WAVE_ARRAY_COUNT-1)'*self.HORIZ_INTERVAL + self.HORIZ_OFFSET;
		end
		% 将浮点数波形数据转换为ADC采样值,会覆盖对象中的数值
		function Voltage2ADCSamples(self,wvfm)
			self.DATA_ARRAY_1 = int16( (wvfm + self.VERTICAL_OFFSET) / self.VERTICAL_GAIN );
		end
		%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
	end
end

下面是一些辅助函数(为每个函数定义一个文件,并将所有文件放至同一目录即可正常运行):

% Read 8Bit signed Byte (not used)
function b=ReadByte(fid, Addr)
	fseek(fid,Addr,'bof');
	b=fread(fid,1,'int8');
end

% Read 16Bit signed Word 
function w=ReadWord(fid, Addr)
	fseek(fid,Addr,'bof');
	w=fread(fid,1,'int16');
end

% Read 32Bit signed Long
function l=ReadLong(fid, Addr)
	fseek(fid,Addr,'bof');
	l=fread(fid,1,'int32');
end

% Read 32Bit IEEE Float
function f=ReadFloat(fid, Addr)
	fseek(fid,Addr,'bof');
	f=fread(fid,1,'float32');
end

% Read 64Bit IEEE Double
function d=ReadDouble(fid, Addr)
	fseek(fid,Addr,'bof');
	d=fread(fid,1,'float64');
end 

% Read timestamp
function t=ReadTimestamp(fid, Addr)
	fseek(fid,Addr,'bof');
	t.Seconds	= fread(fid,1,'float64');
	t.Minutes	= fread(fid,1,'int8');
	t.Hours		= fread(fid,1,'int8');
	t.Days		= fread(fid,1,'int8');
	t.Months	= fread(fid,1,'int8');
	t.Year		= fread(fid,1,'int16');
end

% Read string (up to 16 characters)
function s=ReadString(fid, Addr)
	fseek(fid,Addr,'bof');
	s=fgets(fid,16);
end

% Read string (N characters)
function s=ReadStringN(fid, Addr, n)
	fseek(fid,Addr,'bof');
	s=fgets(fid,n);
end

回写后的文件在力科的 WaveStudio 中的显示效果:

力科(Lecroy)示波器专用波形文件(轨迹文件/trace文件/.trc文件)在MATLAB上的解析与回写_第1张图片

你可能感兴趣的:(测试仪器相关,MATLAB,matlab,开发语言)