74HC595,移位寄存器,串行输入,8位并行输出,一般用于数码管电路以减少使用的IO口数量。
管脚介绍:
Q0~Q7 :八位并行输出位
Q7' : 级联位,若输入位数大于8位,先进入的位会从此口连续输出,用于多片之间的级联
VCC GND 不多介绍
Ds : 串行数据输入位
OE : 输出使能位,低有效,一般直接全程给低电平就行
SHcp : 移位寄存器时钟输入,后文详述
STcp : 存储寄存器时钟输入,同上
MR : 主复位,低有效,一般直接接到VCC拉高
上图为74HC595内部结构,一个8位的移位寄存器,一个8位的存储寄存器,再有一个8位的并行输出。
为讲明Q7'的级联作用,此处应用场景选择为:6位8段数码管,驱动此数码管共需要8位段选端和6位位选端,共14位串行数据输入。
Ds数据输入端串行输入时,在SHcp的上升沿将数据移入移位寄存器内,每个SHcp上升沿移入一位单bit数据,最先输入的一直向后移直到8个SHcp上升沿后,移位寄存器填满,此时若数据输入端还有数据输入,下一个SHcp上升沿到来时,最先输入的1bit数据就会从Q7'输出(此处可理解为队列,先进先出)。在STcp的上升沿,数据会从移位寄存器进入存储寄存器中,当OE低有效时,存储寄存器中的值从Q0~Q7并行输出。
上述应用场景下,将第一片74HC595的Q7‘串行输出端接到第二片的数据输入端Ds,实现级联功能。经过14个时钟SHcp上升沿后,数据已经全部移位进入移位寄存器,一次共输入14位数据,那么第一位输入的串行数据会在第二片74HC595芯片的Q5输出,此时给一个上升沿的STcp信号就可以将信号移入存储寄存器,OE信号持续给低, 即可输出。
上述过程中还存在一个问题,SHCP频率给多少合适?它是有限制的
我实验板子的电压为3.3V,取图中2V的亦可,采用50MHZ的四分频12.5MHZ作为SHCP时钟,计数SHCP时钟上升沿,14个上升沿给出一个STCP的上升沿作为STCP时钟,相当于STCP时钟是SHCP时钟的14分频。
主要难点就在于SHCP和STCP时钟的获得,其他的按步骤来即可。
代码如下,需者自取(静态数码管)文章来源:https://www.toymoban.com/news/detail-402045.html
`timescale 1ns/1ns
module seg_static(
input sys_clk,
input sys_rst_n,
output reg [7:0]seg,
output reg [5:0]sel
);
parameter seg_0 = 8'hc0,
seg_1 = 8'hf9,
seg_2 = 8'ha4,
seg_3 = 8'hb0,
seg_4 = 8'h99,
seg_5 = 8'h92,
seg_6 = 8'h82,
seg_7 = 8'hf8,
seg_8 = 8'h80,
seg_9 = 8'h90,
seg_a = 8'h88,
seg_b = 8'h83,
seg_c = 8'hc6,
seg_d = 8'ha1,
seg_e = 8'h86,
seg_f = 8'h8e;
parameter cnt_500ms = 25'd24_999_999 ;
//parameter cnt_500ms = 25'd32_999_999 ;
reg [24:0]cnt;
reg [3:0]num;
always@(posedge sys_clk or negedge sys_rst_n)
if(sys_rst_n==1'b0)
cnt <= 25'd0;
else if(cnt==cnt_500ms)
cnt <= 25'd0;
else
cnt <= cnt + 1'b1;
always@(posedge sys_clk or negedge sys_rst_n)
if(sys_rst_n==1'b0)
num <= 4'd0;
else if(num==4'd15 && cnt==cnt_500ms)
num <= 4'd0;
else if(cnt==cnt_500ms)
num <= num + 1'b1;
else
num <= num;
always@(posedge sys_clk or negedge sys_rst_n)
if(sys_rst_n==1'b0)
seg <= 8'b1111_1111;
else
case(num)
0 : seg <= seg_0;
1 : seg <= seg_1;
2 : seg <= seg_2;
3 : seg <= seg_3;
4 : seg <= seg_4;
5 : seg <= seg_5;
6 : seg <= seg_6;
7 : seg <= seg_7;
8 : seg <= seg_8;
9 : seg <= seg_9;
10 : seg <= seg_a;
11 : seg <= seg_b;
12 : seg <= seg_c;
13 : seg <= seg_d;
14 : seg <= seg_e;
15 : seg <= seg_f;
default : seg <= 8'b1111_1111;
endcase
always@(posedge sys_clk or negedge sys_rst_n)
if(sys_rst_n==1'b0)
sel <= 6'b0;
else
sel <= 6'b111_111;
endmodule
`timescale 1ns/1ns
module hc595_ctrl(
input sys_clk,
input sys_rst_n,
input wire [7:0]seg,
input wire [5:0]sel,
output reg shcp,
output reg stcp,
output reg ds,
output wire oe
);
reg [1:0]cnt_4;
reg [3:0]cnt_14;
wire [13:0]data;
assign data = {seg[0],seg[1],seg[2],seg[3],seg[4],seg[5],seg[6],seg[7],sel};
always@(posedge sys_clk or negedge sys_rst_n)
if(sys_rst_n==1'b0)
cnt_4 <= 2'b0;
else if(cnt_4==2'd3)
cnt_4 <= 2'b0;
else
cnt_4 <= cnt_4 + 1'b1;
//sys_clk的四分频当作shcp时钟
always@(posedge sys_clk or negedge sys_rst_n)
if(sys_rst_n==1'b0)
shcp <= 1'b0;
else if(cnt_4 <= 2'd1)
shcp <= 1'b0;
else
shcp <= 1'b1;
//产生stcp时钟
always@(posedge sys_clk or negedge sys_rst_n)
if(sys_rst_n==1'b0)
cnt_14 <= 4'b0;
else if(cnt_14==4'd13 && cnt_4==2'd3)
cnt_14 <= 4'b0;
else if(cnt_4==2'd3)
cnt_14 <= cnt_14 + 1'b1;
else
cnt_14 <= cnt_14;
always@(posedge sys_clk or negedge sys_rst_n)
if(sys_rst_n==1'b0)
stcp <= 1'b0;
else if(cnt_14==4'd13 && cnt_4==2'd3)
stcp <= 1'b1;
else
stcp <= 1'b0;
//产生ds信号
always@(posedge sys_clk or negedge sys_rst_n)
if(sys_rst_n==1'b0)
ds <= 1'b0;
else if(cnt_4==2'd0)
ds <= data[cnt_14];
else
ds <= ds;
//产生oe信号
assign oe = ~sys_rst_n;
endmodule
`timescale 1ns/1ns
module smg_static(
input sys_clk,
input sys_rst_n,
output shcp,
output stcp,
output oe,
output ds
);
wire [7:0]seg;
wire [5:0]sel;
seg_static seg_static_inst(
.sys_clk(sys_clk),
.sys_rst_n(sys_rst_n),
.seg(seg),
.sel(sel)
);
hc595_ctrl hc595_ctrl_inst(
.sys_clk(sys_clk),
.sys_rst_n(sys_rst_n),
.seg(seg),
.sel(sel),
.shcp(shcp),
.stcp(stcp),
.ds(ds),
.oe(oe)
);
endmodule
动态数码管随缘更新文章来源地址https://www.toymoban.com/news/detail-402045.html
到了这里,关于74HC595工作原理及FPGA实现数码管驱动方法的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!