草庐IT

接口:基于FPGA的HDMI接口设计

因为我看过月亮啊 2023-09-08 原文

        这篇文章只是一周的学习记录,由于本人只学习了如何利用HDMI传输视频图像并没有传输音频,所以这篇文章只有一个彩条实验。本人想写这篇博客只是对自己学习过程过程中产生的问题的一个记录,其中有些代码是自己借鉴后添加到自己工程中,有问题的代码我没有贴出,后续调通后会贴出代码。本人是一个FPGA的新学者,因为网上很多例程说的都不清楚,所以想通过这种方式有一个记录,如有侵权,指出后,会进行删除。如有不正确的地方也欢迎指出。

一、HDMI概述

        HDMI(High_Definition Multiface Interface)是一种音视频传输协议,主要用于解决VGA接口传输速度过慢以及体积过大的问题。HDMI传输主要是采用的TMDS(Transition Minimized Differential Signaling)协议。此外,使用TMDS也是DVI标准的主要特点 。

二、HDMI物理结构

        上图就是HDMI block结构图,可以看出HDMI在传输数据时,是经过三对差分信号传输数据和一对差分信号传输clock。其他协议暂时没有使用也就不展开说明。 引脚定义在其他博客中也有很多说明,包括在各个厂家购买的开发板上也有详细说明,如果需要的话可以自己在网站中寻找一下。

三、TMDS编码过程

       (1)TMDS编码示意图

        TMDS编码一般是将8位数据经过编码直流平衡达到10位的最小数据。这仿佛是增加了冗余位,对传输要求更高了。但是实际上这种算法使得到的数据在同轴电缆中可靠性更强了,下图就是编码过程,8位并行的RED数据编码后进行并转串。(这些数据在各家提供的开发手册中都有,这些只是为了让自己更明白才写的)

(1)将 8 位并行 RED 数据发送到 TMDS 収送端。
(2)并/串转换。
(3)进行最小化传输处理,加上第 9 位,即编码过程。第 9 位数据称为编码位。

直流平衡:

        直流平衡(DC-balanced)就是指在编码过程中保证信道中直流偏移为零。方法是在原来的 9 位数据癿后面加上第 10 位数据,返样,传输的数据趋于直流平衡,使信号对传输线的电磁干扰减少,提高信号传输的可靠性。

        (2)TMDS发送和接收的链接示意图

        上图是 TMDS 发送端和接收端的连接示意图。DVI 或 HDMI 视频传输所使用的 TMDS 连接通过四个串行通道实现。对于DVI来说,其中三个通道分别用于传输视频中每个像素点的红、绿、蓝三个颜色分量(RGB4:4:4格式)。HDMI 默认也是使用三个 RGB 通道,但是它同样可以选择传输像素点的亮度和色度信息(YCrCb4:4:4或YCrCb 4:2:2格式)。第四个通道是时钟通道,用于传输像素时钟。独立的 TMDS 时钟通道为接收端提供接收的参考频率,保证数据在接收端能够正确恢复。

        在传输视频图像的过程中,数据通道上传输的是编码后的有效像素字符。而在每一帧图像的行与行之间,以及视频中不同帧之间的时间间隔(消隐期)内,数据通道上传输的则是控制字符每个通道上有两位控制信号的输入接口,共对应四种不同的控制字符。这些控制字符提供了视频的行同步(HZYNC)以及帧同步(VSYNC)信息,也可以用来指定所传输数据的边界(用于同步)。对于 DVI 传输,整个视频的消隐期都用来传输控制字符。而 HDMI 传输的消隐期除了控制字符之外,还可以用于传输音频或者其他附加数据(例如字母信息),4-bit 音频和附加数据将通过 TERC4 编码机制转换成 10-bit TERC4 字符,然后再绿色和红色通道上传输。从上图也可以看出这一差别,即“Auxiliary Data”接口标有“HDMI Olny”,即它是 HDMI 所独有的接口。如果我们不需要附加数据,只传输视频数据的话,完全可以把 HDMI 接口当做 DVI 接口进行驱动。下图是DVI编码器示意图:

        每个通道输入的视频像素数据都要使用 DVI 规范中的 TMDS 编码算法进行编码。每个 8-bit 的数据都将被转换成 460 个特定 10-bit 字符中的一个。这个编码机制大致上实现了传输过程中的直流平衡,即一段时间内传输的高电平(数字“1”)的个数大致等于低电平(数字“0”)的个数。同时,每个编码后的 10-bit 字符中状态跳转(“由 1 到 0”或者“由 0 到 1”)的次数将被限制在五次以内。除了视频数据之外,每个通道 2-bit 控制信号的状态也要进行编码,编码后分别对应四个不同的 10-bit 控制字符,分别是 10'b1101010100,10'b0010101011,10'b0101010100,和 10'b1010101011。可以看出,每个控制字符都有七次以上的状态跳转。视频字符和控制字符状态跳转次数的不同将会被用于发送和接收设备的同步。 

  再重复一遍,HDMI 在输入附加数据的同时,还需要输入 ADE(Aux/Audio Data Enable)信号,其作用和 VDE 是类似的:当 ADE 为高电平时,表明输入端的附加数据或者音频数据有效,DIV 是不能传音频的。想了解更多有关 HDMI的细节,可以参考HDMI 接口规范——《High-Definition Multimedia Interface Specification Version 1.3a》,英语不好的也可以查看文档《HDMI1.4规范中文版》。

