文号
947095
阅读
5384
回复
5
收藏
1
在LTSpice中仿真MOS管
2025/09/28
原创
IP:上海

我一直认为 Spice中的非线性元件 BJT/MOS/IGBT等的设计思路并不合理

如果仔细看LTSpice中MOS的模型 Level 1-3已经有不少一般工程师都不可能获取 甚至理解困难 但是又比较重要的工艺参数 至于其他更复杂的模型 LTSpice甚至连参数列表都不提供了 一副"反正你们不会用"的态度 如果去参考HSpice的手册("Chapter 16, Star-Hspice Manual, Release 1998.2") 会发现 从level 1 到level 50 这些高级模型中的参数 越来越抽象 有些只怕连生产厂家都未必去设计或者测量

这是个问题 专注于研究和设计MOS工艺的 应该不会用Spice来仿真 而Spice的真正用户应该是普通电路设计工程师 手上的资源不过是MOS厂提供的宏观参数 却找不到一个真正面向电路设计实践的模型 很少遇到这样的工程师 能够"哎呀 我知道 这是0.5um制程的 电子迁移速率选...."

尽管有类似"XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"这种爱好者编写 从厂家资料来转换成VDMOS参数的小工具 但是不够用 仍有必要去研究一下 在LTSpice仿真一般MOS管的最佳实践方法


前提:

首先 无论哪种MOS 最关键的前提的参数是沟道长和宽 这可以在声明元件时候提供(L, W) 也可以在声明模型中提供(L, W) 或者在.option里面指定(defl, defw) 但是 在实践中建议不设置 不指定 使用缺省值 100um 我们应专注于宏观参数 不去想办法寻找微观参数

其次 模型仅采用缺省的 level 1 其他看起来更高级的模型 于事无补 只会增加复杂度


基本特征:

MOS的特征曲线 包括可变电阻区和恒流区(当Vds>Vgs-Vth) 主要掌握下面三个参数即可 (仅在Level 1-2可用 level 12,44,55也可用 但是有区别 尤其是Lambda参数区别很大 下面只用level 1 或 VDMOS模型 不再赘述)


Vto : 栅极开启电压 一般厂家都会提供 也可用从Ids-Vgs曲线读取 读取曲线开始仰头的Vgs点

Kp: 跨导 建议从Ids-Vgs或者Ids-Vds曲线读取恒流区Ids对(Vgs-Vth)2的变化率, 再乘于2

Lambda: 恒流区变化率 建议从Ids-Vds曲线恒流区读取 读取曲线在Vds增加1V时 Ids增加的百分比


他们的来龙去脉 可以参考下面的公式 (Weff和Leff缺省均100um) (Level 1和VDMOS通用) Lambda对于不考虑工作在恒流区的 比如开关应用 也可以忽略

image.png

image.png

举例说明 比如Toshiba的TPM1R908QM 可以从官网下载LTSPICE库 它也有符合一般情况的说明手册 其Ids-Vgs Ids-Vds曲线 如下

image.png

我们可以从曲线看到 Ids大概在Vgs 3.6V左右开启 所以 Vto=3.6 在4.6V时候 Ids接近90A 所以Kp=180 在Vds增加1V时候 曲线大概上扬5% 所以Lambda=0.05 套入LTSpice 得下面结果

image.png

这样得结果 已经非常接近手册了 足够一般设计仿真使用 如果再精细点 可以使用多个恒流区的点 自己结合二阶方程求解和最小二乘法 算出更精确的3个系数 或者 使用Excel的规划求解功能(可以求解多个自变量 使得总平方误差和最小) 套用level 1的恒流区Ids公式解算出来

image.png

image.png

也可以使用scipy进行规划求解 (结果和excel接近却又有区别 有趣)

>>> import numpy as np

>>> from scipy.optimize import minimize

>>> vgs_vds_ids=((4.1,1,18),(4.1,1.5,19),(4.5,1,72),(4.5,1.5,74),(4.3,1,38.5),(4.3,1.5,40))

>>> vto_kp_lambda=np.array([0., 0., 0.])

>>> solution = minimize(lambda x:sum(map(lambda t:(x[1]/2*(1+x[2]*t[1])*((t[0]-x[0])**2)-t[2])**2, vgs_vds_ids)), vto_kp_lambda, bounds=((0, None),(0,None),(0,None)))

>>> solution.x

array([3.71144745e+00, 2.15308308e+02, 6.71698257e-02])

