站内搜索
发作品签到
LogicPi双通道FPGA数字示波器(基于立创逻辑派开发板)
专业版

LogicPi双通道FPGA数字示波器(基于立创逻辑派开发板)

简介

LogicPi双通道数字示波器,基于立创开发板逻辑派G1

简介:LogicPi双通道数字示波器,基于立创开发板逻辑派G1
星火计划2025

开源协议

LGPL 3.0

创建时间:2025-04-08 15:02:24更新时间:2026-03-10 09:34:33

描述

必看前言

开源协议:

LGPL 3.0

项目初衷:

本项目用于学习制作一个性能较好的DIY示波器,比起直接使用单片机的ADC采集,使用FPGA与高速ADC芯片的方案具有良好性能与更高的上限。在本项目中能学习到综合性很强的模拟电路设计、示波器知识、verilog程序、单片机程序、各种通信协议、屏幕与菜单等等,十分适合电子新手入门学习。

本项目目前只是完成了一个简单的FPGA方案示波器系统,比起市面上的商业示波器与各种成熟的开源示波器还显得十分简陋,但是仍有很大的性能优化与功能扩展的空间。

成本计算(芯片取tb信誉较好的店铺价格):

逻辑派开发板138+AD9288芯片12+3PD5651芯片6+AD603芯片4.5x2+ADA4932芯片12x2+tps82130芯片6.5+AD8065芯片6x2+继电器共10+MCP4728芯片8.6+BNC接头3.5x3+4.0寸LCD屏幕37+剩余的各种阻容芯片和接线座50。

粗略计算的最终成本在300以上,可根据自己需求降本增效。

补丁:
①原来负电压产生电路采用的是TPS5430 DCDC芯片,该芯片启动需要大概5.3V的输入电压,采用USB供电时电压容易达不到要求而无法产生输出。现替换为SCT2433芯片,引脚和功能完全兼容,,其具有低至4.3V的输入电压,更换后需要改一下反馈电阻3.74k->2.2k
②TL431的限流电阻R52在原来的原理图错误地被设置为2K欧,会导致电压上不去,现已修改为100欧
③NE5532输出端有一个到地的电容,用于稳压,运放可能带不动大容性负载,改为默认不焊,根据实际情况焊接
④更新V1.1固件,修复开机部分参数显示错误的问题,优化采样逻辑,改善了错误时序导致的大量噪声,并且去掉了取平均的滤波,带宽有所改善。优化了负电压产生电路。

视频展示:https://www.bilibili.com/video/BV1GD7qzRE37/

项目特点

  • 双核心异构,主控采用高云FPGA GW2A-LV18,GD32F303单片机作为辅助控制
  • 高带宽模拟前端电路,电路采用高度程控,校准高度可调
  • 采用AD9288作ADC采集,采样率达100MHz,存储深度16KB
  • FPGA资源使用量低,功能可高度扩展,性能优化提升空间大
  • 4寸LCD作波形显示,两个EC11编码器与8个按键作为控制,可添加更多事件响应
  • 采用3PD5651作DAC波形输出,可产生程控的波形、幅度、频率
  • 菜单控件与事件使用MCU处理,程序功能扩展简单

系统框图

image.png

AD模拟电路包括两个信号输入通道,由两路相同的信号调理电路进行处理,接入AD9288 ADC的双通道中,由FPGA进行读取。DA输出也由FPGA实现DDS产生可控波形输出,通过简单的调理电路输出。

项目采用了异构的主控,ADC、DAC与LCD显示由FPGA处理,充分发挥并行接口与逻辑电路的性能。对于电路的程控以及显示菜单、控件、事件的处理,为避免在FPGA布置大量复杂的处理逻辑,转由MCU进行处理,二者通过SPI协议进行通信。

实物展示

56.jpg
QQ20250604-151728.png

电路设计

电源

image.png

VDD_3.3V数字电源采用TPS82130 DCDC电路产生,满足较大的电流供给LCD、ADDA芯片等等;

VEE_4.5V为负压电源,用于各个运放的负电源轨供电,采用TPS5430 DCDC降压也是为了满足大电流的需求,若采用一般的电荷泵或LDO难以满足AD603等运放的供电;

VCC_4.5V与VCC_3.3V由低噪声LDO产生,减少电源纹波,用于模拟电源轨供电

模拟输入电路

