2026-08-03
硬件-PCB设计
0

七、PPM-XTAL Calculator PPM-XTAL 计算器

功能:在 Hz(绝对频率偏差) 和 PPM(相对频率精度) 之间换算,并估算外部负载电容对频率的影响。

估算匹配电容(XTAL Capacitor Value)

这个功能解决的是:“晶振规格书说负载电容是10pF,那我该选多大的外接电容?”

  • 原理:晶振的振荡频率会受外部负载电容影响,如果匹配电容不准,频率就会偏。外接的C1和C2通常串联后(再加上PCB杂散电容)共同构成晶振看到的负载电容。

  • 结果解释:软件会给出两种参考值:

    • Based on C1-C2:严格按串联公式计算的值。
    • Rule of Thumb:工程经验值(通常比理论值稍大,以补偿PCB走线和引脚的寄生电容)。
  • Load Capacitance 负载电容: 输入晶体 (XTAL) 的负载电容,这通常在元件数据手册中找到,单位为皮法。

  • Stray Capacitance 杂散电容: 输入从 PCB 走线到/来自晶体 (XTAL) 的焊盘/导体上看到的估计杂散电容。

  • C1 – C2 Value C1 – C2 值: 如果您已经选择了 C1 和 C2 的值,请在此输入。

  • Based on C1–C2: 这是一个基于负载电容、杂散电容以及输入的 C1-C2 值计算出的值。这个值应该与元件数据手册中给出的负载电容相匹配,如果不匹配,则应调整 C1 和 C2 直到匹配为止。

  • Rule of Thumb 经验值: 如果您尚未选择 C1 和 C2 的值,这个“经验值”可以作为一个起点。它仅基于负载电容和杂散电容的输入。这输出值就是软件建议你在PCB上实际放置的C1和C2电容值。

晶振的负载电容计算公式为:CL = (C1 × C2) / (C1 + C2) + Cstray(Cstray为PCB寄生电容,通常约2-5pF)。

  • 如果C1=C2=14pF,串联后为7pF。
  • 加上寄生电容(约3pF),正好接近10pF。
  • 这就是为什么软件给出14pF这个经验值——它是为了补偿寄生电容。

PPM to Hertz: 根据元件的 PPM 值计算晶体振荡器的频率变化。它还会根据给定的 PPM 和中心频率,返回元件应振荡的最小和最大频率。这有助于你评估对通信协议(如USB 2.0要求±250PPM以内)是否满足。

Hertz to PPM: 此功能与 PPM to Hertz 计算器的工作方式相反。输入振荡器的中心频率及其漂移到的最大频率,即可确定 PPM 值。

2026-08-01
硬件-PCB设计
0

一、Program Options 程序选项

IPC Version IPC 版本:
用户可以选择用于当前计算的 IPC 版本。Saturn建议在大多数应用中使用不带修正因子的 IPC-2152。当用户因间距限制需要尽可能减小导体宽度时,可以使用修正因子。

Copper Weight 铜箔重量:

Enter Copper Weight Manually 手动输入铜箔重量:
用户可以选择手动输入基础铜箔重量和电镀厚度的选项。

Conductor Etch Factor 导体蚀刻因子:
理想的 PCB 导体具有矩形横截面,但实际上,由于蚀刻过程,真实的横截面更接近梯形。这会轻微改变导体的横截面积,从而影响载流能力。导体蚀刻因子有助于用更真实的横截面积来模拟导体。典型的蚀刻因子是 1:1,意味着导体每侧蚀刻的距离等于导体的高度。因此,如果我们认为导体的底边等于 H1,顶边等于 H2,那么 H2 = (H1-2T),其中 T 是导体的厚度。也提供 2:1 的蚀刻因子选项,其比率是 1:1 的一半。如果您不想要此选项,则选择“无”作为蚀刻因子。

物理含义:蚀刻因子 = 导体厚度 / 侧壁被蚀刻掉的宽度(单侧)。这个比值越大,说明侧壁侵蚀越少,导线形状越接近矩形;比值越小,则“梯形”效应越明显。

Disable Via Height 禁用过孔高度:
根据 IPC-2152 规范,过孔的高度会影响其散热能力。如果需要,可以通过勾选此框来禁用此计算。

Aspect ratio Limit 纵横比限制:
您可以为通孔和微孔设置 X:1 格式的纵横比。如果违反此规则,纵横比将在“过孔属性”选项卡的信息区域变为红色。

Color Theme 颜色主题:
用户可以从 PCB Toolkit 的五个预装颜色主题中选择一个。

Metric Options 公制选项:

Use Microns 使用微米:
用户可以选择在公制模式下使用微米代替毫米。

2026-08-01
CSharp编程
0

一:数组说明

  数组是一个存储相同类型元素的固定大小的顺序集合。数组是用来存储数据的集合,通常认为数组是一个同一类型变量的集合。

声明数组变量并不是声明 number0、number1、...、number99 一个个单独的变量,而是声明一个就像 numbers 这样的变量,然后使用 numbers[0]、numbers[1]、...、numbers[99] 来表示一个个单独的变量。数组中某个指定的元素是通过索引来访问的。

