数码时钟代码_「每周FPGA案例」 断电重加载时钟工程

本文为明德扬原创及录用文章,转载请注明出处!

1.1 总体设计1.1.1 概述

在微机的发展初期,BIOS都存放在ROM(只读存储器)中。ROM内部的资料是在ROM的制造工序中,在工厂里用特殊的方法烧录进去的,其中的内容只能读不能改,一旦烧录进去,用户只能验证写入的资料是否正确,不能再做任何修改。如果发现资料有任何错误,则只有舍弃不用,重新订做一份。ROM是在生产线上生产的,由于成本高,一般只用在大批量应用的场合。

由于ROM制造和升级的不便,后来人们发明了PROM(Programmable ROM,可编程ROM)。最初从工厂中制作完成的PROM内部并没有资料,用户可以用专用的编程器将自己的资料写入,但是这种机会只有一次,一旦写入后也无法修改,若是出了错误,已写入的芯片只能报废。PROM的特性和ROM相同,但是其成本比ROM高,而且写入资料的速度比ROM的量产速度要慢,一般只适用于少量需求的场合或是ROM量产前的验证。

EPROM(Erasable Programmable ROM,可擦除可编程ROM)芯片可重复擦除和写入,解决了PROM芯片只能写入一次的弊端。EPROM芯片有一个很明显的特征,在其正面的陶瓷封装上,开有一个玻璃窗口,透过该窗口,可以看到其内部的集成电路,紫外线透过该孔照射内部芯片就可以擦除其内的数据,完成芯片擦除的操作要用到EPROM擦除器。EPROM内资料的写入要用专用的编程器,并且往芯片中写内容时必须要加一定的编程电压(VPP=12~24V,随不同的芯片型号而定)。EPROM的型号是以27开头的,如27C020(8*256K)是一片2M Bits容量的EPROM芯片。EPROM芯片在写入资料后,还要以不透光的贴纸或胶布把窗口封住,以免受到周围的紫外线照射而使资料受损。

由于EPROM操作的不便,后来出的主板上BIOS ROM芯片大部分都采用EEPROM(Electrically Erasable Programmable ROM,电可擦除可编程ROM)。EEPROM的擦除不需要借助于其它设备,它是以电子信号来修改其内容的,而且是以Byte为最小修改单位,不必将资料全部洗掉才能写入,彻底摆脱了EPROM Eraser和编程器的束缚。EEPROM在写入数据时,仍要利用一定的编程电压,此时,只需用厂商提供的专用刷新程序就可以轻而易举地改写内容,所以,它属于双电压芯片。借助于EEPROM芯片的双电压特性,可以使BIOS具有良好的防毒功能,在升级时,把跳线开关打至“on”的位置,即给芯片加上相应的编程电压,就可以方便地升级;平时使用时,则把跳线开关打至“off”的位置,防止CIH类的病毒对BIOS芯片的非法修改。所以,仍有不少主板采用EEPROM作为BIOS芯片并作为自己主板的一大特色。

1.1.2 设计目标

整个工程由FPGA、矩阵键盘/按键、数码管和AT93C46组成,实现一个上电后能重新加载,接着上次计数的数字时钟,详细功能如下。

1、 数码管显示时钟值,共使用了6个数码管,分别表示时十位、时个位、分十位、分个位、秒十位和秒个位。

2、 矩阵键盘或者按键可以对数字时钟进行时分秒的设置。

A、 上电后,时钟默认处于计时状态,当按键1按下,跳到时间设置状态,当按键1再次按下,回到计时状态。

B、 当处于时间设置状态时,默认此刻设置的是秒个位,当按键2按下,此刻设置秒十位,以此类推,一次设置为分个位、分十位、时个位和时十位。再按下按键2,则重新设置秒个位。

C、 当处于时间设置状态时,按下按键3,则设置位的值加1,如果溢出,则变成0。例如当目前小时显示05时,设置时十位,按下按键3,变成15,再按下按键3,则变成05.当目前小时显示为03时,设置时十位,按一下按键3,变成13,再按一下按键3,则变成23,再按则为03。

3、 AT93C46则用于保存时钟值,其具有断电保护功能,断电数据不丢失。