image.png

模拟前端电路基本借鉴OSCFUN开源示波器的模拟电路,结合详细的设计教程,很适合新手学习示波器知识。

输入使用固态继电器控制交直流耦合,接着信号继电器选择x1 x10两路衰减,用于实现各个电压档位,衰减的同时满足1M高阻输入与阻抗匹配。后接一级跟随器,进入AD603实现的压控增益(VCA)电路,以实现精确的各档位增益控制,不采用模拟开关芯片避免阻抗的影响。放大输出后进入ADA4932差分放大器,作为AD9288的驱动。

模拟输出电路

image.png

3PD5651为电流输出型DAC,输出为差分信号,通过一级差分转单端的放大电路,后接跟随器,使用RC低通滤波滤除高频噪声,也可选择设计LC等更高阶的滤波器。

其他电路

屏幕与8个按键放到了另一块PCB上,作为顶面面板,使用34pin同向fpc排线连接信号线,并用贴片螺母与螺丝螺柱固定上下PCB,屏幕为4.0寸无触摸LCD,tb链接:https://t.doruo.cn/1Nc3GiYN2 型号为ST7796-IPS显示屏(不带触摸)

底板上采用一片MCP4728产生四通道电压输出,并结合基准源与运放搬移电压,以此产生ADC前端双路的压控放大控制、电压偏置控制。控制电路的运放选择比较宽松,能有效处理直流信号不振荡即可。运放与基准源等的精度无需多虑,可以软件校准。

程序设计

FPGA程序

image.png

ADC输入、滤波

AD9288输出的是补码,在每个时钟上升沿读取输出数据并转换为偏移码

