FPGA模块——SPI协议(读写FLASH)

FPGA模块——SPI协议(读写FLASH)

  • (1)FLASH芯片 W25Q16BV
  • (2)SPI协议
  • (3)芯片部分命令
    • 1.Write Enable(06h)
    • 2.Chip Erase (C7h / 60h)
    • 3.写指令(02h)
    • 4.读指令(03h)
  • (4)代码
    • 1. FPGA做主机的SPI协议
    • 2. SPI协议的使用

(1)FLASH芯片 W25Q16BV

芯片引脚图:
在这里插入图片描述

内部结构图:
存储区域总共分成了32块,每块64KB。每块又分成了16个部分,每个部分4KB。方便进行读取和局部操作。
在这里插入图片描述
电路设计
在这里插入图片描述

(2)SPI协议

SPI的四种模式
在这里插入图片描述

这里使用这个模式:
主机和从机在时钟上升沿放入要输出的数据,在时钟下降沿读取要输入的数据。
8个时钟后交换一个字节8位数据(高位在前)。
在这里插入图片描述

(3)芯片部分命令

有个输入时序的要求 开始时CS拉低等待(tSLCH要求最小5ns)再开始, 结束时CS拉高等待(tSHSL用100ns )再进行下一次操作。
在这里插入图片描述

这个寄存器的第一位数据可以判断操作是否完成(BUSY位)
在这里插入图片描述

1.Write Enable(06h)

写使能:开始时CS拉低等待(tSLCH要求最小5ns)再开始,结束时CS拉高等待(tSHSL取100ns )再进行下一次操作。
在这里插入图片描述

2.Chip Erase (C7h / 60h)

整片擦除,要判断操作是否完成
在这里插入图片描述

3.写指令(02h)

数据写多了会把之前的数据覆盖掉,要判断操作是否完成。
在这里插入图片描述

4.读指令(03h)

要判断操作是否完成
在这里插入图片描述

(4)代码

1. FPGA做主机的SPI协议

在这里插入图片描述
对信号进行同步和提前准备:
100m时钟和clk_cnt配合进行数据的读取和输出(clk_cnt有等于1和0的时候)
spi_clk基于100m时钟输出一个相当于clk_cnt的延时半个周期的时钟,确保输入输出数据稳定。

module spi_drive(

	input             clk_100m      ,
	input             sys_rst_n     ,
	
	//user interface
	input             spi_start     ,//spi开启使能。
	input [7:0 ]      spi_cmd       ,//FLAH操作指令
	input [23:0]      spi_addr      ,//FLASH地址
	input [7:0 ]      spi_data      ,//FLASH写入的数据
	input [3:0 ]      cmd_cnt       ,
	
	output            idel_flag_r   ,//空闲状态标志的上升沿 
	output reg        w_data_req    ,//FLASH写数据请求 
	output reg [7:0]  r_data        ,//FLASH读出的数据
	output reg        erro_flag     ,//读出的数据错误标志
	
	//spi interface
	output reg        spi_cs        ,//SPI从机的片选信号,低电平有效。
	output reg        spi_clk       ,//主从机之间的数据同步时钟。
	output reg        spi_mosi      ,//数据引脚,主机输出,从机输入。
	input             spi_miso       //数据引脚,主机输入,从机输出。

);

//状态机
parameter IDLE         =4'd0;//空闲状态
parameter WEL          =4'd1;//写使能状态
parameter S_ERA        =4'd2;//扇区擦除状态
parameter C_ERA        =4'd3;//全局擦除
parameter READ         =4'd4;//读状态
parameter WRITE        =4'd5;//写状态
parameter R_STA_REG    =4'd6;

//指令集
parameter WEL_CMD      =8'h06;
parameter S_ERA_CMD    =8'h20;
parameter C_ERA_CMD    =8'hc7;
parameter READ_CMD     =8'h03;
parameter WRITE_CMD    =8'h02;
parameter R_STA_REG_CMD=8'h05;

//wire define
wire      idel_flag;

