我是靠谱客的博主 谦让期待,最近开发中收集的这篇文章主要介绍基于FPGA的两位按键控制LED数码管加减计数实验两位按键控制LED数码管加减计数实验,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

两位按键控制LED数码管加减计数实验

        这是一篇拖了一个多月的文章,主要是基于FPGA利用按键消抖原理与动态数码管驱动原理相结合,来实现一个利用两位按键来控制数码管实现0-99的加法计数或者减法计数功能。

1.1 简介

        本文使用的开发板的LED数码管是采用共阳极连接,关于如何进行驱动,可以搜索相关动态数码管扫描实验,这边不进行过多的复述了。

1.2 实验任务

        本章的实验任务是设计一个两位数码管显示0-99的加减法计数,主要功能是数码管显示数值范围0~99,按下KEY0增1;按下KEY1减1;长按KEY0计数不断增加;长按KEY1计数不断减少。

1.3 软件设计

根据实验任务我们需要画出本次实验的系统模块框图,如下图所示:

如上图所示,可知主要由按键消抖模块,计数器模块以及动态数码管驱动模块组成。

程序中各个模块端口及信号连接如图所示:

顶层模块(top_key_seg)例化了以下三个模块:按键消抖模块(key_debounce)、按键计数器模块(key_cnt)以及数码管动态驱动模块(seg_led)。 

顶层代码如下:

module top_key_led(                     
    input            sys_clk  ,         //时钟
    input            sys_rst_n,         //复位(低电平有效)
	input	[1:0]    key      ,         //两个按键key[0]: add  key[1]:sub
        
        
    output   [5:0]   sel  ,         // 数码管位选信号
    output   [7:0]   seg            // 数码管段选信号
);

//wire define
wire            key_value0;             //按键0有效
wire            key_value1;             //按键1有效
wire            key_flag0;              //按键0有效的标志位
wire            key_flag1;              //按键1有效的标志位

wire    [19:0]  data;                   //数码管显示的数值
wire            en;                     //数码管使能


//*****************************************************
//**                    main code
//*****************************************************

//按键消抖加法模块
key_debounce u_add_key_debounce(
    .sys_clk        (sys_clk),			
    .sys_rst_n      (sys_rst_n),		
    
    .key            (key[0]),			
    .key_flag       (key_flag0),		
    .key_value      (key_value0)		
);

//按键消抖减法模块
key_debounce u_sub_key_debounce1(
    .sys_clk        (sys_clk),			
    .sys_rst_n      (sys_rst_n),	    
    
    .key            (key[1]),		    
    .key_flag       (key_flag1),		
    .key_value      (key_value1)		
);

//计数器模块,产生数码管需要显示的数据
key_cnt u_key_cnt(
    .sys_clk       (sys_clk  ),         
    .sys_rst_n     (sys_rst_n),         
	.key_flag0     (key_flag0),		    
    .key_value0    (key_value0),		
	.key_flag1     (key_flag1),		    
    .key_value1    (key_value1),		
	 
    .data          (data     ),       	
    .en            (en       )      	

);