A、 AT93C46一共可以保存128字节的数据。工程将AT93C46分成空间1和空间2。空间1占用的地址为0~3,空间2占用的地址为4~7。

B、 每隔1秒,保存当前时钟值。第一次保存到空间1,第二次保存到空间2,第三次保存带空间1,依此类推。(如果只有一个空间,则可能出现写数据过程中断电,从而得不到完整数据情况)

C、 支持8位的CRC,生成多项式

4d4ebe0155bb258ee27c25cbb575bf86.png

,初始值为全1。

D、 每次保存的值,时十位、时个位、分十位、分个位、秒十位和秒个位各占4bit,共3个字节,加上1个字节的CRC,一共4个字节。

E、 上电后,FPGA将读取两个空间的数值,并作CRC检验。如果两组数据的CRC检验均失败,则不重新加载;如果有一组数据CRC检验失败,则加载正确的一组数据;如果两组数据CRC检验均正确,则加载数值较大的一组数据。


1.1.3 系统结构框图

系统结构框图如下所示:

92b91f6bcc38db42243cadd6860604b3.png

图一

1.1.4模块功能键盘(按键)扫描模块实现功能

1、将外来异步信号打两拍处理,将异步信号同步化。

2、实现20ms按键消抖功能。

3、实现矩阵键盘或者普通案件的检测功能,并输出有效按键信号。

时钟数据产生模块实现功能

负责产生数字时钟需要的时钟信息。包括:

1、 按数字时钟方式进行计数

2、 设置数字时钟的值

3、 将时钟数据输出给外部模块使用

4、 从数据处理模块得到时钟数据,并重新加载

数码管显示模块实现功能

1、 对时钟数据进行译码,然后发到数码管显示

2、 逐一显示时分秒的值数据处理模块实现功能

负责写到AT93C46的数据,或者从AT93C46读到数据后的处理,包括:

1、 上电后,发送EWEN命令,打开AT93C46的写保护。

2、 发送EWEN命令后,开始读存储在AT93C46的两组时钟数据;对数据进行检验,然后选择适合的数据给时钟数据产生模块加载

3、 每隔1秒从时钟数据产生模块获取时分秒的值,并产生CRC值,最后写到AT93C46上CRC处理模块实现功能

负责CRC算法的模块,在数据处理模块内部使用

AT93C46模块实现功能

根据上游模块的EWEN、WRITE和READ命令,产生AT93C46的相应时序,从而写数据或者读到数据。至于数据是什么、有什么用,不关心,只关心AT93C46的时序。

1.1.5顶层信号

54443e094b17d189fe92bb3abf6d90af.png

1.1.6参考代码

`define KEY_SCANmodule at93c46_top_scan(    clk      ,    rst_n    ,    key_col  ,    mo       ,    cs       ,    mi       ,    sk       ,    key_row  ,    seg_sel  ,    seg_data     );    parameter    TIME_1S = 50_000_000;    input               clk          ;    input               rst_n        ;    input [3:0]         key_col      ;    input               mo           ;    output              cs           ;    output              mi           ;    output              sk           ;    output[3:0]         key_row      ;    output[5:0]         seg_sel      ;    output[7:0]         seg_data     ;    wire                rdy          ;    wire                rdata_vld    ;    wire  [3:0]         key_en       ;    wire  [23:0]        data_load    ;    wire                data_load_vld;    wire  [23:0]        clk_data_out ;    wire  [6:0]         addr         ;    wire  [1:0]         mode         ;    wire                start        ;    wire  [7:0]         wdata        ;    wire  [7:0]         rdata        ;             `ifdef KEY_SCAN    key_scan  u_key_scan(                .clk     (clk    ),                .rst_n   (rst_n  ),                .key_col (key_col),                .key_row (key_row),                .key_en  (key_en )             );            `else                key_module  u_key_module(                .clk     (clk     ),                .rst_n   (rst_n   ),                .key_in  (~key_col),                .key_vld (key_en  )             );            `endif    clock_data#(.TIME_1S(TIME_1S)) u_clock_data(                .clk           (clk           ),                .rst_n         (rst_n         ),                .data_load     (data_load     ),                .data_load_vld (data_load_vld ),                .key_en        (key_en        ),                .data_out      (clk_data_out  )     );    seg_disp#(.SEG_NUM(6)) u_seg_disp(                .rst_n       (rst_n       ),                .clk         (clk         ),                .din         (clk_data_out),                .din_vld     ({6{1'b1}}   ),                .seg_sel     (seg_sel     ),                .segment     (seg_data    )              );           data_processor#(.TIME_1S(TIME_1S)) u_data_pro(                      .clk        (clk         )  ,                      .rst_n      (rst_n       )  ,                      .din        (clk_data_out)  ,                      .start      (start       )  ,                      .mode       (mode        )  ,                      .addr       (addr        )  ,                      .wdata      (wdata       )  ,                      .rdata      (rdata       )  ,                      .rdata_vld  (rdata_vld   )  ,                      .rdy        (rdy         )  ,                      .dout       (data_load   )  ,                      .dout_vld   (data_load_vld )            );    at93c46_mix u_at93c46_mix(                   .clk        (clk        )  ,                   .rst_n      (rst_n      )  ,                   .start      (start      )  ,                   .mode       (mode       )  ,                   .addr       (addr       )  ,                   .wdata      (wdata      )  ,                   .rdata      (rdata      )  ,                   .rdata_vld  (rdata_vld  )  ,                   .rdy        (rdy        )  ,                   .do         (mo         )  ,                   .di         (mi         )  ,                   .cs         (cs         )  ,                   .sk         (sk         )        );endmodule

