HC595串转并

发布于:2025-07-17 ⋅ 阅读:(14) ⋅ 点赞:(0)

HC595.v

/**
 https://docs.wokwi.com/zh-CN/parts/wokwi-74hc595
**/
`timescale 1ns / 1ps
module HC595 (
    input wire i_clk,             // 全局时钟,用于同步操作
    input wire i_rst_n,             // 复位信号,清除所有寄存器
    input wire DS,            // 串行数据输入(DS)
    input wire SHCP,            // 移位时钟(SHCP),用于移位操作
    input wire STCP,            // 存储时钟(STCP),用于锁存数据
    output reg [7:0] Q,     // 8 位并行输出(Q)
    output reg Q7S              // 串行输出(从移位寄存器)
);

    reg [7:0] r_shift_reg; // 8 位移位寄存器

    // 移位操作:每当 SHCP 上升沿时,将串行数据输入到移位寄存器
    always @(posedge SHCP or posedge i_rst_n) begin
        if (!i_rst_n) begin
            r_shift_reg <= 8'b0; // 复位时清零移位寄存器
        end else begin
            r_shift_reg <= {r_shift_reg[6:0], DS}; // 左移并输入串行数据
        end
    end

    // 存储操作:每当 STCP 上升沿时,将移位寄存器的内容传递到并行输出寄存器
    always @(posedge STCP or posedge i_rst_n) begin
        if (!i_rst_n) begin
            Q <= 8'b0; // 复位时清空并行输出
        end else begin
            Q <= r_shift_reg; // 将移位寄存器的内容输出到并行输出
        end
    end

    // 串行输出:移位寄存器的最右边位(r_shift_reg[7])作为串行输出
    always @(posedge i_clk) begin
        Q7S <= r_shift_reg[7]; // 串行输出为移位寄存器的最右边位
    end

endmodule


hc595_drive.v

`timescale 1ns / 1ps