对于关心Rds(on)的 按理特征曲线已经包含了需要的结果 换一种仿真和显示方式即可

image.png

在Vgs=6V Vds=0.1V时候 Rds(ON)=2mΩ 和手册一致 一般无需考虑Rs Rd参数 除非在特殊情况下 需要考虑加上Rs Rd参数串联 再联合规划求解Vto Kp Lambda


结电容(静态, 或者厂商没有提供动态特征):

结电容以及因此带来的交流小信号特征 也是MOS管仿真重要部分 其仿真原理可参考下图

image.png

对于MOS Level 1 可以用下面的参数 设置静态结电容参数

栅-源极间电容: 使用Cgso 因为缺省沟道宽度100um 所以可以设为 Cgs*1e4

栅-漏极间电容: 使用 Cgdo 因为缺省沟道宽度100um 所以可以设为 Cgd*1e4

漏-源极间电容 : 虽然bulk和源极实际相连 Cbd似乎是个合适的选择 但是它是动态的 只适合0偏置情况使用 因此这里建议 粗暴的直接查图表取值 外部并联一个确定的电容进行仿真


对于VDMOS

栅-源极间电容: 使用Cgs 不用换算直接指定

栅-漏极间电容: 使用Cgdmin Cgdmax 不用换算 直接同时指定同一个值(因为静态)

漏-源极间电容 : 虽然bulk和源极实际相连 Cjo似乎是个合适的选择 但是它是动态的 只适合0偏置情况使用 因此这里建议 粗暴的直接查图表取值 外部并联一个电容进行仿真


实际上 如果直流特征一致 交流特征一致 可以认为VDMOS和MOS没有区别 指定参数更方便

另外 还有一种方法 就是均在外部直接并联上需要考虑的电容 而MOS/VDMOS 保持缺省均为0的电容参数 在仿真结果上 这样的方法并无二至 而且更加直观


这里还有一件重要的事 就是厂商提供的电容数据 如Ciss, Coss, Crss 大多数是分布参数 而非实际的Cgs Cgd Cds 等独立参数 根据厂商测量环境和标准不同 他们有一定但是根据厂商可能不同的换算关系 比如Toshiba的声明是

image.png

需要反换算一下:

Cgd = Crss

Cgs = Ciss - Crss

Cds = Coss - Crss


这里需要提醒一下 VDMOSTool对Coss的定义 是在栅极开放而不是短接源极的环境下的 与Toshiba的定义不同 所以不能直接套用

image.png


结电容(动态):

需要仿真动态结电容 一般是MOS做开关使用 需要仿真开关曲线 或者小信号时确定工作点

但是使用动态的结电容是需要复杂步骤的 即使是厂商发布的仿真库 也未必会足够精细 比如TPM1R908QM厂商提供的仿真库文件 确实体现了Cgs-Vds的变化 但是Cds却是恒定的 其实Cds实际变化要更大 在开关电源计算效率和功耗时候 Cds挺重要的

2b.png

需要指出的是 LTSPICE在结电容方面 是比较薄弱的 没有CAPOP之类的设置 类似 Cgso Cgdo Cgs等参数 也都是静态的 动态的变化主要来自 Cbd/Cjo 和 VDMOS模型的Cgd 所以需要考虑动态结电容 就使用VDMOS模型


栅极-源极电容: 基本上这个电容没有多少动态特征 大多数手册上(尤其小功率MOS) Ciss都接近一条直线 即使减去Crss 变化也不大 所以大可以使用静态参数Cgso(注意换算Cgs*1e4)或者Cgs(VDMOS模型) 如果一定要精确衡量 必须使用外接非线性电容法


栅极-漏极电容: 小信号电路做工作点仿真时候 推荐使用外接非线性电容法 比如下面这个仿真 就和手册数据比较一致

image.png

但是 开关型MOS 通常需要着重考虑开关交越的情况 既Vds和Vgs互有大小的情况 还是推荐使用VDMOS模型 使用Cgdmin Cgdmax两个参数

image.png

在VDMOStool中 是这样统一推导Cgdmin和Cgdmax的

Cgdmax=Crssmax+(Crssmax-Crssmin)/ATAN(10000)

Cdgmin=Crssmin

解释一下这个算法 这里的Crssmax 实则就是Vgd=Vgs=Vds=0处的Crss 因为一般Crss-Vds图表在Vds=0处最大(几乎没有图表提供Vds为负时候的曲线) 这个点也就是B和D的值 既B=D=Crssmax

因为曲线需要在Vgd=0处连续且平滑 所以A=C