本工程会应用于不同的开发板,主要区别在于使用普通按键还是矩阵键盘,顶层代码中针对这一点进行了设计,如何开发板使用的是矩阵键盘,则顶层代码不需要改,如果使用的是普通按键,只需要将顶层代码最上面的一行删除或者注释掉就可以了。

772380fb53358f8fb286e847a6072f70.png

1.2 键盘(按键)扫描模块设计

1.2.1接口信号

下面为使用矩阵键盘时的接口信号:

26982c579d06525826581d890acd7e09.png

下面是使用普通按键时的接口信号:

9923cf6dd40c18640105a64683b4206f.png

1.2.2 设计思路

在前面的按键控制数字时钟的案例中已经有介绍,所以这里不在过多介绍,详细介绍请看下方链接:

http://fpgabbs.com/forum.php?mod=viewthread&tid=310


1.2.3参考代码

module  key_scan(                 clk    ,                 rst_n  ,                 key_col,                 key_row,                 key_en                  );    parameter      KEY_W    =   4      ;    parameter      CHK_COL  =   0      ;    parameter      CHK_ROW  =   1      ;    parameter      DELAY    =   2      ;    parameter      WAIT_END =   3      ;    parameter      COL_CNT  =   16     ;    parameter      TIME_20MS=   1000000;    input               clk              ;    input               rst_n            ;    input [3:0]         key_col          ;    output[3:0]         key_en           ;    output[KEY_W-1:0]   key_row          ;    reg   [3:0]         key_out          ;    reg   [KEY_W-1:0]   key_row          ;    reg                 key_vld          ;    reg   [3:0]         key_col_ff0      ;    reg   [3:0]         key_col_ff1      ;    reg   [1:0]         key_col_get      ;    reg   [3:0]         key_en           ;    wire                end_shake_cnt    ;    reg                 end_shake_cnt_ff0;    reg   [3:0]         state_c          ;    reg   [19:0]        shake_cnt        ;    reg   [3:0]         state_n          ;    reg   [1:0]         row_index        ;    reg   [15:0]        row_cnt          ;    wire                col2row_start    ;     wire                row2del_start    ;    wire                del2wait_start   ;    wire                wait2col_start   ;    wire                add_row_cnt      ;    wire                end_row_cnt      ;    wire                add_shake_cnt    ;    wire                add_row_index    ;    wire                end_row_index    ;always  @(posedge clk or negedge rst_n)begin    if(rst_n==1'b0)begin        key_col_ff0 <= 4'b1111;        key_col_ff1 <= 4'b1111;    end    else begin        key_col_ff0 <= key_col    ;        key_col_ff1 <= key_col_ff0;    endendalways @(posedge clk or negedge rst_n) begin     if (rst_n==0) begin        shake_cnt <= 0;     end    else if(add_shake_cnt) begin        if(end_shake_cnt)            shake_cnt <= 0;         else            shake_cnt <= shake_cnt+1 ;   endendassign add_shake_cnt = key_col_ff1!=4'hf;assign end_shake_cnt = add_shake_cnt  && shake_cnt == TIME_20MS-1 ;always  @(posedge clk or negedge rst_n)begin    if(rst_n==1'b0)begin        state_c <= CHK_COL;    end    else begin        state_c <= state_n;    endendalways  @(*)begin    case(state_c)        CHK_COL: begin                     if(col2row_start )begin                         state_n = CHK_ROW;                     end                     else begin                         state_n = CHK_COL;                     end                 end        CHK_ROW: begin                     if(row2del_start)begin                         state_n = DELAY;                     end                     else begin                         state_n = CHK_ROW;                     end                 end        DELAY :  begin                     if(del2wait_start)begin                         state_n = WAIT_END;                     end                     else begin                         state_n = DELAY;                     end                 end        WAIT_END: begin                     if(wait2col_start)begin                         state_n = CHK_COL;                     end                     else begin                         state_n = WAIT_END;                     end                  end       default: state_n = CHK_COL;    endcaseendassign col2row_start = state_c==CHK_COL  && end_shake_cnt;assign row2del_start = state_c==CHK_ROW  && row_index==3 && end_row_cnt;assign del2wait_start= state_c==DELAY    && end_row_cnt;assign wait2col_start= state_c==WAIT_END && key_col_ff1==4'hf;always  @(posedge clk or negedge rst_n)begin    if(rst_n==1'b0)begin        key_row <= 4'b0;    end    else if(state_c==CHK_ROW)begin        key_row <= ~(1'b1 << row_index);    end    else begin        key_row <= 4'b0;    endendalways @(posedge clk or negedge rst_n) begin     if (rst_n==0) begin        row_index <= 0;     end    else if(add_row_index) begin        if(end_row_index)            row_index <= 0;         else            row_index <= row_index+1 ;   end   else if(state_c!=CHK_ROW)begin       row_index <= 0;   endendassign add_row_index = state_c==CHK_ROW && end_row_cnt;assign end_row_index = add_row_index  && row_index == 4-1 ;always @(posedge clk or negedge rst_n) begin     if (rst_n==0) begin        row_cnt <= 0;     end    else if(add_row_cnt) begin        if(end_row_cnt)            row_cnt <= 0;         else            row_cnt <= row_cnt+1 ;   endendassign add_row_cnt = state_c==CHK_ROW || state_c==DELAY;assign end_row_cnt = add_row_cnt  && row_cnt == 16-1 ;always  @(posedge clk or negedge rst_n)begin    if(rst_n==1'b0)begin        key_col_get <= 0;    end    else if(state_c==CHK_COL && end_shake_cnt ) begin        if(key_col_ff1==4'b1110)            key_col_get <= 0;        else if(key_col_ff1==4'b1101)            key_col_get <= 1;        else if(key_col_ff1==4'b1011)            key_col_get <= 2;        else             key_col_get <= 3;    endendalways  @(posedge clk or negedge rst_n)begin    if(rst_n==1'b0)begin        key_out <= 0;    end    else if(state_c==CHK_ROW && end_row_cnt)begin        key_out <= {row_index,key_col_get};    end    else begin        key_out <= 0;    endendalways  @(posedge clk or negedge rst_n)begin    if(rst_n==1'b0)begin        key_vld <= 1'b0;    end    else if(state_c==CHK_ROW && end_row_cnt && key_col_ff1[key_col_get]==1'b0)begin        key_vld <= 1'b1;    end    else begin        key_vld <= 1'b0;    endendalways  @(*)begin    if(rst_n==1'b0)begin        key_en = 0;    end    else if(key_vld && key_out==0)begin        key_en = 4'b0001;    end    else if(key_vld && key_out==1)begin        key_en = 4'b0010;    end    else if(key_vld && key_out==2)begin        key_en = 4'b0100;    end    else begin        key_en = 0;    endend

1.3 时间数据产生模块设计1.3.1接口信号

85917f03f54e4e6b9dd32b9fa069bb50.png

1.3.2设计思路

本模块相对于前面的按键控制数字时钟案例中的时间数据产生模块来说,总体的设计思路是相同的,只是增加了一个重载的时钟信号,对于此信号的设计也比较简单,只需要在时分秒的个位和十位计数器中增加一句:在重载的时钟数据有效的时候,使计数器输出重载的时钟对应的数据即可,比如秒个位计数器应该输出重载时钟数据的第0到第3位数据,秒十位计数器应该输出重载时钟数据的第4到第7位数据,以此类推。

其他详细的设计思路可以看一下往期按键控制数字时钟的文章:

1.3.3参考代码

module clock_data(    clk          ,    rst_n        ,    data_load    ,    data_load_vld,    key_en       ,    data_out       );    parameter      TIME_1S    =       50_000_000   ;    input               clk          ;    input               rst_n        ;    input               data_load_vld;    input [23:0]        data_load    ;    input [ 3:0]        key_en       ;    output[23:0]        data_out     ;    wire  [23:0]        data_out     ;    reg   [25:0]        cnt_1s       ;    reg   [3:0]         miao_ge      ;    reg   [3:0]         miao_shi     ;    reg   [3:0]         fen_ge       ;    reg   [3:0]         fen_shi      ;    reg   [3:0]         shi_ge       ;    reg   [3:0]         shi_shi      ;    reg   [2:0]         set_sel      ;    reg                 set_flag     ;    wire                add_set_sel  ;    wire                add_cnt_1s   ;    wire                add_miao_ge  ;    wire                add_miao_shi ;    wire                add_fen_ge   ;    wire                add_fen_shi  ;    wire                add_shi_ge   ;    wire                add_shi_shi  ;    wire                end_cnt_1s   ;    wire                end_set_sel  ;    wire                end_miao_ge  ;    wire                end_miao_shi ;    wire                end_fen_ge   ;    wire                end_fen_shi  ;    wire                end_shi_ge   ;    wire                end_shi_shi  ;    wire                set_miao_ge  ;    wire                set_miao_shi ;    wire                set_fen_ge   ;    wire                set_fen_shi  ;    wire                set_shi_ge   ;    wire                set_shi_shi  ;    reg  [ 3:0]         x            ;    reg  [ 2:0]         y            ;    always  @(posedge clk or negedge rst_n)begin        if(rst_n==1'b0)begin            set_flag <= 1'b0;        end        else if(key_en[0]) begin            set_flag <= ~ set_flag;        end    end    always @(posedge clk or negedge rst_n)begin        if(!rst_n)begin            set_sel <= 0;        end        else if(add_set_sel)begin            if(end_set_sel)                set_sel <= 0;            else                set_sel <= set_sel + 1;        end        else if(set_flag==0)begin            set_sel <= 0;        end    end    assign add_set_sel = set_flag && key_en[1];           assign end_set_sel = add_set_sel && set_sel==6-1 ;       always @(posedge clk or negedge rst_n)begin        if(!rst_n)begin            cnt_1s <= 0;        end        else if(add_cnt_1s)begin            if(end_cnt_1s)                cnt_1s <= 0;            else                cnt_1s <= cnt_1s + 1;        end    end    assign add_cnt_1s = set_flag==0 ;           assign end_cnt_1s = add_cnt_1s && cnt_1s==TIME_1S-1 ;       always @(posedge clk or negedge rst_n)begin        if(!rst_n)begin            miao_ge <= 0;        end        else if(add_miao_ge)begin            if(end_miao_ge)                miao_ge <= 0;            else                miao_ge <= miao_ge + 1;        end        else if(data_load_vld)begin            miao_ge <=  data_load[3:0];        end    end    assign add_miao_ge = (end_cnt_1s || set_miao_ge) ;           assign end_miao_ge = add_miao_ge && miao_ge==10-1 ;    assign set_miao_ge = set_flag    && set_sel==0 && key_en[2];       always @(posedge clk or negedge rst_n)begin        if(!rst_n)begin            miao_shi <= 0;        end        else if(add_miao_shi)begin            if(end_miao_shi)                miao_shi <= 0;            else                miao_shi <= miao_shi + 1;        end        else if(data_load_vld)begin            miao_shi <= data_load[7:4];        end    end    assign add_miao_shi = (end_miao_ge || set_miao_shi);           assign end_miao_shi = add_miao_shi && miao_shi==6-1;    assign set_miao_shi = set_flag     && set_sel==1 && key_en[2];       always @(posedge clk or negedge rst_n)begin        if(!rst_n)begin            fen_ge <= 0;        end        else if(add_fen_ge)begin            if(end_fen_ge)                fen_ge <= 0;            else                fen_ge <= fen_ge + 1;        end        else if(data_load_vld)begin            fen_ge <= data_load[11:8];        end    end    assign add_fen_ge = (end_miao_shi || set_fen_ge);           assign end_fen_ge = add_fen_ge && fen_ge==10-1;    assign set_fen_ge = set_flag     && set_sel==2 && key_en[2];       always @(posedge clk or negedge rst_n)begin        if(!rst_n)begin            fen_shi <= 0;        end        else if(add_fen_shi)begin            if(end_fen_shi)                fen_shi <= 0;            else                fen_shi <= fen_shi + 1;        end        else if(data_load_vld)begin            fen_shi <= data_load[15:12];        end    end    assign add_fen_shi = (end_fen_ge || set_fen_shi);           assign end_fen_shi = add_fen_shi && fen_shi==6-1;    assign set_fen_shi = set_flag     && set_sel==3 && key_en[2];      always @(posedge clk or negedge rst_n)begin        if(!rst_n)begin            shi_ge <= 0;        end        else if(add_shi_ge)begin            if(end_shi_ge)                shi_ge <= 0;            else                shi_ge <= shi_ge + 1;        end        else if(data_load_vld)begin            shi_ge <= data_load[19:16];        end    end    assign add_shi_ge = (end_fen_shi || set_shi_ge);           assign end_shi_ge = add_shi_ge && shi_ge==x-1;    assign set_shi_ge = set_flag     && set_sel==4 && key_en[2];       always @(posedge clk or negedge rst_n)begin        if(!rst_n)begin            shi_shi <= 0;        end        else if(add_shi_shi)begin            if(end_shi_shi)                shi_shi <= 0;            else                shi_shi <= shi_shi + 1;        end        else if(data_load_vld)begin            shi_shi <= data_load[23:20];        end    end    assign add_shi_shi = (end_shi_ge || set_shi_shi);           assign end_shi_shi = add_shi_shi && shi_shi==y-1;    assign set_shi_shi = set_flag     && set_sel==5 && key_en[2];       always  @(*)begin        if(shi_shi<2)            x =  10;        else            x =   4;    end    always  @(*)begin        if(set_flag && set_sel==5 && shi_ge>=4)             y = 2;        else            y = 3;    end    assign data_out = {shi_shi,shi_ge,fen_shi,fen_ge,miao_shi,miao_ge};endmodule

1.4 数码管显示模块设计1.4.1接口信号

3a5b56913cbc6d67461622dcb46bb77e.png

1.4.2设计思路

数码管显示在前面的案例文章已经有讲述,这里不再进行介绍,想了解的可以看一下往期文章:

1.4.3参考代码

always @(posedge clk or negedge rst_n)begin    if(!rst_n)begin        cnt_2ms <= 0;    end    else if(add_cnt_2ms)begin        if(end_cnt_2ms)            cnt_2ms <= 0;        else            cnt_2ms <= cnt_2ms + 1;    endendassign add_cnt_2ms = 1;       assign end_cnt_2ms = add_cnt_2ms && cnt_2ms==TIME_2MS-1 ;   always @(posedge clk or negedge rst_n)begin    if(!rst_n)begin        cnt_sel <= 0;    end    else if(add_cnt_sel)begin        if(end_cnt_sel)            cnt_sel <= 0;        else            cnt_sel <= cnt_sel + 1;    endendassign add_cnt_sel = end_cnt_2ms;       assign end_cnt_sel = add_cnt_sel && cnt_sel== SEG_NUM-1;   always  @(posedge clk or negedge rst_n)begin    if(rst_n==1'b0)begin        seg_sel <= {SEG_NUM{1'b1}};    end    else begin        seg_sel <= ~(1'b1 << cnt_sel);    endendalways  @(posedge clk or negedge rst_n)begin    if(rst_n==1'b0)begin        din_ff0 <= 0;    end    else begin        for(ii=0;ii

由于篇幅限制,请继续看(二)。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值