SPI接口的74HC595驱动数码管实现

摸鱼记录 Day_17      (((^-^)))

review

        前边已经学习了:

        数码管显示原理:数码管动态扫描显示-CSDN博客

        且挖了个SPI的坑坑

1.  今日份摸鱼任务

学习循环移位寄存器18 串行移位寄存器原理详解_哔哩哔哩_bilibili

学习SPI接口的74HC595驱动数码管19 SPI接口的74HC595驱动数码管实验_哔哩哔哩_bilibili

了解SPI协议:SPI协议详解(图文并茂+超详细) - 知乎 (zhihu.com)

                        SPI总线协议及SPI时序图详解 - Ady Lee - 博客园 (cnblogs.com)

2.  循环移位寄存器

        四位D触发器,输入信号1001,经过四次时钟上升沿,D0-D3 1001

        DATA是串行数据,在此结构下,每个上升沿到来,都会改变D0-D3的输出

        为了正确输出四位的串转并数据

        可在红色箭头处,添加一个使能信号,对输出进行控制

此时,使用CLK、DATA、LATCH三根信号线,即可完成将串行信号转为并行信号

3.  74HC959 循环移位寄存器

        一文搞懂74HC595芯片(附使用方法)_74hc595芯片引脚图及功能-CSDN博客

        74HC595的最重要的功能就是:串行输入,并行输出。

        其次,74HC595里面有2个8位寄存器:移位寄存器、存储寄存器。

    第一个从SER送入的bit将会从 Q7 出去

   本篇在草稿呆了很多天,因为上图SHCP  STCP的画法有一定理解上的问题

    SHCP       移位寄存器的时钟输出

    STCP       存储寄存器的时钟输出

    但是在例程中

        STCP是在数据都保存后,完成一次输出,这保证了输出数据是一个完整的

        ACZ702 配套 EDA 扩展板设计用到了芯片 74HC595,该芯片的作用是移位寄存器,通过移位的方式,节省 FPGA 的管脚。FPGA 只需要输出 3 个管脚,即可达到发送数码管数据的目的,与数码管动态扫描显示-CSDN博客的传统段选位选方式相比节省了 IO 设计资源。

        3.3V供电情况下,50MHz -----》25MHz-----》12.5MHz

4. VIO  Virtual Input/Output

        关于这个IP核可以看:Vivado中VIO IP核的使用_vivado vio-CSDN博客

        本次实验,用于设定数码管的显示内容,具体设置如下:

4.  SPI接口的74HC595驱动数码管实现 (((^-^)))

                SPI(Serial Peripheral Interface),串行外围设备接口。

                SPI是一个同步的数据总线,用单独的数据线一个单独的时钟信号来保证发送端和接收端的同步

                可以参考:SPI协议详解(图文并茂+超详细) - 知乎 (zhihu.com)

        对于74HC595,本次SPI协议,是学习SCK MOSI,无需MISO,片选默认选中

4.1   design sources

hex_8  

module hex_8(input clk,
                     input reset_n,
                     input [31:0]disp_data, 

                     //8个数码管进行显示,每个显示0~F,输入格式为disp_data = 32'h12345678
                     output reg [7:0]sel,
                     output reg [7:0]seg
                     );

        //[31:0]disp_data  16hex 4*8
        //[7:0]sel 位选信号
        //[7:0]seg 段选信号

// 1kHz分频时钟 
    reg [14:0]div_clk;
    always@(posedge clk or negedge reset_n)
    if(!reset_n) 
        div_clk <= 1'b0;
    else if(div_clk == 24999) 
        div_clk <= 1'b0;
    else 
        div_clk <= div_clk + 1'b1;
    reg disp_en;
   always@(posedge clk or negedge reset_n)
    if(!reset_n) 
        disp_en <= 1'b0;
    else if(div_clk == 24999) 
        disp_en <= 1'b1;
    else 
        disp_en <= 1'b0;    

//  位选sel
    reg[2:0]sel_num;
    always@(posedge clk or negedge reset_n)
    if(!reset_n) 
        sel_num <= 3'b000;
    else if(disp_en) 
        sel_num <= sel_num + 1'b1;
        
    always@(posedge clk or negedge reset_n)
    if(!reset_n) 
        sel <= 8'b0000_0000;
    else case(sel_num) 
         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   
   