且因为C*atan(左边很远一个点比如-10000)+D=Crssmin 所以C=(Crssmin-D)/atan(-10000)=(D-Crssmin)/atan(10000)=(Crssmax-Crssmin)/atan(10000)

所以Cgdmax=A*tanh(右边很远一个点)+B=A*1+B=C+B=Crssmax+(Crssmax-Crssmin)/atan(10000)

atan(10000)干脆直接用pi/2算了 于是也完全可以这样

Cgdmax=1.6366*Crssmax-0.6366*Crssmin

但是需要注意 Crssmin这个值 并不能简单用图表上最低的点 如TPM1R908QM的图表 在Vds=80V处 Crss截至 但是明显刚过拐点 远不到收敛处 这里需要自己想象并延伸Crss曲线 找到收敛水平线

或者使用另一个算法:

取两个关键点 (Vgd1, Crss1)(Vgd2, Crss2) 注意到A=C B=D a=1 (VDMOS模型缺省值 可设它值 但不建议改) 然后联立解方程 求出A C 和B D 然后使用C*(-pi/2)+D和A+B算出Cgdmin和Cgdmax

在一般情况下 图表的Vgs=0 用-Vds来取代Vgd 然后取Vds=0的Crss0和Vds=Vds1的Crss1 推导过程略过 结果是:

Cgdmin=Crss0-(Crss0-Crss1)/atan(Vds1)*(pi/2)

Cgdmax=Crss0+(Crss0-Crss1)/atan(Vds1)


看图表 在Vgs=0 Vds=50V处 Crss=Cgd=40pF 而在Vgs=Vds=0处 Crss=1300pF 算出:

Cdgmin=1300p-(1300p-40p)/atan(50)*pi/2=23.7p

Cgdmax=1300p+(1300p-40p)/atan(50)=2112.5p

仿真结果如下

image.png

遗憾的是 在Vds=0 和 Vds=50V处 和手册数据一致 在其他地方却相差较大 比如Vds=10V处 仿真得到105pF 手册上的数据却是接近400pF

因为无论采用何种数学规划方式 以多点拟合整体误差最小也好 以关键点一致性为标准也好 以最大化电容为目的从上方逼近也好 都无法改变这只是个2参数模型的拟合 但这也是唯一一个LTSpice可用 同时考虑了Vgs和Vds的模型 一个更好的模型可能就是一篇完整正式论文的工作量了

对比动态和静态Cgd对米勒平台的仿真 深蓝和红色曲线是动态Cgd的效果 还算勉强贴合厂商的数据集 而静态的 偏离手册较远image.png

image.png

漏极-源极电容:

无论使用Cbd还是CJ0 都有动态的效果 它们都是通过仿真二极管反向结电容来实现的 对于普通二极管 是有经典的偏宏观模型 :

Cds = Cbd/(1+Vds/Pb)m 或等效VDMOS模型 Cds = Cjo/(1+Vds/Vj)m

其中Pb和Vj参数 是位垒电压 俗称正向压降 MOS和VDMOS模型中 缺省值分别是0.8V和1V m是浓度掺杂分布的梯度系数 (Body diode grading coefficient) 默认值是1

Cjo = Cbd = Coss - Crss | Vds=0时

Vj = Pb = 正向压降

从Coss--Crss-Vds 曲线上取一个点 (Coss1, Crss1, Vds1) 则

m = ln(Cjo/(Coss1-Crss1))/ln(1+Vds1/Vj)

比如TPM1R908QM 手册给出正向压降1.2V 且Vds=0V时 Cds=Coss-Crss=6000p-1300p=4700p Vds=80V时 Cds=Coss-Crss=950p-32p=918p 可以求得 Cjo=4700p Vj=1.2 m=0.387 仿真下来与手册数据还算接近

image.png

如果需要更精确的仿真 同样 漏-源极电容也可以通过外接非线性电容法来实现


开关时间参数:

image.png

这些参数 受诸如沟道长宽比 电子迁移率等微观因素影响太深 但是在功耗设计和安全设计中 这些参数又比较重要 如果要一一模拟 恐怕只能设计一个附加的传输模型 使用delay()函数一一配合 除此之外 就是使用Rg配合前面设计的各种电容 用充放电来进行一个大致的模拟

一个参数当然很难模拟4个时间 但是往往关键的时间并不多 比如反激式开关电源 主要耗损发生在关断时间上 那么 Tf就比较重要