所有的数组都是由连续的内存位置组成的。最低的地址对应第一个元素,最高的地址对应最后一个元素。

二:声明数组

在 C# 中声明一个数组,您可以使用下面的语法:

csharp
datatype[] arrayName;

其中,

  • datatype 用于指定被存储在数组中的元素的类型。
  • [ ] 指定数组的秩(维度)。秩指定数组的大小。
  • arrayName 指定数组的名称。

例如:

csharp
double[] balance;

三:初始化数组

声明一个数组不会在内存中初始化数组。当初始化数组变量时,您可以赋值给数组。数组是一个引用类型,所以您需要使用 new 关键字来创建数组的实例。

例如:

csharp
double[] balance = new double[10];

四:赋值给数组

您可以通过使用索引号赋值给一个单独的数组元素,比如:

csharp
double[] balance = new double[10]; balance[0] = 4500.0;
csharp
//您可以在声明数组的同时给数组赋值,比如: double[] balance = { 2340.0, 4523.69, 3421.0}; //您也可以创建并初始化一个数组,比如: int [] marks = new int[5] { 99, 98, 92, 97, 95}; //在上述情况下,你也可以省略数组的大小,比如: int [] marks = new int[] { 99, 98, 92, 97, 95}; //您也可以赋值一个数组变量到另一个目标数组变量中。在这种情况下,目标和源会指向相同的内存位置: int [] marks = new int[] { 99, 98, 92, 97, 95}; int[] score = marks;

当您创建一个数组时,C# 编译器会根据数组类型隐式初始化每个数组元素为一个默认值。例如,int 数组的所有元素都会被初始化为 0。

2026-08-01
CSharp编程
0

问:int Calculate(int a, int b, Func<int, int, int> operation) { return operation(a, b); } 以上代码里的func是什么作用?

Func<int, int, int> 在这里的作用是:定义了一个能接收两个 int 参数、并返回一个 int 结果的委托类型**,作为方法的“算法参数”。

简单理解:它就是一个可以让你“把计算方法塞进方法里”的参数。


一、拆解 Func 的含义

Func<int, int, int> 中:

  • 最后一个 int:代表方法的返回值类型
  • 前面的 int, int:代表方法的两个参数类型

所以这个委托可以指向任何符合以下签名的方法:

csharp
int 任意方法名(int x, int y)

生活类比:
这就像在淘宝买一个“智能炒菜机”,它有一个“烹饪模式”插槽(Func),这个插槽要求:

  • 插入的芯片必须有两个输入(食材1、食材2)
  • 芯片必须输出一个结果(成品菜)

你不能把“只听音乐”的芯片插进去(参数不对),也不能把输出是“字符串”的芯片插进去(返回类型不对)。


二、在代码中的实际作用

Calculate 方法本身只负责执行,但不关心具体怎么计算。计算逻辑通过 operation 参数从外部传入。

使用示例:

csharp
// 传入加法 int sum = Calculate(5, 3, (a, b) => a + b); // 返回 8 // 传入减法 int diff = Calculate(5, 3, (a, b) => a - b); // 返回 2 // 传入乘法 int product = Calculate(5, 3, (a, b) => a * b); // 返回 15

如果没有 Func,你只能写三个方法:

csharp
int Add(int a, int b) => a + b; int Subtract(int a, int b) => a - b; int Multiply(int a, int b) => a * b;

调用时写死方法名,无法动态切换算法。

2026-08-01
CSharp编程
0

一、抽象类是什么?

想象你要设计一个**“动物”**的模板,但“动物”本身不是一个具体的生物,比如你不能直接说“我养了一只动物”。
但你知道所有动物都有一些共同的行为(比如呼吸、移动),而具体行为因动物不同而不同(比如鱼游、鸟飞)。
抽象类就是用来定义这种“通用模板”的工具,它规定了子类必须实现的功能,同时自己可以包含一些默认实现。


二、通俗解释

  1. 抽象类像“蓝图”

    • 比如手机的“设计图纸”,图纸本身不能打电话,但规定了手机必须有的功能(打电话、充电)。

    • 具体手机(比如iPhone、华为)继承这个图纸,自己实现具体细节。

  2. 不能被直接使用

    • 就像你不能直接住进“房子的设计图”,必须根据图纸盖出具体的房子。
  3. 强制子类遵守规则

    • 比如抽象类规定“所有动物必须会移动”,子类(鱼、鸟)必须实现如何移动,否则编译报错。

三、代码示例

csharp
// 抽象类:动物 public abstract class Animal { // 抽象方法:子类必须实现“如何移动” public abstract void Move(); // 普通方法:所有动物共享的“呼吸”功能 public void Breathe() { Console.WriteLine("动物在呼吸..."); } } // 具体类:鱼 public class Fish : Animal { public override void Move() { Console.WriteLine("鱼在游泳!"); } } // 具体类:鸟 public class Bird : Animal { public override void Move() { Console.WriteLine("鸟在飞翔!"); } }

使用:

csharp
Animal fish = new Fish(); fish.Breathe(); // 输出:动物在呼吸... fish.Move(); // 输出:鱼在游泳! Animal bird = new Bird(); bird.Breathe(); // 输出:动物在呼吸... bird.Move(); // 输出:鸟在飞翔!