加入星计划,您可以享受以下权益:

  • 创作内容快速变现
  • 行业影响力扩散
  • 作品版权保护
  • 300W+ 专业用户
  • 1.5W+ 优质创作者
  • 5000+ 长期合作伙伴
立即加入
  • 正文
    • 1.概述
    • 2. 硬件原理
    • 3. 软件实现
  • 推荐器件
  • 相关推荐
  • 电子产业图谱
申请入驻 产业图谱

FPGA入门基础之数码管显示

06/01 10:25
4839
阅读需 17 分钟
加入交流群
扫码加入
获取工程师必备礼包
参与热点资讯讨论

引言:本文介绍数码管显示译码基本工作原理及Verilog HDL驱动代码编写,进一步熟练掌握FPGA入门基础知识。

1.概述

数码管是显示屏其中一类,通过对其不同的管脚输入相对的电流,会使其发亮,从而显示出数字能够显示 时间、日期、温度等所有可用数字表示的参数。

由于它的价格便宜,使用简单,在电器特别是家电领域应用极为广泛,空调、热水器、冰箱等等。绝大多数热水器用的都是数码管,其他家电也用液晶屏与荧光屏。

2. 硬件原理

如图2所示,数码管按段数分为七段数码管和八段数码管,八段数码管比七段数码管多一个发光二极管单元(多一个小数点显示)。按能显示多少个“8”可分为1 位、2 位、4 位等等数码管。

如图2所示,按发光二极管单元连接方式分为共阳极数码管和共阴极数码管

图2:数码管共阴极(左侧)和共阳极(右侧)接法

共阴数码管是指将所有发光二极管的阴极接到一起形成公共阴极(COM)的数码管,共阴数码管在应用时应将公共极 COM接到地线 GND 上,当某一字段发光二极管的阳极为高电平时,相应字段就点亮,当某一字段的阳极为低电平时,相应字段就不亮。共阳数码管是指将所有发光二极管的阳极接到一起形成公共阳极(COM)的数码管,共阳数码管在应用时应将公共极COM 接到+3.3V(高电平),当某一字段发光二极管的阴极为低电平时,相应字段就点亮,当某一字段的阴极为高电平时,相应字段就不亮。图3:4位数码管共阳极接法

如图3所示,4位数码管的每段全部连接在一起,如果想动态控制每位数码管,就不能将四位数码管的COM端连接在一起,必须分别控制每位数码管的COM端,即增加位选择控制信号。8位数码管共阳极连接原理图如图4所示。

图4:8位数码管原理图

如图4所示,8位数码管通过Sel[7..0]8个数据IO实现位选择,通过Disp[7..0]8个数据IO实现段选择。由于FPGA IO口驱动电流能力弱,增加三极管可提高驱动能力。如图4所示,基极为低电平,三极管导通,数码管被选中,被选中的数码管相应的段发光显示。由于4位数码管的的数据端(ABCDEFG)是公用的,而每一位的数码管的公共阳极(COM)是单独,若某一位数码管显示字符,则这一位的公共阳极就要连接到低电平。

3. 软件实现

数码管显示有静态显示和动态显示两种方式。

在静态显示中,只考虑段选信号。在不同的时刻,各个位选信号保持不变,并根据真值表,选择要显示的数字或者字母。由于多位数码管段信号是连在一起的,所以这种情况下每位数码管显示的内容是想通过的。要想每位数码管显示不同内容,只能采用动态显示方式。

在动态显示中,需要将位选信号考虑进来。在不同的时刻,各个位的位选信号随时改变,并根据真值表,选择显示不同的数字或者字母。

3.1 数码管静态显示

根据图4硬件原理图,数码管位选择信号为低电平“0”时,同时数码管段为低电平“0”时,点亮数码管内部LED发光二极管。

数码管静态显示代码如下所示。