虽然也可能通过推导得到Rg 但是还是建议搭建厂商手册提供的测试环境 通过调整Rg得到合适的效果 然后这个Rg就可以用到正式的仿真中 比如对于TPM1R908QM Rg为15Ω时候 Tf比较接近手册数值 虽然此时其他参数难免或大或小相差较大 比如Tr=25ns 而手册是50ns Toff是200ns 而手册是130ns

image.png

此外 如果是同步整流等情况 需要考虑伴生二极管的恢复时间 可以使用Tt参数 但是该参数的具体设置 我现在也没有具体资料 也是建议通过简单仿真对比手册数据获取


此外 还有噪声仿真等 感觉在较长阶段都没有必要考虑 就先不研究了

[ 修改于1年1个月前 - 2025/09/28 18:44:17 ]
m24h作者
1年1个月前修改于 1年1个月前IP:上海
947108
1楼

作为一个补充 我这里说一下多次加黑提及 但未给出实现步骤的“外接非线性电容法”

实际上 在稍大规模的仿真中 是建议直接使用MOS和VD模型 去接受其中的不完美

我仅仅在“工作点仿真”中 给出了受控于参数{Vds} 而不是状态V(Drain)的一个用table()函数实现的一个非线性电容的例子

真要实现非线性电容是很复杂的事 绝非直接利用Q=xC(y)就可以的 实际上 为了保证电荷的连续性和守恒性 Q实际是C(y)对x的积分 需要通过y和x的关系 自己推导出公式 其中还要考虑一大堆诸如计算精度 收敛问题 连续且多阶导数连续问题 有些函数比如idt/ddt在AC仿真可能不可用 等等诸多复杂的问题

或者做出子电路 少用自定义公式 多利用现有模型 去搭建出效果

一般来说 在需要时候 通过外接个精心设计的公式 弥补一个两个关键点 就已经很难了

引用
评论
1
m24h作者
1年1个月前修改于 1年1个月前IP:上海
947175
2楼

用python做了个类似VDMOSTool的小工具 可以对转移特征曲线和电容做一些多点拟合 因为有程序且有规划求解 所以Cgd的a值也多点逼近出来(但如果只给两点 则还是用默认的1)

.... 现在的代码框怎么这样了 失望 如果有缩进问题 需要自己解决了

#!/usr/bin/python3

import math

import tkinter as tk

import tkinter.ttk as ttk

from tkinter import messagebox

from scipy.optimize import minimize

class Vdmos:

def init(self, master=None, data_pool=None):

# build ui

self.main = XXXXXXXXXXXX(master)

self.main.configure(cursor="arrow")

self.main.overrideredirect("false")

self.main.resizable(True, True)

self.main.title("VDMOS")

self.main.geometry('+%d+100'%((self.main.winfo_screenwidth()-600)/2))

validatefloat = (self.main.register(self.validate_float), "%P")

frame_1 = ttk.Frame(self.main)

frame_1.configure(height=200)

notebook_1 = ttk.Notebook(frame_1)

frame_2 = ttk.Frame(notebook_1)

label_1 = ttk.Label(frame_2)

label_1.configure(justify="right", text='Vto(V)')

label_1.grid(column=0, row=0, sticky="e")

self.vto = ttk.Entry(frame_2)

self.vto.configure(

justify="right",

validate="key",

validatecommand=_validate_float,

width=10)

self.vto.grid(column=1, columnspan=2, row=0, sticky="w")

label_4 = ttk.Label(frame_2)

label_4.configure(

anchor="ne",

justify="right",

text='Vgs(V)',

width=10)

label_4.grid(column=0, row=1, sticky="e")

label_5 = ttk.Label(frame_2)

label_5.configure(justify="right", text='Vds(V)')

label_5.grid(column=1, row=1, sticky="e")

label_6 = ttk.Label(frame_2)

label_6.configure(justify="right", text='Id(A)')

label_6.grid(column=2, row=1, sticky="e")

self.vgs_vds_id = []

for i in range(8):

self.vgs_vds_id.append((ttk.Entry(frame_2), ttk.Entry(frame_2), ttk.Entry(frame_2)))

for j in range(3):

self.vgs_vds_id[i][j].configure(

justify="right",

validate="key",

validatecommand=_validate_float,

width=10)

self.vgs_vds_id[i][j].grid(column=j, row=i+2)

notebook_1.add(frame_2, text='Basic')

frame_4 = ttk.Frame(notebook_1)

frame_4.configure(height=200, width=200)

label_2 = ttk.Label(frame_4)

