数码管动态扫描显示

摸鱼记录 Day_16 (゚O゚)

review

前边已经学习了:

串口接收:Vivado 串口接收优化-CSDN博客

1. 今日摸鱼任务

|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| 串口接收数据 并用数码管显示 (゚O゚) 小梅哥视频: 17A 数码管段码显示与动态扫描原理_哔哩哔哩_bilibili 17B 数码管动态扫描显示数字逻辑建模_哔哩哔哩_bilibili 17C 数码管动态扫描显示的Verilog实现_哔哩哔哩_bilibili 17D 使能时钟和门控时钟的原理与差异_哔哩哔哩_bilibili //虽然看起来很多,但是不会很难滴 (゚O゚) |

2. 数码管显示原理

ACZ702 EDA 扩展板上板载的是共阳数码管。同时为了显示数字或字符,必须对数字或字符进行编码译码。

先不考虑小数点也就是简化为 7 段数码管,其编码译码格式如下表所示:

段式数码管工作方式有两种:静态显示方式和动态显示方式。

静态显示:每个数码管的段选必须接一个 8 位数据线来保持显示的字形码。当送入一次字形码后,显示字形可一直保持,直到送入新字形码为止。

这种方法由于每个数码管均需要独立的数据线,硬件电路比较复杂,成本较高,很少使用。

动态显示:将所有位数码管的段选线并联在一起,由位选线控制是哪一位数码管有效。选亮数码管采用动态扫描显示。所谓动态扫描显示即轮流向各位数码管送出字形码和相应的位选,利用发光管的余辉和人眼视觉暂留作用,使人的感觉好像各位数码管同时都在显示。
电路结构如下所示,这样 3 个数码管接在一起就比静态的少了 7*2 个 I/O 。
sel拉高选中

3. 时钟分频:门控时钟与使能时钟

|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| 门控时钟: 使用计数器和逻辑门翻转产生 |
| reg [14:0]div_clk; always@(posedge clk or negedge reset_n) if(!reset_n) div_clk <= 1'b0; else if(div_clk == 24999) div_clk <= 1'b0; else div_clk <= div_clk + 1'b1; always@(posedge clk or negedge reset_n) if(!reset_n) clk_1 <= 1'b0; else if(div_clk == 24999) clk_1 <= ~clk_1; |
| 使能时钟: 用到计数器,但是不会用到反相器,生成的信号也不会直接用于其他电路的触发 |
| reg [14:0]div_clk; always@(posedge clk or negedge reset_n) if(!reset_n) div_clk <= 1'b0; else if(div_clk == 24999) div_clk <= 1'b0; else div_clk <= div_clk + 1'b1; always@(posedge clk or negedge reset_n) if(!reset_n) disp_en <= 1'b0; else if(div_clk == 24999) disp_en <= 1'b1; else disp_en <= 1'b0; |
| |
| 对比: 门控时钟的时钟延迟不稳定,且延迟比较大 使得时钟的波形变差 驱动能力差 小结:设计中一般情况下使用使能时钟的时钟分频方式 |

4. hex_8

4.1 design sources

