VGA原理与FPGA实现

推荐参考小梅哥视频学习
使用FPGA驱动VGA不适合用来显示复杂多变的图像内容,但是却常用于显示实时图像内容,例如显示图像传感器实时采集到的图像。此种方式数据流由图像传感器实时提供,FPGA只需要控制好图像数据流的存储和传输即可,无需主动生成需要绘制的图像数据,所以实现相对简单。

我们来看看生活中常见到的VGA接口:

见识过 VGA 接口的外观,接下来对接口各引脚功能并没有进一步的认识,下
面,我们结合 VGA 接口引脚图和各引脚定义表格,对 VGA 接口各引脚做一下简单介绍:


上图中,引脚标黄的就是我们需要着重掌握的。我们再来看看Digilent公司给的参考图:

最后一句:To understand how these signals should be driven, we need to take a look at how our monitors actually work.不过在这里关于VGA显示器成像原理不管是CRT还是液晶显示器都不做赘述(有需要的可以去官网等地方学习),我们直接从它的时序分析,从而深入理解。

一、VGA时序详解

由于VGA时序的诞生,最早就是为了驱动阴极射线管(CRT)。也因为CRT的物理特性,才有了多个与之相关的物理时间参数,所以为了让大家彻底理解VGA时序中各个参数的物理意义,这里以一张图像在基于CRT结构的显示器上显示为例,介绍显示器完整展现这幅图的各个阶段和每个阶段的物理意义。

该图片来源于:小梅哥《VGA控制器设计与验证》文档。可能在不同的地方看到的有一些出入,只要理解他的含义就好,下图再给出Digilent公司的参考图:

从上面两张图可以看出白底的卡通人物图像(Display Area)就是我们希望显示的图像内容。我们的目的就是要让该图像恰好完全显示在显示器上。而CRT是怎么样实现图像显示的呢? 它是通过对一张图片进行一行一行的扫描,原理如下图:

1.CRT行扫描过程

对于CRT显示器,虽然扫描的时候是按照一行一行的方式进行的,但不是扫描完一行有效数据段之后就立马返回,而是会继续向右扫描一段区域,这个区域称为右边界区域(horizontal right border),该区域已经不在有效的显示范围内,如果从物理结构的角度来说,这一段对应的荧光屏玻璃上就不再有荧光粉了,但是电子枪还在继续向右走,大家可以形象理解为显示器右边的黑边。同理,也有左边界区域(horizontal left border)。可以参考图中Display Area周围的Border(边界)

那么,电子枪什么时候会到最左侧准备开始新一行图像的扫描呢?当电子枪扫描一行图像到达荧光屏的最右端后,其并不会自动回到最左边准备下一行,而是需要有一个通知信号,通知其回去,这个通知信号就是行同步信号脉冲(horizontal sync pulse)。行同步信号是一个脉冲,当该脉冲出现后,电子枪的指向会在一定时间内从最右侧回到显示屏的最左侧。而这个回去的过程需要耗费一定的时间,这个时间就称为horizontal back porch。这也是这个名词中back的意义所在,即出现行同步信号后,电子枪从显示屏最右侧回到最左侧的时间。

当电子枪扫描过了右侧没有荧光粉的区域后,还没有收到回到最左侧的命令(行同步信号脉冲)之前,电子枪需要关闭以实现消隐,这个消隐的时间段就称为horizontal front porch,直观一点理解就是完成了一行图像的扫描,但还没收到回到最左侧命令之前的一段时间。这也是这个名词中front的意义所在。

2.CRT场扫描过程

理解了行扫描中的"参数"含义理解场扫描中的名词就非常简单了。首先来讲,CRT在扫描一行图像的时候,电子枪的水平位置是保持稳定不变的,而当一行图像扫描完成,开始扫描下一行图像的时候,电子枪的水平位置会向下调整一定的值。因此,我们可以认为,场时序就是在垂直方向上从上往下依次扫描。