label_2.configure(text='Vj(V)')

label_2.grid(column=0, row=0, sticky="e")

self.vj = ttk.Entry(frame_4)

self.vj.configure(

justify="right",

validate="key",

validatecommand=_validate_float,

width=10)

self.vj.grid(column=1, columnspan=3, row=0, sticky="w")

label_7 = ttk.Label(frame_4)

label_7.configure(text='Vds(V)')

label_7.grid(column=0, row=1, sticky="e")

label_8 = ttk.Label(frame_4)

label_8.configure(text='Ciss(pF)')

label_8.grid(column=1, row=1, sticky="e")

label_9 = ttk.Label(frame_4)

label_9.configure(text='Coss(pF)')

label_9.grid(column=2, row=1, sticky="e")

label_10 = ttk.Label(frame_4)

label_10.configure(text='Crss(pF)')

label_10.grid(column=3, row=1, sticky="e")

self.vds_ciss_coss_crss = []

for i in range(8):

self.vds_ciss_coss_crss.append((ttk.Entry(frame_4), ttk.Entry(frame_4), ttk.Entry(frame_4), ttk.Entry(frame_4)))

for j in range(4):

self.vds_ciss_coss_crss[i][j].configure(

justify="right",

validate="key",

validatecommand=_validate_float,

width=10)

self.vds_ciss_coss_crss[i][j].grid(column=j, row=i+2)

self.vds_ciss_coss_crss[0][0].insert(0, "0")

self.vds_ciss_coss_crss[0][0].configure(state='disabled')

notebook_1.add(frame_4, text='Cap')

notebook_1.pack(expand=True, fill="x", side="top")

frame_1.pack(side="top")

frame_5 = ttk.Frame(self.main)

self.result = tk.Text(frame_5, name="result")

self.result.configure(

borderwidth=1,

height=9,

relief="flat",

setgrid=False,

state="disabled",

undo=False,

width=30)

self.result.pack(

anchor="w",

expand=True,

fill="x",

ipadx=2,

padx=5,

side="left")

button_1 = ttk.Button(frame_5)

button_1.configure(text='Resolve')

button_1.pack(side="top")

button_1.configure(command=self.resolve)

button_2 = ttk.Button(frame_5, name="button_exit")

button_2.configure(text='Exit')

button_2.pack(side="top")

button_2.configure(command=exit)

frame_5.pack(anchor="w", side="top")

# Main widget

self.mainwindow = self.main

def run(self):

self.mainwindow.mainloop()

def validate_float(self, p_entry_value):

p_entry_value = p_entry_value.replace('.','',1)

return p_entry_value=='' or p_entry_value.isdigit()

@staticmethod

def calc_id(vgs, vds, vto, kp, lamb):

return 0 if vgs<vto else \

kp*(1+lamb*vds)*(vgs-vto-vds/2)*vds if vds<vgs-vto else \

kp*(1+lamb*vds)*(vgs-vto)*(vgs-vto)/2

@staticmethod

def calc_cgd(vds, a, cgdmin, cgdmax):

return (cgdmax*math.pi/2+cgdmin-(cgdmax-cgdmin)*math.atan(a*vds))/(1+math.pi/2)

@staticmethod

def calc_cds(vds, vj, cjo, m):

return cjo/math.pow(1+vds/vj, m)

def resolve(self):

self.result.configure(state='normal')

self.result.delete("1.0", tk.END)

self.result.insert(tk.END, ".model <name> VDMOS\n")

try:

# get vto, kp, lambda

vgs_vds_id = tuple(map(lambda x:tuple(map(lambda y:float(y.get()), x)),

filter(lambda z:all(map(lambda t:t.get()!='', z)),

self.vgs_vds_id)))

if self.vto.get()=='' and len(vgs_vds_id)>=3:

vto_kp_lambda=[0., 0., 0.]

solution = minimize(lambda x:sum(map(lambda y:(Vdmos.calc_id(y[0], y[1], x[0], x[1], x[2])-y[2])**2, vgs_vds_id)),

vto_kp_lambda, bounds=((0, None),(0,None),(0,None)))

if solution.success:

self.result.insert(tk.END, f'+ vto={solution.x[0]:10.4e} kp={solution.x[1]:10.4e} lambda={solution.x[2]:10.4e}\n')

elif self.vto.get()!='' and len(vgs_vds_id)>=2:

vto=float(self.vto.get())