wire [7:0] DIN_B = $unsigned(AD9288_DIN_B + 8'd127);
    
always @(posedge clk) begin
    if (!rst_n) begin
        AD9288_DOUT_A <= 0;
    end
    else begin
        AD9288_DOUT_A <= DIN_A;      
    end
end

由于实测发现读取的数据存在较大噪声与毛刺,后级接入简单的滑动均值滤波,可根据需要替换为更优的滤波方案

wire [11:0] sum = data_reg[0] + data_reg[1] + data_reg[2] + data_reg[3] + data_reg[4] + data_reg[5] + data_reg[6] + data_reg[7]; 
assign dout = sum >> AVE_DATA_BIT; //右移3 等效为÷8
波形存储与触发

信号经过一个比较器后生成脉冲,捕获其上下边沿产生触发信号

wire trig_pulse = trig_edge ? ((ad_data_r >= trig_level) && ((trig_ch ? ad_data_b : ad_data_a) < trig_level)) : ((ad_data_r <= trig_level) && ((trig_ch ? ad_data_b : ad_data_a) > trig_level)) ;

在数字波形存储的状态机中,先往环形ram预先存入一半深度的信号数据,等待触发,触发成功后继续存储直到达指定存储深度

			1:begin
				if(deci_valid) begin
					write_enable<=1;
					write_addr<=(write_addr+1'b1)&14'h3FFF;					
					write_data_a<=ad_data_a; write_data_b<=ad_data_b;
					ad_cnt<=ad_cnt+1;
					state<=(ad_cnt>=8191)?(state+1'b1):state;
				end
				else begin
					state<=state;
					ad_cnt<=ad_cnt;
					write_addr<=write_addr;
				end
		  	end		
	   		2:begin
				if(auto_trig||trig_flag)begin
					write_enable <= 1;
					write_addr <= (write_addr+1'b1)&14'h3FFF;
					trig_pos <= (write_addr+1'b1)&14'h3FFF;
					ad_cnt <= ad_cnt+1;
					write_data_a<=ad_data_a; write_data_b<=ad_data_b;
					state <= state+1;
					if(trig_mode==2) trig_ok<=1;
					else trig_ok<=0; end
				else begin
					state<=state;
					if(deci_valid) begin
						write_enable<=1;
						write_addr<=(write_addr+1'b1)&14'h3FFF;
						ad_cnt<=8191;
						write_data_a<=ad_data_a; write_data_b<=ad_data_b;
					end else begin
						state<=state;
						ad_cnt<=ad_cnt;
						write_addr<=write_addr;
					end
				end
			end	  	
频率计

对信号周期脉冲采用常见的等精度测量方案测量频率

MCU通信

在FPGA中布置了一组16位寄存器,长度可根据实际需要修改,编写一个SPI收发模块,用于接收MCU通过SPI总线发送的修改与访问寄存器指令与数据,根据寄存器地址将收到的数据写入寄存器中,单片机读取寄存器数据也同理

RECEIVE_ADDR: begin 
                   if (bit_count < 8) begin
                       if(sck_pos)begin
                           // 接收地址的每一位
                           address[7-bit_count] <= MOSI;
                           bit_count <= bit_count + 1;
                       end
                   end 
                   else begin
                       // 根据WR信号选择操作
                       if (WR) begin // WR高电平为写操作
                           current_state <= WRITE_DATA;
                           bit_count <= 0;
                       end 
                       else begin // WR低电平为读操作
                           current_state <= SEND_DATA;
                           if(address < 8'd16)  data_to_read <= regs[address[4:0]]; // 使用地址的低5位
                           else if(address == 8'd32) data_to_read <= key_reg;
                           bit_count <= 0;
                       end
                   end
           end

各个寄存器的值将会经过译码,生成各路控制线与数据线,控制全局模块的各个功能

/****耦合方式****/
assign acdc = regs[0][0];
assign dis_acdc_buff = acdc?"AC":"DC";

/****触发边沿****/
assign trig_edge = regs[1][2];
assign dis_trig_edge_buff = trig_edge?"NEG":"POS";

/****触发模式****/
assign trig_mode = regs[1][1:0];
assign dis_trig_mode_buff = (trig_mode==2'b0)?"AUTO  ":((trig_mode==2'b01)?"NORMAL":"SINGLE");

/****触发电平****/
assign trig_level = regs[6][7:0];
wire [3:0] trig_level_unit;
wire [3:0] trig_level_ten;
wire [3:0] trig_level_hun;
wire [8:0] trig_level_1=trig_level>>2;
bcd_8421 bcd_8421_1(
	.sys_clk(clk),   
    .sys_rst_n(rst_n),   
    .data(trig_level_1),   
    .unit(trig_level_unit),  
    .ten(trig_level_ten),  
    .hun(trig_level_hun)    
);
assign dis_trig_level_buff = {4'd0,trig_level_hun,4'd0,trig_level_ten,4'd0,trig_level_unit};   

寄存器表定义:
QQ20250530-225840.png

LCD显示

屏幕的显示逻辑较为复杂,使用了一个庞大的状态机,主状态机为整个刷新周期的循环。里面又分成一个个小状态机例如屏幕初始化、波形绘制、字符显示等等,他们又会调用更底层的画点、刷屏状态机,用高级编程语言的角度来看就是一个个函数,只不过放在verilog里面需要用状态跳转来实现复杂的逻辑。

 SCAN:begin
                case(cnt_scan)
                    5'd0: begin ram_addr<=trig_pos_minus_step;; cnt_scan <= cnt_scan + 1'b1; end // 使用预计算地址
                    5'd1: begin ram_en <= HIGH; cnt_scan <= cnt_scan + 1'b1;end	
                    5'd2: begin ram_addr<=ram_addr_next; cnt_scan <= cnt_scan + 1'b1; end	// RAM时钟使能
                    5'd3: begin 
                        ram_data_r1 <= (255-ram_data_a); 
                        ram_data_r2 <= (255-ram_data_b); 
                        cnt_scan <= cnt_scan + 1'b1;
                    end
                    5'd4: begin 							
                        if(y_cnt == 256) begin	
                            y_cnt <= 0;
                            if(x_cnt==400) begin x_cnt<=0; cnt_scan<=cnt_scan+1'b1; end	// 如果是最后一行就跳出循环
                            else begin  
                                x_cnt <= x_cnt + 1'b1; 
                                cnt_scan <= 5'd2; // 提早返回到地址更新,形成流水线
                            end	
                        end else begin
                            if(ram_data_r1==y_cnt)begin
                                current_y1 <= ram_data_r1;
                                prev_y1 <= current_y1;
                            end
                            if(ram_data_r2==y_cnt)begin
                                current_y2 <= ram_data_r2;
                                prev_y2 <= current_y2;
                            end
                            y_cnt <= y_cnt + 1'b1;
                            y <= y_cnt; 
                            x <= ((ram_data_r1==y_cnt || ram_data_r2==y_cnt) && (x_cnt!=400))?x_cnt+1:x_cnt;
                            if(trig_flag) color <= ORANGE;
                            else if((ram_data_r1==y_cnt)||line_flag1) color <= YELLOW;
                            else if((ram_data_r2==y_cnt)||line_flag2) color <= BLUE;
                            else if(cor_flag) color <= WHITE;
                            else if(cor_flag1) color <= GREY;
                            else color <= color_b;
                                state <= POINT;	// 跳转至WRITE状态
                                state_backback <= SCAN;	// 执行完WRITE及DELAY操作后返回SCAN状态
                            end
                        end
                    5'd5: begin cnt_scan <= 0; state <= MAIN; ram_en <= LOW; end
                    default: state <= IDLE;
                endcase
            end

UI界面设计:
image.png

DDS与DAC

DDS调用了高云的DDS_II IP核,其实这个IP核和XILINX的DDS IP核一模一样,熟悉XILINX的人马上就能直接使用起来。DDS根据32位频率控制字会产生指定频率的正弦波,将其通过一个比较器就得到了方波。同时dds还支持输出相位字,其波形是一个锯齿波,经过整流后可以生成三角波,这就形成了四个常见波形。

reg signed [9:0] square_wave; // 方波输出

// 方波生成
always @(posedge clk) begin
    if (dds_phase[31:16] < 16'h8000) // 比较相位累加器的高 16 位
        square_wave <= 10'd511;  // 高电平(满量程)
    else
        square_wave <= -10'd512; // 低电平(满量程)
end

/*****************************************************************************/
wire signed [9:0] dds_phase_2 = dds_phase>>>22;
reg signed [9:0] triangle_wave;  // 10 位三角波输出

// 三角波生成
always @(posedge clk) begin
    if (dds_phase_2 >= 0) begin
        triangle_wave <= (dds_phase_2 - 12'd256)<<<1; // 映射到 -512 到 +511
    end else begin
        triangle_wave <= (12'd768 - dds_phase_2)<<<1; // 映射到 -512 到 +511
    end

使用移位加法可以控制输出的波形的幅度衰竭

reg signed [9:0] temp_add1, temp_add2;

always @(posedge clk or negedge rst_n) begin
    if (!rst_n) begin
        temp_add1 <= 10'd0;
        temp_add2 <= 10'd0;
    end else begin
        temp_add1 <= (wave_reg >>> 1) + (wave_reg >>> 2);
        temp_add2 <= (wave_reg >>> 3);
    end
end
    
always @(posedge clk or negedge rst_n) begin
    if (!rst_n)
        DAC_out_r <= 10'd0;
    else
        case (attenuation_sel)
            8'd0: DAC_out_r <= wave_reg;
            8'd1: DAC_out_r <= temp_add1 + temp_add2;
            8'd2: DAC_out_r <= temp_add1;
            8'd3: DAC_out_r <= (wave_reg >>> 1) + (wave_reg >>> 3);
            8'd4: DAC_out_r <= wave_reg >>> 1;
            8'd5: DAC_out_r <= (wave_reg >>> 2) + (wave_reg >>> 3);
            8'd6: DAC_out_r <= wave_reg >>> 2;
            8'd7: DAC_out_r <= wave_reg >>> 3;
            default: DAC_out_r <= wave_reg;
        endcase
end

MCU程序

image.png

FPGA通信

使用GD32的硬件SPI读写FPGA的内部寄存器,可以尽可能减少响应时间。

// 写寄存器函数
void SPI_WriteRegister(uint8_t address, uint16_t data) {
    // 组合发送数据:地址 + 高8位 + 低8位
    uint8_t tx_buf[3] = {address, (data >> 8) & 0xFF, data & 0xFF};

    gpio_bit_reset(SPI_GPIO_PORT, SPI_PIN_CS);
    gpio_bit_set(SPI_GPIO_PORT, SPI_PIN_WR);// 设置WR为写模式(高电平)

    for (int i = 0; i < 3; i++) {
        while (spi_i2s_flag_get(SPI_INSTANCE, SPI_FLAG_TBE) == RESET);
        spi_i2s_data_transmit(SPI_INSTANCE, tx_buf[i]);
        while (spi_i2s_flag_get(SPI_INSTANCE, SPI_STAT_RBNE) == RESET);
        spi_i2s_data_receive(SPI_INSTANCE);
    }

    gpio_bit_set(SPI_GPIO_PORT, SPI_PIN_CS);
	gpio_bit_reset(SPI_GPIO_PORT, SPI_PIN_WR);
}

// 读寄存器函数
uint16_t SPI_ReadRegister(uint8_t address) {
    uint8_t tx_buf[3] = {address, 0xFF, 0xFF}; // 发送地址和填充字节
    uint8_t rx_buf[3];

    gpio_bit_reset(SPI_GPIO_PORT, SPI_PIN_CS);
    // 设置WR为读模式(低电平)
    gpio_bit_reset(SPI_GPIO_PORT, SPI_PIN_WR);

    for (int i = 0; i < 3; i++) {

        while (spi_i2s_flag_get(SPI_INSTANCE, SPI_FLAG_TBE) == RESET);
        spi_i2s_data_transmit(SPI_INSTANCE, tx_buf[i]);
        while (spi_i2s_flag_get(SPI_INSTANCE, SPI_STAT_RBNE) == RESET);
        rx_buf[i] = spi_i2s_data_receive(SPI_INSTANCE);
    }

    gpio_bit_set(SPI_GPIO_PORT, SPI_PIN_CS);

    // 组合返回的16位数据(高8位+低8位)
    return ((uint16_t)rx_buf[1] << 8) | rx_buf[2];
}
事件响应

由于逻辑派开发板设计,GD32引脚不足,所以编码器与各个按键连接到了fpga的引脚,然后在定时器中断处理中,通过上述的SPI接口读取FPGA存储按键电平的寄存器,并进行消抖、双击长按识别。

// 定时器中断服务程序
void TIMER2_IRQHandler(void) {
    static bool A1=1,B1=1,A1_r=1,B1_r=1;
	static bool A2=1,B2=1,A2_r=1,B2_r=1;
	if (RESET != timer_interrupt_flag_get(TIMER2, TIMER_INT_FLAG_UP)) {
        timer_interrupt_flag_clear(TIMER2, TIMER_INT_FLAG_UP);
		
		uint16_t key_state = SPI_ReadRegister(32);
		A1 = (key_state&0x0400)==0x0400;  B1 = (key_state&0x0800)==0x0800;
		A2 = (key_state&0x1000)==0x1000;  B2 = (key_state&0x2000)==0x2000;

		if(!A1 && A1_r && B1) EC11_flag1 = 2;//反传
		A1_r = A1;               
        if(!B1 && B1_r && A1) EC11_flag1 = 1;//正转
		B1_r = B1;  
		if(!A2 && A2_r && B2) EC11_flag2 = 2;
		A2_r = A2;               
        if(!B2 && B2_r && A2) EC11_flag2 = 1;
		B2_r = B2;  
		
		for(uint8_t i = 0;i < 10;i++)
		{
			key[i].key_status = (key_state >> i) & 0x1;
            //此处是判断按键是否稳定
			switch(key[i].click_status)
			{
				case 0://状态0:第一次按下
					if(key[i].key_status == RESET)
					{
						key[i].click_status = 1;//跳转状态1
					}
					break;
				case 1://状态1:电平已稳定
					if(key[i].key_status == RESET)
					{
						key[i].click_status = 2;
						key[i].click_time = 0; //计时器清零,准备调用
					}
					else
					{
						key[i].click_status = 0;
					}
					break;
              .................................................

按键功能:
8个顶板按键:耦合方式、活跃通道切换、打开/关闭(通道)、光标模式、自动触发、正常触发、单次触发、暂停/启动
编码器1:切换控件、切换DAC选择位数
编码器2:选项切换、数值增减
编码器1按键:进入与退出
编码器2按键:切换粗调细调

菜单控件处理

将每个可操控的控件都定义一个任务函数,main主循环将依次访问各控件任务,执行事件响应

int main(void)
{
	systick_config();
	usart_init();
	printf("helloworld\n");
	bsp_spi_init();
	timer2_init();
	I2C_Init();
	ctrl_init();
	for(int i=0;i<17;i++){
		update_reg(i);
	}
	update_reg(20);
	update_ch_gear();
	update_reg(6);
	while(1){	
		object_task();
	}
}

void TRIG_CH_task(){
	if(EC11_flag1 == 2){
		EC11_flag1=0;
		object++; update_reg(14);
	}else if(EC11_flag1 == 1){
		EC11_flag1=0;
		object=11; update_reg(14);
	}else if(EC11_flag2 == 1){
		EC11_flag2=0;
		trig_ch=!trig_ch;
		update_reg(1);
	}else if(EC11_flag2 == 2){
		EC11_flag2=0;
		trig_ch=!trig_ch;
		update_reg(1);
	}else if(key[8].signed_flag==1){
		key[8].signed_flag=0;
		
	}
	else if(key[9].signed_flag==1){
		key[9].signed_flag=0;
		
	}
}

制作调试与其他

1.注意原理图标注的部分,有些地方是不用焊接的。
2.上下板直接要使用螺柱与贴片螺母连接,需要自备合适高度的螺柱、螺丝等,实测上下板需要有25mm的高度。
3.编码器在3D图中是直插的,实际上需要使用侧插的编码器。
4.原理图BOM不一定准确,建议根据器件型号和值来选。
5.上下板连接的排线选择34P-0.5mm-同向,如果买的是5cm或者更长,需要卷曲一下不然会翘出去。
6.各个电压量程的实现需要同时进行继电器控制衰竭档位切换与改变MCP4728输出AD603增益控制电压,校准信息在GD32的程序中:

typedef struct
{
	uint16_t dac_poff;//通道增益控制字
	uint16_t vertical_offset;//通道垂直基线偏移
	bool gain_sel;//衰减选择
}Calibration;                        
                               
//对应10个档位5 10 20 50 100 200 500 1000 2000 5000 mV
Calibration ch1_cali[10]={
	{600,2330,1}, //5mV
	{900,2435,1}, //10mV
	{1300,2485,1},//20mV 
	{1850,2520,1},//50mV
	{2270,2530,1},//100mV
	{2675,2530,1},//200mV
	{1425,2530,0},//500mV
	{1840,2535,0},//1V
	{2270,2540,0},//2V
	{2740,2535,0},//5V
};                            

校准方法:

信号源输出直流0V,改变第二个参数即电压偏移,使0V的波形直线归零到正中央,偏移电压即可确定。

再让信号源输出一定的电压,例如1V档位时输入3V电压,改变第一个参数即放大增益,时波形直线落在3V的坐标线上,那么增益也确定下来。

MCP4728的控制字范围是0-4095。第三个参数是继电器控制x1 x10档位的,一般情况不用改。

7.板上有四个可调电容,用于调节示波器通道的阻抗匹配,当出现同一增益下直流量与交流量放大倍数不一致的时候,可以尝试调节电容,这将会改变交流信号的幅度与相位;或者当输入的方波失真,可进行调节电容校准。
8.由于设计思路改变以及代码的一些时序问题,部分预期的功能并没有实际实现,例如cursor测量功能、峰峰值测量、通道开关等等,但是也留了一些占位槽。
9.时序报告与资源用量:
QQ20250529-231711.png
QQ20250529-231730.png
10.

参考

OSCFUN开源示波器:http://oscfun.com/
开源项目:https://oshwhub.com/Alpha-go/a5IITjkVGF1cA9kyTV2V9sIHra7GcIg2
开源项目:https://oshwhub.com/824366a/fpga-oscilloscope-824366a

设计图

未生成预览图,请在编辑器重新保存一次

BOM

暂无BOM

3D模型

序号文件名称下载次数
暂无数据

附件

序号文件名称下载次数
1
视频1.mp4
264
2
视频2.mp4
212
3
LogicPi_V1.1_2026.3.9.zip
202
克隆工程
添加到专辑
0
0
分享
侵权投诉

工程成员

知识产权声明&复刻说明

本项目为开源硬件项目,其相关的知识产权归创作者所有。创作者在本平台上传该硬件项目仅供平台用户用于学习交流及研究,不包括任何商业性使用,请勿用于商业售卖或其他盈利性的用途;如您认为本项目涉嫌侵犯了您的相关权益,请点击上方“侵权投诉”按钮,我们将按照嘉立创《侵权投诉与申诉规则》进行处理。

请在进行项目复刻时自行验证电路的可行性,并自行辨别该项目是否对您适用。您对复刻项目的任何后果负责,无论何种情况,本平台将不对您在复刻项目时,遇到的任何因开源项目电路设计问题所导致的直接、间接等损害负责。

底部导航