//reg define
reg[3:0]  current_state  ;
reg[3:0]  next_state     ;
reg[7:0 ] data_buffer    ;
reg[7:0 ] cmd_buffer     ;
reg[7:0 ] sta_reg        ;
reg[23:0] addr_buffer    ;
reg[31:0] bit_cnt        ;
reg       clk_cnt        ;
reg       dely_cnt       ;
reg[31:0] dely_state_cnt ;
reg[7:0 ] rd_data_buffer ;
reg       spi_clk0       ;
reg       stdone         ;
reg[7:0 ] data_check     ;
reg       idel_flag0     ;
reg       idel_flag1     ;

//*****************************************************
//**                    main code
//*****************************************************

//*抓取上升沿
assign idel_flag=(current_state==IDLE)?1:0;//空闲状态标志
assign idel_flag_r=idel_flag0&&(~idel_flag1);//空闲状态标志的上升沿

//*抓取上升沿要用的
always @(posedge clk_100m or negedge sys_rst_n )begin
	if(!sys_rst_n)begin
		idel_flag0<=1'b1;
		idel_flag1<=1'b1;
	end
	else begin
		idel_flag0<=idel_flag;
		idel_flag1<=idel_flag0;
	end
end

//请求数据 + 把数据放入buffer 
always @(posedge clk_100m or negedge sys_rst_n )begin
	if(!sys_rst_n)
		w_data_req<=1'b0;
	else if((bit_cnt+2)%8==0&&bit_cnt>=30&&clk_cnt==0&&current_state==WRITE) //提前2个时钟周期
		w_data_req<=1'b1;
	else
		w_data_req<=1'b0;
end

always @(posedge clk_100m or negedge sys_rst_n )begin//读出的数据移位寄存
	if(!sys_rst_n)
		rd_data_buffer<=8'd0;
	else if(bit_cnt>=32&&bit_cnt<=2080&&clk_cnt==0&&current_state==READ)									
		rd_data_buffer<={rd_data_buffer[6:0],spi_miso};
	else
		rd_data_buffer<=rd_data_buffer;
end

always @(posedge clk_100m or negedge sys_rst_n )begin//检查读出的数据是否正确
	if(!sys_rst_n)
		data_check<=8'd0;
	else if(bit_cnt%8==0&&bit_cnt>=40&&clk_cnt==1&&current_state==READ)
		data_check<=data_check+1'd1;
	else
		data_check<=data_check;
end

always @(posedge clk_100m or negedge sys_rst_n )begin//读出的数据
	if(!sys_rst_n)
		r_data<=8'd0;
	else if(bit_cnt%8==0&&bit_cnt>38&&clk_cnt==1&&current_state==READ)
		r_data<=rd_data_buffer;
	else
		r_data<=r_data;
end

always @(posedge clk_100m or negedge sys_rst_n )begin//读出的数据错误标志
	if(!sys_rst_n)
		erro_flag<=1'd0;
	else if(bit_cnt>32&&bit_cnt<=2080&&current_state==READ&&cmd_cnt==6)begin
		if(data_check!=r_data)
			erro_flag<=1'd1;
		else
			erro_flag<=erro_flag;
		end
	else
		erro_flag<=erro_flag;
end
	
//*把数据放入buffer 提前一个周期
always @(posedge clk_100m or negedge sys_rst_n )begin
	if(!sys_rst_n)
		data_buffer<=8'd0;
	else if((bit_cnt+1)%8==0&&bit_cnt>30&&clk_cnt==1)//*把数据放入buffer 提前一个周期
		data_buffer<=spi_data;
	else if(clk_cnt==1&&current_state==WRITE&&bit_cnt>=32)
		data_buffer<={data_buffer[6:0],data_buffer[7]};
	else
		data_buffer<=data_buffer;
end