solution = minimize(lambda x:sum(map(lambda y:(Vdmos.calc_id(y[0], y[1], vto, x[0], x[1])-y[2])**2, vgs_vds_id)),

(0., 0.), bounds=((0, None),(0,None)))

if solution.success:

self.result.insert(tk.END, f'+ vto={vto:10.4e} kp={solution.x[0]:10.4e} lambda={solution.x[1]:10.4e}\n')

# get cgd

vds_crss = tuple(map(lambda x: (float(x[0].get()), float(x[3].get())),

filter(lambda z:z[0].get()!="" and z[3].get()!="", self.vds_ciss_coss_crss)))

a_cgdmin_cgdmax = None

if len(vds_crss)>=3:

solution = minimize(lambda x:sum(map(lambda y:(Vdmos.calc_cgd(y[0], x[0], x[1], x[2])-y[1])**2, vds_crss)),

(1., 0., 0.), bounds=((0, None),(0, None),(0,None)))

if solution.success:

a_cgdmin_cgdmax = solution.x

elif len(vds_crss)>=2:

solution = minimize(lambda x:sum(map(lambda y:(Vdmos.calc_cgd(y[0], 1.0, x[0], x[1])-y[1])**2, vds_crss)),

(0., 0.), bounds=((0, None),(0, None)))

if solution.success:

a_cgdmin_cgdmax = (1.0, *solution.x)

elif len(vds_crss)>=1:

a_cgdmin_cgdmax = (1.0, vds_crss[0][1], vds_crss[0][1])

if a_cgdmin_cgdmax is not None:

self.result.insert(tk.END, f'+ a={a_cgdmin_cgdmax[0]:10.4e} cgdmin={a_cgdmin_cgdmax[1]/1e12:10.4e} cgdmax={a_cgdmin_cgdmax[2]/1e12:10.4e}\n')

# get cgs

vds_ciss = tuple(map(lambda x: (float(x[0].get()), float(x[1].get())),

filter(lambda z:z[0].get()!="" and z[1].get()!="", self.vds_ciss_coss_crss)))

if len(vds_ciss)>=1:

if a_cgdmin_cgdmax is not None:

cgs = max(map(lambda x:x[1]-Vdmos.calc_cgd(x[0], *a_cgdmin_cgdmax), vds_ciss))

else:

cgs = max(map(lambda x:x[1], vds_ciss))

self.result.insert(tk.END, f'+ cgs={cgs/1e12:10.4e}\n')

# get cds

vds_cds = tuple(map(lambda x: (float(x[0].get()), float(x[2].get())),

filter(lambda z:z[0].get()!="" and z[2].get()!="", self.vds_ciss_coss_crss)))

if a_cgdmin_cgdmax is not None:

vds_cds = tuple(map(lambda x: (x[0], x[1]-Vdmos.calc_cgd(x[0], *a_cgdmin_cgdmax)), vds_cds))

if self.vj.get()=='' and len(vds_cds)>=3:

solution = minimize(lambda x:sum(map(lambda y:(Vdmos.calc_cds(y[0], x[0], x[1], x[2])-y[1])**2, vds_cds)),

(0., 0., 0.), bounds=((0.2, 2),(0, None),(0, None)))

if solution.success:

self.result.insert(tk.END, f'+ vj={solution.x[0]:10.4e} cjo={solution.x[1]/1e12:10.4e} m={solution.x[2]:10.4e}\n')

elif self.vj.get()!='' and len(vds_cds)>=2:

vj = float(self.vj.get())

solution = minimize(lambda x:sum(map(lambda y:(Vdmos.calc_cds(y[0], vj, x[0], x[1])-y[1])**2, vds_cds)),

(0., 0.), bounds=((0, None),(0, None)))

if solution.success:

self.result.insert(tk.END, f'+ vj={vj:10.4e} cjo={solution.x[0]/1e12:10.4e} m={solution.x[1]:10.4e}\n')

except Exception as e:

messagebox.showinfo("Exception", e)

self.result.configure(state='disabled')

if name == "__main__":

app = Vdmos()

XXXXXXXXXXXXXX()


引用
评论
笔记
{{note.content}}
{{n.user.username}}
{{fromNow(n.toc)}} {{n.status === noteStatus.disabled ? "已屏蔽" : ""}} {{n.status === noteStatus.unknown ? "正在审核" : ""}} {{n.status === noteStatus.deleted ? '已删除' : ''}}
  • 编辑
  • 删除
  • {{n.status === 'disabled' ? "解除屏蔽" : "屏蔽" }}
我也是有底线的