栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > C/C++/C#

74HC595D介绍与实现(C语言与verilog实现)

C/C++/C# 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

74HC595D介绍与实现(C语言与verilog实现)

1.特性
  • 8位串行输入

  • 8位可串行或并行输出

  • 具有3种状态输出的存储寄存器

  • 具有复位功能的移位寄存器

  • 具有串行输入(DS)和串行输出(Q7S)来级联的功能。

  • 移位寄存器和存储寄存器的时钟可分开控制。

2.引脚说明

引脚名引脚号说明
Q0、Q1、Q2、Q3、Q4、Q5、Q6、Q715,1,2,3,4,5,6,7并行数据输出
Q7S9串行数据输出
MR10主复位引脚,为0时复位移位寄存器
SHCP11移位寄存器时钟输入,上升沿时DS上的数据会移入移位寄存器
STCP12存储寄存器时钟输入,上升沿时移位寄存器的数据传输到存储寄存器
OE13输出使能,为0时,存储器中的数据并行输出到Q0-Q7引脚;为1时,输出为高阻态
DS14串行数据输入
3.逻辑与时序操作 3.1 逻辑操作

由上图可看出,8位以为寄存由DS、SHCP、MR这三个引脚控制,8位存储寄存器有STCP引脚控制,而输出由OE引脚控制。Q7S引脚控制级联。数据先经过移位寄存器,再锁存到存储寄存器中,最后在OE引脚为低时数据并行输出。

3.2 时序操作

由3.1的逻辑图和上图结合可看出:

  • 驱动74HC595主要控制SHCP、DS、STCP、MR、OE这5个引脚,可把MR引脚拉高不复位移位寄存器、OE引脚拉低一直输出,这样实际控制的引脚只有3个。

  • DS引脚上的数据在SHCP处于上升沿时写入到移位寄存器;

  • DS引脚先送高位再送低位,如写入二进制数据10110111,则最先写入1到Q1上,再写入0,则Q0上的1被挤到Q1,Q0上的数据变为0,以此类推。最后移位寄存器上Q7-Q0的数据为10110111;

  • MR引脚为低时清空移位寄存器中的数据;

  • 当写入的数据超过8位时,最先写入的数据会经过Q7S引脚输出,如写入数据10110111,此时再写入一位数据0,则Q7上的数据1会被挤到Q7S上,Q6的数据挤到Q7上,以此类推,Q0补上新写入的数据0,此时Q7~Q0的数据为01101110;

  • 当STCP引脚处于上升沿时,移位寄存器上的8位数据将一次性锁存到存储寄存器中;

  • OE引脚为低电平时,存储寄存器上的数据会输出到并出输出引脚(Q0-Q7)上。为高电平时,并行输出引脚(Q0-Q7)则为高阻态

4.级联

使用级联功能时,所有的74HC595D的第10、11、12引脚全部连接到主控芯片的引脚上,U27的第9引脚连接到U26的第14引脚上,形成级联功能;13引脚接地,使得595芯片一直输出。

级联的数据由U27的14引脚输入,当写入的数据超过8位时,最先写入的数据会通过第9引脚输出到U26的14引脚,写入到U26的移位寄存器中。

5.C语言实现 5.1 引脚初始化

主控芯片:STM32F103RCT6

使用到的引脚PB4->STCP、PB5->MR、PB6->SHCP、PB7->DS,全部配置成通用推挽输出,需要注意的是由于使用到PB4引脚,PB4默认启用时不是普通引脚,是JTAG的复用功能-NJTRST,因此需要关闭JTAG-DP,启用SW-DP需要增加以下两行代码

RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE);
GPIO_PinRemapConfig(GPIO_Remap_SWJ_JTAGDisable,ENABLE);
void HC595_init()
{
    GPIO_InitTypeDef GPIO_InitStructure;
    RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOB, ENABLE );
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE);
    GPIO_PinRemapConfig(GPIO_Remap_SWJ_JTAGDisable,ENABLE);
​
    GPIO_InitStructure.GPIO_Pin =GPIO_Pin_4 | GPIO_Pin_5 | GPIO_Pin_6 | GPIO_Pin_7;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;  //通用推挽输出
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_Init(GPIOB, &GPIO_InitStructure);
    GPIO_ResetBits(GPIOB,GPIO_Pin_4|GPIO_Pin_6|GPIO_Pin_7);//拉低
    GPIO_SetBits(GPIOB,GPIO_Pin_5);//MR一直为高,不复位移位寄存器    
}
​
5.2 发送数据
​
void HC595_send_data(u8 *data,u16 len)
{
    u8 i,j;
    u8 temp;
    for(i = 0;i < len;i++)
    {
        temp = data[i];
        for(j = 0;j < 8;j++)
        {
            if(temp & 0x80)//先发送高位
                GPIO_SetBits(GPIOB,GPIO_Pin_7);
            else
                GPIO_ResetBits(GPIOB,GPIO_Pin_7);
            GPIO_ResetBits(GPIOB,GPIO_Pin_6);
            delay(2);
            GPIO_SetBits(GPIOB,GPIO_Pin_6);//SHCP为上升沿时写入数据
            delay(2);
            temp <<= 1;
        }
    }
    GPIO_ResetBits(GPIOB,GPIO_Pin_4);
    delay(2);
    GPIO_SetBits(GPIOB,GPIO_Pin_4);//STCP为上升沿时移位寄存器上的数据锁存到存储寄存器上
    delay(2);
}
5.3 main函数
int main()
{
    u8 data[5]={0x88,0x88,0x88,0x88,0x88};
    HC595_init();
    HC595_send_data(data,2);
    while(1)
    {
        ;
    }
}
6.Verilog实现