四、HDMI电路原理

        这边直接引用的是黑金AX7050底板的HDMI原理图接口:

 

         AZ1045_04F是TVS二极管,防止外面静电对FPGA产生损坏。本次实验只使用到TMDS数据,时钟,相关的管脚约束如下所示:

############## NET - IOSTANDARD ##################
set_property CFGBVS VCCO [current_design]
set_property CONFIG_VOLTAGE 3.3 [current_design]
#############SPI Configurate Setting##################
set_property BITSTREAM.CONFIG.SPI_BUSWIDTH 4 [current_design]
set_property CONFIG_MODE SPIx4 [current_design]
set_property BITSTREAM.CONFIG.CONFIGRATE 50 [current_design]

create_clock -period 20.000 [get_ports sys_clk]
set_property IOSTANDARD LVCMOS33 [get_ports sys_clk]
set_property PACKAGE_PIN P15 [get_ports sys_clk]

set_property IOSTANDARD LVCMOS33 [get_ports rst_n]
set_property PACKAGE_PIN M15 [get_ports rst_n]
#############HDMI_O##################
set_property IOSTANDARD LVTTL [get_ports tmds_clk_n]
set_property PACKAGE_PIN A20 [get_ports tmds_clk_n]

set_property PACKAGE_PIN B20 [get_ports tmds_clk_p]
set_property IOSTANDARD LVTTL [get_ports tmds_clk_p]

set_property IOSTANDARD LVTTL [get_ports {tmds_data_n[0]}]
set_property PACKAGE_PIN A17 [get_ports {tmds_data_n[0]}]

set_property PACKAGE_PIN A16 [get_ports {tmds_data_p[0]}]
set_property IOSTANDARD LVTTL [get_ports {tmds_data_p[0]}]

set_property IOSTANDARD LVTTL [get_ports {tmds_data_n[1]}]
set_property PACKAGE_PIN A13 [get_ports {tmds_data_n[1]}]

set_property PACKAGE_PIN B13 [get_ports {tmds_data_p[1]}]
set_property IOSTANDARD LVTTL [get_ports {tmds_data_p[1]}]

set_property IOSTANDARD LVTTL [get_ports {tmds_data_n[2]}]
set_property PACKAGE_PIN A12 [get_ports {tmds_data_n[2]}]

set_property PACKAGE_PIN A11 [get_ports {tmds_data_p[2]}]
set_property IOSTANDARD LVTTL [get_ports {tmds_data_p[2]}]

         需要注意的是,TMDS 数据和时钟信号需要在约束文件中指定电平标准为 LVTTL,此时钟约束是黑金AX7050提供的时钟约束。虽然差分信号vivado会在我们引导正极引脚位置后自动对负极进行分配,但是本人在测试后发现没有实现效果所以采用黑金提供的时序约束进行代码编写。