/*************************************************数码管静态显示按键计数值。*************************************************///位选信号     assign segma_sel_o = 8'h00; //使能所有数码管位   //段选信号,关闭DP点显示  always @(posedge sys_clk_i or negedge rst_n_i) begin         if(!rst_n_i) begin        segma_disp_o  <= 8'b0000001_1;           end  else begin      case(cnt) //按键计数值          4'd0: segma_disp_o  <= 8'b0000001_1; //"0"          4'd1: segma_disp_o  <= 8'b1001111_1; //"1"          4'd2: segma_disp_o  <= 8'b0010010_1; //"2"        4'd3: segma_disp_o  <= 8'b0000110_1; //"3"        4'd4: segma_disp_o  <= 8'b1001100_1; //"4"        4'd5: segma_disp_o  <= 8'b0100100_1; //"5"        4'd6: segma_disp_o  <= 8'b0100000_1; //"6"        4'd7: segma_disp_o  <= 8'b0001111_1; //"7"        4'd8: segma_disp_o  <= 8'b0000000_1; //"8"        4'd9: segma_disp_o  <= 8'b0000100_1; //"9"        4'd10: segma_disp_o <= 8'b0001000_1; //"A"        4'd11: segma_disp_o <= 8'b1100000_1; //"B"        4'd12: segma_disp_o <= 8'b0110001_1; //"C"        4'd13: segma_disp_o <= 8'b1000010_1; //"D"        4'd14: segma_disp_o <= 8'b0110000_1; //"E"        4'd15: segma_disp_o <= 8'b0111000_1; //"F"              endcase       endend

‍测试结果如下:

3.2 数码管动态显示

数码管动态动态扫描显示,实际上是利用了两个现象:人眼的视觉暂留特性和数码管的余晖效应。人眼在观察景物时,光信号传入到大脑神经需要经过一段时间,光的作用结束之后我们的视觉影像并不会立刻的消失,这种残留的视觉被称为后像,这种现象就被称为视觉暂留;数码管的余晖效应是什么意思呢?当我们停止向发光二极管供电时,发光二极管的亮度仍能够维持一段时间。我们的动态扫描利用这两个特性就实现了数码管的动态显示。

(1)数码管位扫描控制代码:编写计数器cnt_scanf,周期性产生数码管选择信号seg_wei_num,根据seg_wei_num解码对应的需要使能数码管位segma_wei_o。

// 计数器,控制数码管位reg [23:0] cnt_scanf;always @(posedge clk_i or negedge rst_n_i) beginif(!rst_n_i) begin    cnt_scanf <= 24'd0;  endelse begin     if(cnt_scanf == timer_scanf_i)       cnt_scanf <= 24'd0;    else      cnt_scanf <= cnt_scanf + 24'd1;  endend
//数码管扫描序号reg [2:0] segma_wei_num; always @(posedge clk_i or negedge rst_n_i) beginif(!rst_n_i) begin    segma_wei_num <= 3'd0;  endelse begin    if(cnt_scanf == timer_scanf_i)      segma_wei_num <= segma_wei_num + 3'd1;    else      segma_wei_num <= segma_wei_num;  endend
//解码选中的数码管always @(posedge clk_i or negedge rst_n_i) beginif(!rst_n_i) begin    segma_wei_o <= 8'b1111_1111;  endelse begin    case(segma_wei_num)      3'd0: segma_wei_o <= 8'b1110_1111; //选中第1个数码管      3'd1: segma_wei_o <= 8'b1101_1111; //选中第2个数码管      3'd2: segma_wei_o <= 8'b1011_1111; //选中第3个数码管      3'd3: segma_wei_o <= 8'b0111_1111; //选中第4个数码管          3'd4: segma_wei_o <= 8'b1111_1110; //选中第5个数码管      3'd5: segma_wei_o <= 8'b1111_1101; //选中第6个数码管      3'd6: segma_wei_o <= 8'b1111_1011; //选中第7个数码管      3'd7: segma_wei_o <= 8'b1111_0111; //选中第8个数码管       default: segma_wei_o <= 8'b1111_1111;      endcase  endend

(2)数码管段显示控制代码:根据当前使能的数码管位segma_wei_num,获取当前数码管位需要显示的数据信息led_duan,然后根据led_duan数据解码映射到需要显示的每段发光二极管,数码管DP段单独控制。