其次来说,对于CRT显示器来说,其不是扫描完所有行的图像后就立马返回最上方,而是会继续向下扫描一段区域,这个区域称为下边界区域(vertical bottom border),该区域已经不在有效的显示范围内,如果从物理结构的角度来说,这一段对应的荧光屏玻璃上就不再有荧光粉了,但是电子枪还在继续向下走,大家可以形象理解为显示器下边的黑边。同样的,显示器上边也有这样一段黑边,在开始显示有效数据之前,电子枪扫描到的这段区域同样也是没有荧光粉的,不会显示图像, 这个区域称为上边界区域(vertical top border)。

再来说说,电子枪什么时候会到最上方准备开始新一场图像的扫描。当电子枪扫描一场图像到达荧光屏的最下方后,其并不会自动回到最上边准备下一场,而是需要有一个通知信号,通知其回去,这个通知信号就是场同步信号脉冲(vertical sync pulse)。场同步信号是一个脉冲,当该脉冲出现后,电子枪的指向会在一定时间内从最下方回到显示屏的最上方。而这个回去的过程需要耗费一定的时间,这个时间就称为vertical back porch。这也是这个名词中back的意义所在,即出现场同步信号后,电子枪从显示屏最下方回到最上方的时间。

当电子枪扫描过了下方没有荧光粉的区域后,还没有收到回到最上方的命令(场同步信号脉冲)之前,电子枪需要关闭以实现消隐,这个消隐的时间段就称为vertical front porch,直观一点理解就是完成了一场图像的扫描,但还没收到回到最上方命令之前的一段时间。这也是这个名词中front的意义所在。

3.VGA时序

在上面介绍行、场同步脉冲信号的时候,我们只说了是脉冲信号,但是并未定义脉冲信号的极性,VGA时序标准支持四种极性,但是并不是所有的显示设备都支持这四种极性,本文默认以应用最为广泛的行、场同步信号都为低脉冲进行介绍。所谓行、场同步信号都是低电平,就是说在产生同步脉冲信号的时候,行、场同步信号变为低电平,其他时刻为高电平。注意:Digilent公司提供的参考图中是以高脉冲为例,但是其下开发板并不都是高脉冲。
下图分别为行扫描时序和场扫描时序的示意图。


上述两幅图中,都只给出了时序参数的名称,并没有给出每个参数具体的值是多少。而每个参数具体的值是多少,并不是固定的,而是根据需要扫描的有效图像区域的大小确定的。需要扫描的有效图像区域的大小,一般用分辨率来表示。例如标准VGA时序的分辨率就是640*480个像素点。除了VGA标准,还有很多表示更大或更小分辨率的标准,如QVGA、SVGA、XVGA等等。

4.各常见分辨率时序参数

下表给出了若干个常见分辨率对应的行场时序中各个参数的具体数值,注意,这些参数值中,行相关的参数都是以像素的更新频率,也就是像素时钟作为单位,而场相关的参数,则是以行作为单位


即使 VGA 显示分辨率相同,但刷新频率不同的话,相关参数也存在差异,如 640x480@60、640x480@75,这两个显示模式虽然具有相同的分辨率,但是 640x480@75 的刷新频率更快,所以像素时钟更快,时序参数也有区别。
下面我们以显示模式 640x480@60、640x480@75 为例,学习一下时钟频率的计算方法。

行扫描周期 * 场扫描周期 * 刷新频率 = 时钟频率

640x480@60
行扫描周期:800(像素),场扫描周期:525(行扫描周期) 刷新频率:60Hz
800 * 525 * 60 = 25,200,000 ≈ 25.175MHz (误差忽略不计)
640x480@75:
行扫描周期:840(像素) 场扫描周期:500(行扫描周期) 刷新频率:75Hz
840 * 500 * 75 = 31,500,000 = 31.5MHz

计算时钟频率时,读者要谨记一点,要使用行扫描周期和场扫描周期的参数进行计算不能使用有效图像的参数进行计算,虽然在有效图像外的其他阶段图像信息均无效,但图像无效阶段的扫描也花费了扫描时间。