主控芯片:EP4CE10F17C8

module hc595d_drive(
	input 				clk,
	input				rst_n,
	
	input	wire		hc595d_wr_en,
	
	output 	reg 		hc595d_stcp,
	output 	wire		hc595d_mr,
	output 	reg			hc595d_shcp,
	output 	reg 		hc595d_ds
);

reg [31:0]	wr_data;			//待写入的数据
reg [2:0]	wr_data_len;		//待写入数据的字节长度
reg			wr_data_flag;		//开始写入数据标志
reg [2:0]	wr_bitdata_cnt;		//计数写入数据的字节数
reg [3:0]	wr_bytedata_cnt;	//计数写入数据的位数
reg	[3:0]	wr_state;			//写入数据的状态
reg [7:0]	byte_num;		//统计写入的位数

//上升沿接口
wire       en_flag;
reg        en_d0; 
reg        en_d1; 

 
//hc595d_scl拉高,不复位移位寄存器
assign hc595d_mr = 1;
//写入的数据
assign	wr_data = {8'h11,8'h11,8'h11,8'h11};
//写入的字节数
assign	wr_data_len = 3'd4;
//捕获hc595d_wr_en上升沿,可以写入数据
assign en_flag = (~en_d1) & en_d0;



                                                
//对写使能信号hc595d_wr_en延迟两个时钟周期
always @(posedge clk or negedge rst_n) begin         
    if (!rst_n) begin
        en_d0 <= 1'b0;                                  
        en_d1 <= 1'b0;
    end                                                      
    else begin                                               
        en_d0 <= hc595d_wr_en;                               
        en_d1 <= en_d0;                            
    end
end

//写入标志位控制
always @(posedge clk or negedge rst_n) begin
	if(!rst_n) begin
		wr_data_flag <= 0;
	end
	else begin
		if(en_flag) begin //接收数据,开始写入数据标志位置1
			wr_data_flag <= 1;
		end
		else if(wr_bitdata_cnt == wr_data_len) begin //写完了
			wr_data_flag <= 0;
		end
		else begin
			wr_data_flag <= wr_data_flag;
		end
	end			
end

//写入wr_data_len个字节的数据
always @(posedge clk or negedge rst_n) begin
	if(!rst_n) begin
		wr_bitdata_cnt <= 2'd0;
		wr_bytedata_cnt <= 4'd0;
		wr_state <= 0;
		hc595d_stcp <= 0;
		hc595d_shcp <= 1'd0;
		hc595d_ds <= 0;
		byte_num <= 0;
	end
	else begin
		if(wr_data_flag)begin
			case(wr_state)
				4'd0:begin  
					hc595d_stcp <= 1'd0;
					hc595d_shcp <= 1'd0;
					wr_state <= 4'd1;
				end
				4'd1:begin
					hc595d_ds <= wr_data[4'd31 - byte_num];//输出高位数据
					wr_state <= 4'd2;
				end
				4'd2:begin
					hc595d_shcp <= 1'd1; //上升沿,数据写入移位寄存器
					wr_bytedata_cnt <= wr_bytedata_cnt + 1;//位数+1
					byte_num <= byte_num + 1;//位数+1
					wr_state <= 4'd3;
				end
				4'd3:begin
					if(wr_bytedata_cnt == 4'd8)begin //8位一个字节
						wr_bytedata_cnt <= 0;
						wr_bitdata_cnt <= wr_bitdata_cnt + 1;//字节数+1
						wr_state <= 4'd4;
					end
					else begin
						wr_state <= 4'd0;
					end
				end
				4'd4:begin
					wr_state <= 4'd0;
					if(wr_bitdata_cnt == wr_data_len)begin //写完了
						wr_bitdata_cnt = 2'd0;
						hc595d_stcp <= 1'd1;//上升沿,移位寄存器所存在存储寄存器并输出
						byte_num <= 0;
					end
					
				end
				default:begin
					;
				end
			endcase
		end
		else begin
			wr_bitdata_cnt <= 2'd0;
			wr_bytedata_cnt <= 4'd0;
			wr_state <= 0;
			hc595d_stcp <= 0;
			hc595d_shcp <= 1'd0;
			hc595d_ds <= 0;
			byte_num <= 0;
		end
	end			
end

endmodule

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/976369.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号