当前位置: 首页 > news >正文

18 19 SPI接口的74HC595驱动数码管实验

1. 串行移位寄存器原理(以四个移位寄存器为例)

1. 通过移位寄存器实现串转并:一个数据输入端口可得到四位并行数据。

通过给data输送0101数据,那么在经过四个时钟周期后,与data相连的四个寄存器的输出端口得到了0101这样的数据,然后我们将latch信号拉高,在下一个时钟周期,D0, D1, D2, D3同时分别获得了这四个数据1010。(其中DFF指D触发器,LATCH信号也可连接锁存器来控制输出)

2. 级联

级联:数据输出端口作为另外的移位寄存器数据端的输入。

2.使用74HC595驱动数码管

1. ACX720上不是直接用fpga的管脚驱动数码管的,而是用74HC595这样的一种串转并的串行移位寄存器来驱动的

2.1 74HC595端口图:

2.2 74HC595时序图

 2.3 74HC595时钟工作频率

取工作频率为12.5MHz。

3. 使用74HC595芯片驱动数码管的verilog代码实现

1.要完成的模块为hc595_driver,实现将16位并行数据转为串行数据发送至74HC595中,实现三线制控制数码管。因此我们的输入需遵循74HC595时序图。

3.1 设计代码

我们要输出shcp,stcp和ds,并满足它们的时序波形(照葫芦画瓢)。shcp的为最小的时间单元,我们可以根据它来作为其他信号波形的参照,但是切记不可将其作为门控时钟,我们只需要把这些要输出的信号当成普通信号,按照时序图上的时序输出即可。

1. shcp的时钟频率为12.5MHz,即一个周期为80ns,我们取半个周期为最小时间单元进行变化,即40ns。

2. 根据最小时间单元产生对应的节点,需要一个计数器记录这些节点(节点执行完开始下一次节点执行),产生节点后再在每个节点做相应的事情即可。

3. hc595_driver里的寄存器是从小到大排列的(0到15),即第0位数据最后进,放在最外面,第15位数据放在最里面。先进15,最后进0。

module hex8_2(clk,rstn,disp_data,sel,led
);parameter times = 50000; // 1msinput clk;input rstn;input [31:0]disp_data;output reg [7:0] sel;output reg [7:0] led;reg [15:0]div_cnt;always@(posedge clk or negedge rstn)if(!rstn)div_cnt <= 0;else if(div_cnt >= times - 1)div_cnt <= 0;elsediv_cnt <= div_cnt + 1'd1;//使能时钟  reg clk_lk;always@(posedge clk or negedge rstn)if(!rstn)clk_lk <= 0;else if(div_cnt == times - 1)clk_lk <= 1'd1;elseclk_lk <= 0;//cnt累加器reg [2:0] num_cnt;    always@(posedge clk_lk or negedge rstn)if(!rstn)num_cnt <= 0;else if(clk_lk == 1)num_cnt <= num_cnt + 1'd1;//三八译码器    always@(posedge clk or negedge rstn)if(!rstn)sel <= 0;else case(num_cnt)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//八选一多路器reg [3:0]disp_tmp;always@(posedge clk)case(num_cnt)0:disp_tmp = disp_data[3:0];1:disp_tmp = disp_data[7:4];2:disp_tmp = disp_data[11:8];3:disp_tmp = disp_data[15:12];4:disp_tmp = disp_data[19:16];5:disp_tmp = disp_data[23:20];6:disp_tmp = disp_data[27:24];7:disp_tmp = disp_data[31:28];endcase//四十六译码器 always@(posedge clk)case(disp_tmp)0:led = 8'hc0;1:led = 8'hf9;2:led = 8'ha4;3:led = 8'hb0;4:led = 8'h99;5:led = 8'h92;6:led = 8'h82;7:led = 8'hf8;8:led = 8'h80;9:led = 8'h90;4'ha:led = 8'h88;4'hb:led = 8'h83;4'hc:led = 8'hc6;4'hd:led = 8'ha1;4'he:led = 8'h86;4'hf:led = 8'h8e;  default:led = 8'hc0;endcaseendmodule
module hc595_driver(clk,rstn,data,s_en,shcp,stcp,ds  
);parameter times = 2; //40ns为最小刻度input clk;input rstn;input [15:0] data;input s_en;output reg shcp;output reg stcp;output reg ds;reg [15:0] r_data;always@(posedge clk)if(s_en)r_data <= data;//1.产生74hc595时序所需的最小时间单元reg [7:0] div_cnt;//脉冲信号wire sck_plus;assign sck_plus = div_cnt >= times - 1;always@(posedge clk or negedge rstn)if(!rstn)div_cnt <= 0;else if(div_cnt >= times - 1)div_cnt <= 0;elsediv_cnt <= div_cnt + 1'd1;//2.依据sck_plus做相对应的事情//先记录sck_plus的节点数reg [5:0]shcp_edge_counter;    always@(posedge clk or negedge rstn)if(!rstn)   shcp_edge_counter <= 0;else if(sck_plus) //sck_plus不是寄存器的输出    if(shcp_edge_counter == 32)            shcp_edge_counter <= 0;elseshcp_edge_counter <=  shcp_edge_counter + 1'd1;always@(posedge clk or negedge rstn)if(!rstn) beginshcp <= 0;stcp <= 0;ds <= 0;endelse case(shcp_edge_counter)0: begin shcp <= 0; ds <= r_data[15]; stcp <= 0; end1: shcp <= 1'd1;2: begin shcp <= 0; ds <= r_data[14]; end3: shcp <= 1'd1;4: begin shcp <= 0; ds <= r_data[13]; end5: shcp <= 1'd1;6: begin shcp <= 0; ds <= r_data[12]; end7: shcp <= 1'd1;8: begin shcp <= 0; ds <= r_data[11]; end9: shcp <= 1'd1;10: begin shcp <= 0; ds <= r_data[10]; end11: shcp <= 1'd1;12: begin shcp <= 0; ds <= r_data[9]; end13: shcp <= 1'd1;14: begin shcp <= 0; ds <= r_data[8]; end15: shcp <= 1'd1;16: begin shcp <= 0; ds <= r_data[7]; end17: shcp <= 1'd1;18: begin shcp <= 0; ds <= r_data[6]; end19: shcp <= 1'd1;20: begin shcp <= 0; ds <= r_data[5]; end21: shcp <= 1'd1;22: begin shcp <= 0; ds <= r_data[4]; end23: shcp <= 1'd1;24: begin shcp <= 0; ds <= r_data[3]; end25: shcp <= 1'd1;26: begin shcp <= 0; ds <= r_data[2]; end27: shcp <= 1'd1;28: begin shcp <= 0; ds <= r_data[1]; end29: shcp <= 1'd1;30: begin shcp <= 0; ds <= r_data[0]; end31: shcp <= 1'd1;32: begin shcp <= 0; stcp <= 1; ds <= 0; enddefault : beginshcp <= 0;stcp <= 0;ds <= 0;endendcaseendmodule