// 段选seg   [31:0]disp_data  16hex 4*8
    reg [3:0] dis_tmp;
    always@(posedge clk )
    case(sel_num) //高位放前面
         0:dis_tmp <= disp_data[31:28];
         1:dis_tmp <= disp_data[27:24];
         2:dis_tmp <= disp_data[23:20];
         3:dis_tmp <= disp_data[19:16];
         4:dis_tmp <= disp_data[15:12];
         5:dis_tmp <= disp_data[11:8];
         6:dis_tmp <= disp_data[7:4];
         7:dis_tmp <= disp_data[3:0];
    endcase 
    
    always@(posedge clk )
    case(dis_tmp) 
         0:seg <= 8'hc0;
         1:seg <= 8'hf9;
         2:seg <= 8'ha4;
         3:seg <= 8'hb0;
         4:seg <= 8'h99;
         5:seg <= 8'h92;
         6:seg <= 8'h82;
         7:seg <= 8'hf8;
         8:seg <= 8'h80;
         9:seg <= 8'h90;
         4'ha:seg <= 8'h88;
         4'hb:seg <= 8'h83;
         4'hc:seg <= 8'hc6;
         4'hd:seg <= 8'ha1;
         4'he:seg <= 8'h86;
         4'hf:seg <= 8'h8e;
    endcase 

endmodule

hc595_driver   //在Verilog中,不能使用数字开头命名