|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| hex_8 |
| |
| |
| module hex_8(input clk, input reset_n, input [31:0]disp_data, output reg [7:0]sel, output reg [7:0]seg ); //[31:0]disp_data 16hex 4*8 //[7:0]sel 位选信号 //[7:0]seg 段选信号 // 1kHz分频时钟 reg [14:0]div_clk; always@(posedge clk or negedge reset_n) if(!reset_n) div_clk <= 1'b0; else if(div_clk == 24999) div_clk <= 1'b0; else div_clk <= div_clk + 1'b1; reg disp_en; always@(posedge clk or negedge reset_n) if(!reset_n) disp_en <= 1'b0; else if(div_clk == 24999) disp_en <= 1'b1; else disp_en <= 1'b0; // 位选sel reg[2:0]sel_num; always@(posedge clk or negedge reset_n) if(!reset_n) sel_num <= 3'b000; else if(disp_en) sel_num <= sel_num + 1'b1; //sel_num =3'b111; +1'b1 3'b000; always@(posedge clk or negedge reset_n) if(!reset_n) sel <= 8'b0000_0000; else case(sel_num) 0:sel <= 8'b0000_0001; 1:sel <= 8'b0000_0010; 2:sel <= 8'b0000_0100; 3:sel <= 8'b0000_1000; 4:sel <= 8'b0001_0000; 5:sel <= 8'b0010_0000; 6:sel <= 8'b0100_0000; 7:sel <= 8'b1000_0000; endcase // 段选seg [31:0]disp_data 16hex 4*8 reg [3:0] dis_tmp; always@(posedge clk ) case(sel_num) //高位放前面 0:dis_tmp <= disp_data[31:28]; 1:dis_tmp <= disp_data[27:24]; 2:dis_tmp <= disp_data[23:20]; 3:dis_tmp <= disp_data[19:16]; 4:dis_tmp <= disp_data[15:12]; 5:dis_tmp <= disp_data[11:8]; 6:dis_tmp <= disp_data[7:4]; 7:dis_tmp <= disp_data[3:0]; endcase always@(posedge clk) case(dis_tmp) 0:seg <= 8'hc0; 1:seg <= 8'hf9; 2:seg <= 8'ha4; 3:seg <= 8'hb0; 4:seg <= 8'h99; 5:seg <= 8'h92; 6:seg <= 8'h82; 7:seg <= 8'hf8; 8:seg <= 8'h80; 9:seg <= 8'h90; 4'ha:seg <= 8'h88; 4'hb:seg <= 8'h83; 4'hc:seg <= 8'hc6; 4'hd:seg <= 8'ha1; 4'he:seg <= 8'h86; 4'hf:seg <= 8'h8e; endcase endmodule |

4.2 hex_8_tb

