做靓号网站,WordPress新版文章,掌上大学微信管理系统,东莞营销网站建前3节视频目的是实现显示0~F的数码管仿真#xff0c;后3节是用驱动芯片驱动数码管。
目录
1.数码管显示原理
2.代码过程
2.1仿真结果
3.串行移位寄存器原理
3.1原理
编辑 3.2 数据手册
3.3 先行设计思路
4.程序
4.1确定SRCLK的频率
4.2序列计数器
4.3 不同coun…前3节视频目的是实现显示0~F的数码管仿真后3节是用驱动芯片驱动数码管。
目录
1.数码管显示原理
2.代码过程
2.1仿真结果
3.串行移位寄存器原理
3.1原理
编辑 3.2 数据手册
3.3 先行设计思路
4.程序
4.1确定SRCLK的频率
4.2序列计数器
4.3 不同counter值干不同事
4.4仿真
5.实验结果 1.数码管显示原理
分为共阳极与共阴极驱动共阴极发光二极管负极都接地a~dp接入端口引脚输出高电平就点亮共阳极与之相反。 不同位的高低电平可以组成不同的数字符号后面查找表的值就看这张图。 在驱动多个数码管场景中往往a~dg与每个数码管对应的二极管是互联的而sel端的电压可以控制三极管是否导通以此可以单独让某个数码管亮灭。 根据以上分析可以画出电路图
1.首先SEL决定了点亮哪个数码管需要用到38译码器进行选择而38译码器的输出选择需要用到一个3位的状态计数切换器。
2.如何让状态切换即加入一个计数器记到1ms当大于1ms时让状态加1且计数器本身清0。
3.SEG决定了数码管哪段亮在没有规律的情况下可以用查表法把这些状态一一列出来例如这里有16个状态那么需要一个4位的变量来表示对应的索引号。
4.将状态计数切换器值传到8选1数据选择器分别代表8个数码管对应的通道值作为索引。 2.代码过程
1.实现1ms的计数器 2.位切换逻辑计数器每满一次状态位切换1 3.38译码器实现连接哪个数码管 4.位选择控制逻辑。
1查找表case完成SEG的配置。 2位切换逻辑将8个数码管对应的值当作索引传进去。这里数组顺序错了。 代码
module Shuma_guan(input clk,input reset,input[31:0] Dis_data,output reg[7:0] SEL,output reg[7:0] SEG);
reg[29:0] counter_1ms;
reg[2:0] which_sel;
reg[3:0] data_temp; //存放索引值
//数码管亮的时间
parameter Base_freq 50_000_000;
parameter goal_freq 1000;
parameter cworth Base_freq/goal_freq-1;//计数器
always(posedge clk or negedge reset)
beginif(!reset)counter_1ms 1d0;else if(counter_1ms cworth)counter_1ms 1d0;elsecounter_1ms counter_1ms1d1;
end//数码管状态切换
always(posedge clk or negedge reset)
beginif(reset)which_sel 1d0;else if(counter_1ms cworth)which_sel which_sel1d1;elsewhich_sel which_sel;
end//38译码器确定哪个数码管亮
always(posedge clk)
begincase(which_sel)0:SEL 8b0000_0001;1:SEL 8b0000_0010;2:SEL 8b0000_0100;3:SEL 8b0000_1000;4:SEL 8b0001_0000;5:SEL 8b0010_0000;6:SEL 8b0100_0000;7:SEL 8b1000_0000;endcase
end//建立查找表,共阳
always(posedge clk)
begincase(data_temp)0:SEG 8b1100_0000;1:SEG 8b1111_1001;2:SEG 8b1010_0100;3:SEG 8b1011_0000;4:SEG 8b1001_1001;5:SEG 8b1001_0010;6:SEG 8b1000_0010;7:SEG 8b1111_1000;8:SEG 8b1000_0000;9:SEG 8b1001_0000;10:SEG 8b1000_1000;11:SEG 8b1000_0011;12:SEG 8b1100_0110;13:SEG 8b1010_0001;14:SEG 8b1000_0110;15:SEG 8b1000_1110;endcase
end//将状态值传给索引
always(*)
begincase(which_sel)0:data_temp Dis_data[3:0];1:data_temp Dis_data[7:4];2:data_temp Dis_data[11:8];3:data_temp Dis_data[15:12];4:data_temp Dis_data[19:16];5:data_temp Dis_data[23:20];6:data_temp Dis_data[27:24];7:data_temp Dis_data[31:28];endcase
endendmodule
仿真
timescale 1ns / 1nsmodule Shuma_guan_tb();
reg clk;
reg reset;
reg[31:0] Dis_data;
wire[7:0] SEL;
wire[7:0] SEG;Shuma_guan Shuma_guan_inst0(.clk(clk),.reset(reset),.Dis_data(Dis_data),.SEL(SEL),.SEG(SEG)
); initial clk 1;
always #10 clk~clk;initial beginreset 0;Dis_data 32h12345678;#201;reset 1;#20_000_000;Dis_data 32h9abcdef0;#20_000_000;$stop;
end
endmodule
2.1仿真结果
切换状态计数没有随着计数器增加到49999而加1原因是在切换状态的时序逻辑中复位没有取反直接ifreset相当于复位信号为1时状态计数就会为0所以一直不会增加。 修改后正确 3.串行移位寄存器原理
3.1原理 为了节省IO口引脚一般会使用驱动芯片74HC595驱动数码管芯片的原理是基于串行移位寄存器。将上节输出的SEG与SEL传输到74HC595。 基本原理为顺次连接4个D触发器每经过一个时钟就依次将DATA存储的值传送到下一个D触发器例如经过5个时钟周期后 此时DFF3~DFF0存储的值为1001。如果想在这个时刻把每个D触发器存储的值取出来就在每个D触发器的输出端再接入一个D触发器加的这4个D触发器单独用一个时钟进行控制然后将输出分别接至各自端口。 当要移位8位16位时直接加更多的D触发器就行。
74HC595能够驱动8位移位寄存器SER是数据传输口SRCLK是第一路串联触发器的时钟SRCLR非应该是复位信号RCLK是是每个单独加入的触发器的时钟OE非是输出的使能信号。第1个74HC595的输出串联到了第2个74HC595的输入以此构成16位移位寄存器输出。 左边的74HC连接的是选择使能哪个数码管右边的74HC是决定数码管哪段亮。DIO是数据输入SRCLK是第一路串联触发器的时钟RCLK是加入单个D触发器的时钟。 3.2 数据手册
从时序图可以看出RCLK有方波时才有输出。
移位寄存器时钟为上升沿时其实也就是让移位寄存器存前一阶段的数据。RCLK为上升沿时移位寄存器的数据存储在存储寄存器中。 时钟频率最低为5MHz其中SRCLK/RCLK的高低电平时间至少为时钟周期的一半电平为2V时SER在SRCLK上升沿前125ns必须稳定SRCLK的上升沿必须RCLK上升沿之前的94ns。
3.3 先行设计思路 4.程序
4.1确定SRCLK的频率
取50MHz的乘除整数倍取SRCLK的频率为12.5MHz定义一个分频计数器在SRCLK下降沿将数据传到DIO上升沿DIO将数据传给驱动芯片的寄存器。计数器计数两次为1个SRCLK周期可根据counter找到SRCLK的上升沿和下降沿。
4.2序列计数器
根据时序图与原理图先传的SEG后传的SEL。1ms切换了一次人眼看不出来实际上应该是闪烁的数字循环跳变。共32个状态需要拉低拉高。
4.3 不同counter值干不同事
counter0拉低SRCLK将SEG[7]的值传给DIO将RCLK拉高。
counter1拉高SRCLK驱动芯片自动会将DIO的数据传给寄存器RCLK拉低。
......
counter31拉高SRCLK 4.4仿真
仿真的RCLK刚开始就拉高了这是因为if后面没有跟else直接按照每个时钟沿开始执行程序了。 正确的仿真波形 此时代码
module tube_active(input clk,input reset,input[7:0] SEL,input[7:0] SEG,output reg SRCLK,output reg RCLK,output reg DIO);reg[29:0] divi_counter;
reg[4:0] state_counter; //序列计数器
//确定SRCLK的频率为12.5MHz
parameter base_frequence 50_000_000;
parameter goal_frequence 12500_000;
parameter goal_counter base_frequence/(goal_frequence*2)-1;//分频计数器
always(posedge clk or negedge reset)
beginif(!reset)divi_counter 1d0;else if(divi_counter goal_counter)divi_counter 1d0;elsedivi_counter divi_counter 1d1;
end//序列计数器
always(posedge clk or negedge reset)
beginif(!reset)state_counter 1d0;else if(divi_counter goal_counter)state_counter state_counter1d1;elsestate_counter state_counter;
end//不同counter值做不同事,下降沿将值传给DIO上升沿将DIO的值送给驱动芯片
always(posedge clk or negedge reset)
beginif(!reset)beginSRCLK 1d0;RCLK 1d0;DIO 1d0;endelse begincase(state_counter)0:begin DIO SEG[7]; SRCLK 1d0; RCLK 1d1; end1:begin SRCLK 1d1; RCLK 1d0; end2:begin DIO SEG[6]; SRCLK 1d0;end3:begin SRCLK 1d1; end4:begin DIO SEG[5]; SRCLK 1d0;end 5:begin SRCLK 1d1; end6:begin DIO SEG[4]; SRCLK 1d0;end7:begin SRCLK 1d1; end8:begin DIO SEG[3]; SRCLK 1d0;end 9:begin SRCLK 1d1; end10:begin DIO SEG[2]; SRCLK 1d0;end11:begin SRCLK 1d1; end12:begin DIO SEG[1]; SRCLK 1d0;end13:begin SRCLK 1d1; end14:begin DIO SEG[0]; SRCLK 1d0;end15:begin SRCLK 1d1; end16:begin DIO SEL[7]; SRCLK 1d0;end17:begin SRCLK 1d1; end18:begin DIO SEL[6]; SRCLK 1d0;end19:begin SRCLK 1d1; end20:begin DIO SEL[5]; SRCLK 1d0;end 21:begin SRCLK 1d1; end22:begin DIO SEL[4]; SRCLK 1d0;end23:begin SRCLK 1d1; end24:begin DIO SEL[3]; SRCLK 1d0;end 25:begin SRCLK 1d1; end26:begin DIO SEL[2]; SRCLK 1d0;end27:begin SRCLK 1d1; end28:begin DIO SEL[1]; SRCLK 1d0;end29:begin SRCLK 1d1; end30:begin DIO SEL[0]; SRCLK 1d0;end31:begin SRCLK 1d1; endendcaseend
end
endmodule仿真代码
timescale 1ns / 1nsmodule tube_active_tb();reg clk;reg reset;reg [7:0]SEL;reg [7:0]SEG;wire SRCLK;wire RCLK;wire DIO;tube_active tube_active_inst0(.clk(clk), .reset(reset), .SEL(SEL),.SEG(SEG),.SRCLK(SRCLK),.RCLK(RCLK), .DIO(DIO)
);initial clk 1;
always #10 clk ~clk;initial beginreset 0;SEL 8b0000_0001;SEG 8b0101_0101;#201;reset 1;#5000;SEL 8b0000_0010;SEG 8b1010_1010; #5000;SEL 8b1010_0101;SEG 8b0000_1101; #5000;$stop;
end
endmodule
在现有模块添加新的源文件必须点击这里的左上角的会出错。新源文件调用了上面的两个模块让这两个模块连在一起然后引出三根线与驱动芯片连接。 module tube_shuma_test(input clk,input reset,output SRCLK,output RCLK,output DIO,input [1:0] SW
);wire[7:0] SEL,SEG; //将两个例化的端口连接起来
reg[31:0] Dis_data; //调用的并转串模块
tube_active tube_active_inst0(.clk(clk), .reset(reset), .SEL(SEL),.SEG(SEG),.SRCLK(SRCLK),.RCLK(RCLK), .DIO(DIO)
);//调用的hex8模块
Shuma_guan Shuma_guan_inst0(.clk(clk),.reset(reset),.Dis_data(Dis_data),.SEL(SEL),.SEG(SEG)
); always(*)
begincase(SW)0:Dis_data 32h01234567;1:Dis_data 32h89abcdef;2:Dis_data 32haaaabbbb;3:Dis_data 32h66666666;endcase
endendmodule
5.实验结果
根据拨码开关的开关情况数码管显示不同的数字。