module hc595_driver(
                    input clk,
                    input reset_n,
                    input [15:0]data,
                    input s_en,
                    
                    output reg sh_cp,
                    output reg st_cp,
                    output reg ds
                 );

                /启动信号s_en时,保存当前data

             reg [15:0]r_data;
            always@(posedge clk)
            if(s_en)
                r_data <= data;


    parameter CNT_MAX = 2;
   // 3.3V 状态下工作于 12.5MHz   

    reg [7:0]divider_cnt;//分频计数器
    always@(posedge clk or negedge reset_n)
    if(!reset_n)
        divider_cnt <= 0;
    else if(divider_cnt == CNT_MAX - 1'b1)
        divider_cnt <= 0;
    else
        divider_cnt <= divider_cnt + 1'b1;
        
    wire sck_plus;
    assign sck_plus = (divider_cnt == CNT_MAX - 1'b1);
        
    reg [5:0]SHCP_EDGE_CNT;
    
    always@(posedge clk or negedge reset_n)
    if(!reset_n)
        SHCP_EDGE_CNT <= 0;
    else if(sck_plus)
        begin
            if(SHCP_EDGE_CNT == 6'd32) //32 16个数据,按照SH_CP上升沿、下降沿
                SHCP_EDGE_CNT <= 0;
            else
                SHCP_EDGE_CNT <= SHCP_EDGE_CNT + 1'b1;
        end
    else
        SHCP_EDGE_CNT <= SHCP_EDGE_CNT;
        
    always@(posedge clk or negedge reset_n)
    if(!reset_n)
        begin
            st_cp <= 1'b0;
            ds <= 1'b0;
            sh_cp <= 1'd0;
        end 
    else begin
        case(SHCP_EDGE_CNT)//重点就是线性序列机这部分分析啦

                        //SH_CP 移位寄存器的时钟

                        //在SH_CP上升沿  0->1 输出数据

                        //在SH_CP下降沿  1->0 改变数据
            0: begin sh_cp <= 0; st_cp <= 1'd0;ds <= r_data[15];end
            1: begin sh_cp <= 1; st_cp <= 1'd0;end
            2: begin sh_cp <= 0; ds <= r_data[14];end
            3: begin sh_cp <= 1; end
            4: begin sh_cp <= 0; ds <= r_data[13];end    
            5: begin sh_cp <= 1; end
            6: begin sh_cp <= 0; ds <= r_data[12];end    
            7: begin sh_cp <= 1; end
            8: begin sh_cp <= 0; ds <= r_data[11];end    
            9: begin sh_cp <= 1; end
            10: begin sh_cp <= 0; ds <= r_data[10];end    
            11: begin sh_cp <= 1; end
            12: begin sh_cp <= 0; ds <= r_data[9];end    
            13: begin sh_cp <= 1; end
            14: begin sh_cp <= 0; ds <= r_data[8];end    
            15: begin sh_cp <= 1; end
            16: begin sh_cp <= 0; ds <= r_data[7];end    
            17: begin sh_cp <= 1; end
            18: begin sh_cp <= 0; ds <= r_data[6];end    
            19: begin sh_cp <= 1; end
            20: begin sh_cp <= 0; ds <= r_data[5];end    
            21: begin sh_cp <= 1; end
            22: begin sh_cp <= 0; ds <= r_data[4];end    
            23: begin sh_cp <= 1; end
            24: begin sh_cp <= 0; ds <= r_data[3];end    
            25: begin sh_cp <= 1; end
            26: begin sh_cp <= 0; ds <= r_data[2];end    
            27: begin sh_cp <= 1; end
            28: begin sh_cp <= 0; ds <= r_data[1];end            
            29: begin sh_cp <= 1; end
            30: begin sh_cp <= 0; ds <= r_data[0];end
            31: begin sh_cp <= 1; end
            32: st_cp <= 1'd1;//最后拉高一下st_cp锁存器输出
            default:        
                begin
                    st_cp <= 1'b0;
                    ds <= 1'b0;
                    sh_cp <= 1'd0;
                end
        endcase
    end

endmodule

hex_top

module hex_top(
                clk,
                reset_n,
                sh_cp,
                st_cp,
                ds
                 );

    input clk;    //50M
    input reset_n;
    
    output sh_cp;
    output st_cp;
    output ds;
    
    wire [31:0]disp_data;
    wire [7:0] sel;//数码管位选(选择当前要显示的数码管)
    wire [7:0] seg;//数码管段选(当前要显示的内容)
    
    vio_0 vio_0 (
        .clk(clk), 
        .probe_out0(disp_data)  
    );
    
    hc595_driver hc595_driver(
        .clk(clk),
        .reset_n(reset_n),
        .data({seg,sel}),  //将段选与位选信号拼接在一起
        .s_en(1'b1),
        .sh_cp(sh_cp),
        .st_cp(st_cp),
        .ds(ds)
    );
    
    hex8 hex8(
        .clk(clk),
        .reset_n(reset_n),
        .en(1'b1),
        .disp_data(disp_data),
        .sel(sel),
        .seg(seg)
    );
    
endmodule

4.2  板级验证

//好啦, (((^-^)))

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/web/184.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

List实现(2)| LinkedList

参考&#xff1a;LinkedList 源码分析 在Java中&#xff0c;LinkedList是一个双向链表&#xff0c;实现了List和Deque接口&#xff0c;可以被当作列表&#xff08;List&#xff09;、队列&#xff08;Queue&#xff09;或者双端队列&#xff08;Deque&#xff09;使用。它允许…

简单3步制作纸质英语绘本的mp3英语朗读音频

孩子学英语&#xff0c;需要看很多英语绘本&#xff0c;而且要听配套的音频。但有些英语绘本是没有对应音频的&#xff0c;下面简单三步&#xff0c;就可以将任意英语绘本制作出对应的英语朗读音频。 第一步&#xff0c;手机拍照做成PDF文件&#xff1a; 绘本每一页拍照后&…

第三方软件测评报告测试内容详解

随着信息技术的迅猛发展&#xff0c;软件产品在各行各业的应用越来越广泛。为了确保软件产品的质量和性能&#xff0c;第三方软件测评报告成为了不可或缺的一环。那么&#xff0c;第三方软件测评报告测试内容究竟包括哪些呢&#xff1f;本文将从多个方面进行详细解析。 一、功…

解决IDEA https://start.spring.io/连接不上

1.换成下边这个地址试试 https://start.springboot.io/2.换成阿里云试试&#xff0c;绝对可行&#xff0c;但是版本有点低 https://start.aliyun.com

【C++]C/C++的内存管理

这篇博客将会带着大家解决以下几个问题 1. C/C内存分布 2. C语言中动态内存管理方式 3. C中动态内存管理 4. operator new与operator delete函数 5. new和delete的实现原理 6. 定位new表达式(placement-new) 1. C/C内存分布 我们先来看下面的一段代码和相关问题 int global…

Cesium实现加载离线地形数据(nginx发布数据,cesiumLab地形切片数据)

实现效果如图&#xff1a; 详细步骤 1 下载地形数据&#xff08;DEM&#xff09; 下载地址&#xff1a;地理空间数据云 (gscloud.cn) 操作步骤&#xff1a; 注意&#xff1a;第3步可以自主选择DEM的分辨率&#xff0c;然后下载。 下载结果解压后如下图&#xff1a; 2 使用…

excel里如何的科学计数法的数字转换成数值?

比如下图&#xff0c;要想把它们转换成3250跟1780&#xff0c;有什么快捷的办法吗&#xff1f; 科学计数法在excel里的格式&#xff0c;与我们常规在数学上写的有差异。这个转换可以这样做&#xff1a; 1.转换后的效果&#xff1a; 2.问题分析 题目中所附截图&#xff0c;单元…

vue3.0项目生成标签条形码(插件:jsbarcode)并打印(插件:Print.js)支持pda扫码枪扫描

文章目录 功能场景生成条形码设置打印功能踩坑 功能场景 功能场景&#xff1a;供应链中对一些货品根据赋码规则进行赋码&#xff0c;赋码之后生成根据赋码结果生成条形码&#xff0c;执行打印功能&#xff0c;贴在货品之上&#xff0c;打印之后可以用pda的手枪进行扫描&#x…

从AdTech转战Martech,驰骛科技的PaaS之路

中国最早的Adtech公司之一&#xff0c;在被全资收购后&#xff0c;其创始团队又创立了一家Martech公司。赛道的变更也从侧面反映出中国营销技术市场的发展轨迹。 驰骛科技创始团队来自易传媒核心团队&#xff0c;驰骛科技创始人程华奕是易传媒创始人兼CTO&#xff0c;是中国最早…

现在给政府机关医院学校部队供货的方式有哪些?

给政府机关、医院、学校和部队供货的方式主要包括以下几种&#xff1a; 直接采购&#xff1a;政府机关、医院、学校和部队通过招标或直接与供应商进行谈判&#xff0c;确定采购的产品和价格。这种方式常见于大宗或重要物资的采购&#xff0c;能够确保采购过程的透明度和公正性…

使用 Citavi 和 NVivo 简化您的文献综述和研究分析

NVivo 是一款支持定性研究方法和混合研究方法的软件。它可以帮助您收集、整理和分析访谈、焦点小组讨论、问卷调查、音频等内容。NVivo&#xff08;1.0版&#xff09;是Windows和Mac的主要版本。遵循最新的主要版本NVivo 12&#xff08;Windows和Mac&#xff09;。 NVivo 强大…

Linux服务器硬件及RAID配置

一、服务器硬件 塔式服务器&#xff1a;最初的服务器形态之一&#xff0c;类似于传统的台式电脑&#xff0c;但具有更强的处理能力和稳定性&#xff0c;适合小型企业或部门使用。 机架式服务器&#xff1a;设计为可安装在标准化机架内的模块化单元&#xff0c;可以有效地节省空…

jetson nx 外接按钮,实现开机功能

本文参考自https://blog.csdn.net/m0_59584375/article/details/128050175 首先第一步&#xff0c;要短接jetson nx背面的AUTO ON 和DISABLE引脚 可以用跳帽短接&#xff0c;也可以直接用一根杜邦线连接这两个针脚 AUTO ON 和DISABLE引如下图红色圈 跳帽的样子如下图 我是直…

Mabtech:与结核病相关的肽库

Mabtech 新研发出了三个涵盖结核蛋白&#xff08;EspC、ESAT-6、CFP-10&#xff09;的肽库&#xff0c;可以区分潜伏性结核病和活动性结核病的区别。所有肽库都经过验证&#xff0c;都可用于ELISpot、FluoroSpot实验。 1. EspC scanning pool ● EspC scanning pool包含来自结…

42-软件部署实战(下):IAM系统安全加固、水平扩缩容实战

IAM应用安全性加固 iam-apiserver、iam-authz-server、MariaDB、Redis和MongoDB这些服务&#xff0c;都提供了绑定监听网卡的功能。将服务绑定到内网网卡上。 我们也可以通过iptables来实现类似的功能&#xff0c;通过将安全问题统一收敛到iptables规则&#xff0c;可以使我…

速看!2024中国(厦门)国际康复医疗展览会

2024中国&#xff08;厦门&#xff09;国际康复医疗展览会 2024 China (Xiamen) International Rehabilitation Medical Exhibition 时 间&#xff1a;2024年8月13-15日 August 13-15, 2024 地 点&#xff1a;厦门国际会展中心 Xiamen International Conference & Exh…

Java工具类:批量发送邮件(带附件)

​ 不好用请移至评论区揍我 原创代码,请勿转载,谢谢! 一、介绍 用于给用户发送特定的邮件内容,支持附件、批量发送邮箱账号必须要开启 SMTP 服务(具体见下文教程)本文邮箱设置示例以”网易邮箱“为例,其他如qq邮箱或企业邮箱均可,只要在设置中对应开启SMTP及授权码等操…

Java岗大厂面试百日冲刺 - 日积月累,每日三题【Day11】 —— MyBatis1

市面上主流ORM框架: EJB&#xff1a;重量级、高花费的ORM技术&#xff0c;支持JPA&#xff0c;尤其是EJB3低侵入式 的设计&#xff0c;增加了Annotation Hibernate&#xff1a;开源&#xff0c;支持JPA &#xff0c;被选作JBoss的持久层解决方案 iBatis&#xff1a;”SQL Mappi…

SpringBoot多数据源配置之事务管理

SpringBoot多数据源配置之事务管理 1.Spring编程式事务1.1 简单案例 2.mybatis多数据源事务2.1 简单mybatis项目结构2.2 application.yml配置2.3 读写数据源配置 3.测试 1.Spring编程式事务 Spring编程式事务是一种通过编写具体代码来实现事务管理的方式。 在编程式事务中, 开…

如何用ChatGPT进行论文撰写?

原文链接&#xff1a;如何用ChatGPT进行论文撰写&#xff1f;https://mp.weixin.qq.com/s?__bizMzUzNTczMDMxMg&mid2247601619&idx1&snb686fbe87dedfac2df3a6afe780b2ffe&chksmfa820c34cdf5852251dca64597024ea62ddbde280086535ec251f4b62b848d9f9234688384e6…