//*----位移cmd指令存储器 开始:cs选中且dely未生效,提前了100mhz的周期------------
//使50mhz时数据提前半个周期获得
always @(posedge clk_100m or negedge sys_rst_n )begin
	if(!sys_rst_n)
		cmd_buffer<=8'd0;
	else if(spi_cs==0&&dely_cnt==0)
		cmd_buffer<=spi_cmd;
	else if(clk_cnt==1&&(current_state==WEL||current_state==S_ERA||current_state==C_ERA
	       ||current_state==READ||current_state==WRITE||current_state==R_STA_REG)&&bit_cnt<8)
		cmd_buffer<={cmd_buffer[6:0],1'b1};
	else
		cmd_buffer<=cmd_buffer;
end

//取出地址每一位
always @(posedge clk_100m or negedge sys_rst_n )begin
	if(!sys_rst_n)
		addr_buffer<=8'd0;
	else if(spi_cs==0&&dely_cnt==0)
		addr_buffer<=spi_addr;
	else if(clk_cnt==1&&(current_state==READ||current_state==WRITE)&&bit_cnt>=8&&bit_cnt<32)
		addr_buffer<={addr_buffer[22:0],addr_buffer[23]};
	else
		addr_buffer<=addr_buffer;
end

//------------使能后clk_cnt输出50M时钟用于操作信号--------------
always @(posedge clk_100m or negedge sys_rst_n )begin
	if(!sys_rst_n)
		clk_cnt<=1'd0;
	else if(dely_cnt==1)
		clk_cnt<=clk_cnt+1'd1;
	else 
		clk_cnt<=1'd0;
end

//*---------cs选中器件后的信号输出的  dely_cnt 可以认为是使能操作------------
always @(posedge clk_100m or negedge sys_rst_n )begin
	if(!sys_rst_n)
		dely_cnt<=1'd0;
	else if(spi_cs==0)begin
	    if(dely_cnt<1)
			dely_cnt<=dely_cnt+1'd1;
		else
			dely_cnt<=dely_cnt;
	end
	else
		dely_cnt<=1'd0;
end

//*-----------------结束的延时计时器------------------------------------
always @(posedge clk_100m or negedge sys_rst_n )begin
	if(!sys_rst_n)
		dely_state_cnt<=1'd0;
	else if(spi_cs)begin
	    if(dely_state_cnt<400000000)
			dely_state_cnt<=dely_state_cnt+1'd1;
		else
			dely_state_cnt<=dely_state_cnt;
	end
	else
		dely_state_cnt<=1'd0;
end

//*-------------------------bit读写计数---------------------
always @(posedge clk_100m or negedge sys_rst_n )begin
	if(!sys_rst_n)
		bit_cnt<=11'd0;
	else if(dely_cnt==1)begin
			if(clk_cnt==1'b1)
				bit_cnt<=bit_cnt+1'd1;
			else
				bit_cnt<=bit_cnt;
	end
	else
		bit_cnt<=11'd0;
end

状态机 :每个状态该干什么,怎么转移
修改里面的命令和转态就可以移植到其他的地方了。

//三段式状态机
always @(posedge clk_100m or negedge sys_rst_n )begin
	if(!sys_rst_n)
		current_state<=IDLE;
	else
		current_state<=next_state;
end

always @(*)begin

	case(current_state)
	
	   IDLE: begin
	          if(spi_start&&spi_cmd==WEL_CMD)
				next_state=WEL;
			  else if(spi_start&&spi_cmd==C_ERA_CMD)
				next_state=C_ERA;
			  else if(spi_start&&spi_cmd==S_ERA_CMD)
				next_state=S_ERA;
			  else if(spi_start&&spi_cmd==READ_CMD)
				next_state=READ;
			  else if(spi_start&&spi_cmd==WRITE_CMD)
				next_state=WRITE;
			  else if(spi_start&&spi_cmd==R_STA_REG_CMD)
				next_state=R_STA_REG;
			  else
	            next_state=IDLE;
			end
	
		WEL: begin
			  if(stdone&&bit_cnt>=8)
				   next_state=IDLE;
			  else
		           next_state=WEL;
			  end
			 
		S_ERA: begin
				if(stdone)
					next_state=IDLE;
				else
					next_state=S_ERA;
				end
		C_ERA: begin		
				if(stdone)
					next_state=IDLE;
				else
					next_state=C_ERA;
				end
		READ: begin 		
				if(stdone&&bit_cnt>=8)
					next_state=IDLE;
				else
					next_state=READ;
				end
		WRITE: begin		
				 if(stdone&&bit_cnt>=8)
					next_state=IDLE;
				else
					next_state=WRITE;
				end
		R_STA_REG: begin		
				 if(stdone)
					next_state=IDLE;
				else
					next_state=R_STA_REG;
				end
		
	default: next_state=IDLE;			
	endcase				
end
									
always @(posedge clk_100m or negedge sys_rst_n )begin
	if(!sys_rst_n) begin
		spi_cs<=1'b1;
		spi_clk<=1'b0;
		spi_clk0<=1'b0;
		spi_mosi<=1'b0;	
		stdone<=1'b0;		
	end
	else begin
		case(current_state)
			IDLE: begin
				spi_cs<=1'b1;
				spi_clk<=1'b0;
				spi_mosi<=1'b0;				
			end
			
			WEL: begin
			     stdone<=1'b0;
				 spi_cs<=1'b0;
					 if(dely_cnt==1&&bit_cnt<8) begin						
						spi_clk0<=~spi_clk0;
						spi_clk<=spi_clk0;
						spi_mosi<=cmd_buffer[7];
						end
					 else if(bit_cnt==8&&clk_cnt==0)begin
					    stdone<=1'b1;
						spi_clk<=1'b0;						
						spi_mosi<=1'b0;						
					 end
					 else if(bit_cnt==8&&clk_cnt==1)begin
						spi_cs<=1'b1;						
				 end
				 end
			C_ERA: begin
					stdone<=1'b0;
			         if(dely_state_cnt==10)                
						spi_cs<=1'b0;
					 else if(dely_cnt==1&&bit_cnt<8) begin						
						spi_clk0<=~spi_clk0;
						spi_clk<=spi_clk0;
						spi_mosi<=cmd_buffer[7];
						end
					 else if(bit_cnt==8&&clk_cnt==0)begin
					    stdone<=1'b1;				    
						spi_clk<=1'b0;
						spi_mosi<=1'b0;	
					 end
					  else if(bit_cnt==8&&clk_cnt==1)begin
						spi_cs<=1'b1;						
				 end
				 end
			S_ERA: begin
			       stdone<=1'b0;				 
					if(dely_state_cnt==10)                
						spi_cs<=1'b0;
					 else if(dely_cnt==1&&bit_cnt<8) begin						
						spi_clk0<=~spi_clk0;
						spi_clk<=spi_clk0;
						spi_mosi<=cmd_buffer[7];
						end
					 else if(bit_cnt>=8&&bit_cnt<32&&spi_cs==0)begin
					    spi_cs<=1'b0;
						spi_clk0<=~spi_clk0;
						spi_clk<=spi_clk0;
						spi_mosi<=addr_buffer[23];
					 end
					 else if(bit_cnt==32&&clk_cnt==0) begin
						spi_cs<=1'b1;
						spi_clk<=1'b0;
						spi_mosi<=1'b0;
						stdone<=1'b1;
					 end
				 end
            READ: begin
			      stdone<=1'b0;
				  if(dely_state_cnt==10)                
						spi_cs<=1'b0;
					else if(dely_cnt==1&&bit_cnt<8) begin						
						spi_clk0<=~spi_clk0;
						spi_clk<=spi_clk0;
						spi_mosi<=cmd_buffer[7];
						end
					 else if(bit_cnt>=8&&bit_cnt<32&&spi_cs==0)begin					    
						spi_clk0<=~spi_clk0;
						spi_clk<=spi_clk0;
						spi_mosi<=addr_buffer[23];
					 end
					 else if(bit_cnt>=32&&bit_cnt<2080)begin						
						spi_clk0<=~spi_clk0;
						spi_clk<=spi_clk0;
						spi_mosi<=1'b0;						
					 end
					 else if(bit_cnt==2080&&clk_cnt==0) begin						
						spi_clk<=1'b0;
						spi_mosi<=1'b0;
						stdone<=1'b1;						
					 end
					  else if(bit_cnt==2080&&clk_cnt==1) begin
						spi_cs<=1'b1;
					 end
				 end
            WRITE: begin
			     stdone<=1'b0;
				  if(dely_state_cnt==10)                
						spi_cs<=1'b0;
					 else if(dely_cnt==1&&bit_cnt<8) begin						
						spi_clk0<=~spi_clk0;
						spi_clk<=spi_clk0;
						spi_mosi<=cmd_buffer[7];
						end
					 else if(bit_cnt>=8&&bit_cnt<32&&spi_cs==0)begin					   
						spi_clk0<=~spi_clk0;
						spi_clk<=spi_clk0;
						spi_mosi<=addr_buffer[23];
					 end
					 else if(bit_cnt>=32&&bit_cnt<2080)begin						
						spi_clk0<=~spi_clk0;
						spi_clk<=spi_clk0;
						spi_mosi<=data_buffer[7];
					 end
					 else if(bit_cnt==2080&&clk_cnt==0) begin
						
						spi_clk<=1'b0;
						spi_mosi<=1'b0;
						stdone<=1'b1;
					 end
					  else if(bit_cnt==2080&&clk_cnt==1) begin
						spi_cs<=1'b1;
					 end
                  end
			R_STA_REG:begin				              
						stdone<=1'b0;
				     if(dely_state_cnt==10)                
						spi_cs<=1'b0;
					else if(dely_cnt==1&&bit_cnt<8)begin						
						spi_clk0<=~spi_clk0;
						spi_clk<=spi_clk0;
						spi_mosi<=cmd_buffer[7];
						end
					 else if(bit_cnt==8)begin					   				    
						spi_clk0<=~spi_clk0;
						spi_clk<=spi_clk0;
						spi_mosi<=1'b0;						
					 end                      				 
					  else if(~spi_miso&&bit_cnt%8==0)begin
					    spi_clk<=1'b0;
						spi_cs<=1'b1;
						stdone<=1'b1;
				      end
					 else if(~spi_cs&&dely_cnt==1)begin
						spi_clk0<=~spi_clk0;
						spi_clk<=spi_clk0;
				 end	   			         	 
			  end 
             default: begin
			            stdone<=1'b0;
                        spi_cs<=1'b1;
				        spi_clk<=1'b0;
						spi_clk0<=1'b0;
				        spi_mosi<=1'b0;				        
			end
         endcase
	end
end

endmodule

2. SPI协议的使用

首先系统开始运行,来几个周期延伸。
spi_start信号只是一个周期脉冲。
idel_flag_r是进入空闲状态的标志位也就是意味着上一步操作完成。
cmd计数指令不断加来切换不同的命令。
spi_cmd 输出命令

module flash_rw(

	input            sys_clk      ,
	input            sys_rst_n    ,
	
	input            idel_flag_r  ,
	input            w_data_req   ,
	output reg[3:0 ] cmd_cnt      ,
	output reg       spi_start    ,//spi开启使能。
	output reg[7:0 ] spi_cmd      ,
	output reg[7:0 ] spi_data      
   
);

//指令集
parameter WEL_CMD      =16'h06;
parameter S_ERA_CMD    =16'h20;
parameter C_ERA_CMD    =16'hc7;
parameter READ_CMD     =16'h03;
parameter WRITE_CMD    =16'h02;
parameter R_STA_REG_CMD=8'h05 ;

//reg define
reg[3:0] flash_start;


//SPI 要写入的数据
always @(posedge sys_clk or negedge sys_rst_n )begin
	if(!sys_rst_n)
		flash_start<=0;
	else if(flash_start<=5)
	    flash_start<=flash_start+1;
	else
		flash_start<=flash_start;
end

always @(posedge sys_clk or negedge sys_rst_n )begin
	if(!sys_rst_n)
		cmd_cnt<=0;
	else if(flash_start==4)
	    spi_start<=1'b1;
	else if(idel_flag_r&&cmd_cnt<10)begin
	    cmd_cnt<=cmd_cnt+1;
		spi_start<=1'b1;
	end
	else begin
		cmd_cnt<=cmd_cnt;
		spi_start<=1'b0;
	end
end

always @(posedge sys_clk or negedge sys_rst_n )begin
	if(!sys_rst_n)
		spi_data<=8'd0;
	else if(w_data_req)
		spi_data<=spi_data+1'b1;
	else
		spi_data<=spi_data;
end

always @(*)begin
	case(cmd_cnt)
		0:spi_cmd=WEL_CMD;
		1:spi_cmd=C_ERA_CMD;
		2:spi_cmd=R_STA_REG_CMD;
		3:spi_cmd=WEL_CMD;
		4:spi_cmd=WRITE_CMD;
		5:spi_cmd=R_STA_REG_CMD;
		6:spi_cmd=READ_CMD;
		7:spi_cmd=WEL_CMD;
		8:spi_cmd=S_ERA_CMD;
		9:spi_cmd=R_STA_REG_CMD;
		10:spi_cmd=READ_CMD;
		
	default:;
	endcase
end

endmodule

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

华为ospf路由协议防环和次优路径中一些难点问题分析

第一种情况是ar3的/0/0/2口和ar4的0/0/2口发布在区域1时&#xff0c;当ar1连接ar2的线断了以后&#xff0c;骨干区域就断了&#xff0c;1.1.1.1到2.2.2.2就断了&#xff0c;ping不通了。但ar5和ar6可以ping通2.2.2.2和1.1.1.1&#xff0c;ar3和ar4不可以ping通2.2.2.2和1.1.1.1…

中伟视界:AI智能分析盒子实现全方位人车监测,保障管道安全

在油气管道长又无人的场景下&#xff0c;人和车的监测问题一直是一个难题。传统的监测手段往往存在盲区和误报问题&#xff0c;给管道运行安全带来了一定的隐患。然而&#xff0c;随着人工智能技术的不断发展&#xff0c;利用AI盒子的智能分析算法可以有效解决这一问题。 首先&…

【从浅识到熟知Linux】基本指定之cat、more和less

&#x1f388;归属专栏&#xff1a;从浅学到熟知Linux &#x1f697;个人主页&#xff1a;Jammingpro &#x1f41f;每日一句&#xff1a;写完这篇我要去吃晚饭啦&#xff01;&#xff01; 文章前言&#xff1a;本文介绍cat、more和less指令三种查看文件的用法并给出示例和截图…

MUYUCMS v2.1:一款开源、轻量级的内容管理系统

MuYuCMS&#xff1a;一款基于Thinkphp开发的轻量级开源内容管理系统&#xff0c;为企业、个人站长提供快速建站解决方案。它具有以下的环境要求&#xff1a; 支持系统&#xff1a;Windows/Linux/Mac WEB服务器&#xff1a;Apache/Nginx/ISS PHP版本&#xff1a;php > 5.6 (…

输出后,我悟了!

大家好&#xff0c;我是木川 今天和前同事吃饭聊天&#xff0c;谈到了输出&#xff0c;今天简单谈下关于输出的重要性 一、为什么要输出 1、不输出容易忘&#xff0c;如果不输出很容易就忘记了&#xff0c;如果再遇见一次&#xff0c;还是需要重新学习&#xff0c;实际上是浪费…

Transformer——decoder

上一篇文章&#xff0c;我们介绍了encoder&#xff0c;这篇文章我们将要介绍decoder Transformer-encoder decoder结构&#xff1a; 如果看过上一篇文章的同学&#xff0c;肯定对decoder的结构不陌生&#xff0c;从上面框中可以明显的看出&#xff1a; 每个Decoder Block有两个…

STK Components 二次开发-创建卫星

1.卫星数据 可以用stk 里面自带的 参数帮助文档。 也可以自己下载 CelesTrak: Current GP Element Sets 这里你所需要的最新卫星数据全有。 其实创建需要的就是卫星的二根数。 给定二根数也可以。 读取数据库中的卫星数据 这个接口优先下载最新的。 var tleList TwoL…

Web3 进入“殖民时代”

最近在 AI 和 Web3 领域发生了两件“大”事&#xff0c;两件事都具有指标意义&#xff0c;但在媒体上其意义都被大量的八卦细节给掩埋了。 其实看待任何重大事件&#xff0c;都可以有两种不同的视角。第一是娱乐的视角&#xff0c;在新闻事件中找乐子。如果是本着这个目的&…

HarmonyOS应用开发者高级认证【题库答案】

HarmonyOS应用开发者基础认证【题库答案】 一、判断题 云函数打包完成后&#xff0c;需要到AppGallery Connect创建对应函数的触发器才可以在端侧中调用&#xff08;错&#xff09;在column和Row容器组件中&#xff0c;aligntems用于设置子组件在主轴方向上的对齐格式&#xf…

自建私有化证书颁发机构(Certificate Authority,CA)实战之 《0x02 Nginx 配置 https双向认证》

自建CA实战之 《0x02 Nginx 配置 https双向认证》 上一章节我们已经实现了Nginx上配置https单向认证&#xff0c;主要场景为客户端验证服务端的身份&#xff0c;但是服务端不验证客户端的身份。 本章节我们将实现Nginx上配置https双向认证&#xff0c;主要场景为客户端验证服…

深度学习第二天:RNN循环神经网络

☁️主页 Nowl &#x1f525;专栏《机器学习实战》 《机器学习》 &#x1f4d1;君子坐而论道&#xff0c;少年起而行之 文章目录 介绍 记忆功能对比展现 任务描述 导入库 处理数据 前馈神经网络 循环神经网络 编译与训练模型 模型预测 可能的问题 梯度消失 梯…

【基础知识】AB软件RSLinx如何实现OPC通讯组态

哈喽&#xff0c;大家好&#xff0c;我是雷工。 在上一节了解了什么是RSLinx&#xff1f;以及RSLinx Lite、RSLinx Classice、RSLinx Professional、RSLinx Gateway几个版本的特点。 本节了解AB的RSLinx如何实现OPC组态。 一、创建RSLinx通讯&#xff1a; 1.1、【Communicati…

RabbitMQ之发送者(生产者)可靠性

文章目录 前言一、生产者重试机制二、生产者确认机制实现生产者确认&#xff08;1&#xff09;定义ReturnCallback&#xff08;2&#xff09;定义ConfirmCallback 总结 前言 生产者重试机制、生产者确认机制。 一、生产者重试机制 问题&#xff1a;生产者发送消息时&#xff0…

(Matalb回归预测)GA-BP遗传算法优化BP神经网络的多维回归预测

目录 一、程序及算法内容介绍&#xff1a; 基本内容&#xff1a; 亮点与优势&#xff1a; 二、实际运行效果&#xff1a; 三、部分代码&#xff1a; 四、分享本文全部代码数据说明手册&#xff1a; 一、程序及算法内容介绍&#xff1a; 基本内容&#xff1a; 本代码基于M…

IT行业多项目管理的方法与策略:优化资源分配与提升项目成功率

多项目管理已成为项目经理们面临的常态&#xff0c;IT行业如何高效进行项目管理呢&#xff1f; 多项目管理过程中存在的问题 1、多类型项目并行&#xff0c;项目流程掺杂混乱&#xff0c;项目进度难以监控&#xff0c;反应缓慢&#xff0c;容易产生延误风险。 2、团队资源有…

arp报文及使用go实现

一、ARP协议报文格式及ARP表 ARP&#xff08;Address Resolution Protocal&#xff0c;地址解析协议&#xff09;是将IP地址解析为以太网的MAC地址&#xff08;或者称为物理地址&#xff09;的协议。在局域网中&#xff0c;当主机或其他网络设备有数据要发送给另一个主机或设备…

03:2440--UART

目录 一:UART 1:概念 2:工作模式 3:逻辑电平 4:串口结构图 5:时间的计算 二:寄存器 1:简单的UART传输数据 A:GPHCON--配置引脚 B:GPHUP----使能内部上拉​编辑 C: UCON0---设置频率115200 D: ULCON0----数据格式8n1 E:发送数据 A:UTRSTAT0 B:UTXHO--发送数据输…

二维数值型数组例题2

1、内部和 题目描述 给定一个m行n列的二维矩阵&#xff0c;求其内部元素和 输入要求 第一行为两个整数&#xff1a;m和n&#xff08;0<m,n<10&#xff09;&#xff0c;接下来输入m*n的二维矩阵 输出要求 二维矩阵内部元素和 输入样例 3 3 1 2 3 4 5 6 7 8 9 …

基于python+Django+SVM算法模型的文本情感识别系统

欢迎大家点赞、收藏、关注、评论啦 &#xff0c;由于篇幅有限&#xff0c;只展示了部分核心代码。 文章目录 一项目简介1. 简介2. 技术栈3. 系统架构4. 关键模块介绍5. 如何运行 二、功能三、系统四. 总结 一项目简介 # 基于 Python Django SVM 算法模型的文本情感识别系统介…

芯片安全和无线电安全底层渗透技术

和传统网络安全不同&#xff0c;硬件安全、芯片安全、无线电安全属于网络底层安全的重要细分领域&#xff0c;是网络安全的真正基石&#xff0c;更是国家安全的重要组成部分&#xff0c;“夯实网络底层安全基础&#xff0c;筑牢网络强国安全底座”&#xff0c;是底网安全重要性…