学习目的
- 掌控用Verilog写一个定时触发的功能
- 掌控数码管的动态扫描原理
学习内容
让6位数码管显示“123456”(动态扫描)
实验平台
- 小精灵开发板
- QuartusII 11.0
原理分析
我们上一讲讲了数码管的静态显示,如果只有一位,用静态扫描的方式那么我们需要控制8个段选,1个位选,总共9个引脚。如果我们要控制6位数码管,而同样采用静态扫描的方式,那总共要用9*6=54个管脚,事必会造成管脚的严重浪费。为了节约管脚,同时又能显示多位信息,我们可以采用动态扫描的方式来驱动多位数码管,同样的驱动6位数码管,用动态扫描的方式只需要控制8个段选,6个位选信号,总共14个管脚,比静态扫描节约了40个,所以,利用动态扫描方式驱动数码管,是我们学习以及工作中必需要学会的。动态扫描原理图如下:
多位数码管用于显示更多的数值信息,其由多个数码管组成,这些数码管的段(a~h)一一对应连接在一起,公共极独立。动态扫描即按照一定的方向逐一选中数码管(通过位选接口来选中要点亮的数码管),然后给段选管脚输入事先准备好的编码数据(编号数据参照入门学习第四天)并保持一定的时间,如此循环。由于人眼的视觉暂留效应,我们看到的现象便是多位同时显示,这就像我们小时候翻看动画书,当翻得很快时,我们就发现书里面的小动物跑起来了,当时还乐此不疲的找过各种动画书。根据经验,当帧率为15fps以上时,动画是连贯的,帧率越高动画也越流畅。对于我们的6位数码管,扫描1次(显示6个数字)为一帧。我们可以观察不同的扫描频率对应的数码管显示效果,找到显示效果较好的扫描方式。经实验发现,当每一个数字显示10ms,数码管有明显的闪烁现象,当改为5ms时则显示稳定。
实物效果展示
代码展示
module smg(
input clk,
input rst_n,
output reg [5:0] sm_bit, //数码管选择输出引脚
output reg [7:0] sm_seg //数码管段输出引脚
);
reg[3:0] disp_dat; //定义显示数据寄存器
reg[24:0]count; //定义计数寄存器
//秒信号产生部分
always @(posedge clk or negedge rst_n) //定义clock上升沿触发
begin
if(!rst_n)
count<=0;
//for sim
else if(count == 25'd250000)//if(count == 25'd25000000) //0.5S到了吗?
count = 25'd0; //计数器清零
else
count = count + 1'b1;
end
//数码管动态扫描显示部分
always @(posedge clk or negedge rst_n) //count[17:15]大约1ms改变一次
begin
if(!rst_n)
disp_dat<=0;
else
//case(count[17]) //选择扫描显示数据
//for sim
case(count[15:13]) //选择扫描显示数据
3'd0:disp_dat <= 1; //个位
3'd1:disp_dat <= 2; //十位
3'd2:disp_dat <= 3; //百位
3'd3:disp_dat <= 4; //千位
3'd4:disp_dat <= 5; //万位
3'd5:disp_dat <= 6; //十万位
endcase
end
always @(posedge clk) //count[17:15]大约1ms改变一次
begin
//case(count[17]) //选择数码管显示位
//for sim
case(count[15:13]) //选择扫描显示数据
3'd0:sm_bit <= 6'b111110; //选择第七个数码管显示
3'd1:sm_bit <= 6'b111101; //选择第八个数码管显示
3'd2:sm_bit <= 6'b111011; //选择第七个数码管显示
3'd3:sm_bit <= 6'b110111; //选择第八个数码管显示
3'd4:sm_bit <= 6'b101111; //选择第八个数码管显示
3'd5:sm_bit <= 6'b011111; //选择第八个数码管显示
endcase
end
always @(posedge clk)
begin
case(disp_dat)
4'h0:sm_seg <= 8'hc0; //显示0
4'h1:sm_seg <= 8'hf9; //显示1
4'h2:sm_seg <= 8'ha4; //显示2
4'h3:sm_seg <= 8'hb0; //显示3
4'h4:sm_seg <= 8'h99; //显示4
4'h5:sm_seg <= 8'h92; //显示5
4'h6:sm_seg <= 8'h82; //显示6
4'h7:sm_seg <= 8'hf8; //显示7
4'h8:sm_seg <= 8'h80; //显示8
4'h9:sm_seg <= 8'h90; //显示9
4'ha:sm_seg <= 8'hbf; //显示-
default:sm_seg <= 8'hff; //不显示
endcase
end
endmodule
我们在新建工程时,按照原理图绑定好管脚后,编译会报如下错误:
错误提示我们不能把管脚绑在多功能管脚上,这个问题是由于101管脚是多功能复用管脚,默认为programing pin,所以不用用作我们的普通IO口,这时我们在Quartusii中将101管脚(nce)设置为普通IO口即可。如下图所示:
设置好以后,再次编译,便不会再报错。如果还有小伙伴不知道如何设置,可以参考视频教程,链接如下:https://pan.baidu.com/s/1sfeqGeJ2T5L3IHGHu9Co3Q
提取码:7nxi
结语
通过本实验,我们掌握了数码管动态扫描原理,小伙伴可以自行设计一个秒表,只用在我提供的代码部份稍加修改便可,加油!
视频教程链接:https://pan.baidu.com/s/1LRPfsNM0fr9wf48C5yHUBg
提取码:18ua