|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| `timescale 1ns / 1ns module hex_8_tb( ); reg clk , reset_n; reg [31:0]disp_data; wire[7:0]sel; wire[7:0]seg; hex_8 hex_8_(. clk(clk), . reset_n(reset_n), . disp_data(disp_data), . sel(sel), . seg(seg) ); initial clk = 1 ; always#10 clk = ~clk; initial begin reset_n = 0 ; #201; reset_n = 1 ; disp_data = 32'h01234567; #10000000; disp_data = 32'h89abcdef; #10000000; $stop; end endmodule |
| |
| 红色框框内输入数据发生了改变,但是很快就会闪过去 所以没有像串口发送添加一个存储数据让其保持一个运行周期 Vivado 串口通信(UART)------串口发送-CSDN博客 |

5. 串口接收 + 数码管动态显示

5.1 design sources

|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| module uart_rx(input clk , input reset_n , input uart_rx , output reg [7:0]rx_data, output reg rx_done ); //默认使用波特率BAUD 9600 时钟频率 CLK_FREQ 50MHz // parameter start_bit = 0 ; // parameter stop_bit = 1 ; parameter BAUD = 9600; parameter CLK_FREQ = 50_000_000; parameter bps_c = CLK_FREQ / BAUD ; reg rx_en ; reg[3:0] rx_flag; // bps reg [30:0] counter_bps ; always@(posedge clk or negedge reset_n) if(! reset_n) counter_bps <= 0 ; else if (rx_en) if(counter_bps == bps_c - 1) counter_bps <= 0 ; else counter_bps <= counter_bps + 1'b1 ; else counter_bps <= 0 ; reg dff_rx_0 , dff_rx_1 ; reg r_uart_rx; wire neg_rx_go ; always@(posedge clk ) dff_rx_0 <= uart_rx ; always@(posedge clk ) dff_rx_1 <= dff_rx_0 ; always@(posedge clk ) r_uart_rx <= dff_rx_1 ; assign neg_rx_go = (dff_rx_1 == 0)&&(r_uart_rx == 1); // rx_en always@(posedge clk or negedge reset_n) if(! reset_n) rx_en <= 0 ; else if(neg_rx_go) rx_en <= 1 ; else if((rx_flag==9)&&(counter_bps == bps_c / 2)) rx_en <= 0 ; else if((rx_flag==0)&&(counter_bps == bps_c/2 )&&(dff_rx_1==1)) rx_en <= 0 ; // rx_flag always@(posedge clk or negedge reset_n) if(!reset_n) rx_flag <= 4'b0000 ; else if((rx_flag == 9)&&(counter_bps == bps_c /2)) rx_flag <= 4'b0000 ; else if(counter_bps == bps_c - 1) rx_flag <= rx_flag + 1'b1 ; // [7:0]r_rx_data reg [7:0] r_rx_data; always@(posedge clk ) if(!rx_en) r_rx_data <= r_rx_data; else if(counter_bps == bps_c / 2) begin case(rx_flag) 1 : r_rx_data[0] <= dff_rx_1; 2 : r_rx_data[1] <= dff_rx_1; 3 : r_rx_data[2] <= dff_rx_1; 4 : r_rx_data[3] <= dff_rx_1; 5 : r_rx_data[4] <= dff_rx_1; 6 : r_rx_data[5] <= dff_rx_1; 7 : r_rx_data[6] <= dff_rx_1; 8 : r_rx_data[7] <= dff_rx_1; default : r_rx_data <= r_rx_data; endcase end // rx_done always@(posedge clk) rx_done <= (rx_flag==9)&&(counter_bps == bps_c /2); // rx_data ; always@(posedge clk) if(rx_done) rx_data <= r_rx_data; endmodule |
| rx_hex8 |
| module rx_hex8(input clk, input reset_n, input uart_rx , output [7:0]sel, output [7:0]seg ); reg [1:0] rx_done_flag; reg [31:0]disp_data; wire [7:0] rx_data; wire rx_done; uart_rx uart_rx_(. clk(clk) , . reset_n(reset_n) ,.uart_rx(uart_rx) , . rx_data(rx_data), . rx_done(rx_done) ); always@(posedge clk or negedge reset_n) if(! reset_n) rx_done_flag <= 2'b11 ; else if(rx_done) rx_done_flag <= rx_done_flag + 1'b1 ; always@(posedge clk or negedge reset_n) if(! reset_n) disp_data <= 8'h0000_0000 ; else case(rx_done_flag) 0:begin disp_data <= disp_data; disp_data[7:0] <= rx_data;end 1:begin disp_data <= disp_data; disp_data[15:8] <= rx_data;end 2:begin disp_data <= disp_data; disp_data[23:16] <= rx_data;end 3:begin disp_data <= disp_data; disp_data[31:24] <= rx_data;end endcase hex_8 hex_8_(. clk(clk), . reset_n(reset_n), . disp_data(disp_data), .sel(sel), .seg(seg) ); endmodule |

5.2 rx_hex8_tb

|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| `timescale 1ns / 1ns module hex_8_tb( ); reg clk , reset_n , uart_rx_; wire[7:0]sel; wire[7:0]seg; rx_hex8 rx_hex8_(. clk(clk), . reset_n(reset_n), . uart_rx(uart_rx_), . sel(sel), . seg(seg) ); initial clk = 1 ; always#10 clk = ~clk; initial begin reset_n = 0 ; #201; reset_n = 1 ; uart_rx_ = 1 ;#(5208*20); //0 f uart_rx_ = 0 ; #(5208*20); uart_rx_ = 0 ; #(5208*20);uart_rx_ = 0 ; #(5208*20); uart_rx_ = 0 ; #(5208*20);uart_rx_ = 0 ; #(5208*20); uart_rx_ = 1 ; #(5208*20);uart_rx_ = 1 ; #(5208*20); uart_rx_ = 1 ; #(5208*20);uart_rx_ = 1 ; #(5208*20); uart_rx_ = 1 ; #(5208*20); //9 6 uart_rx_ = 0 ; #(5208*20); uart_rx_ = 1 ; #(5208*20);uart_rx_ = 0 ; #(5208*20); uart_rx_ = 0 ; #(5208*20);uart_rx_ = 1 ; #(5208*20); uart_rx_ = 0 ; #(5208*20);uart_rx_ = 1 ; #(5208*20); uart_rx_ = 1 ; #(5208*20);uart_rx_ = 0 ; #(5208*20); uart_rx_ = 1 ; #(5208*20); //4 5 uart_rx_ = 0 ; #(5208*20); uart_rx_ = 0 ; #(5208*20);uart_rx_ = 0 ; #(5208*20); uart_rx_ = 1 ; #(5208*20);uart_rx_ = 0 ; #(5208*20); uart_rx_ = 1 ; #(5208*20);uart_rx_ = 0 ; #(5208*20);uart_rx_ = 1 ; #(5208*20);uart_rx_ = 0 ; #(5208*20); uart_rx_ = 1 ; #(5208*20); // 3 c uart_rx_ = 0 ; #(5208*20); uart_rx_ = 0 ; #(5208*20);uart_rx_ = 0 ; #(5208*20); uart_rx_ = 1 ; #(5208*20);uart_rx_ = 1 ; #(5208*20); uart_rx_ = 1 ; #(5208*20);uart_rx_ = 1 ; #(5208*20); uart_rx_ = 0 ; #(5208*20);uart_rx_ = 0 ; #(5208*20); uart_rx_ = 1 ; #(5208*20); //0 f uart_rx_ = 0 ; #(5208*20); uart_rx_ = 0 ; #(5208*20);uart_rx_ = 0 ; #(5208*20); uart_rx_ = 0 ; #(5208*20);uart_rx_ = 0 ; #(5208*20); uart_rx_ = 1 ; #(5208*20);uart_rx_ = 1 ; #(5208*20); uart_rx_ = 1 ; #(5208*20);uart_rx_ = 1 ; #(5208*20); uart_rx_ = 1 ; #(5208*20); uart_rx_ = 0 ; #(5208*20); uart_rx_ = 0 ; #(5208*20);uart_rx_ = 0 ; #(5208*20); uart_rx_ = 0 ; #(5208*20);uart_rx_ = 0 ; #(5208*20); uart_rx_ = 1 ; #(5208*20);uart_rx_ = 1 ; #(5208*20); uart_rx_ = 1 ; #(5208*20);uart_rx_ = 1 ; #(5208*20); uart_rx_ = 1 ; #(5208*20); uart_rx_ = 0 ; #(5208*20); uart_rx_ = 0 ; #(5208*20);uart_rx_ = 0 ; #(5208*20); uart_rx_ = 0 ; #(5208*20);uart_rx_ = 0 ; #(5208*20); uart_rx_ = 1 ; #(5208*20);uart_rx_ = 1 ; #(5208*20); uart_rx_ = 1 ; #(5208*20);uart_rx_ = 1 ; #(5208*20); uart_rx_ = 1 ; #(5208*20); uart_rx_ = 0 ; #(5208*20); uart_rx_ = 0 ; #(5208*20);uart_rx_ = 0 ; #(5208*20); uart_rx_ = 0 ; #(5208*20);uart_rx_ = 0 ; #(5208*20); uart_rx_ = 1 ; #(5208*20);uart_rx_ = 1 ; #(5208*20); uart_rx_ = 1 ; #(5208*20);uart_rx_ = 1 ; #(5208*20); uart_rx_ = 1 ; #(5208*20); uart_rx_ = 0 ; #(5208*20); uart_rx_ = 0 ; #(5208*20);uart_rx_ = 0 ; #(5208*20); uart_rx_ = 0 ; #(5208*20);uart_rx_ = 0 ; #(5208*20); uart_rx_ = 1 ; #(5208*20);uart_rx_ = 1 ; #(5208*20); uart_rx_ = 1 ; #(5208*20);uart_rx_ = 1 ; #(5208*20); uart_rx_ = 1 ; #(5208*20); # 10000; $stop; end endmodule |
| |

