实验四 七段数码管的动态扫描显示
专业:电子信息科学与技术 姓名:高晓骏 学号:2012021199010
一.实验目的
(1)进一步熟悉Quartus II软件进行FPGA设计的流程;
(2)掌握利用宏功能模块进行常用的计数器,译码器的设计;
(3)学习和了解动态扫描数码管的工作原理的程序设计方法;
二.实验器材
(1)PC机
(2)Quartus II开发工具软件
三.实验原理
实验板上常用4位联体的共阳极7段数码管,其接口电路是把所有数码管的8个笔划段a-h同名端连在一起,而每一个数码管由一个独立的公共极COM端控制。
当向数码管发送字形码时,所有数码管都接收到相同的字形码时,但究竟是那个数码管亮,取决于COM端,这一端是由I/O控制的,所以就可以自行决定何时显示哪一位。动态扫描即采用分时方法,轮流控制各个LED轮流点亮。
在轮流点亮扫描过程中,每一位显示器的点亮时间是极为短暂的,但由于人的视觉暂留现象及发光二极管的余辉效应,尽管实际上每个显示器并非同时点亮,但只要扫描的速度足够快,给人的印象就是一组稳定的显示数据,不会有闪烁感。
四、实验要求:
实现显示0000-9999的十进制计数器。
五.实验内容及步骤
1.建立工程
建立名为leddisplay的工程,并建立顶层图。
2.设计计数时钟
设计一个分频器,对50MHz分频输出到计数器,让计数器以较慢的速度递增。
module int_div(clk,div_out);
input clk;
output reg div_out;
reg [31:0] clk_div;
parameter CLK_FREQ = 'D50_000_000; //系统时钟50MHz
parameter DCLK_FREQ = 'D10; //输出频率10/2Hz
always@(posedge clk)
begin
if(clk_div < (CLK_FREQ/DCLK_FREQ))
clk_div <= clk_div + 1;
else
begin
clk_div <= 0;
div_out <= ~div_out;
end
end
endmodule
输入完成后,将该文件设为顶层实体,该命令在Project->Set as top-level Entity。
分析该设计文件:执行工具栏处的“Start Analysis &Synthesis命令按钮,开始分析综合,此步骤在这里用于检查设计错误。
分析成功后要生成一个分频器的元件符号,执行File->Create Symbol files for current file,开始建立该文件的元件符号。
3.调用宏功能模块设计计数器
module cnt10000(qout,clr,clk);
input clr;
input clk;
output[15:0] qout;
reg[15:0] qout;
always@(posedge clk)
if(!clr) qout[15:0]=0;
else if(qout[3:0]==9)
begin
qout[3:0]=0;
if(qout[7:4]==9)
begin
qout[7:4]=0;
if(qout[11:8]==9)
begin
qout[11:8]=0;
if(qout[15:12]==9) qout[15:12]=0;
else qout[15:12]=qout[15:12]+1'b1;
end
else qout[11:8]=qout[11:8]+1'b1;
end
else qout[7:4]=qout[7:4]+1'b1;
end
else qout[3:0]=qout[3:0]+1'b1;
endmodule
输入完成后,将其设为顶层实体,检验后生成元件符号。
4.数码管扫描显示程序设计(不含小数点)
module segmain(clk,reset_n,datain,seg_data, seg_com);
input clk;
input reset_n;
input [15:0] datain;
output [7:0] seg_data;
output [3:0] seg_com;
reg [3:0] seg_com;
reg [7:0] seg_data;
reg [3:0] bcd_led;
reg [26:0] count;
always@(posedge clk)
begin
if (!reset_n) count <= 0;
else count <= count + 1;
end
always@(count[14:13] or datain)
begin
case(count[14:13])
2'b00:
begin
bcd_led = datain[3:0];
seg_com = 4'b1110;//
end
2'b01:
begin
bcd_led = datain[7:4];
seg_com = 4'b1101;//
end
2'b10:
begin
bcd_led = datain[11:8];
seg_com = 4'b1011;//
end
2'b11:
begin
bcd_led = datain[15:12];
seg_com = 4'b0111;//
end
endcase
end
always@(seg_com or bcd_led)
begin
case(bcd_led)
4'h0: seg_data = 8'hc0;//0
4'h1: seg_data = 8'hf9;//1
4'h2: seg_data = 8'ha4;//2
4'h3: seg_data = 8'hb0;//3
4'h4: seg_data = 8'h99;//4
4'h5: seg_data = 8'h92;//5
4'h6: seg_data = 8'h82;//6
4'h7: seg_data = 8'hf8;//7
4'h8: seg_data = 8'h80;//8
4'h9: seg_data = 8'h90;//9
4'ha: seg_data = 8'h88;//a
4'hb: seg_data = 8'h83;//b
4'hc: seg_data = 8'hc6;//c
4'hd: seg_data = 8'ha1;//d
4'he: seg_data = 8'h86;//e
4'hf: seg_data = 8'h8e;//f
default: seg_data = 8'h80;//0
endcase
end
endmodule
输入完成后,将其设为顶层实体,检验后生成元件符号。
5.设计完整的顶层
返回顶层原理图,并注意重新将顶层原理图设为顶层实体。
双击顶层图空白的地方,弹出symbol对话框,展开Libraries栏的Project库,可看到上述步骤建立的一些元件符号。
按OK,在图纸上空白地方点击即可输入相应的元件,添加其它元件,完成下图连接:
6.设置芯片和管脚。设置芯片型号、配置芯片型号等内容。
参照以下文件配置芯片管脚,并运行该tcl 脚本。
#Setup.tcl ------ Setup pin setting for EP3C25-V5 main board
set_global_assignment -name RESERVE_ALL_UNUSED_PINS "AS INPUT TRI-STATED"
set_global_assignment -name ENABLE_INIT_DONE_OUTPUT OFF
set_location_assignment PIN_149 -to clk
set_location_assignment PIN_90 -to reset
#seg7led ------ 78LED
set_location_assignment PIN_148 -to 78ledcom[0]
set_location_assignment PIN_147 -to 78ledcom[1]
set_location_assignment PIN_160 -to 78ledcom[2]
set_location_assignment PIN_159 -to 78ledcom[3]
# set_location_assignment PIN_162 -to 78ledcom[4]
# set_location_assignment PIN_161 -to 78ledcom[5]
# set_location_assignment PIN_166 -to 78ledcom[6]
# set_location_assignment PIN_164 -to 78ledcom[7]
set_location_assignment PIN_145 -to 78leddata[0]
set_location_assignment PIN_143 -to 78leddata[1]
set_location_assignment PIN_137 -to 78leddata[2]
set_location_assignment PIN_139 -to 78leddata[3]
set_location_assignment PIN_144 -to 78leddata[4]
set_location_assignment PIN_146 -to 78leddata[5]
set_location_assignment PIN_135 -to 78leddata[6]
set_location_assignment PIN_142 -to 78leddata[7]
7.编译
执行菜单命令Project->Set as top-level Entity,将顶层图设为当前顶层实体,然后编译。
8.下载
(1)下载设置:使用下载线下载配置文件到FPGA。
(2)下载完毕后可看到实验现象:数码管实现显示0000-9999的十进制计数器。
六.思考题
count[14:13] or datain是什么意思?
这条语句是判断已经计数的状态,并将相应的数码管变亮,选择扫描显示数据,count[14:13]大约1ms改变一次,而count[26:25]则闪烁的时间更短,人眼无法看清,故出现不正常显示的现象。
七.实验小结
(1)这是我们这学期数字电路EDA综合实验的第一次实验报告,在前几次的实验中,已经熟悉了QuartusII设计软件的基本功能、原理图输入和HDL输入方法、功能仿真、综合、配置与编程的设计过程,尤其是针对QuartusII的使用初步花了几节课的时间,毕竟这个软件对于我们来说是很陌生的。
(2)在前面的实验中,学习QuartusII的基础实验中,课本上的介绍是很详细的,每一个操作步骤都是有截图的,所以跟着步骤一步一步的,只要小心谨慎,是不会出现错误的。
(3)这次的实验是对前几次的实验的整合,在LED的按键控制的基础上进行的实验,在我做实验的工程中,查找错误是最麻烦的琐碎的,往往错误源于很小的失误,比如忘记建立顶层图、调用宏功能模块设计计数器时选错选项等等。这些错误看似微不足道,但是检查起来异常麻烦,所以我们在做实验的时候一定要小心谨慎,切记三心二意。
(4)通过这一次的实验练习,希望为以后打下坚实的基础。
第二篇:4数码管动态扫描显示
1.利用动态扫描方法在六位数码管上显示出稳定的87654321.
#include<reg52.h>
#define uint unsigned int
#define uchar unsigned char
uchar code tabledu[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71};
uchar code tablewe[]={0x7f,0xbf,0xdf,0xef,0xf7,0xfb,0xfd,0xfe};
uint numdu,numwe,a;/*用uint 或int时只能65536-(1000~5000),用uchar和char则不会*/ void main()
{numdu=8;
numwe=0;
a=0;
EA=1;
ET1=1;
TR1=1;
TMOD=0x10;
TH1=(65536-1000)/256;
TL1=(65536-1000)%256;
while(1)
{ if(a==1)
{a=0;
P0=tabledu[numdu];
numdu--;
if(numdu==0)
numdu=8;
P2=tablewe[numwe];
numwe++;
if(numwe==8)
numwe=0;
}
}
}
void time1() interrupt 3
{TH1=(65536-1000)/256;
TL1=(65536-1000)%256;
a++;
}
2.用动态扫描方法和定时器0在数码管的前三位显示出秒表,精确到1%秒,即后两位显示1%秒,一直循环下去。
#include<reg52.h>
#define uint unsigned int
#define uchar unsigned char
uint temp,aa=0,bai,shi,ge; /*不能用uchar或char,可用uint或int*/
uchar code table[]={
0x3f,0x06,0x5b,0x4f,
0x66,0x6d,0x7d,0x07,
0x7f,0x6f,0x77,0x7c,
0x39,0x5e,0x79,0x71};
void display(uchar bai,uchar shi,uchar ge);
void delay(uint z);
void init();
void main()
{
init();//初始化子程序
while(1)
{
display(bai,shi,ge);
}
}
void delay(uint z)
{
uint x,y;
for(x=z;x>0;x--)
for(y=110;y>0;y--);
}
void display(uchar bai,uchar shi,uchar ge)
{
P2=0x7f;
P0=table[bai]+0x80;
delay(5);
P2=0xbf;
P0=table[shi];
delay(5);
P2=0xdf;
P0=table[ge];
delay(5);
}
void init()
{
temp=0;
TMOD=0x01;
TH0=(65536-10000)/256;
TL0=(65536-10000)%256;
EA=1;
ET0=1;
TR0=1;
}
void timer0() interrupt 1
{
TH0=(65536-10000)/256;
TL0=(65536-10000)%256;
aa++;
if(aa==1) /*放主函数中达不到此效果*/
{
aa=0;
temp++;
if(temp==1000)
{
temp=0;
}
bai=temp/100;
shi=temp%100/10;
ge=temp%10;
}
}
3、利用动态扫描和定时器1在数码管上显示出从765432开始以1/10秒的速度往下递减直至765398并保持显示此数,与此同时利用定时器0以500MS速度进行流水灯从上至下移动,当数码管上数减到停止时,实验板上流水灯也停止然后全部开始闪烁,3秒后(用T0定时)流水灯全部关闭、数码管上显示出“HELLO”。到此保持住。
#include<reg52.h>
#include<intrins.h>
#define uint unsigned int
#define uchar unsigned char
uint temp,c,aa=0,bb=0,shiwan,wan,qian,bai,shi,ge,flag=0,flag1=0; /*不能用uchar或char,可用uint或int*/
uchar code table[]={
0x3f,0x06,0x5b,0x4f,
0x66,0x6d,0x7d,0x07,
0x7f,0x6f,0x77,0x7c,
0x39,0x5e,0x79,0x71,0x76,0x79,0x38,0x3f,0};
void display(uchar shiwan,uchar wan,uchar qian,uchar bai,uchar shi,uchar ge); void delay(uint z);
void init();
void main()
{
init();
while(1)
{if(flag1!=1)
display(7,6,5,bai,shi,ge);
else
display(16,17,18,18,19,20);
}
}
void delay(uint z)
{
uint x,y;
for(x=z;x>0;x--)
for(y=110;y>0;y--);
}
void display(uchar shiwan,uchar wan,uchar qian,uchar bai,uchar shi,uchar ge) {
P2=0x7f;
P0=table[shiwan];
delay(1);
P2=0xbf;
P0=table[wan];
delay(1);
P2=0xdf;
P0=table[qian];
delay(1);
P2=0xef;
P0=table[bai];
delay(1);
P2=0xf7;
P0=table[shi];
delay(1);
P2=0xfb;
P0=table[ge];
delay(1);
}
void init()
{ c=0xfe;
P3=c;
temp=432;
TMOD=0x11;
TH0=(65536-50000)/256; TL0=(65536-50000)%256; EA=1;
ET0=1;
TR0=1;
TH1=(65536-50000)/256; TL1=(65536-50000)%256; ET1=1;
TR1=1;
}
void timer0() interrupt 1 {
TH0=(65536-50000)/256; TL0=(65536-50000)%256; bb++;
if(flag!=1)
{if(bb==10) {
bb=0;
c=_crol_(c,1); P3=c;
}
}
else
{if(bb%4==0) P3=~P3; if(bb==60) {TR0=0; P3=0xff; flag1=1; }
}
}
void timer1() interrupt 3
{
TH1=(65536-50000)/256;
TL1=(65536-50000)%256;
aa++;
if(aa==2) {
aa=0;
temp--;
bai=temp/100;
shi=temp%100/10; ge=temp%10;
if(temp==398)
{
TR0=0;
TH0=(65536-50000)/256; TL0=(65536-50000)%256; TR0=1;
flag=1;
bb=0;
P1=0xff;
TR1=0;
} }
}