在本教程中,您将学习如何在 EAGLE CAD 中编写您的第一个 ULP,以便为您的 CAD 工具添加新功能。
用户语言程序 (ULP) 是 EAGLE CAD 用户的一组扩展程序,用于以自动化方式促进日常工作或完成在没有 ULP 帮助的情况下无法完成的工作。例如,将图像导入 PCB 设计的唯一方法是使用命令 import-bmp ULP。在原理图中自动放置、导出 BOM 和重新编号零件都是 ULP 可以提供帮助的日常工作。
从开发人员的角度来看,EAGLE ULP 与 C 有很多相似之处——实际上,它是一种用于开发这些扩展的类 C 语言。那么为什么它是一门重要的编程语言要学习呢?主要原因是开发自己的 ULP 来帮助自己和其他设计师。此外,ULP 主要由业余爱好者和工程师在空闲时间编写,这通常意味着将来很少进行维护或修订。
就个人而言,我一直在使用 ULP 在 PCB 上产生倒置(又名负)丝印。网络上唯一可用的 ULP, negasilk (链接打开 zip 文件)可以执行我想要的工作,但步骤繁琐。因为这个 ULP 不能直接应用于我的设计,所以我应该在一个新的 PCB 文件中运行它——复制输出,然后将其粘贴回原始设计。了解 ULP 的基础知识帮助我改进了流程,首先让我自己和其他人更容易。
ULP 的第一眼
EAGLE 用户语言可用于访问 EAGLE 数据结构并创建各种输出文件。
EAGLE 中有三种主要的数据结构类型:lbr、sch 和 brd。我认为称它们为对象更明智,因为这些数据结构有两种类型的成员:数据成员和循环成员。
数据成员存储文件名、网格单元和符号名称等数据,而循环成员用于在相同对象类型的元素之间切换,如原理图文件或库对象中零件的循环功能。循环的每个运行实例成员都包含数据成员。
你感到困惑吗?别担心,下面的例子会让事情变得更清楚。示例 ULP 将获取每个部件名称并计算部件数量。基本上,要开发 ULP,您需要一个文本编辑器和一个带有 ulp 扩展名的文本文件。
string Names,result;
int Number=0;
schematic(S)
{
S.parts(P)
{
Number++;
Names+=P.name;
Names+=“,”;
}
sprintf(result,“%d Parts, Names:%s”,Number,Names);
dlgMessageBox(result,“+OK”);
}
运行上一个 ULP 的输出。
原理图(S)语句用于访问原理图的上下文以分别到达其中的所有对象。S,原理图对象的标识符,执行{。.}之间的代码块。原理图对象(UL_SCHEMATIC 对象)有自己的数据和循环成员来访问其他对象(零件、图纸等)。
如我们所见, S.parts(P)是负责为每个部分P制作循环的方法。
UL_SCHEMATIC 对象的数据和循环成员。
在 ULP 手册中,您可以找到有关每个对象及其成员的大量文档。我将在树形图中总结它们。
让我们退后一步;通常,ULP 的结构包括声明变量、定义函数(如果可用),最后是主程序。无需放置 main 函数(void main()),尽管我可以找到一些带有/不带有 main 函数的 ULP。简单地说,函数和变量定义之后的任何语句都被认为是主函数。
让我们修改第一个示例以计算设计有多少张图纸以及每张图纸中有多少零件。
string Names,result;
int Number=0; schematic(S) { S.parts(P) { Number++; Names+=P.name; Names+=","; } sprintf(result,"%d Parts, Names:%s",Number,Names); dlgMessageBox(result,"+OK"); }
让我们在树上遵循这个:
将命令传递给编辑器
有两种方法可以将命令传递给 EAGLE 编辑器。
第一个选项是使用 exit()函数。这是最前沿的方式;它终止 ULP 的执行并将命令传递给编辑器。命令必须是此内置函数的字符串参数。例如, exit(“Move R1”)将使 EAGLE 在终止 ULP 后执行该命令。
第二个选项是创建一个可以稍后执行的脚本文件。虽然脚本(.src 文件)不是我们对本教程的兴趣,但知道脚本包含(非常基本)一组编辑器命令就足够了。
ULP 执行后,会创建脚本文件,您可以使用SCRIPT file_name 运行它;命令或从菜单栏中的脚本图标。一般来说,使用退出函数比较常见。
要查看退出函数的实际作用,我们将编写一个简单的程序,将当前日期作为文本添加到第 21 层中的设计中。
string Names,result;
int Number=0,Sh_Number=0; schematic(S) { S.sheets(Sh) { Sh_Number++; Sh.parts(P) { Number++; Names+=P.name; Names+=","; } sprintf(result,"Sheet #%d with %d Parts, Names:%s",Sh_Number,Number,Names); dlgMessageBox(result,"+OK"); Number=0; Names=""; } }
库和原理图是整数常量,如果当前编辑器窗口是库或原理图则返回 1,否则返回 0。
dlgMessageBox("! Open this ULP from PCB Editor","+OK");
这将带来一个带有消息的弹出窗口。我们将简要解释 ULP 中的对话框。
exit(-1);
将终止 ULP(错误情况)。
string Months[]= {"Jan","Feb","Mar","Apr","May","June","July","Aug","Sept","Oct","Nov","Dec"}; int t = time(); string CMD,text;
这是变量声明。
time()函数是一个内置函数,它以数字格式返回系统时间。
CMD = "GRID INCH;LAYER 21;"; CMD += "CHANGE SIZE 0.066;"; CMD += "CHANGE RATIO 15%;"; CMD += "CHANGE FONT VECTOR;";
这些命令用于将网格单位设置为英寸并更改文本大小、比例和字体类型。您必须用分号分隔命令。
sprintf(text,"TEXT '%d %s %d'",t2day(t),Months[t2month(t)],t2year(t));
sprintf函数用于格式化数据字符串。
exit(CMD);
exit函数会将 CMD 字符串传递给编辑器并终止 ULP 执行。
EAGLE ULP 中的对话框
ULP 为作为用户语言程序前端的对话框提供了一组内置函数。
dlgDialog是任何其他对话框对象的基本容器。它执行由括号{..}之间的块定义的对话框。
作为介绍,我们将构建一个简单的对话框,该对话框由一个带有“Hello”标题和“Ok”按钮的窗口组成。
int Result = dlgDialog("Hello") { dlgLabel("Hello world"); dlgPushButton("OK") { dlgMessageBox("! YOU PRESSED OK!","OK"); dlgAccept(); } };
dlgDialog有一个字符串参数来定义对话框标题。
dlgPushButton添加一个名为 OK 的按钮,而 dlgMessageBox显示一个带有 OK 按钮的简单消息框。最后,退出对话框dlgAccept函数接受对话框内容(这里没有内容)并关闭它。
运行上一个 ULP 的输出。
注意:对话框中的文本中使用了一些特殊字符,如&、+和-来完成特定工作。
‘&’指定热键以使焦点转到该对象/标签。
‘+’当您按 Enter 时选择按钮。
‘-’ 当您按下 Esc 时使按钮被选中。
例子:
int result = dlgMessageBox("Try To Press:","+Enter","&O","-Esc");
switch(result) { case 0: dlgMessageBox("YOU PRESSED OK!"); break; case 1: dlgMessageBox("YOU PRESSED O!"); break; case 2: dlgMessageBox("YOU PRESSED Esc!"); break; }
运行上一个 ULP 的输出。
其他对话框功能用于用户输入,如列表视图、单选按钮和数据字段输入。
阅读其用法说明后,您可以轻松使用任何其他对话框功能。同时,在 ULP 手册中还可以找到许多同类别的其他功能。
dlgListView
dlgListView使用给定数组的内容定义了一个多列列表视图。它需要三个主要参数:第一个参数是定义列表视图标题的字符串参数,第二个参数是要显示为列表项的字符串数组,第三个参数是反映所选索引的整数数组中的 listview 元素。dlgListView可以包含在您双击元素时执行的代码块。
dlgRadioButton
dlgRadioButton定义一个带有给定文本的单选按钮。它有两个参数:第一个参数是使用字符串来定义按钮旁边的文本,第二个参数是一个整数,它反映了从使用 dlgGroup函数定义的组中选择的单选按钮。同一组内的所有单选按钮必须使用相同的选择变量。
dlgString编辑
dlgStringEdit定义了一个字符串输入字段。它有一个字符串参数来包含用户输入的值。注意:它的工作方式与 dlgRealEdit 和 dlgIntEdit 的工作方式相同。
让我们将上述信息付诸实践。在下面的示例中,我们将检查dlgListView、dlgRadioButton和dlgStringEdit的用法。
string Items[] = { "Item One", "Item Two", "Item Three" }, Item ;
int L_Selected = 0,R_Selected=0; // initially selects "One" int Result = dlgDialog("Items") { dlgLabel("Choose One:"); dlgHBoxLayout { dlgListView("Name\tDescription", Items, L_Selected) { dlgMessageBox("You have selected " + Items[L_Selected]); } dlgGroup("Items") { dlgRadioButton("&One", R_Selected); dlgRadioButton("&Two", R_Selected) {dlgMessageBox("You have selected " + Items[L_Selected]);} dlgRadioButton("&Three", R_Selected); } } dlgVBoxLayout { dlgLabel("Enter &Item"); dlgStringEdit(Item); dlgPushButton("OK") { dlgMessageBox("You have selected from ListView " + Items[L_Selected] + ". From RadioButton " + Items[R_Selected] + ", and entered "+ Item); dlgAccept(); } } };
运行上一个 ULP 的输出。
dlgListView(“Name\tDescription”, Items, L_Selected)
如上图所示,列表视图具有“名称”和“描述”标题,并显示项目数组的元素。所选项目索引将存储在L_Selected中。
如果您在列表的任何项目上单击两次——代码块将执行。
dlgGroup("Items")
{ dlgRadioButton("&One", R_Selected); dlgRadioButton("&Two", R_Selected) {dlgMessageBox("You have selected " + Items[L_Selected]);} dlgRadioButton("&Three", R_Selected); }
单选按钮必须使用dlgGroup组合在一起,并共享相同的选择变量R_Selected。如果单击单选按钮“Two”,您将看到一条消息,这是单选按钮如何执行代码的示例。
注意: dlgHBoxLayout和dlgVBoxLayout分别用于水平和垂直排列布局。
锻炼
作为一个小练习,您可以编写一个简单的 ULP,根据其大小使用框架库中的可用框架将适当的框架添加到您的示意图中。我为您测量了框架,以便在本练习中使用它。您需要扫描图纸以了解其尺寸。
以 Mil 为单位的尺寸
要解决此练习,您将使用以下技能:
使用数据和循环成员获取计算图纸尺寸所需的数据的能力。
使用 EAGLE 命令将设备添加到设计中的能力。
在 ULP 中使用对话框的能力。
注意:只是为了好玩,我在菜单栏上添加了一个图标。您可以通过在 SCH: 部分中将以下行添加到位于安装目录中 src 文件夹中的 eagle.scr 文件中来做到这一点。
‘[FrameIt.png] Add Frame : Run AddFrame.ulp;’\
全部0条评论
快来发表一下你的评论吧 !