//好耶~~~~~

//摸鱼结束哩 (゚O゚)

//顺便挖坑SPI协议

相关推荐
江将好...1 小时前
定时器实验(Proteus 与Keil uVision联合仿真)
单片机·嵌入式硬件
地球空间-技术小鱼1 小时前
嵌入式系统学习
嵌入式硬件·学习
物随心转1 小时前
中断系统的原理
单片机·嵌入式硬件
FreakStudio9 小时前
全网最适合入门的面向对象编程教程:56 Python字符串与序列化-正则表达式和re模块应用
python·单片机·嵌入式·面向对象·电子diy
EVERSPIN12 小时前
分享国产32位单片机的电机控制方案
单片机·嵌入式硬件
每天一杯冰美式oh12 小时前
51单片机的家用煤气报警系统【proteus仿真+程序+报告+原理图+演示视频】
嵌入式硬件·51单片机·proteus
芯橦15 小时前
【瑞昱RTL8763E】音频
单片机·嵌入式硬件·mcu·物联网·音视频·visual studio code·智能手表
夜间去看海19 小时前
基于单片机的智能浇花系统
单片机·嵌入式硬件·智能浇花
VirtuousLiu19 小时前
LM74912-Q1用作电源开关
单片机·嵌入式硬件·ti·电源设计·lm74912·电源开关
打地基的小白19 小时前
软件I2C-基于江科大源码进行的原理解析和改造升级
stm32·单片机·嵌入式硬件·通信模式·i2c