Skip to content

电路的抽象

DodoZhang edited this page Jun 22, 2022 · 5 revisions

在利用计算机对电路进行仿真前,我们先需要寻找一种抽象结构用于在计算机中表述待仿真的电路模型。
我们给出如下定义:

  • 电路Circuit:模型的整体,由若干个元件网络组成;
  • 元件Element:用于描述电路中的例如电阻器、电容器的基本元器件,每种元件包含确定数量个引脚
  • 引脚Pin元件与外围电路的接线,电流通过引脚流入或流出元件;
  • 网络Net:若干个引脚相互连接产生的节点,同一网络上的所有引脚的电位相同;
  • ground:电位为零的一个网络,用于为电路模型提供电位参考。

我们可以使用以下伪代码来实现上述结构:

// Circuit.h

class Circuit {
	QList<Element *> m_elements;	// 组成电路的元件
	QList<Net *> m_nets;		// 组成电路的网络
	Net *m_ground;			// 电路的地
}
// Element.h

class Element {
	Circuit *m_circuit;		// 元件所属的电路
	QList<Pin *> m_pins;		// 元件的引脚
}
// Pin.h

#include <QList>

class Element;
class Net;

class Pin {
	Element *m_element;		// 引脚所属的元件
	Net *m_net;			// 引脚连接到的网络,如果悬空则为 nullptr
}
// Net.h

#include <QList>

class Circuit;
class Pin;

class Net {
	Circuit *m_circuit;		// 网络所属的电路
	QList<Pin *> m_nets;		// 网络所连接的引脚
}

为了便于资源的管理,我们在元件网络在构造时自动加入所属电路的列表中,在引脚构造时自动加入所属元件的列表中。同理在析构时自动从列表中剔除自身。

Element::Element(Circuit *circuit) {
	m_circuit = circuit;
	circuit.m_elements.append(this);
}

Element::~Element() {
	m_circuit.m_elements.removeLast(this);
	if (!m_pins.empty()) delete m_pins.last();
}
Net::Net(Circuit *circuit) {
	m_circuit = circuit;
	circuit.m_nets.append(this);
}

Net::~Net() {
	m_circuit.m_nets.removeLast(this);
	if (!m_pins.empty()) m_pins.last().setNet(nullptr);
}
Pin::Pin(Element *element) {
	m_element = element;
	element.m_pins.append(this);
}

Pin::~Pin() {
	m_element.m_pins.removeLast(this);
}

void Pin::setNet(Net *net)
{
	if (m_net == net) return;
	if (m_net) m_net.m_pins.removeLast(this);
	m_net = net;
	if (net) net.m_pins.append(this);
}

为了便于将电路模型输入计算机,我们可以构造静态函数Net *Pin::connect(Pin *a, Pin *b)来将两个引脚连接起来,并返回合并后的网络。我们可以用如下方法实现该函数:

// 将 a 网络和 b 网络合并,并返回合并后的网络
// static 
Net *Net::merge(Net *a, Net *b) {
	if (a == a.m_circuit.m_ground) return merge(b, a);
	a.m_pins.append(b.m_pins);
	for (auto iter = b.m_pins.begin(); iter != b.m_pins.end(); iter ++) (*iter)->setNet(a);
	b.m_pins.clear();
	delete b;
	return a;
}
// static
Net *Pin::connect(Pin *a, Pin *b) {
	if (a.m_net) {
		if (b.m_net) Net::merge(a.m_net, b.m_net);
		else b.setNet(a.m_net);
	} else {
		if (b.m_net) a.setNet(b.m_net);
		else {
			a.setNet(new Net(a.m_element.m_circuit));
			b.setNet(a.m_net);
		}
	}
	return a.m_net;
}

假设我们已经完成了对元件的派生类电阻器Resistor和电压源VoltageSource的定义和声明,那么我们可以使用下述代码将以下的电路图在计算机中表示。

纯电阻电路

auto *circuit = new Circuit();

// 构造元件
auto *source = new VoltageSource(circuit, 5);
auto *resistor1 = new Resistor(circuit, 10);
auto *resistor2 = new Resistor(circuit, 10);
auto *resistor3 = new Resistor(circuit, 20);

// 连接元件
Pin::connect(source->pin(1), resistor1->pin(0));	// 将电源正极连接到电阻1的一个引脚
Pin::connect(source->pin(1), resistor2->pin(0));	// 将电源正极连接到电阻2的一个引脚
Pin::connect(resistor1->pin(1), resistor3->pin(0));	// 将电阻1的另一个引脚连接到电阻3的一个引脚
Pin::connect(resistor2->pin(1), resistor3->pin(0));	// 将电阻2的另一个引脚连接到电阻3的一个引脚
Pin::connect(resistor3->pin(1), source->pin(0));	// 将电阻3的另一个引脚连接到电源负极

// 设定地
circuit->setGround(source->pin(0)->net());

通过上述方法就可以使用简单易读的代码将电路模型放入计算机中。

Clone this wiki locally