//数码管模块
seg_dynamic seg_dynamic_inst
(
    .sys_clk     (sys_clk  ), //系统时钟,频率50MHz
    .sys_rst_n   (sys_rst_n), //复位信号,低有效
    .data        (data     ), //数码管要显示的值
    .point       (1'b0     ), //小数点显示,高电平有效
    .seg_en      (1'b1     ), //数码管使能信号,高电平有效
    .sign        (1'b0     ), //符号位,高电平显示负号
                           
    .sel         (sel      ), //数码管位选信号
    .seg         (seg      )  //数码管段选信号
);

endmodule

        顶层模块主要完成对子模块的例化,并且实现各模块之间的信号的交互。按键消抖模块的输出连接计数器模块,计数器模块的输出data和en传递给动态数码管驱动模块,最后将数据从数码管中显示出来。

按键消抖模块的代码如下所示:

1  module key_debounce(                     
2      input            sys_clk	,           //时钟
3      input            sys_rst_n,          //复位信号,低电平有效
4      
5      input            key		,           //外部按键输入
6      output reg       key_flag	,       //按键数据有效信号标志位
7  	   output reg       key_value           //按键有效值  
8      );
9  
10 //parameter define
11 //10ms计数最大值 19'd500_000
12 parameter CNT_10MS_MAX = 19'd500_000; 
13 
14 //reg define    
15 reg [18:0] cnt_10ms;		//计数器
16 reg        key_reg0 ;		//按键寄存器0
17 reg        key_reg1 ;		//按键寄存器1
18 
19 //*****************************************************
20 //**                    main code
21 //*****************************************************
22 
23 //检测按键状态
24 always @(posedge sys_clk or negedge sys_rst_n) begin 
25     if (!sys_rst_n) begin 
26         key_reg0 <= 1'b1;                //按键寄存器低电平有效
27 		key_reg1 <= 1'b1;
28         cnt_10ms <= 19'd0;
29     end
30     else begin
31 		key_reg0 <= key;				    //按键信号给寄存器0
32         key_reg1 <= key_reg0;			//寄存器0的值传送给寄存器1
33 		if(key_reg1 != key_reg0)            //寄存器key0和key1不相等,说明有按键被按下或释放
34             cnt_10ms <= CNT_10MS_MAX;    //10ms延迟计数器
35         else if(cnt_10ms > 19'd0)
36             cnt_10ms <= cnt_10ms - 19'd1;       
37     end   
38 end
39 
40 //给按键消抖后的数据赋值
41 always @(posedge sys_clk or negedge sys_rst_n) begin 
42     if (!sys_rst_n) begin 
43         key_flag  <= 1'b0;
44         key_value <= 1'b1;             
45     end
46     else begin
47         if(cnt_10ms == 19'd1) begin   //当计数器递减到1时,说明按键稳定状态维持了10ms
48             key_flag  <= 1'b1;        //此时消抖过程结束,给出一个时钟周期的标志信号
49             key_value <= key_reg1;    //并寄存此时按键的值
50         end
51         else begin
52             key_flag  <= 1'b0;
53             key_value <= key_value; 
54         end  
55     end   
56 end
57   
58 endmodule 

按键消抖模块从第33行开始不断检测按键有没有被按下,当检测到按键被按下赋给10ms寄存器一个10ms的最大值,然后进行逐一递减,当10ms计数器减到1时,说明按键已经进入稳定状态,按键消抖完成,然后输出一个按键消抖标志位信号同时将按键的有效值记录下来。

按键计数器模块代码如下:

1  module key_cnt(              
2      input               sys_clk  	,	// 时钟信号
3      input               sys_rst_n	,	// 复位信号
4  	input               key_flag0	,	//按键数据有效信号标志位0
5  	input               key_value0	,	//按键消抖后的数据 key0: add
6  	input               key_flag1	,	//按键数据有效信号标志位1
7  	input               key_value1	,	//按键消抖后的数据 key1:sub
8      
9      output   reg [19:0] data 	    ,	// 6个数码管要显示的数值
10     output   reg        en   			// 数码管使能信号
11 );
12 
13 //parameter define
14 //100ms计数最大值 23'd5_000_000
15 parameter CNT_1S_MAX = 26'd50_000_000;
16 parameter CNT_100MS_MAX = 25'd5_000_000;
17 
18 //wire define
19 reg	[25:0]	cnt_1s		;               //1s长按计数器
20 reg			down_flag	;               //长按标志
21 reg	[24:0]	down_100ms	;               //100ms长按累加/减
22 reg			flag	    ;               //长按累加/减标志位
23 
24 //*****************************************************
25 //**                    main code
26 //*****************************************************
27 
28 //判断按键是否处于长按状态
29 always @ (posedge sys_clk or negedge sys_rst_n) begin
30 	if (!sys_rst_n) begin
31 		cnt_1s <= 26'd0;
32 		down_flag <= 1'd0;
33 	end
34 	else if((key_value0 == 1'd1) && (key_value1 == 1'd1)) begin			//按键未被按下时延时计数器和长按标志赋初值
35 		cnt_1s <= 26'd0;
36 		down_flag <= 1'd0;
37 	end
38 	else if( (key_value0 == 1'd0) || (key_value1 == 1'd0) ) begin		//按键按下有效时
39 		if(cnt_1s < CNT_1S_MAX) begin
40 			cnt_1s <= cnt_1s + 1'd1;
41 			down_flag <= 1'd0;
42 		end
43 		else begin																		//延时计数器计数1s时,判定为长按状态,并将长按标志拉高
44 			cnt_1s <= cnt_1s;
45 			down_flag <= 1'd1;
46 		end
47 	end
48 end
49 
50 //长按状态下每100ms,输出一个时钟周期的脉冲信号
51 always @(posedge sys_clk or negedge sys_rst_n) begin
52 	if (!sys_rst_n) begin
53 		down_100ms <= 25'd0;
54 		flag <=	1'd0;
55 	end
56 	else if(down_flag) begin							
57 		if(down_100ms < CNT_100MS_MAX) begin
58 			down_100ms <= down_100ms + 1'd1;
59 			flag	<=	1'd0;
60 		end
61 		else begin
62 			down_100ms <= 25'd0;
63 			flag <=	1'd1;
64 		end	
65 	end
66 end
67 
68 //数码管需要显示的数据,从0到99进行累加/减计算
69 always @(posedge sys_clk or negedge sys_rst_n) begin
70 	if (!sys_rst_n) begin
71 		data <= 20'b0;
72 		en <= 1'b0;
73 	end 
74 	else begin           			
75 		en <= 1'b1;               																			
76 		if ((key_value0 == 1'd0) && (key_flag0 || flag) ) begin		//按键0按下时显示数值按下时累加一次,或长按状态时每隔0.1s累加一次
77 			if(data < 20'd99) 
78 				data <= data + 1'b1;     
79 			else if (data == 20'd99)
80                 data <= 20'd0;
81             else    
82 				data <= data;
83 		end 
84 		else if((key_value1 == 1'd0) && (key_flag1 || flag)) begin	//按键1按下时显示数值按下时累减一次,或长按状态时每隔0.1s累减一次
85 			if(data > 20'd0) 
86 				data <= data - 1'b1;     
87 			else if(data == 20'd0)
88                 data <= 20'd99;
89             else    
90 				data <= data;
91 		end
92 	end 
93 end 
94 
95 endmodule 

按键计数器模块主要实现将消抖后的按键信号,进行进一步判定。在39行之中增加了一个按下超过1s判定为长按的判定,如果超过1s以上的将按键信号判定为长按,并且增加一个长按按键标志位。在长按之后的每0.1s进行对数码管计数累加/减的判定;当按下key0时数码管累加等于99的时候,让数码管数据归零然后继续进行相应的累加,当按下key1进行递减运算的时候,在等于0时,进行一个判定让数码管下一个数据等于99,就完成了本次实验所需求的功能拓展。按键计数模块最后输出一个使能信号以及一个数据信号传递给下一层的数码管驱动模块。

数码管驱动模块:

`timescale  1ns/1ns

// Author  : EmbedFire
// 实验平台: 野火FPGA系列开发板
// 公司    : http://www.embedfire.com
// 论坛    : http://www.firebbs.cn
// 淘宝    : https://fire-stm32.taobao.com


module  seg_dynamic
(
    input   wire            sys_clk     , //系统时钟,频率50MHz
    input   wire            sys_rst_n   , //复位信号,低有效
    input   wire    [19:0]  data        , //数码管要显示的值
    input   wire    [5:0]   point       , //小数点显示,高电平有效
    input   wire            seg_en      , //数码管使能信号,高电平有效
    input   wire            sign        , //符号位,高电平显示负号

    output  reg     [5:0]   sel         , //数码管位选信号
    output  reg     [7:0]   seg           //数码管段选信号
);

//********************************************************************//
//****************** Parameter and Internal Signal *******************//
//********************************************************************//

//parameter define
parameter   CNT_MAX =   16'd49_999;  //数码管刷新时间计数最大值

//wire  define
wire    [3:0]   unit        ;   //个位数
wire    [3:0]   ten         ;   //十位数
wire    [3:0]   hun         ;   //百位数
wire    [3:0]   tho         ;   //千位数
wire    [3:0]   t_tho       ;   //万位数
wire    [3:0]   h_hun       ;   //十万位数

//reg   define
reg     [23:0]  data_reg    ;   //待显示数据寄存器
reg     [15:0]  cnt_1ms     ;   //1ms计数器
reg             flag_1ms    ;   //1ms标志信号
reg     [2:0]   cnt_sel     ;   //数码管位选计数器
reg     [5:0]   sel_reg     ;   //位选信号
reg     [3:0]   data_disp   ;   //当前数码管显示的数据
reg             dot_disp    ;   //当前数码管显示的小数点

//********************************************************************//
//***************************** Main Code ****************************//
//********************************************************************//

//data_reg:控制数码管显示数据
 always@(posedge sys_clk or  negedge sys_rst_n)
    if(sys_rst_n == 1'b0)
        data_reg    <=  24'b0;
//若显示的十进制数的十万位为非零数据或需显示小数点,则六个数码管全显示
    else    if((h_hun) || (point[5]))
        data_reg    <=  {h_hun,t_tho,tho,hun,ten,unit};
//若显示的十进制数的万位为非零数据或需显示小数点,则值显示在5个数码管上
//打比方我们输入的十进制数据为20’d12345,我们就让数码管显示12345而不是012345
    else    if(((t_tho) || (point[4])) && (sign == 1'b1))//显示负号
        data_reg <= {4'd10,t_tho,tho,hun,ten,unit};//4'd10我们定义为显示负号
    else    if(((t_tho) || (point[4])) && (sign == 1'b0))
        data_reg <= {4'd11,t_tho,tho,hun,ten,unit};//4'd11我们定义为不显示
//若显示的十进制数的千位为非零数据或需显示小数点,则值显示4个数码管
    else    if(((tho) || (point[3])) && (sign == 1'b1))
        data_reg <= {4'd11,4'd10,tho,hun,ten,unit};
    else    if(((tho) || (point[3])) && (sign == 1'b0))
        data_reg <= {4'd11,4'd11,tho,hun,ten,unit};
//若显示的十进制数的百位为非零数据或需显示小数点,则值显示3个数码管
    else    if(((hun) || (point[2])) && (sign == 1'b1))
        data_reg <= {4'd11,4'd11,4'd10,hun,ten,unit};
    else    if(((hun) || (point[2])) && (sign == 1'b0))
        data_reg <= {4'd11,4'd11,4'd11,hun,ten,unit};
//若显示的十进制数的十位为非零数据或需显示小数点,则值显示2个数码管
    else    if(((ten) || (point[1])) && (sign == 1'b1))
        data_reg <= {4'd11,4'd11,4'd11,4'd10,ten,unit};
    else    if(((ten) || (point[1])) && (sign == 1'b0))
        data_reg <= {4'd11,4'd11,4'd11,4'd11,ten,unit};
//若显示的十进制数的个位且需显示负号
    else    if(((unit) || (point[0])) && (sign == 1'b1))
        data_reg <= {4'd11,4'd11,4'd11,4'd11,4'd10,unit};
//若上面都不满足都只显示一位数码管
    else
        data_reg <= {4'd11,4'd11,4'd11,4'd11,4'd11,unit};

//cnt_1ms:1ms循环计数
always@(posedge sys_clk or negedge sys_rst_n)
    if(sys_rst_n == 1'b0)
        cnt_1ms <=  16'd0;
    else    if(cnt_1ms == CNT_MAX)
        cnt_1ms <=  16'd0;
    else
        cnt_1ms <=  cnt_1ms + 1'b1;

//flag_1ms:1ms标志信号
always@(posedge sys_clk or negedge sys_rst_n)
    if(sys_rst_n == 1'b0)
        flag_1ms    <=  1'b0;
    else    if(cnt_1ms == CNT_MAX - 1'b1)
        flag_1ms    <=  1'b1;
    else
        flag_1ms    <=  1'b0;

//cnt_sel:从0到5循环数,用于选择当前显示的数码管
always@(posedge sys_clk or negedge sys_rst_n)
    if(sys_rst_n == 1'b0)
        cnt_sel <=  3'd0;
    else    if((cnt_sel == 3'd5) && (flag_1ms == 1'b1))
        cnt_sel <=  3'd0;
    else    if(flag_1ms == 1'b1)
        cnt_sel <=  cnt_sel + 1'b1;
    else
        cnt_sel <=  cnt_sel;

//数码管位选信号寄存器
always@(posedge sys_clk or negedge sys_rst_n)
    if(sys_rst_n == 1'b0)
        sel_reg <=  6'b000_000;
    else    if((cnt_sel == 3'd0) && (flag_1ms == 1'b1))
        sel_reg <=  6'b000_001;
    else    if(flag_1ms == 1'b1)
        sel_reg <=  sel_reg << 1;
    else
        sel_reg <=  sel_reg;

//控制数码管的位选信号,使六个数码管轮流显示
always@(posedge sys_clk or  negedge sys_rst_n)
    if(sys_rst_n == 1'b0)
        data_disp    <=  4'b0;
    else    if((seg_en == 1'b1) && (flag_1ms == 1'b1))
        case(cnt_sel)
        3'd0:   data_disp    <=  data_reg[3:0]  ;  //给第1个数码管赋个位值
        3'd1:   data_disp    <=  data_reg[7:4]  ;  //给第2个数码管赋十位值
        3'd2:   data_disp    <=  data_reg[11:8] ;  //给第3个数码管赋百位值
        3'd3:   data_disp    <=  data_reg[15:12];  //给第4个数码管赋千位值
        3'd4:   data_disp    <=  data_reg[19:16];  //给第5个数码管赋万位值
        3'd5:   data_disp    <=  data_reg[23:20];  //给第6个数码管赋十万位值
        default:data_disp    <=  4'b0        ;
        endcase
    else
        data_disp   <=  data_disp;

//dot_disp:小数点低电平点亮,需对小数点有效信号取反
always@(posedge sys_clk or negedge sys_rst_n)
    if(sys_rst_n == 1'b0)
        dot_disp    <=  1'b1;
    else    if(flag_1ms == 1'b1)
        dot_disp    <=  ~point[cnt_sel];
    else
        dot_disp    <=  dot_disp;

//控制数码管段选信号,显示数字
always@(posedge sys_clk or  negedge sys_rst_n)
    if(sys_rst_n == 1'b0)
        seg <=  8'b1111_1111;
    else    
        case(data_disp)
            4'd0  : seg  <=  {dot_disp,7'b100_0000};    //显示数字0
            4'd1  : seg  <=  {dot_disp,7'b111_1001};    //显示数字1
            4'd2  : seg  <=  {dot_disp,7'b010_0100};    //显示数字2
            4'd3  : seg  <=  {dot_disp,7'b011_0000};    //显示数字3
            4'd4  : seg  <=  {dot_disp,7'b001_1001};    //显示数字4
            4'd5  : seg  <=  {dot_disp,7'b001_0010};    //显示数字5
            4'd6  : seg  <=  {dot_disp,7'b000_0010};    //显示数字6
            4'd7  : seg  <=  {dot_disp,7'b111_1000};    //显示数字7
            4'd8  : seg  <=  {dot_disp,7'b000_0000};    //显示数字8
            4'd9  : seg  <=  {dot_disp,7'b001_0000};    //显示数字9
            4'd10 : seg  <=  8'b1011_1111          ;    //显示负号
            4'd11 : seg  <=  8'b1111_1111          ;    //不显示任何字符
            default:seg  <=  8'b1100_0000;
        endcase

//sel:数码管位选信号赋值
always@(posedge sys_clk or negedge sys_rst_n)
    if(sys_rst_n == 1'b0)
        sel <=  6'b000_000;
    else
        sel <=  sel_reg;

//********************************************************************//
//*************************** Instantiation **************************//
//********************************************************************//

//---------- bsd_8421_inst ----------
bcd_8421    bcd_8421_inst
(
    .sys_clk     (sys_clk  ),   //系统时钟,频率50MHz
    .sys_rst_n   (sys_rst_n),   //复位信号,低电平有效
    .data        (data     ),   //输入需要转换的数据

    .unit        (unit     ),   //个位BCD码
    .ten         (ten      ),   //十位BCD码
    .hun         (hun      ),   //百位BCD码
    .tho         (tho      ),   //千位BCD码
    .t_tho       (t_tho    ),   //万位BCD码
    .h_hun       (h_hun    )    //十万位BCD码
);

endmodule

BCD8421模块

module  bcd_8421
(
    input   wire            sys_clk     ,   //系统时钟,频率50MHz
    input   wire            sys_rst_n   ,   //复位信号,低电平有效
    input   wire    [19:0]  data        ,   //输入需要转换的数据

    output  reg     [3:0]   unit        ,   //个位BCD码
    output  reg     [3:0]   ten         ,   //十位BCD码
    output  reg     [3:0]   hun         ,   //百位BCD码
    output  reg     [3:0]   tho         ,   //千位BCD码
    output  reg     [3:0]   t_tho       ,   //万位BCD码
    output  reg     [3:0]   h_hun           //十万位BCD码
);

//********************************************************************//
//******************** Parameter And Internal Signal *****************//
//********************************************************************//

//reg   define
reg     [4:0]   cnt_shift   ;   //移位判断计数器
reg     [43:0]  data_shift  ;   //移位判断数据寄存器
reg             shift_flag  ;   //移位判断标志信号

//********************************************************************//
//***************************** Main Code ****************************//
//********************************************************************//

//cnt_shift:从0到21循环计数
always@(posedge sys_clk or negedge sys_rst_n)
    if(sys_rst_n == 1'b0)
        cnt_shift   <=  5'd0;
    else    if((cnt_shift == 5'd21) && (shift_flag == 1'b1))
        cnt_shift   <=  5'd0;
    else    if(shift_flag == 1'b1)
        cnt_shift   <=  cnt_shift + 1'b1;
    else
        cnt_shift   <=  cnt_shift;
       
//data_shift:计数器为0时赋初值,计数器为1~20时进行移位判断操作
always@(posedge sys_clk or negedge sys_rst_n)
    if(sys_rst_n == 1'b0)
        data_shift  <=  44'b0;
    else    if(cnt_shift == 5'd0)
        data_shift  <=  {24'b0,data};
    else    if((cnt_shift <= 20) && (shift_flag == 1'b0))
        begin
            data_shift[23:20]   <=  (data_shift[23:20] > 4) ? (data_shift[23:20] + 2'd3) : (data_shift[23:20]);
            data_shift[27:24]   <=  (data_shift[27:24] > 4) ? (data_shift[27:24] + 2'd3) : (data_shift[27:24]);
            data_shift[31:28]   <=  (data_shift[31:28] > 4) ? (data_shift[31:28] + 2'd3) : (data_shift[31:28]);
            data_shift[35:32]   <=  (data_shift[35:32] > 4) ? (data_shift[35:32] + 2'd3) : (data_shift[35:32]);
            data_shift[39:36]   <=  (data_shift[39:36] > 4) ? (data_shift[39:36] + 2'd3) : (data_shift[39:36]);
            data_shift[43:40]   <=  (data_shift[43:40] > 4) ? (data_shift[43:40] + 2'd3) : (data_shift[43:40]);
        end
    else    if((cnt_shift <= 20) && (shift_flag == 1'b1))
        data_shift  <=  data_shift << 1;
    else
        data_shift  <=  data_shift;

//shift_flag:移位判断标志信号,用于控制移位判断的先后顺序
always@(posedge sys_clk or negedge sys_rst_n)
    if(sys_rst_n == 1'b0)
        shift_flag  <=  1'b0;
    else
        shift_flag  <=  ~shift_flag;

//当计数器等于20时,移位判断操作完成,对各个位数的BCD码进行赋值
always@(posedge sys_clk or negedge sys_rst_n)
    if(sys_rst_n == 1'b0)
        begin
            unit    <=  4'b0;
            ten     <=  4'b0;
            hun     <=  4'b0;
            tho     <=  4'b0;
            t_tho   <=  4'b0;
            h_hun   <=  4'b0;
        end
    else    if(cnt_shift == 5'd21)
        begin
            unit    <=  data_shift[23:20];
            ten     <=  data_shift[27:24];
            hun     <=  data_shift[31:28];
            tho     <=  data_shift[35:32];
            t_tho   <=  data_shift[39:36];
            h_hun   <=  data_shift[43:40];
        end

endmodule

本次修改了数码管驱动代码,不推荐各位学习使用乘除法进行驱动。主要FPGA的资源还是很宝贵的,代码已经贴出来了,如果需要源码可以私聊。代码是通用的,不过源码是vivado的。

最后

以上就是谦让期待为你收集整理的基于FPGA的两位按键控制LED数码管加减计数实验两位按键控制LED数码管加减计数实验的全部内容,希望文章能够帮你解决基于FPGA的两位按键控制LED数码管加减计数实验两位按键控制LED数码管加减计数实验所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(66)

评论列表共有 0 条评论

立即
投稿
返回
顶部