//时间:20200610 //作者:郝爽 //功能:测量线程 using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using SmartSEMControl; using MeasureData; namespace MeasureThread { public enum FMode { Manual, Auto } public class Measure { //全局只有一个fatorySEM static FactoryHardware factorySEM = FactoryHardware.Instance; ISEMControl iSEM = factorySEM.ISEM; //测量文件 private MeasureFile m_measureFile; public MeasureFile MeasureFile { get { return this.m_measureFile; } set { this.m_measureFile = value; } } //测量的切割孔 private List m_cutHoles; public List cutHoles { get { return this.m_cutHoles; } set { this.m_cutHoles = value; } } //工作文件夹 private string m_WorkingFolder; public string WorkingFolder { get { return this.m_WorkingFolder; } set { this.m_WorkingFolder = value; } } //线程状态 private ThreadStatus m_ThreadStatus; public ThreadStatus TStatus { get { return this.m_ThreadStatus; } set { this.m_ThreadStatus = value; } } //对焦模式 private FMode m_bFocusMode; public FMode FocusMode { get { return this.m_bFocusMode; } set { this.m_bFocusMode = FocusMode; } } //// SEM data general //CSEMDataGnrPtr m_pSEMDataGnr; ////MeasureAppFormName //CString m_strMAppFormName; //HWND m_hWnd; //构造函数 public Measure() { Init(); } public void Init() { FocusMode = FMode.Manual; } //初始化测量业务, 读测量文件,判断是否有可测试的切孔 public bool InitMeas(MeasureFile a_measureFile) { m_measureFile = a_measureFile; List listHoles = m_measureFile.ListCutHole; foreach (CutHole h in listHoles ) { if (h.SWITCH == true) { m_cutHoles.Add(h); } } if(m_cutHoles.Count == 0) return false; return true; } //测量流程 public void DoMeasure() { //创建线程的测量状态的更新 this.TStatus.ComputeTime(THREAD_TIME_TYPE.START); //将这个开始时间传递给主界面 //检查硬件连接是否正常 if (!ConnectHardware()) { return; } //设置工作文件夹 if (!SetWorkingFolderStr()) { return; } //第一个孔的测试 FirstHole(); //非第一个孔的测试 OtherHole(); } //检查硬件连接是否正常 public bool ConnectHardware() { //返回硬件的连接状态 return iSEM.ConnectStatus(); } //设置工作文件夹 public bool SetWorkingFolderStr() { //获取工作文件路径 string pathName = m_measureFile.FilePath; //判断工作文件路径是否为空或无效 if (string.IsNullOrEmpty(pathName)) { return false; } //文件未保存 else if (pathName.CompareTo(MeasureFile.UNTITLED_FILE_NAME) == 0) { return false; } //获取工作文件所在文件夹 string folder = System.IO.Path.GetDirectoryName(pathName); if (string.IsNullOrEmpty(folder)) { return false; } WorkingFolder += @"\\"; return false; } //第一个孔的测试过程 public void FirstHole() { MeasureData.CutHole firstHole = m_cutHoles[0]; //12.根据样品类型参数确定是否需要PT沉积,控制PT针插入 if (firstHole.PT == PTType.Have) { if (!iSEM.InsertPT()) { return; } } //13.自动定位切割 { //1.控制SEM放大600X if (!iSEM.SetMagnification(600)) { return; } //2.控制SEM自动对焦、亮度、对比度 if (FocusMode == FMode.Manual) { //弹出手动对焦的窗口 } else if (FocusMode == FMode.Auto) { //调用自动对焦模块 } else { return; } //3.设置SEM进行角度补偿54度 //4.控制SEM拍照 //5.保存照片 { //1. 创建目录 //2. 设置图片名称 //3. 保存图片1 } //6.设置FIB拍照参数——扫描时间、束流等 //7.控制FIB自动亮度、对比度 //8.控制FIB拍照 //9.保存照片 { //1. 设置图片名称 //2. 保存图片2 } //10.将照片传给客户,返回梯形位置坐标,及样品类型参数(是否需要PT沉积,PT坐标位置,PT宽度、PT高度、梯形上、下边及深度、扫描时间、束流、样品放大倍数1、样品放大倍数2等切割参数) //11.自动工具样品类型参数确定是否需要PT沉积 { //1. 根据客户PT沉积坐标控制FIB调整到中心位置 //2. 验证移动准确性:获取当前FIB中心位置坐标,与客户返回坐标对比,验证是否一定正确 //3. 根据坐标进行PT沉积 } //12.根据梯形坐标控制FIB调整到中心位置 //13.验证移动准确性:获取当前FIB中心位置坐标,与客户返回坐标对比,验证是否移动正确 //14.保存样品1第1号孔中心位置6轴坐标1 XYZMRT到数据库,保存客户返回值信息到数据库 } //14.自动控制FIB切割 { //1.根据参数设置FIB草率时间(使图清晰),设置梯形上下边及深度、设置束流 //2.控制FIB进行切割 //3.控制FIB拍照600X //4.保存图片 { //1.设置图片名称 //2.保存图片3 } //5.验证切割准确性:与切割前对比,如果对比误差大,则停止自动执行,进行报警 //6.设置FIB解冻:先读取状态,如果冻结状态则进行解冻 } //15.根据样品类型决定是否撤出PT针 //16.自动调整SEM找到切割位置 { //1.控制SEM放大到300倍 //2.控制SEM自动对焦、亮度、对比度-接口 //3.控制SEM拍照 //4.将照片传给客户,获取偏移坐标,以及偏移角度 //5.根据坐标控制SEM移动到切孔位置,居中 //6.验证移动准确性:获取当前SEM中心位置坐标,与客户返回坐标对比,验证是否移动正确 } //17.自动控制SEM拍截面照 { //1.控制SEM放大到指定参数大小范围,6000x //2.控制SEM自动对焦、消像散、亮度、对比度 //3.设置SEM角度补偿cos36度 //4.控制SEM拍照 //5.保存照片4 //6.将照片传给客户,获取偏移坐标 //7.根据坐标控制SEM移动到分析位置 //8.验证移动准确性:获取当前SEM中心位置坐标,与客户返回坐标对比,验证是否移动正确 //9.控制SEM平行校正,并记录校正前初始值 //10.控制SEM放大到指定参数大小范围 //11.控制SEM自动对焦、消像散、亮度、对比度 //12.控制SEM对分析位置拍照 //13.保存照片 //14.控制SEM取消电子束校正,回到初始值 } //18.自动层高分析 { //1.获取SEM Pixel Size给客户传入参数 //2.将照片传给客户,客户进行层高分析(返回分析后的图像、相对坐标、分辨率、各层编号以及各层对应的层高数据),如果客户自行出分析报告则无需返回数据 } //19.自动能谱分析 { //1. 确定能谱位置 //2. 控制牛津打能谱 //3. 能谱分析——面扫+线扫描 } } //非第一个孔的测试过程 public void OtherHole() { } //角度补偿 public bool TiltCorrection(float a_fAngle) { bool bTilt = false; float fOldTilt = iSEM.GetTiltCorrection(); if (fOldTilt == float.NaN) { return false; } else if (fOldTilt == 1) { bTilt = true; } else if (fOldTilt == 0) { bTilt = false; } if (!iSEM.SetTiltCorrectionOn()) { return false; } if (!iSEM.SetTiltAngle(a_fAngle)) { return false; } //恢复原始角度 if (bTilt) { if (!iSEM.SetTiltCorrectionOn()) { return; } } else { if (!iSEM.SetTiltCorrectionOff()) { return; } } return false; } } }