查看: 1175|回复: 0

[评测分享] 【超越者Spartan-6 FPGA开发板】 +4、电容触摸计数器

[复制链接]
  • TA的每日心情
    开心
    2024-10-25 14:50
  • 签到天数: 1071 天

    连续签到: 1 天

    [LV.10]以坛为家III

    发表于 2021-5-16 00:17:03 | 显示全部楼层 |阅读模式
    分享到:
    本帖最后由 TLLED 于 2021-5-16 00:17 编辑

        学习下数码管动态驱动的程序。要实现的功能:按一次触摸按键,数码计数值加1。

        一、硬件电路


        数码管硬件电路
        001.png



       二、驱动程序



        2.1、动态数码管驱动程序seg_led_dynamic.v
        这段是官网驱动的例程。
       

    1. module seg_led_dynamic(
    2.         input            clk  ,        
    3.         input            rst_n,
    4.         
    5.         input         [19:0]    data   ,        // 6位数码管要显示的数值
    6.         input         [5:0]     point  ,        // 小数点具体显示的位置,从高到低,高电平有效
    7.         input                   en     ,        // 数码管使能信号
    8.         input                   sign   ,        // 符号位(高电平显示"-"号)
    9.         
    10.         output  reg  [5:0]  seg_sel ,   // 数码管位选
    11.         output  reg  [7:0]  seg_led     // 数码管段选
    12.         );

    13. //parameter define        
    14. localparam  CLK_DIVIDE = 4'd10     ;        // 时钟分频系数
    15. localparam  MAX_NUM    = 13'd5000  ;        // 对数码管驱动时钟(5MHz)计数1ms所需的计数值

    16. //reg define
    17. reg    [ 3:0]             clk_cnt  ;        // 时钟分频计数器
    18. reg                       dri_clk  ;        // 数码管的驱动时钟,5MHz
    19. reg    [23:0]             num      ;        // 24位bcd码寄存器
    20. reg    [12:0]             cnt0     ;        // 数码管驱动时钟计数器
    21. reg                       flag     ;        // 标志信号(标志着cnt0计数达1ms)
    22. reg    [2:0]              cnt_sel  ;        // 数码管位选计数器
    23. reg    [3:0]              num_disp ;        // 当前数码管显示的数据
    24. reg                       dot_disp ;        // 当前数码管显示的小数点

    25. //wire define
    26. wire   [3:0]              data0    ;        // 个位数
    27. wire   [3:0]              data1    ;        // 十位数
    28. wire   [3:0]              data2    ;        // 百位数
    29. wire   [3:0]              data3    ;        // 千位数
    30. wire   [3:0]              data4    ;        // 万位数
    31. wire   [3:0]              data5    ;        // 十万位数

    32. //提取显示数值所对应的十进制数的各个位
    33. assign  data0 = data % 4'd10;               // 个位数
    34. assign  data1 = data / 4'd10 % 4'd10   ;    // 十位数
    35. assign  data2 = data / 7'd100 % 4'd10  ;    // 百位数
    36. assign  data3 = data / 10'd1000 % 4'd10 ;   // 千位数
    37. assign  data4 = data / 14'd10000 % 4'd10;   // 万位数
    38. assign  data5 = data / 17'd100000;          // 十万位数

    39. //对系统时钟10分频,得到的频率为5MHz的数码管驱动时钟dri_clk
    40. always @(posedge clk or negedge rst_n) begin
    41.    if(!rst_n) begin
    42.        clk_cnt <= 4'd0;
    43.        dri_clk <= 1'b1;
    44.    end
    45.    else if(clk_cnt == CLK_DIVIDE/2 - 1'd1) begin
    46.        clk_cnt <= 4'd0;
    47.        dri_clk <= ~dri_clk;
    48.    end
    49.    else begin
    50.        clk_cnt <= clk_cnt + 1'b1;
    51.        dri_clk <= dri_clk;
    52.    end
    53. end

    54. //将20位2进制数转换为8421bcd码(即使用4位二进制数表示1位十进制数)
    55. always @ (posedge dri_clk or negedge rst_n) begin
    56.     if (!rst_n)
    57.         num <= 24'b0;
    58.     else begin
    59.         if (data5 || point[5]) begin     //如果显示数据为6位十进制数,
    60.             num[23:20] <= data5;         //则依次给6位数码管赋值
    61.             num[19:16] <= data4;
    62.             num[15:12] <= data3;
    63.             num[11:8]  <= data2;
    64.             num[ 7:4]  <= data1;
    65.             num[ 3:0]  <= data0;
    66.         end
    67.         else begin                        
    68.             if (data4 || point[4]) begin //如果显示数据为5位十进制数,则给低5位数码管赋值
    69.                 num[19:0] <= {data4,data3,data2,data1,data0};
    70.                 if(sign)                    
    71.                     num[23:20] <= 4'd11; //如果需要显示负号,则最高位(第6位)为符号位
    72.                 else
    73.                     num[23:20] <= 4'd10; //不需要显示负号时,则第6位不显示任何字符
    74.             end
    75.             else begin                   //如果显示数据为4位十进制数,则给低4位数码管赋值
    76.                 if (data3 || point[3]) begin
    77.                     num[15: 0] <= {data3,data2,data1,data0};
    78.                     num[23:20] <= 4'd10; //第6位不显示任何字符
    79.                     if(sign)             //如果需要显示负号,则最高位(第5位)为符号位
    80.                         num[19:16] <= 4'd11;
    81.                     else                 //不需要显示负号时,则第5位不显示任何字符
    82.                         num[19:16] <= 4'd10;
    83.                 end
    84.                 else begin               //如果显示数据为3位十进制数,则给低3位数码管赋值
    85.                     if (data2 || point[2]) begin
    86.                         num[11: 0] <= {data2,data1,data0};
    87.                                          //第6、5位不显示任何字符
    88.                         num[23:16] <= {2{4'd10}};
    89.                         if(sign)         //如果需要显示负号,则最高位(第4位)为符号位
    90.                             num[15:12] <= 4'd11;
    91.                         else             //不需要显示负号时,则第4位不显示任何字符
    92.                             num[15:12] <= 4'd10;
    93.                     end
    94.                     else begin           //如果显示数据为2位十进制数,则给低2位数码管赋值
    95.                         if (data1 || point[1]) begin
    96.                             num[ 7: 0] <= {data1,data0};
    97.                                          //第6、5、4位不显示任何字符
    98.                             num[23:12] <= {3{4'd10}};
    99.                             if(sign)     //如果需要显示负号,则最高位(第3位)为符号位
    100.                                 num[11:8]  <= 4'd11;
    101.                             else         //不需要显示负号时,则第3位不显示任何字符
    102.                                 num[11:8] <=  4'd10;
    103.                         end
    104.                         else begin       //如果显示数据为1位十进制数,则给最低位数码管赋值
    105.                             num[3:0] <= data0;
    106.                                          //第6、5位不显示任何字符
    107.                             num[23:8] <= {4{4'd10}};
    108.                             if(sign)     //如果需要显示负号,则最高位(第2位)为符号位
    109.                                 num[7:4] <= 4'd11;
    110.                             else         //不需要显示负号时,则第2位不显示任何字符
    111.                                 num[7:4] <= 4'd10;
    112.                         end
    113.                     end
    114.                 end
    115.             end
    116.         end
    117.     end
    118. end

    119. //每当计数器对数码管驱动时钟计数时间达1ms,输出一个时钟周期的脉冲信号
    120. always @ (posedge dri_clk or negedge rst_n) begin
    121.     if (rst_n == 1'b0) begin
    122.         cnt0 <= 13'b0;
    123.         flag <= 1'b0;
    124.      end
    125.     else if (cnt0 < MAX_NUM - 1'b1) begin
    126.         cnt0 <= cnt0 + 1'b1;
    127.         flag <= 1'b0;
    128.      end
    129.     else begin
    130.         cnt0 <= 13'b0;
    131.         flag <= 1'b1;
    132.      end
    133. end

    134. //cnt_sel从0计数到5,用于选择当前处于显示状态的数码管
    135. always @ (posedge dri_clk or negedge rst_n) begin
    136.     if (rst_n == 1'b0)
    137.         cnt_sel <= 3'b0;
    138.     else if(flag) begin
    139.         if(cnt_sel < 3'd5)
    140.             cnt_sel <= cnt_sel + 1'b1;
    141.         else
    142.             cnt_sel <= 3'b0;
    143.     end
    144.     else
    145.         cnt_sel <= cnt_sel;
    146. end

    147. //控制数码管位选信号,使6位数码管轮流显示
    148. always @ (posedge dri_clk or negedge rst_n) begin
    149.     if(!rst_n) begin
    150.         seg_sel  <= 6'b111111;              //位选信号低电平有效
    151.         num_disp <= 4'b0;           
    152.         dot_disp <= 1'b1;                   //共阳极数码管,低电平导通
    153.     end
    154.     else begin
    155.         if(en) begin
    156.             case (cnt_sel)
    157.                 3'd0 :begin
    158.                     seg_sel  <= 6'b111110;  //显示数码管最低位
    159.                     num_disp <= num[3:0] ;  //显示的数据
    160.                     dot_disp <= ~point[0];  //显示的小数点
    161.                 end
    162.                 3'd1 :begin
    163.                     seg_sel  <= 6'b111101;  //显示数码管第1位
    164.                     num_disp <= num[7:4] ;
    165.                     dot_disp <= ~point[1];
    166.                 end
    167.                 3'd2 :begin
    168.                     seg_sel  <= 6'b111011;  //显示数码管第2位
    169.                     num_disp <= num[11:8];
    170.                     dot_disp <= ~point[2];
    171.                 end
    172.                 3'd3 :begin
    173.                     seg_sel  <= 6'b110111;  //显示数码管第3位
    174.                     num_disp <= num[15:12];
    175.                     dot_disp <= ~point[3];
    176.                 end
    177.                 3'd4 :begin
    178.                     seg_sel  <= 6'b101111;  //显示数码管第4位
    179.                     num_disp <= num[19:16];
    180.                     dot_disp <= ~point[4];
    181.                 end
    182.                 3'd5 :begin
    183.                     seg_sel  <= 6'b011111;  //显示数码管最高位
    184.                     num_disp <= num[23:20];
    185.                     dot_disp <= ~point[5];
    186.                 end
    187.                 default :begin
    188.                     seg_sel  <= 6'b111111;
    189.                     num_disp <= 4'b0;
    190.                     dot_disp <= 1'b1;
    191.                 end
    192.             endcase
    193.         end
    194.         else begin
    195.             seg_sel  <= 6'b111111;          //使能信号为0时,所有数码管均不显示
    196.             num_disp <= 4'b0;
    197.             dot_disp <= 1'b1;
    198.         end
    199.     end
    200. end

    201. //控制数码管段选信号,显示字符
    202. always @ (posedge dri_clk or negedge rst_n) begin
    203.     if (!rst_n)
    204.         seg_led <= 8'hc0;
    205.     else begin
    206.         case (num_disp)
    207.             4'd0 : seg_led <= {dot_disp,7'b1000000}; //显示数字 0
    208.             4'd1 : seg_led <= {dot_disp,7'b1111001}; //显示数字 1
    209.             4'd2 : seg_led <= {dot_disp,7'b0100100}; //显示数字 2
    210.             4'd3 : seg_led <= {dot_disp,7'b0110000}; //显示数字 3
    211.             4'd4 : seg_led <= {dot_disp,7'b0011001}; //显示数字 4
    212.             4'd5 : seg_led <= {dot_disp,7'b0010010}; //显示数字 5
    213.             4'd6 : seg_led <= {dot_disp,7'b0000010}; //显示数字 6
    214.             4'd7 : seg_led <= {dot_disp,7'b1111000}; //显示数字 7
    215.             4'd8 : seg_led <= {dot_disp,7'b0000000}; //显示数字 8
    216.             4'd9 : seg_led <= {dot_disp,7'b0010000}; //显示数字 9
    217.             4'd10: seg_led <= 8'b11111111;           //不显示任何字符
    218.             4'd11: seg_led <= 8'b10111111;           //显示负号(-)
    219.             default:
    220.                    seg_led <= {dot_disp,7'b1000000};
    221.         endcase
    222.     end
    223. end


    224. endmodule
    复制代码
            2.2、触摸按键驱动数码管部分程序
       
        在按键松开的上升沿,数码计数一次
       
    1. //数码管需要显示的数据,从0累加到999999
    2. always @ (posedge switch or negedge rst_n) begin
    3.     if (!rst_n)begin
    4.         data_t  <= 20'b0;
    5.         point_t <=6'b000000;
    6.         en_t    <= 1'b0;
    7.         sign_t  <= 1'b0;
    8.     end
    9.     else begin
    10.         point_t <= 6'b000000;             //不显示小数点
    11.         en_t    <= 1'b1;                  //打开数码管使能信号
    12.         sign_t  <= 1'b0;                  //不显示负号
    13.         //if (switch) begin                 //显示数值每隔0.01s累加一次
    14.             if(data_t < 20'd999999)
    15.                 data_t <= data_t +1'b1;     
    16.             else
    17.                 data_t <= 20'b0;
    18.         //end
    19.     end
    20. end
    复制代码

        2.3、主程序部分
       
        将触摸按键的值传递给数码管驱动子程序
    1. //触摸按键
    2. touch u_touch(
    3.     .clk        (sys_clk  ),
    4.     .rst_n      (sys_rst_n),
    5.     .t_key      (touch_key),
    6.     .switch     (key_val ),
    7.          .beep_val   (beep),
    8.          
    9.          .data_t          (data     ),       // 6位数码管要显示的数值
    10.     .point_t         (point    ),       // 小数点具体显示的位置,高电平有效
    11.     .en_t            (en       ),       // 数码管使能信号
    12.     .sign_t          (sign     )        // 符号位
    13. );
    复制代码

        2.4、程序源码    fpag_test-20210515.rar (2.9 MB, 下载次数: 0)
    回复

    使用道具 举报

    您需要登录后才可以回帖 注册/登录

    本版积分规则

    关闭

    站长推荐上一条 /4 下一条

    手机版|小黑屋|与非网

    GMT+8, 2024-11-23 13:18 , Processed in 0.116609 second(s), 17 queries , MemCache On.

    ICP经营许可证 苏B2-20140176  苏ICP备14012660号-2   苏州灵动帧格网络科技有限公司 版权所有.

    苏公网安备 32059002001037号

    Powered by Discuz! X3.4

    Copyright © 2001-2024, Tencent Cloud.