//获取当前数码管位DP段always @(*) begin  case(segma_wei_num)    3'd0: segma_duan_o[0] <= i_led0_data[4]; // 第1个数码管DP段数据    3'd1: segma_duan_o[0] <= i_led1_data[4]; // 第2个数码管DP段数据        3'd2: segma_duan_o[0] <= i_led2_data[4]; // 第3个数码管DP段数据    3'd3: segma_duan_o[0] <= i_led3_data[4]; // 第4个数码管DP段数据        3'd4: segma_duan_o[0] <= i_led4_data[4]; // 第5个数码管DP段数据    3'd5: segma_duan_o[0] <= i_led5_data[4]; // 第6个数码管DP段数据        3'd6: segma_duan_o[0] <= i_led6_data[4]; // 第7个数码管DP段数据    3'd7: segma_duan_o[0] <= i_led7_data[4]; // 第8个数码管DP段数据      endcaseend
//获取当前数码管位其他段数据reg [3:0] led_duan;always @(*) begin  case(segma_wei_num)    3'd0: led_duan <= i_led0_data[3:0]; // 第1个数码管其他段数据    3'd1: led_duan <= i_led1_data[3:0]; // 第2个数码管其他段数据        3'd2: led_duan <= i_led2_data[3:0]; // 第3个数码管其他段数据    3'd3: led_duan <= i_led3_data[3:0]; // 第4个数码管其他段数据        3'd4: led_duan <= i_led4_data[3:0]; // 第5个数码管其他段数据    3'd5: led_duan <= i_led5_data[3:0]; // 第6个数码管其他段数据        3'd6: led_duan <= i_led6_data[3:0]; // 第7个数码管其他段数据    3'd7: led_duan <= i_led7_data[3:0]; // 第8个数码管其他段数据      endcaseend
//解码数码管段数据always @(*) begin  case(led_duan)      4'd0: segma_duan_o[7:1]  <= 7'b0000001; //"0"       4'd1: segma_duan_o[7:1]  <= 7'b1001111; //"1"      4'd2: segma_duan_o[7:1]  <= 7'b0010010; //"2"      4'd3: segma_duan_o[7:1]  <= 7'b0000110; //"3"      4'd4: segma_duan_o[7:1]  <= 7'b1001100; //"4"      4'd5: segma_duan_o[7:1]  <= 7'b0100100; //"5"      4'd6: segma_duan_o[7:1]  <= 7'b0100000; //"6"      4'd7: segma_duan_o[7:1]  <= 7'b0001111; //"7"      4'd8: segma_duan_o[7:1]  <= 7'b0000000; //"8"      4'd9: segma_duan_o[7:1]  <= 7'b0000100; //"9"      4'd10: segma_duan_o[7:1] <= 7'b0001000; //"A"      4'd11: segma_duan_o[7:1] <= 7'b1100000; //"B"      4'd12: segma_duan_o[7:1] <= 7'b0110001; //"C"      4'd13: segma_duan_o[7:1] <= 7'b1000010; //"D"      4'd14: segma_duan_o[7:1] <= 7'b0110000; //"E"      4'd15: segma_duan_o[7:1] <= 7'b0111000; //"F"      endcaseend

测试结果如下:

欢迎关注FPGA技术实战公众号,喜欢就多多转发吧!

推荐器件

更多器件
器件型号 数量 器件厂商 器件描述 数据手册 ECAD模型 风险等级 参考价格 更多信息
A3P1000-FG484I 1 Microchip Technology Inc Field Programmable Gate Array, 24576 CLBs, 1000000 Gates, 350MHz, CMOS, PBGA484
$375.77 查看
EP3C16Q240C8N 1 Intel Corporation Field Programmable Gate Array, 15408 CLBs, 472.5MHz, 15408-Cell, CMOS, PQFP240, 34.60 X 34.60 MM, 4.10 MM HEIGHT, 0.50 MM PITCH, PLASTIC, LEAD FREE, QFP-240

ECAD模型

下载ECAD模型
$45.2 查看
EP2C8Q208I8N 1 Altera Corporation Field Programmable Gate Array, 516 CLBs, 402.5MHz, 8256-Cell, CMOS, PQFP208, LEAD FREE, PLASTIC, QFP-208
$39.64 查看

相关推荐

电子产业图谱

专注FPGA技术开发,涉及Intel FPGA、Xilinx FPGA技术开发,开发环境使用,代码风格、时序收敛、器件架构以及软硬件项目实战开发,个人公众号:FPGA技术实战。