二、640*480分辨率VGA 控制器设计与验证

有关于设计思路呢,我认为从宏观上来说Digilent公司介绍的不错:

尤其是上图框图中的计数器、时钟分频器写的很清楚,当然细节一步步的代码怎么写如果要仔细介绍,就过于冗余了,相信很多人看了时序分析就已经会自己写了,如果不会写,可以随机搜一个代码啃一遍肯定会获益更多。

设计代码
module VGA_CTRL(Clk,Reset_n,Data,Data_Req,hcount,vcount,VGA_HS,VGA_VS,VGA_BLK,VGA_RGB);input Clk;input Reset_n;input [23:0]Data;output reg Data_Req;   //根据波形调试得到output reg [9:0]hcount; //当前扫描点的有效图片H坐标output reg [9:0]vcount; //当前扫描点的有效图片V坐标       用于test模块output reg VGA_HS;output reg VGA_VS; output reg VGA_BLK;   //BLK表示的就是 输出有效图片 信号  高电平有效output reg [23:0]VGA_RGB;//  RGB888localparam Hsync_End = 800;          //行扫描结束   即行的总时间     单位 像素时钟localparam HS_End = 96;                //行同步信号脉冲localparam Vsync_End = 525;          //场扫描结束   即场的总时间      单位   行localparam VS_End = 2;                   //场同步信号脉冲localparam Hdat_Begin = 144;        //行输出有校图片  开始localparam Hdat_End = 784;           //行输出有校图片  结束localparam Vdat_Begin =  35;         //场输出有校图片  开始localparam Vdat_End = 515;           //场输出有校图片  结束//行扫描计数器reg [9:0]hcnt;always@(posedge Clk or negedge Reset_n)if(!Reset_n)hcnt <= 0;else if(hcnt >= Hsync_End -1)hcnt <= 0;elsehcnt <= hcnt + 1'b1;//行同步信号always@(posedge Clk)VGA_HS <= (hcnt < HS_End)?0:1;        //用的使能是常见的低脉冲有效//场扫描计数器    reg [9:0]vcnt;always@(posedge Clk or negedge Reset_n)if(!Reset_n)vcnt <= 0;else if(hcnt == Hsync_End -1)beginif(vcnt >= Vsync_End -1)vcnt <= 0;elsevcnt <= vcnt + 1'd1;endelsevcnt <= vcnt;//场同步信号        always@(posedge Clk)VGA_VS  <= (vcnt < VS_End)?0:1;//BLK表示的就是输出有效图片 部分always@(posedge Clk)Data_Req <= ((hcnt >= Hdat_Begin - 1) && (hcnt < Hdat_End - 1) && (vcnt >= Vdat_Begin) && (vcnt < Vdat_End))?1:0;always@(posedge Clk)VGA_BLK <= Data_Req;     always@(posedge Clk)VGA_RGB <= Data_Req? Data:0;            always@(posedge Clk)hcount <= Data_Req? hcnt - Hdat_Begin:0; always@(posedge Clk)vcount <= Data_Req? vcnt - Vdat_Begin:0;         endmodule
测试代码
`timescale 1ns / 1psmodule VGA_CRTL_tb ;reg Clk;reg Reset_n;reg [23:0]Data;wire Data_Req;wire [9:0]hcount;wire [8:0]vcount;wire VGA_HS;wire VGA_VS; wire VGA_BLK;wire [23:0]VGA_RGB;//{R[7:0]、G[7:0]、B[7:0]}VGA_CTRL VGA_CTRL(Clk,Reset_n,Data,Data_Req,hcount,vcount,VGA_HS,VGA_VS,VGA_BLK,VGA_RGB);initial Clk = 1;always #20 Clk = ~Clk;//HS 的变化位置//VS 的变化位置//待显示数据和HS、VS的位置关系initial beginReset_n = 0;#201;Reset_n = 1;#200000000;$stop;endalways@(posedge Clk or negedge Reset_n)if(!Reset_n)Data <= 0;else if(!Data_Req)Data <= Data;elseData <= Data + 1'd1;endmodule
仿真结果


仿真结果建议自己跑一下,然后对照时序挨个验证一下,关于这里的代码主要注意两点:
1.Data_Req 和 VGA_BLK
2.hcnt和VGA_HS在仿真结果中可能得理解一下

三、拓展

1.等宽彩条

VGA控制器的像素时钟为25MHz,而很多开发板或者晶振提供的是50MHz的时钟,所以首先大家可以在在vivado下的clocking wizard配置25MHz时钟,这里我配置中没有选择reset和locked。

module VGA_CTRL_test(Clk,Reset_n,VGA_RGB,    //有效数据输出VGA_HS,     //行同步信号VGA_VS,     //场同步信号VGA_BLK,   //VGA 场消隐信号VGA_CLK   //25MHz);input Clk;input Reset_n;output [23:0] VGA_RGB;output VGA_HS;output VGA_VS;output VGA_BLK;output VGA_CLK;reg disp_data;wire Clk25M;wire Data_Req;wire [9:0] hcount;wire [9:0] vcount;assign VGA_CLK= Clk25M;vga_pll vga_pll(.clk_out1(Clk25M),.clk_in1(Clk));VGA_CTRL VGA_CTRL(.Clk(Clk25M),.Reset_n(Reset_n),.Data(disp_data),.Data_Req(Data_Req),.hcount(hcount),.vcount(vcount),.VGA_HS(VGA_HS),.VGA_VS(VGA_VS),.VGA_BLK(VGA_BLK),.VGA_RGB(VGA_RGB));//定义颜色编码
localparam BLACK         = 24'h000000, //黑色BLUE            = 24'h0000FF, //蓝色RED                = 24'hFF0000, //红色PURPPLE        = 24'hFF00FF, //紫色GREEN       = 24'h00FF00, //绿色CYAN         = 24'h00FFFF, //青色YELLOW      = 24'hFFFF00, //黄色WHITE        = 24'hFFFFFF; //白色//定义每个像素块的默认显示颜色值
localparam R0_C0 = BLACK,  //第0行0列像素块R0_C1 = BLUE,   //第0行1列像素块R1_C0 = RED,    //第1行0列像素块R1_C1 = PURPPLE,//第1行1列像素块R2_C0 = GREEN,  //第2行0列像素块R2_C1 = CYAN,   //第2行1列像素块R3_C0 = YELLOW, //第3行0列像素块R3_C1 = WHITE;  //第3行1列像素块wire R0_act = vcount >= 0 && vcount < 120;  //正在扫描第0行wire R1_act = vcount >= 120 && vcount < 240;//正在扫描第1行wire R2_act = vcount >= 240 && vcount < 360;//正在扫描第2行wire R3_act = vcount >= 360 && vcount < 480;//正在扫描第3行wire C0_act = hcount >= 0 && hcount < 320; //正在扫描第0列wire C1_act = hcount >= 320 && hcount < 640;//正在扫描第1列 wire R0_C0_act=R0_act & C0_act;//第0行0列像素块处于被扫描中标志信号wire R0_C1_act=R0_act & C1_act;//第0行1列像素块处于被扫描中标志信号wire R1_C0_act=R1_act & C0_act;//第1行0列像素块处于被扫描中标志信号wire R1_C1_act=R1_act & C1_act;//第1行1列像素块处于被扫描中标志信号wire R2_C0_act=R2_act & C0_act;//第2行0列像素块处于被扫描中标志信号wire R2_C1_act=R2_act & C1_act;//第2行1列像素块处于被扫描中标志信号wire R3_C0_act=R3_act & C0_act;//第3行0列像素块处于被扫描中标志信号wire R3_C1_act=R3_act & C1_act;//第3行1列像素块处于被扫描中标志信号always@(*)case({R3_C1_act,R3_C0_act,R2_C1_act,R2_C0_act,R1_C1_act,R1_C0_act,R0_C1_act,R0_C0_act})8'b0000_0001:disp_data = R0_C0;8'b0000_0010:disp_data = R0_C1;8'b0000_0100:disp_data = R1_C0;8'b0000_1000:disp_data = R1_C1;8'b0001_0000:disp_data = R2_C0;8'b0010_0000:disp_data = R2_C1;8'b0100_0000:disp_data = R3_C0;8'b1000_0000:disp_data = R3_C1;default:disp_data = R0_C0;endcaseendmodule

2.多分辨率适配型VGA控制器设计

**条件编辑原理:**所谓条件编译,就是当设计中满足某个条件时,将该条件下的一段代码编译进设计中。因此,我们只需要合理设置编译条件,并在对应的编译条件下编写正确的代码,就可以实现条件编译。以一个最简单的例子来说明。
对于一个最简单的16位计数器,我们可以根据不同的需求,设置其计数的最大值,从而来设置其计数一周所占用的时间。假设这个计数最大值用CNT_MAX表示,如果定义了工作在条件一(CASE_A)的情况下,该计数最大值为2000,如果定义了工作在条件二(CASE_B)的情况下,该计数最大值为2500,则该代码可以按照如下方式编写。

`define CASE_A
//`define CASE_B`ifdef CASE_A`define CNT_MAX 2000
`elsif CASE_B`define CNT_MAX 2500
`endif

实际使用时,只需要在代码中定义工作在条件一还是条件二,就能选择让CNT_MAX为对应的值。在Verilog代码中,只需要直接使用CNT_MAX这个参数即可,如下所示。

always@(posedge Clk or negedge Rst_n)
if(!Rst_n)cnt <= 0;
else if(cnt == `CNT_MAX)cnt <= 0;
elsecnt <= cnt + 1'b1;