3.2 针对hc595_driver的仿真代码

`timescale 1ns / 1psmodule hc595_driver_tb();reg clk;reg rstn;reg [15:0] data;reg s_en;wire shcp;wire stcp;wire ds;hc595_driver hc595_driver_inst(clk,rstn,data,s_en,shcp,stcp,ds  );initial clk = 1;always #10 clk = ~clk;initial beginrstn = 0;#201;rstn = 1;#200;s_en = 1;data = 16'h1357;#4000;s_en = 0;#200;s_en = 1;data = 16'h2468;#4000;s_en = 0;$stop;endendmodule

3.3 针对hc595_driver的仿真波形

 3.4 针对数码管的管脚约束文件

http://www.lryc.cn/news/299883.html

相关文章:

  • 计算机网络概述习题拾遗
  • 你的电脑关机吗
  • flask+python儿童福利院管理系统pycharm毕业设计项目
  • React:高阶组件|ref转发
  • AI:127-基于卷积神经网络的交通拥堵预测
  • MongoDB聚合操作符:$abs
  • 【element-ui】输入框组件el-input输入数字/输出Number类型:type=“number“、v-model.number用法
  • 算法与数据结构
  • C++动态规划-线性dp算法
  • 基于 Python 深度学习的电影评论情感分析系统,附源码
  • 如何查看Apple Watch的步数?这里提供几个方法
  • 解决‘vue‘ 不是内部或外部命令,也不是可运行的程序(设置全局变量)
  • JavaWeb学习|i18n
  • 数据库日志已经很大了,比如200多G,不能收缩到几兆,实际操作过只能到30G
  • docker常用容器命令
  • 蓝桥杯(Web大学组)2022省赛真题:冬奥大抽奖
  • 单调队列 单调栈
  • Java基础-泛型
  • Vue 全组件 局部组件
  • 几个经典金融理论
  • c++语言max函数的使用
  • c++阶梯之类与对象(下)
  • 机器学习--K-近邻算法常见的几种距离算法详解
  • <网络安全>《30 网络信息安全基础(1)常用术语整理》
  • Git远程仓库的使用(Gitee)及相关指令
  • vscode +markdown 的安装和使用
  • Python爬虫之自动化测试Selenium#7
  • 快速学习Spring
  • c语言操作符(上)
  • vue3 可视化大屏自适应屏幕组件