五、HDMI程序设计

        TMDS在逻辑功能上有两个阶段:编码和并转串。编码阶段就是将8bit的像素数据,行场数据分别编码成10bit的数据,在进行并转串设计,分别将RGB以及时钟信号发送出去。整个过程示意图如下:

 其中详解可以得到如下框图:

         Encoder模块负责对数据进行编码,即8bit编码成为10bit数据。

设计流程     

(1)上述框图中,图片数据来源模块与VGA模块的设计,可以在CSDN上寻找现成的代码。

(2)Encoder模块设计

        这部分编码可以在Xilinx官网下载例程(关于Xilinx官网下载代码,这个操作比较麻烦,以后找到方法会在列出)在此直接贴出代码,此代码的开发笔记可以在Xilinx提供的DocNav软件中找到(如何操作有时间会贴出)。

        Encoder模块把 8 比特的数据进行从新映射为 10bit 数据,防止连续的 0 和 1 出现导致直流不平衡造成误码率升高。

`timescale 1 ps / 1ps

module encode (
  input            clkin,    // pixel clock input
  input            rstin,    // async. reset input (active high)
  input      [7:0] din,      // data inputs: expect registered
  input            c0,       // c0 input
  input            c1,       // c1 input
  input            de,       // de input
  output reg [9:0] dout      // data outputs
);

  
  // Counting number of 1s and 0s for each incoming pixel
  // component. Pipe line the result.
  // Register Data Input so it matches the pipe lined adder
  // output
  
  reg [3:0] n1d; //number of 1s in din
  reg [7:0] din_q;

  always @ (posedge clkin) begin
    n1d <=#1 din[0] + din[1] + din[2] + din[3] + din[4] + din[5] + din[6] + din[7];

    din_q <=#1 din;
  end

  ///
  // Stage 1: 8 bit -> 9 bit
  // Refer to DVI 1.0 Specification, page 29, Figure 3-5
  ///
  wire decision1;

  assign decision1 = (n1d > 4'h4) | ((n1d == 4'h4) & (din_q[0] == 1'b0));
  wire [8:0] q_m;
  assign q_m[0] = din_q[0];
  assign q_m[1] = (decision1) ? (q_m[0] ^~ din_q[1]) : (q_m[0] ^ din_q[1]);
  assign q_m[2] = (decision1) ? (q_m[1] ^~ din_q[2]) : (q_m[1] ^ din_q[2]);
  assign q_m[3] = (decision1) ? (q_m[2] ^~ din_q[3]) : (q_m[2] ^ din_q[3]);
  assign q_m[4] = (decision1) ? (q_m[3] ^~ din_q[4]) : (q_m[3] ^ din_q[4]);
  assign q_m[5] = (decision1) ? (q_m[4] ^~ din_q[5]) : (q_m[4] ^ din_q[5]);
  assign q_m[6] = (decision1) ? (q_m[5] ^~ din_q[6]) : (q_m[5] ^ din_q[6]);
  assign q_m[7] = (decision1) ? (q_m[6] ^~ din_q[7]) : (q_m[6] ^ din_q[7]);
  assign q_m[8] = (decision1) ? 1'b0 : 1'b1;

  /
  // Stage 2: 9 bit -> 10 bit
  // Refer to DVI 1.0 Specification, page 29, Figure 3-5
  /
  reg [3:0] n1q_m, n0q_m; // number of 1s and 0s for q_m
  always @ (posedge clkin) begin
    n1q_m  <=#1 q_m[0] + q_m[1] + q_m[2] + q_m[3] + q_m[4] + q_m[5] + q_m[6] + q_m[7];
    n0q_m  <=#1 4'h8 - (q_m[0] + q_m[1] + q_m[2] + q_m[3] + q_m[4] + q_m[5] + q_m[6] + q_m[7]);
  end

  parameter CTRLTOKEN0 = 10'b1101010100;
  parameter CTRLTOKEN1 = 10'b0010101011;
  parameter CTRLTOKEN2 = 10'b0101010100;
  parameter CTRLTOKEN3 = 10'b1010101011;

  reg [4:0] cnt; //disparity counter, MSB is the sign bit
  wire decision2, decision3;

  assign decision2 = (cnt == 5'h0) | (n1q_m == n0q_m);
  /
  // [(cnt > 0) and (N1q_m > N0q_m)] or [(cnt < 0) and (N0q_m > N1q_m)]
  /
  assign decision3 = (~cnt[4] & (n1q_m > n0q_m)) | (cnt[4] & (n0q_m > n1q_m));

  
  // pipe line alignment
  
  reg       de_q, de_reg;
  reg       c0_q, c1_q;
  reg       c0_reg, c1_reg;
  reg [8:0] q_m_reg;

  always @ (posedge clkin) begin
    de_q    <=#1 de;
    de_reg  <=#1 de_q;
    
    c0_q    <=#1 c0;
    c0_reg  <=#1 c0_q;
    c1_q    <=#1 c1;
    c1_reg  <=#1 c1_q;

    q_m_reg <=#1 q_m;
  end

  ///
  // 10-bit out
  // disparity counter
  ///
  always @ (posedge clkin or posedge rstin) begin
    if(rstin) begin
      dout <= 10'h0;
      cnt <= 5'h0;
    end else begin
      if (de_reg) begin
        if(decision2) begin
          dout[9]   <=#1 ~q_m_reg[8]; 
          dout[8]   <=#1 q_m_reg[8]; 
          dout[7:0] <=#1 (q_m_reg[8]) ? q_m_reg[7:0] : ~q_m_reg[7:0];

          cnt <=#1 (~q_m_reg[8]) ? (cnt + n0q_m - n1q_m) : (cnt + n1q_m - n0q_m);
        end else begin
          if(decision3) begin
            dout[9]   <=#1 1'b1;
            dout[8]   <=#1 q_m_reg[8];
            dout[7:0] <=#1 ~q_m_reg;

            cnt <=#1 cnt + {q_m_reg[8], 1'b0} + (n0q_m - n1q_m);
          end else begin
            dout[9]   <=#1 1'b0;
            dout[8]   <=#1 q_m_reg[8];
            dout[7:0] <=#1 q_m_reg[7:0];

            cnt <=#1 cnt - {~q_m_reg[8], 1'b0} + (n1q_m - n0q_m);
          end
        end
      end else begin
        case ({c1_reg, c0_reg})
          2'b00:   dout <=#1 CTRLTOKEN0;
          2'b01:   dout <=#1 CTRLTOKEN1;
          2'b10:   dout <=#1 CTRLTOKEN2;
          default: dout <=#1 CTRLTOKEN3;
        endcase

        cnt <=#1 5'h0;
      end
    end
  end
  
endmodule

 Encoder模块是依据DVI接口规范中TMDS编码算法进行的,不过这部分是在Xilinx官方网站中直接贴出。如果对TMDS编码算法有兴趣的同学可以依据下图算法进行学习:

 TMDS是DVI接口所定义的,不做深入研究,其中各个参数的定义如下:

D视频信号
C0 C1控制信号
DE使能信号
Cnt寄存器参数
N0{X}输入视频信号中“0”的个数
N1{X}输入视频信号中“1”的个数
q_out编码后输出

        Encoder模块的调用编码完成后例化时需要注意,在Blue里的c0和c1输入的是hsync 和 vsync,另外的颜色通道是不需要的。

例化过程如下:

encode encb (
.clkin      (pixelclk),
.rstin      (rstin),
.din        (blue_din),
.c0         (hsync),
.c1         (vsync),
.de         (de),
.dout       (blue)) ;

encode encr (
.clkin      (pixelclk),
.rstin      (rstin),
.din        (green_din),
.c0         (1'b0),
.c1         (1'b0),
.de         (de),
.dout       (green)) ;

encode encg (
.clkin      (pixelclk),
.rstin      (rstin),
.din        (red_din),
.c0         (1'b0),
.c1         (1'b0),
.de         (de),
.dout       (red)) ;

 (3)并转串模块设计

        并转串行 模块通过调用 OSERDESE2 原语来实现 10:1 的并串转换。原语是 Xilinx 器件底层硬件中的功能模块,它使用专用的资源来实现一系列的功能。相比于 IP 核,原语的调用方法更简单,但是一般只用于实现一些简单的功能。OSERDESE2 详细介绍见 Xilinx 官方提供的UG768(P338)和UG471(P161)手册(该手册寻找方式和上方寻找例程方式一样)。OSERDESE2 原语模型如下所示:

        在UG471用户手册中指出如果只采用一个OSERDESE2只能实现8:1的转换速率,当采用10:1或者14:1转换的时候,需要采用两个原语级联的方式。我们需要将 10bit 数据进行串行化,因此根据文档说明,我们需要使用两个OSERDESE2原语进行级联,OSERDESE2 原语的 Master 端承接 10bit 数据的低 8 位,OSERDESE2 原语的 Slave 端的 D1、D2 不使用,D3 和 D4 承接10bit数据的高 2bit,(若是14:1则可以继续使用D5,D6,D7,D8,依然不使用D1,D2)。并将 Slave 的输出 SHIFTOUT1, SHIFTOUT2 连接到 master 的 SHIFTIN1, SHIFTIN2,输入的 10bit 数据将会按照由低位到高位的顺序从 DataOut 端输出。因此可以通过对位宽的拓展实现10:1的转换,转换模型图如下所示:

        OSERDESE2原语获取方法如下所示:

         原语的使用可以参考Xilinx提供的手册UG768。这一部分原语的使用本人在使用时出现了问题所以这部分代码就不贴出,后续验证正确,在贴出这段代码。

(4)差分模块设计:

        OBUFDS原语用于将三路数据和一路时钟信号转换成差分信号输出,OBUFDS 是差分输出缓冲器,用于将来自 FPGA 内部逻辑的信号转换成差分信号输出,支持 TMDS 电平标准。OBUFDS 原语示意图如下所示:

 OBUFDS获取途径如下所示:

为了程序简单化,可以将此模块也放入上面 Serializer10_1 模块的 OSERDESE2 调用后面,如下所示:

OBUFDS
#(
   .IOSTANDARD      ("DEFAULT"      ), // Specify the output I/O standard
   .SLEW            ("SLOW"         )  // Specify the output slew rate
)
OBUFDS_inst
(
   .O               (do_p           ), // Diff_p output (connect directly to top-level port)
   .OB              (do_n           ), // Diff_n output (connect directly to top-level port)
   .I               (do             )  // Buffer input
);

(5)模块链接设计:

        创建一个HDMI_trans模块将上述编码,由于本人能力有限,采用的是黑金提供的链接代码,并没有采用上述的原语设计,代码就不采用贴出。后续如果自己能完整调试出代码,那么在后续贴出代码,感谢各位理解

(6)顶层模块设计:

        可以看出 HDMI 模块还是比较复杂的,因此我们添加 VGA 时序模块,和 HDMI_trans 模块一起封装成顶层模块,以后可以直接把这个模块拿来用。HDMI_top 的框图如下所示(此模块也是黑金AX7050所提供的代码生成的模块):

六、上板现象:

建立工程,编译下载后会产生一个彩条,最后结果如下:

 参考资料:

[1]黑金FPGA开发手册

[2]野火FPGA开发指南

[3]协议——HDMI - 咸鱼FPGA - 博客园 (cnblogs.com)https://www.cnblogs.com/xianyufpga/p/12114497.html#:~:text=HDMI%20%E6%98%AF%E6%96%B0%E4%B8%80%E4%BB%A3%E7%9A%84%E5%A4%9A%E5%AA%92%E4%BD%93%E6%8E%A5%E5%8F%A3%E6%A0%87%E5%87%86%EF%BC%8C%E8%8B%B1%E6%96%87%E5%85%A8%E7%A7%B0%E6%98%AF%20High-Definition,Multimedia%20Interface%EF%BC%8C%E5%8D%B3%E9%AB%98%E6%B8%85%E5%A4%9A%E5%AA%92%E4%BD%93%E6%8E%A5%E5%8F%A3%E3%80%82%20%E5%AE%83%E8%83%BD%E5%A4%9F%E5%90%8C%E6%97%B6%E4%BC%A0%E8%BE%93%E8%A7%86%E9%A2%91%E5%92%8C%E9%9F%B3%E9%A2%91%EF%BC%8C%E7%AE%80%E5%8C%96%E4%BA%86%E8%AE%BE%E5%A4%87%E7%9A%84%E6%8E%A5%E5%8F%A3%E5%92%8C%E8%BF%9E%E7%BA%BF%EF%BC%9B%E5%90%8C%E6%97%B6%E6%8F%90%E4%BE%9B%E4%BA%86%E6%9B%B4%E9%AB%98%E7%9A%84%E6%95%B0%E6%8D%AE%E4%BC%A0%E8%BE%93%E5%B8%A6%E5%AE%BD%EF%BC%8C%E5%8F%AF%E4%BB%A5%E4%BC%A0%E8%BE%93%E6%97%A0%E5%8E%8B%E7%BC%A9%E7%9A%84%E6%95%B0%E5%AD%97%E9%9F%B3%E9%A2%91%E5%8F%8A%E9%AB%98%E5%88%86%E8%BE%A8%E7%8E%87%E8%A7%86%E9%A2%91%E4%BF%A1%E5%8F%B7%E3%80%82

有关接口:基于FPGA的HDMI接口设计的更多相关文章

  1. ruby-on-rails - Rails - 子类化模型的设计模式是什么? - 2

    我有一个模型:classItem项目有一个属性“商店”基于存储的值,我希望Item对象对特定方法具有不同的行为。Rails中是否有针对此的通用设计模式?如果方法中没有大的if-else语句,这是如何干净利落地完成的? 最佳答案 通常通过Single-TableInheritance. 关于ruby-on-rails-Rails-子类化模型的设计模式是什么?,我们在StackOverflow上找到一个类似的问题: https://stackoverflow.co

  2. ruby-on-rails - 使用 rails 4 设计而不更新用户 - 2

    我将应用程序升级到Rails4,一切正常。我可以登录并转到我的编辑页面。也更新了观点。使用标准View时,用户会更新。但是当我添加例如字段:name时,它​​不会在表单中更新。使用devise3.1.1和gem'protected_attributes'我需要在设备或数据库上运行某种更新命令吗?我也搜索过这个地方,找到了许多不同的解决方案,但没有一个会更新我的用户字段。我没有添加任何自定义字段。 最佳答案 如果您想允许额外的参数,您可以在ApplicationController中使用beforefilter,因为Rails4将参数

  3. 叮咚买菜基于 Apache Doris 统一 OLAP 引擎的应用实践 - 2

    导读:随着叮咚买菜业务的发展,不同的业务场景对数据分析提出了不同的需求,他们希望引入一款实时OLAP数据库,构建一个灵活的多维实时查询和分析的平台,统一数据的接入和查询方案,解决各业务线对数据高效实时查询和精细化运营的需求。经过调研选型,最终引入ApacheDoris作为最终的OLAP分析引擎,Doris作为核心的OLAP引擎支持复杂地分析操作、提供多维的数据视图,在叮咚买菜数十个业务场景中广泛应用。作者|叮咚买菜资深数据工程师韩青叮咚买菜创立于2017年5月,是一家专注美好食物的创业公司。叮咚买菜专注吃的事业,为满足更多人“想吃什么”而努力,通过美好食材的供应、美好滋味的开发以及美食品牌的孵

  4. 基于C#实现简易绘图工具【100010177】 - 2

    C#实现简易绘图工具一.引言实验目的:通过制作窗体应用程序(C#画图软件),熟悉基本的窗体设计过程以及控件设计,事件处理等,熟悉使用C#的winform窗体进行绘图的基本步骤,对于面向对象编程有更加深刻的体会.Tutorial任务设计一个具有基本功能的画图软件**·包括简单的新建文件,保存,重新绘图等功能**·实现一些基本图形的绘制,包括铅笔和基本形状等,学习橡皮工具的创建**·设计一个合理舒适的UI界面**注明:你可能需要先了解一些关于winform窗体应用程序绘图的基本知识,以及关于GDI+类和结构的知识二.实验环境Windows系统下的visualstudio2017C#窗体应用程序三.

  5. postman接口测试工具-基础使用教程 - 2

    1.postman介绍Postman一款非常流行的API调试工具。其实,开发人员用的更多。因为测试人员做接口测试会有更多选择,例如Jmeter、soapUI等。不过,对于开发过程中去调试接口,Postman确实足够的简单方便,而且功能强大。2.下载安装官网地址:https://www.postman.com/下载完成后双击安装吧,安装过程极其简单,无需任何操作3.使用教程这里以百度为例,工具使用简单,填写URL地址即可发送请求,在下方查看响应结果和响应状态码常用方法都有支持请求方法:getpostputdeleteGet、Post、Put与Delete的作用get:请求方法一般是用于数据查询,

  6. LC滤波器设计学习笔记(一)滤波电路入门 - 2

    目录前言滤波电路科普主要分类实际情况单位的概念常用评价参数函数型滤波器简单分析滤波电路构成低通滤波器RC低通滤波器RL低通滤波器高通滤波器RC高通滤波器RL高通滤波器部分摘自《LC滤波器设计与制作》,侵权删。前言最近需要学习放大电路和滤波电路,但是由于只在之前做音乐频谱分析仪的时候简单了解过一点点运放,所以也是相当从零开始学习了。滤波电路科普主要分类滤波器:主要是从不同频率的成分中提取出特定频率的信号。有源滤波器:由RC元件与运算放大器组成的滤波器。可滤除某一次或多次谐波,最普通易于采用的无源滤波器结构是将电感与电容串联,可对主要次谐波(3、5、7)构成低阻抗旁路。无源滤波器:无源滤波器,又称

  7. 计算机毕业设计ssm+vue基本微信小程序的小学生兴趣延时班预约小程序 - 2

    项目介绍随着我国经济迅速发展,人们对手机的需求越来越大,各种手机软件也都在被广泛应用,但是对于手机进行数据信息管理,对于手机的各种软件也是备受用户的喜爱小学生兴趣延时班预约小程序的设计与开发被用户普遍使用,为方便用户能够可以随时进行小学生兴趣延时班预约小程序的设计与开发的数据信息管理,特开发了小程序的设计与开发的管理系统。小学生兴趣延时班预约小程序的设计与开发的开发利用现有的成熟技术参考,以源代码为模板,分析功能调整与小学生兴趣延时班预约小程序的设计与开发的实际需求相结合,讨论了小学生兴趣延时班预约小程序的设计与开发的使用。开发环境开发说明:前端使用微信微信小程序开发工具:后端使用ssm:VU

  8. kvm虚拟机安装centos7基于ubuntu20.04系统 - 2

    需求:要创建虚拟机,就需要给他提供一个虚拟的磁盘,我们就在/opt目录下创建一个10G大小的raw格式的虚拟磁盘CentOS-7-x86_64.raw命令格式:qemu-imgcreate-f磁盘格式磁盘名称磁盘大小qemu-imgcreate-f磁盘格式-o?1.创建磁盘qemu-imgcreate-fraw/opt/CentOS-7-x86_64.raw10G执行效果#ls/opt/CentOS-7-x86_64.raw2.安装虚拟机使用virt-install命令,基于我们提供的系统镜像和虚拟磁盘来创建一个虚拟机,另外在创建虚拟机之前,提前打开vnc客户端,在创建虚拟机的时候,通过vnc

  9. ruby-on-rails - 设计注册确认 - 2

    我在我的项目中有一个用户和一个管理员角色。我使用Devise创建了身份验证。在我的管理员角色中,我没有任何确认。在我的用户模型中,我有以下内容:devise:database_authenticatable,:confirmable,:recoverable,:rememberable,:trackable,:validatable,:timeoutable,:registerable#Setupaccessible(orprotected)attributesforyourmodelattr_accessible:email,:username,:prename,:surname,:

  10. ruby-on-rails - 设计通过 reset_password_token 获取用户 - 2

    我正在尝试创建密码规则来设计可恢复的密码更改。我通过passwords_controller.rb做了一个父类(superclass),但我需要在应用规则之前检查用户角色,但我所拥有的只是reset_password_token。 最佳答案 假设您的模型是用户:User.with_reset_password_token(your_token_here)Source 关于ruby-on-rails-设计通过reset_password_token获取用户,我们在StackOverflow

随机推荐