代码

//`define Resolution_480x272 1  //刷新率为60Hz时像素时钟为9MHz
//`define Resolution_640x480 1 //刷新率为60Hz时像素时钟为25.175MHz
`define Resolution_800x480 1   //刷新率为60Hz时像素时钟为33MHz
//`define Resolution_800x600 1 //刷新率为60Hz时像素时钟为40MHz
//`define Resolution_1024x768 1    //刷新率为60Hz时像素时钟为65MHz
//`define Resolution_1280x720 1    //刷新率为60Hz时像素时钟为74.25MHz
//`define Resolution_1920x1080 1   //刷新率为60Hz时像素时钟为148.5MHz`ifdef Resolution_480x272    `define H_Right_Border 0`define H_Front_Porch 2`define H_Sync_Time 41`define H_Back_Porch 2`define H_Left_Border 0`define H_Data_Time 480`define H_Total_Time 525`define V_Bottom_Border 0`define V_Front_Porch 2`define V_Sync_Time 10`define V_Back_Porch 2`define V_Top_Border 0`define V_Data_Time 272`define V_Total_Time 286`elsif Resolution_640x480`define H_Total_Time  12'd800`define H_Right_Border  12'd8`define H_Front_Porch  12'd8`define H_Sync_Time  12'd96`define H_Data_Time 12'd640`define H_Back_Porch  12'd40`define H_Left_Border  12'd8`define V_Total_Time  12'd525`define V_Bottom_Border  12'd8`define V_Front_Porch  12'd2`define V_Sync_Time  12'd2`define V_Data_Time 12'd480`define V_Back_Porch  12'd25`define V_Top_Border  12'd8`elsif Resolution_800x480`define H_Total_Time 12'd1056`define H_Right_Border 12'd0`define H_Front_Porch 12'd40`define H_Sync_Time 12'd128`define H_Data_Time 12'd800`define H_Back_Porch 12'd88`define H_Left_Border 12'd0`define V_Total_Time 12'd525`define V_Bottom_Border 12'd8`define V_Front_Porch 12'd2`define V_Sync_Time 12'd2`define V_Data_Time 12'd480`define V_Back_Porch 12'd25`define V_Top_Border 12'd8`elsif Resolution_800x600`define H_Total_Time 12'd1056`define H_Right_Border 12'd0`define H_Front_Porch 12'd40`define H_Sync_Time 12'd128`define H_Data_Time 12'd800`define H_Back_Porch 12'd88`define H_Left_Border 12'd0`define V_Total_Time 12'd628`define V_Bottom_Border 12'd0`define V_Front_Porch 12'd1`define V_Sync_Time 12'd4`define V_Data_Time 12'd600`define V_Back_Porch 12'd23`define V_Top_Border 12'd0`elsif Resolution_1024x768`define H_Total_Time 12'd1344`define H_Right_Border 12'd0`define H_Front_Porch 12'd24`define H_Sync_Time 12'd136`define H_Data_Time 12'd1024`define H_Back_Porch 12'd160`define H_Left_Border 12'd0`define V_Total_Time 12'd806`define V_Bottom_Border 12'd0`define V_Front_Porch 12'd3`define V_Sync_Time 12'd6`define V_Data_Time 12'd768`define V_Back_Porch 12'd29`define V_Top_Border 12'd0`elsif Resolution_1280x720`define H_Total_Time 12'd1650`define H_Right_Border 12'd0`define H_Front_Porch 12'd110`define H_Sync_Time 12'd40`define H_Data_Time 12'd1280`define H_Back_Porch 12'd220`define H_Left_Border 12'd0`define V_Total_Time 12'd750`define V_Bottom_Border 12'd0`define V_Front_Porch 12'd5`define V_Sync_Time 12'd5`define V_Data_Time 12'd720`define V_Back_Porch 12'd20`define V_Top_Border 12'd0`elsif Resolution_1920x1080`define H_Total_Time 12'd2200`define H_Right_Border 12'd0`define H_Front_Porch 12'd88`define H_Sync_Time 12'd44`define H_Data_Time 12'd1920`define H_Back_Porch 12'd148`define H_Left_Border 12'd0`define V_Total_Time 12'd1125`define V_Bottom_Border 12'd0`define V_Front_Porch 12'd4`define V_Sync_Time 12'd5`define V_Data_Time 12'd1080`define V_Back_Porch 12'd36`define V_Top_Border 12'd0  `endif