module hc595_drive (
    input wire        i_clk,       // 全局时钟
    input wire        i_rst_n,     // 低电平复位
    input wire        i_start,     // 启动信号
    input wire [7:0]  i_data,     // 8 位数据输入
    output reg        o_shcp,      // 移位时钟
    output reg        o_stcp,      // 存储时钟
    output reg        o_ds,      // 串行数据输出
    output reg        o_done       // 传输完成信号
);

    // 状态编码
    localparam S_IDLE        = 3'd0,
               S_LOAD        = 3'd1,
               S_SHIFT_LOW   = 3'd2,
               S_SHIFT_HIGH  = 3'd3,
               S_LATCH_LOW   = 3'd4,
               S_LATCH_HIGH  = 3'd5,
               S_DONE        = 3'd6;

    reg [2:0] state;
    reg [3:0] r_bit_cnt;
    reg [7:0] r_shift_reg;

    always @(posedge i_clk or negedge i_rst_n) begin
        if (!i_rst_n) begin
            o_shcp      <= 1'b0;
            o_stcp      <= 1'b0;
            o_ds      <= 1'b0;
            o_done      <= 1'b0;
            r_bit_cnt   <= 4'd0;
            r_shift_reg <= 8'd0;
            state       <= S_IDLE;
        end else begin
            case (state)
                S_IDLE: begin
                    o_done <= 1'b0;
                    o_shcp <= 1'b0;
                    o_stcp <= 1'b0;
                    if (i_start) begin
                        state <= S_LOAD;
                    end
                end

                S_LOAD: begin
                    r_shift_reg <= i_data;
                    r_bit_cnt   <= 4'd0;
                    state       <= S_SHIFT_LOW;
                end

                S_SHIFT_LOW: begin
                    o_ds <= r_shift_reg[7];
                    o_shcp <= 1'b0;
                    state  <= S_SHIFT_HIGH;
                end

                S_SHIFT_HIGH: begin
                    o_shcp      <= 1'b1;
                    r_shift_reg <= {r_shift_reg[6:0], 1'b0};  // 左移
                    r_bit_cnt   <= r_bit_cnt + 1;
                    if (r_bit_cnt == 4'd7)
                        state <= S_LATCH_LOW;
                    else
                        state <= S_SHIFT_LOW;
                end

                S_LATCH_LOW: begin
                    o_stcp <= 1'b0;
                    state  <= S_LATCH_HIGH;
                end

                S_LATCH_HIGH: begin
                    o_stcp <= 1'b1;
                    state  <= S_DONE;
                end

                S_DONE: begin
                    o_stcp <= 1'b0;
                    o_shcp <= 1'b0;
                    o_done <= 1'b1;
                    state  <= S_IDLE;
                end
            endcase
        end
    end

endmodule


tb.v

`timescale 1ns / 1ps

module tb;

    reg clk;
    reg rst_n;
    reg start;
    reg [7:0] dat;
    wire SHCP;
    wire STCP;
    wire DS;
    wire done;
    wire [7:0] Q;
    wire Q7S;

    // 实例化 HC595
    HC595 u_hc595 (
        .i_clk(clk),
        .i_rst_n(rst_n),
        .DS(DS),
        .SHCP(SHCP),
        .STCP(STCP),
        .Q(Q),
        .Q7S(Q7S)
    );

    // 实例化驱动模块
    hc595_drive u_hc595_drive (
        .i_clk(clk),
        .i_rst_n(rst_n),
        .i_start(start),
        .i_data(dat),
        .o_shcp(SHCP),
        .o_stcp(STCP),
        .o_ds(DS),
        .o_done(done)
    );

    // 生成时钟
    initial clk = 0;
    always #5 clk = ~clk; // 100MHz

    initial begin
        // 初始化
        rst_n = 0;
        start = 0;
        dat = 8'h00;

        #20;
        rst_n = 1;
        #20;

        // 写入 0x38
        dat = 8'h38;
        start = 1;
        #10;
        start = 0;

        // 等待传输完成
        wait(done == 1);
        #10;
        $display("Q_OUT after 0x38 = %b", Q);

        // 写入 0x46
        dat = 8'h46;
        start = 1;
        #10;
        start = 0;

        wait(done == 1);
        #10;
        $display("Q_OUT after 0x46 = %b", Q);

        #50;
        $finish;
    end

endmodule



wokwi

main.ino

#include <Arduino.h>
#define datapin  2
#define clockpin  3
#define latchpin  4
#define HC595_SCLK(x)  digitalWrite(clockpin, x)
#define HC595_RCLK(x)  digitalWrite(latchpin, x)
#define HC595_SDAT(x)  digitalWrite(datapin, x)
void hc595_drive(unsigned char dat_h)
{
    unsigned char i;
    unsigned char dat_temp;
    HC595_SCLK(0);
    HC595_RCLK(0);
    dat_temp = dat_h;
    for (i = 0; i<8; i++)
    {
        HC595_SDAT(dat_temp >= 0x80);

        HC595_SCLK(0);
        delay(1);
        HC595_SCLK(1);
        delay(1);

        dat_temp = dat_temp << 1;
    }
    HC595_RCLK(0);
    delay(1);
    HC595_RCLK(1);
    delay(1);
    HC595_SCLK(0);
    HC595_RCLK(0);
    HC595_SDAT(0);
}
void hc595_init()
{
    pinMode(datapin, OUTPUT);
    pinMode(clockpin, OUTPUT);
    pinMode(latchpin, OUTPUT);
}


void setup()
{
    hc595_init();
    hc595_drive(0x01);
}

void loop()
{


}

diagram.json

{
  "version": 1,
  "author": "Uri Shaked",
  "editor": "wokwi",
  "parts": [
    { "type": "wokwi-arduino-uno", "id": "uno", "top": 231, "left": -135, "attrs": {} },
    {
      "type": "wokwi-74hc595",
      "id": "sr1",
      "top": 94.66,
      "left": 178.9,
      "rotate": 270,
      "attrs": {}
    },
    {
      "type": "wokwi-led-bar-graph",
      "id": "bargraph1",
      "top": 72,
      "left": 321.6,
      "attrs": { "color": "lime" }
    },
    { "type": "wokwi-gnd", "id": "gnd1", "top": 182.4, "left": 345, "attrs": {} }
  ],
  "connections": [
    [ "sr1:DS", "uno:2", "blue", [ "h-75.6", "h0", "v115.2" ] ],
    [ "sr1:STCP", "uno:4", "purple", [ "h-56.4", "v0", "h-61.5" ] ],
    [ "sr1:SHCP", "uno:3", "gray", [ "h-75.6", "v0", "h-32.8" ] ],
    [ "sr1:Q0", "bargraph1:A1", "green", [ "h-18", "v28.8", "h67.2", "v-86.4" ] ],
    [ "sr1:Q1", "bargraph1:A2", "green", [ "h38.4", "v-57.6" ] ],
    [ "sr1:Q2", "bargraph1:A3", "green", [ "h28.8", "v-38.4" ] ],
    [ "sr1:Q3", "bargraph1:A4", "green", [ "h9.6", "v-19.2" ] ],
    [ "sr1:Q4", "bargraph1:A5", "green", [ "h0" ] ],
    [ "sr1:Q5", "bargraph1:A6", "green", [ "h9.6", "v-48", "h67.2", "v67.2" ] ],
    [ "sr1:Q6", "bargraph1:A7", "green", [ "h57.6", "v48" ] ],
    [ "sr1:Q7", "bargraph1:A8", "green", [ "h48", "v57.6" ] ],
    [ "bargraph1:C1", "bargraph1:C2", "green", [ "v0" ] ],
    [ "bargraph1:C3", "bargraph1:C4", "green", [ "h0" ] ],
    [ "bargraph1:C5", "bargraph1:C6", "green", [ "h0" ] ],
    [ "bargraph1:C7", "bargraph1:C8", "green", [ "h0" ] ],
    [ "bargraph1:C9", "bargraph1:C10", "green", [ "h0" ] ],
    [ "bargraph1:C8", "bargraph1:C9", "green", [ "h0" ] ],
    [ "bargraph1:C2", "bargraph1:C3", "green", [ "h0" ] ],
    [ "bargraph1:C4", "bargraph1:C5", "green", [ "h0" ] ],
    [ "bargraph1:C6", "bargraph1:C7", "green", [ "h0" ] ],
    [ "gnd1:GND", "bargraph1:C10", "black", [ "v0" ] ]
  ],
  "dependencies": {}
}

hc595_drive.c

void hc595_drive(unsigned char dat_h/*,unsigned char dat_l*/)
{
	unsigned char i;
	unsigned char dat_temp;
	HC595_SCLK = 0;
	HC595_RCLK = 0;
	dat_temp = dat_h;
	for (i = 0; i<8; i++)
	{
		if (dat_temp >= 0x80)HC595_SDAT = 1;
		else HC595_SDAT = 0;

		HC595_SCLK = 0;
		_delay(1);
		HC595_SCLK = 1;
		_delay(1);
		dat_temp = dat_temp << 1;
	}
	/*dat_temp=dat_l;
	for(i=0;i<8;i++)
	{
	if(dat_temp>=0x80)HC595_SDAT=1;
	else HC595_SDAT=0;

	HC595_SCLK=0;
	_delay(1);
	HC595_SCLK=1;
	_delay(1);

	dat_temp=dat_temp<<1;
	}*/
	HC595_RCLK = 0;
	_delay(1);
	HC595_RCLK = 1;
	_delay(1);

	HC595_SCLK = 0;
	HC595_RCLK = 0;
	HC595_SDAT = 0;
}

arduino


#include <Arduino.h>

int datapin = 2; 
int clockpin = 3;
int latchpin = 4;
#define HC595_SCLK(x)  digitalWrite(3, x)
#define HC595_RCLK(x)  digitalWrite(4, x)
#define HC595_SDAT(x)  digitalWrite(2, x)
void hc595_drive(unsigned char dat_h)
{
    unsigned char i;
    unsigned char dat_temp;
    HC595_SCLK(0);
    HC595_RCLK(0);
    dat_temp = dat_h;
    for (i = 0; i<8; i++)
    {
        HC595_SDAT(dat_temp >= 0x80);
        
        HC595_SCLK(0);
        delay(1);
        HC595_SCLK(1);
        delay(1);

        dat_temp = dat_temp << 1;
    }
    HC595_RCLK(0);
    delay(1);
    HC595_RCLK(1);
    delay(1);
    HC595_SCLK(0);
    HC595_RCLK(0);
    HC595_SDAT(0);
}



void setup()
{
  pinMode(datapin, OUTPUT);
  pinMode(clockpin, OUTPUT);  
  pinMode(latchpin, OUTPUT);
  hc595_drive(0x01);
}


void loop()
{

  
}





diagram.json

{
  "version": 1,
  "author": "Uri Shaked",
  "editor": "wokwi",
  "parts": [
    { "type": "wokwi-arduino-uno", "id": "uno", "top": 231, "left": -135, "attrs": {} },
    {
      "type": "wokwi-74hc595",
      "id": "sr1",
      "top": 94.66,
      "left": 178.9,
      "rotate": 270,
      "attrs": {}
    },
    {
      "type": "wokwi-led-bar-graph",
      "id": "bargraph1",
      "top": 72,
      "left": 321.6,
      "attrs": { "color": "lime" }
    },
    { "type": "wokwi-gnd", "id": "gnd1", "top": 182.4, "left": 345, "attrs": {} }
  ],
  "connections": [
    [ "sr1:DS", "uno:2", "blue", [ "h-75.6", "h0", "v115.2" ] ],
    [ "sr1:STCP", "uno:4", "purple", [ "h-56.4", "v0", "h-61.5" ] ],
    [ "sr1:SHCP", "uno:3", "gray", [ "h4", "v30", "h-66" ] ],
    [ "sr1:Q0", "bargraph1:A1", "green", [ "h-18", "v28.8", "h67.2", "v-86.4" ] ],
    [ "sr1:Q1", "bargraph1:A2", "green", [ "h38.4", "v-57.6" ] ],
    [ "sr1:Q2", "bargraph1:A3", "green", [ "h28.8", "v-38.4" ] ],
    [ "sr1:Q3", "bargraph1:A4", "green", [ "h9.6", "v-19.2" ] ],
    [ "sr1:Q4", "bargraph1:A5", "green", [ "h0" ] ],
    [ "sr1:Q5", "bargraph1:A6", "green", [ "h9.6", "v-48", "h67.2", "v67.2" ] ],
    [ "sr1:Q6", "bargraph1:A7", "green", [ "h57.6", "v48" ] ],
    [ "sr1:Q7", "bargraph1:A8", "green", [ "h48", "v57.6" ] ],
    [ "bargraph1:C1", "bargraph1:C2", "green", [ "v0" ] ],
    [ "bargraph1:C3", "bargraph1:C4", "green", [ "h0" ] ],
    [ "bargraph1:C5", "bargraph1:C6", "green", [ "h0" ] ],
    [ "bargraph1:C7", "bargraph1:C8", "green", [ "h0" ] ],
    [ "bargraph1:C9", "bargraph1:C10", "green", [ "h0" ] ],
    [ "bargraph1:C8", "bargraph1:C9", "green", [ "h0" ] ],
    [ "bargraph1:C2", "bargraph1:C3", "green", [ "h0" ] ],
    [ "bargraph1:C4", "bargraph1:C5", "green", [ "h0" ] ],
    [ "bargraph1:C6", "bargraph1:C7", "green", [ "h0" ] ],
    [ "gnd1:GND", "bargraph1:C10", "black", [ "v0" ] ]
  ],
  "dependencies": {}
}
···


网站公告

今日签到

点亮在社区的每一天
去签到