修改VGA_CTRL模块中的hcount和vcount的位宽,以及相关参数:

    `include "vga_parameter.v"            //注意该命令localparam Hsync_End = `H_Total_Time;localparam HS_End = `H_Sync_Time;localparam Hdat_Begin = `H_Sync_Time + `H_Back_Porch + `H_Left_Border;localparam Hdat_End = `H_Sync_Time + `H_Left_Border + `H_Back_Porch + `H_Data_Time;localparam Vsync_End = `V_Total_Time;localparam VS_End = `V_Sync_Time;localparam Vdat_Begin =  `V_Sync_Time + `V_Back_Porch + `V_Top_Border;localparam Vdat_End = `V_Sync_Time + `V_Back_Porch + `V_Top_Border + `V_Data_Time;

参考文献:
小梅哥VGA学习资料
野火FPGA学习资料
添加链接描述Digilent 的 VGA Display Controller

【边学边记_12】——VGA原理与FPGA实现相关推荐

  1. python 实现记牌器原理

    python 实现记牌器原理 方案一(减牌记牌) 方案二(增牌记牌) 字典Update更新初学者常见报错问题 方案一(减牌记牌) 假设与这"333445667788QQJ"十五张牌 ...

  2. laocchang的Linux随学随记

    Linux随学随记 README 系统目录结构 前置 目录作用 附 /mnt : Mount point for a temporarily mounted filesystem Purpose /m ...

  3. 1024点fft原理及fpga实现

    1024点fft原理及fpga实现 关于傅里叶变换的原理,可以参考以下的博文: 如何理解傅里叶变换公式. FFT即快速傅里叶变换,是有限长序列作离散傅里叶变换(DFT)的快速算法. DFT公式为 X[ ...

  4. iOS 边学边记 直播原理总结,从理论到实践

    一.直播原理及流程 1.一个完整直播app原理 直播原理:把主播录制的视频,推送到服务器,在由服务器分发给观众观看. 直播环节:推流端(采集.美颜处理.编码.推流).服务端处理(转码.录制.截图.鉴黄 ...

  5. 学完java后学编译原理_一个资深程序员对Java初学者的学习思维路线建议

    如何学习Java,学完后尽快成为一个可以参加工作的Java开发者.现在还在待业期间,如何准备转行学习Java.相信很多初学java者都在考虑这个问题. 如果你是在校学生,务必要在学好基础(比如计算机系 ...

  6. JVM 调优 2:GC 如何判断对象是否为垃圾,三色标记算法应用原理及存在的问题?

    文章目录 前言 一.如何判断一个对象是否为垃圾? 1.1.reference count(引用计数) 1.2.reference count(引用计数)存在的问题 二.Root Searching(根 ...

  7. 学php记不住函数,为什么都是记不住PHP 的函数名

    为什么都是记不住PHP 的函数名 回复讨论(解决方案) 用多了就记住了 虽然 php 的函数很多,但常用的也就几十个 恩.刚开始是这样.用多了自然就能记住了. 翁曰:我亦无他,唯手熟尔 恩,干程序员久 ...

  8. 计算机怎么学要记笔记,留法十全大补汤 | 学姐告诉你在法国上课如何记笔记,复习,考试!...

    原标题:留法十全大补汤 | 学姐告诉你在法国上课如何记笔记,复习,考试! ▣开学有一段时间啦,各位同学上课感觉怎么样?是不是已经开始在票圈嗷嗷吐槽法国人上课的节奏了? 学姐作为过来人,今天就跟大家分享 ...

  9. 我的学厨记——香煎鸡翅

     前记:近日书协要办书法展览 ,要求交作品回去参展 ,昨晚拿作品(质量很不满意 )回学校,路上闲来无事,想起过年时候在小姨家吃的鸡翅 ,口感很不错   ,想到昨天学的妙味排骨还剩下点香料,反正是五一放 ...

最新文章

  1. 二叉树(遍历、建立、深度)
  2. SAP Spartacus 的 Above-the-Fold Loading 加载机制
  3. 最短路径算法----floyd(转)
  4. java io-File
  5. NLP之路-一点小语言工具函数
  6. python实战运用_python实例运用
  7. TM1640驱动程序
  8. linux如何生成awr报告,手工生成AWR报告方法记录
  9. Android竖屏视频录制
  10. namecheap域名解析
  11. 《Python程序设计(第3版)》[美] 约翰·策勒(John Zelle) 第 9 章 答案
  12. 2017年异步社区优秀图书和作译者评选TOP10
  13. JVM参数-XX:+HeapDumpOnOutOfMemoryError使用方法
  14. mysqladmin命令简介
  15. 植入「电子神经」,瘫痪小鼠也能踢球,鲍哲南团队成果登Nature子刊
  16. HTML5+css+jquery网页设计+加静态网页部署到服务器上
  17. Matlab中将行向量转为列向量的方法
  18. 《单片机》实验——实验4 MCS-51内部定时/计数器实验(2)
  19. Junos日常维护命令
  20. Mycat之——实现MySQL垂直分库

热门文章

  1. 【开发】前端工程——ReactJS
  2. python练习之CheckiO-HOME小岛
  3. Android EditText设置弹出数字输入法键盘
  4. 梯度下降与随机梯度下降
  5. 网站运营活动策划方案模板[转载]
  6. 仿知乎日报图文小程序模板
  7. 【高通SDM660平台 Android 10.0】(14) --- Camera ISP
  8. python 视频字幕合并_怎么把字幕和视频合并(教你两者合并方法)
  9. 更改C盘用户名的惨痛教训
  10. 停车场管理系统(一)